Page 1 of 1
Evil Floppy!!
Posted: Tue Jul 01, 2003 2:18 pm
by Tux
I just want to know how many people have a working floppy driver. Why? It seems to me not a lot of people have it and that is the stopping point of OS dev. On IRC, many people can't go ahead because of the floppy driver.
(Newbie's, please remember this is pmode only)
Re:Evil Floppy!!
Posted: Tue Jul 01, 2003 3:17 pm
by Pype.Clicker
if you get a look at Linux's implementation of the floppy disk, you'll see the maintainer is complaining about the low-level aspect of this device during a dozen of lines.
By having worked on a HDD driver, i would add that disk drivers are not as simple as keyboard/mouse for a few technical reasons:
1. the documentation is a bit harder to find, mainly because less people dare to do disk accesses
2. when the controller gets wrong, you need to reset it, which usually require a timer. And having a timer doesn't only means you have a clock interrupt, it also require you to count "real" time rather than clock ticks (i.e. you must compute how much ticks make a millisecond, and so on), handle several such timers and being able to wake up tasks on demand. trust me, waking up a sleeping task is *much* more complex than running 2 "hello world" tasks, especially if you don't feel like keeping a semaphore on each of these.
3. being able to do the data transfer means that you have a buffer ready for it, whatever address space you're in, thus potentially needing a buffers manager.
now, it is still possible to achieve ... just more complicated than one could figure by looking at the "INT 13h" api...
Re:Evil Floppy!!
Posted: Tue Jul 01, 2003 3:19 pm
by Tim
Me. In fact, I have two working floppy drivers.
Here's one of them:
http://cvs.sourceforge.net/cgi-bin/view ... ivers/fdc/
I originally based my code off Fabian Nunez's driver (see Chris Giese's site), but I later rewrote my driver, using Debs' page as a reference (
http://debs.future.easyspace.com/Progra ... loppy.html).
Re:Evil Floppy!!
Posted: Tue Jul 01, 2003 3:31 pm
by Pype.Clicker
nice one. personnally, i find pretty interresting the approach Tim seems to have generalized in his code, i.e. to have first a list of "low level abstraction" functions for the I/O operations and then the implementation of high-level API using the abstractions and as little inb/outb as possible.
though i might have sent it one step further by
Code: Select all
#define fdcSeek(track) FdcSendByte(fdc, CMD_SEEK);\
FdcSendByte(fdc, 0);\
FdcSendByte(fdc, track);
but maybe that's because i'm a #geek
Re:Evil Floppy!!
Posted: Tue Jul 01, 2003 3:36 pm
by Pype.Clicker
hmm ... the "state machine" code makes it clear to read too ... i might spent a few time re-drawing the state diagram to see what it gives ... It should make the implementation more straightforward than trying to deduce it from the hw docs.
Re:Evil Floppy!!
Posted: Tue Jul 01, 2003 4:47 pm
by Tim
In my latest driver, I have those command sequences as arrays of uint8_t's. You might notice from my current sources that the roles of floppy drive controller and floppy drive are merged into one. I now have separate controller and drive objects; SendCommand(uint8_t*) is a function of the controller.
The state machine came about as a byproduct of Mobius' asynchronous I/O architecture (all I/O in the kernel is asynchronous; devices and FSDs never block while handling a request). The newer driver has a worker thread for each controller, which handles a queue of requests coming in from each drive, and translates the state machine you see here into a series of function calls.
I like state machines, and if I see a suitable place for one, I'll use it. The classical application of state machines is in handling ANSI ecape sequences for a terminal. Another place I use a machine is when paging memory; each page has "not present", "clean", "dirty", "I/O in progress", "I/O failed", etc. states. The page fault handler switch()'es on the page state and makes the appropriate transition (e.g. not present -> I/O in progress -> clean or I/O failed).
Re:Evil Floppy!!
Posted: Wed Jul 02, 2003 3:30 am
by Pype.Clicker
hmm, just one more question about asynchronous I/O. say you received and completed a request for a block transfer that had a pages list describing its buffer (quite common approach for async io, if i'm not wrong).
The questions are:
- when in the sequence would you lock the pages for the i/o transfer ? i personnally tried to make it a part of the "read()" command, but it appeared that locking page out of the read() was easier to maintain ...
- when would you unlock the pages ? right at request completion (i.e. in the worker thread or interrupt), in a synchronous part of the disk driver (something like request_code=read(...); terminate(request_code); ) or attempt to have this done automatically when the requestor thread is activated but before it gets notified of I/O completion.
- as I/O blocks may (?) be smaller than pages and memory regions described for them might not be aligned, what policy would you recommend if the same thread attemps to issue several read() on the same pages but on different requests (so that the latter one finds the page already locked).
i personnally solved those problems by stating that asynchronous I/O did not take care of locking buffers but rather assumed that another service made the lock, but it doesn't satisfy me completely ...
Re:Evil Floppy!!
Posted: Wed Jul 02, 2003 6:55 am
by Tim
Pype.Clicker wrote:when in the sequence would you lock the pages for the i/o transfer ? i personnally tried to make it a part of the "read()" command, but it appeared that locking page out of the read() was easier to maintain ...
Physical pages are locked when the page_array_t structure is created, i.e. at the start of the request. This means that each page for the buffer is faulted in, so that its physical address is available. These pages are mapped into the kernel address space just after IRQ6 is handled, so that the driver can use memcpy to copy from its DMA window into the user buffer.
when would you unlock the pages ? right at request completion (i.e. in the worker thread or interrupt), in a synchronous part of the disk driver (something like request_code=read(...); terminate(request_code); ) or attempt to have this done automatically when the requestor thread is activated but before it gets notified of I/O completion.
My driver unmaps the pages just after calling memcpy, but only unlocks the pages on completion of the whole request (i.e. just before notifying the app that the request has finished).
as I/O blocks may (?) be smaller than pages and memory regions described for them might not be aligned, what policy would you recommend if the same thread attemps to issue several read() on the same pages but on different requests (so that the latter one finds the page already locked).
I don't handle this yet. However, the memory manager locks pages based on an 8-bit lock count, so in theory there should be no problem locking a particular page twice.