DRIVERS
These hardware device drivers are done:
- VGA video (w/ VT102 emulation), PS/2 keyboard (w/ VT102 emulation), PS/2 mouse
- DEC 21041 and 21140A (tulip) ethernet cards
- Realtek 8139 ethernet cards (thanks to Tim Robinson for helping me with it)
- Floppy
- LSI Logic 53C875 scsi card
(I wanted to do an Adaptec driver because my motherboard has a built-in Adaptec
chipset, but Adaptec was 'less than forthcoming' with programming info)
- IDE ATA and ATAPI disk (supports generic PIO, and PCI-based PIIX4 and AMD 768 chips)
- Timer
There are also these 'software' drivers:
- ISO-9660 CDROM filesystem
- Console class driver with line-editing functions
- Pseudo-terminals (there is also a telnet client and daemon)
- Disk file system
- Disk partitioner
- Ethernet-like loopback
- TCP/IP stack
- Mutex (like unix semaphores, or VMS enq/deq)
- Pipes (stream and record oriented)
- RAM Disk
- SCSI Disk
- Steganographic disk driver
Borrowing Drivers
There are two methods I have for borrowing drivers from other OS's.
- Project UDI was designed for such a purpose
- Borrowing an MS SCSI driver
Neither method has proven completely successful, however.
Driver Entrypoints
- Initialization
- Shutdown
- Create clone device
- Delete clone device
- New I/O channel being assigned
- I/O channel being deassigned
- Abort I/O request
- Start I/O request
- Perform select (not implemented)
Only Initialization and Start I/O request are required.
Initialization
Drivers can be initialized in any way suited to the task. These ways are
currently implemented in one or more drivers:
- boot-time: called once during system boot
- auto-gen: called when someone tries to access the device when it is not set up
No matter how it is called, its purpose is to create appropriate device
structs that applications can see and to initialize any associated
hardware controllers.
Shutdown
This routine is called when the system is being shut down. It can flush caches out and hardware reset controllers.
Create clone device
This routine is called when a clone device is about to be created. Clone devices are used for such things as
pseudo-terminals, ie, where the device exists only when it is being used.
Delete clone device
This routine is called when the clone device is no longer being used. The driver aborts and closes all processing being
performed on the device.
New I/O channel being assigned
This routine is called when a new channel has been assigned to the device. The driver initializes the per-channel device
struct.
I/O channel being deassigned
The driver closes anything opened on the channel.
Abort I/O request
The driver makes an attempt to abort the indicated I/O operations as soon as it can. Usually, it marks them for abort then
tells the controller to stop processing them.
Start I/O request
This is used to initiate an I/O request. It returns as soon as it can. The I/O is performed either as a series of
interrupt routines or as a kernel thread. When the requested operation has completed, a callback is made to the os to
inform it of such and of the completion status.
Related Data Structures (Kernel Objects)
- OZ_Devunit - there is one of these per device in the system. It is basically opaque to the driver, but the
driver has its own private extension of this struct called the Devex where it can put stuff like
the base I/O port number, a queue of I/O requests in progress, etc. The Devex area is initialized
by either the driver's Initialization or Create clone device routines. It is
terminated by either Shutdown or Delete clone device.
- OZ_Iochan - there is one of these per assigned I/O channel to the device. Drivers have their own private
extension area to these called the Chnex where they can put stuff like what file is open on the
channel. The Chnex area is initialized by the Assign routine and is terminated by the
Deassign routine.
- OZ_Ioop - there is one of these per I/O request. The driver extension area is called Iopex where the driver can
put stuff like queue links, physical page numbers and other saved parameters. The Iopex area is
initialized by the Start I/O routine and is terminated when the request is complete.
The function table
The entrypoints (all except the initialization routine) are located in the driver's function table. The elements of the
function table are:
size of Devex
size of Chnex
size of Iopex
int (*shutdown) (OZ_Devunit *devunit,
void *devex)
uLong (*clonecre) (OZ_Devunit *template_devunit,
void *template_devex,
int template_cloned,
OZ_Procmode procmode,
OZ_Devunit **cloned_devunit)
int (*clonedel) (OZ_Devunit *cloned_devunit,
void *devexv,
int cloned)
uLong (*assign) (OZ_Devunit *devunit,
void *devexv,
OZ_Iochan *iochan,
void *chnexv,
OZ_Procmode procmode)
int (*deassign) (OZ_Devunit *devunit,
void *devexv,
OZ_Iochan *iochan,
void *chnexv)
void (*abort) (OZ_Devunit *devunit,
void *devexv,
OZ_Iochan *iochan,
void *chnexv,
OZ_Ioop *ioop,
void *iopexv,
OZ_Procmode procmode)
uLong (*start) (OZ_Devunit *devunit,
void *devexv,
OZ_Iochan *iochan,
void *chnexv,
OZ_Procmode procmode,
OZ_Ioop *ioop,
void *iopexv,
uLong funcode,
uLong as,
void *ap)
The drivers are interfaced to by module oz_knl_devio.c.