Outdated material; included only for historical reference
If you are going to do SCO Unix driver development (I won't ask why) you need their Hardware Developers Kit, which includes documentation and sample drivers.
One thing that comes up in this context is dual ported ram because apparently it's handled differently in all operating systems. "KERNEL PANIC when my Device Driver accesses hardware" talks about that on SCO Unix.
Device Driver. Two words that strike fear in the hearts of
programmers and users of Unix systems. It's dark, mysterious
territory filled with strange names like splx() and wakeup(). Only
the very bravest dabble here, because it's all very difficult and
But once you understand a little bit about device drivers, what they do and how they work, it's not all that mysterious. And it's not much more dangerous than just logging in as root.
Even if you have no desire to actually write device drivers, you do need to know what they do and how the system gathers them all together to make a Unix kernel. Having just a little knowledge here can help you with installing other people's drivers, and sometimes even with problems that crop up later.
At it's heart, a device driver is just a piece of software code that manages access to a piece of hardware: a printer, a multiport card or the hard drive, for example. What makes drivers different from stand-alone programs is that they are actually part of the Unix kernel: the kernel is made up from the base code that is Unix itself plus all the driver code that tells it how to talk to the hardware it is running on.
The driver has the responsibility of hiding the details of the hardware from the operating system and, ultimately, from you as the user. This is important, because hardware changes all the time. Neither you nor Unix itself wants to work with the details of a hard drive, for instance. You want to 'cat' a file, and Unix translates that into "I need Block Number 3025 from the disk". How to get block 3025 depends on a number of factors: what kind of hard drive is this (IDE,SCSI,ESDI)? What's it's geometry (Cylinders, Heads)? It's the driver code that has the answers to all that and is thus able to quietly come up with the desired block.
If that were all there was too it, why not just have the kernel know all about SCSI and IDE to start with? Build it in, why complicate the issue? Well, we use IDE and SCSI hard drives now, but in a few years our mass storage may be based on light! Obviously our overworked Unix kernel can't be prepared to handle whatever strange storage device pops up in the future. But, a driver can be written for that device that will handle the nitty-gritty details and give Unix what it wants: block number 4077, please.
So what make device drivers so hard to understand? Nothing, really. All a device driver does is take data from one place and transfer it to another. That's not the kind of task that causes anguish to the average programmer. There are two things that make this process difficult: programming around interrupts, and the miscellaneous quirks of the actual hardware device itself.
I'll take up interrupts first. If you don't already understand what a hardware interrupt is, think of it as a way for a device (such as a printer port) to get the computer's attention. That is exactly how they work: there is an electrical line on the CPU called INT (for Interrupt, of course). The details of this get a little complicated because the device doesn't use that line directly. Instead, the "Hey, I need something" call goes through something called a Programmable Interrupt Controller. To make it even worse, there are actually two of these PIC's. All this complication is necessary because (in general) each device has it's own interrupt number. For example, COM1 (tty1A) uses Interrupt 4, lp0 uses Interrupt 5, and so on. While it is possible for two devices to share the same interrupt number, it is obviously much cleaner and simpler to have a unique interrupt for each separate device.
Leaving out the gory details, a device can signal an interrupt through the PIC's and ultimately the CPU gets tapped on the shoulder. As part of acknowledging the tap, the CPU finds out the interrupt number. This is where the term "Interrupt Vector" comes into play. At this point, the CPU knows that the device that uses interrupt 4 (for example) needs attention. That's a great piece of news, but what's the CPU supposed to do about it? CPU's execute instructions, so somebody had better have provided some executable code that knows what to do with Interrupt 4! In fact, each device driver will have provided such code, and will have specifically identified it as being the "interrupt routine". At the time of linking together all the device drivers, a "vector table" is constructed that effectively says "If you get an Interrupt 4, jump to this address and start executing code."
Taking the printer as an example, the INT line is asserted when the printer is done printing the last character you sent to it. The purpose behind this is so that your program (or somebody else's program) can continue doing useful work in the time between sending a character to the printer and the time that the printer is ready to accept another character. The "interrupt" effectively says "I'm done with that, send me more".
SCO Device Drivers Part II
© 1998 Anthony Lawrence. All rights reserved.
Got something to add? Send me email.
More Articles by Tony Lawrence © 2012-07-14 Tony Lawrence
I wanted to learn how to swim, so Google showed me how to turn on the water at the sink and let me splash it around a bit. They then dragged me into a helicopter, flew way out into the ocean and dumped me out. (Tony Lawrence)