|
Figure 10(a) - ISA device controllers: data structures for configuring devices
/* Per device structure. */
struct isa_device {
struct isa_driver *id_driver; /* per driver configuration info */
short id_iobase; /* Base i/o address register */
short id_irq; /* Interrupt request */
short id_drq; /* DMA request */
caddr_t id_maddr; /* Physical shared memory address on bus */
int id_msize; /* Size of shared memory */
int (*id_intr)(); /* Interrupt interface routine */
int id_unit; /* Physical unit number within driver */
int id_scsiid; /* SCSI id if SCSI device */
int id_alive; /* Device is present and accounted for */
};
/* Per driver structure. */
struct isa_driver {
int (*probe)(); /* Test whether device is present */
int (*attach)(); /* Setup driver for a device */
char *name; /* Device name */
};
A key advantage of Berkeley UNIX is its ability to configure at boot time devices present on the system. This feature, while difficult to implement on the ISA given numerous conflicts, was considered valuable and was implemented. Figure 10 (b) - ISA device controllers: sample table of possible devices
/* ISA Bus devices */
#include "machine/isa/device.h" /* device structure */
/* Software drivers */
#define V(s) V/**/s
extern struct driver wddriver; extern V(wd0)();
extern struct driver cndriver; extern V(cn0)();
extern struct driver comdriver; extern V(com0)(); extern V(com1)();
extern struct driver fddriver; extern V(fd0)();
extern struct driver nedriver; extern V(ne0)();
/* Possible hardware devices */
#define C (caddr_t)
struct isa_device isa_devtab_bio[] = {
/* driver iobase irq drq maddr msiz intr unit */
{ &wddriver, IO_WD0, IRQ14, -1, C 0,0, V(wd0), 0},
{ &wddriver, IO_WD1, IRQ13, -1, C 0,0, V(wd1), 1},
{ &fddriver, IO_FD0, IRQ6, 2, C 0,0, V(fd0), 0},
{ &fddriver, IO_FD1, IRQ6, 2, C 0,0, V(fd1), 1},
0
};
struct isa_device isa_devtab_tty[] = {
/* driver iobase irq drq maddr msiz intr unit */
{ &vgadriver, IO_VGA, 0, -1, C 0xa0000, 0x10000, 0, 0},
{ &cgadriver, IO_CGA, 0, -1, C 0xa0000, 0x4000, 0, 0},
{ &mdadriver, IO_MDA, 0, -1, C 0xb8000, 0x4000, 0, 0},
{ &kbddriver, IO_KBD, IRQ1, -1, C 0, 0, V(kbd0), 0},
{ &cndriver, IO_KBD, IRQ1, -1, C 0 0, V(cn0), 0},
{ &comdriver, IO_COM0,IRQ4, -1, C 0, 0, V(com0), 0},
{ &comdriver, IO_COM1,IRQ3, -1, C 0, 0, V(com1), 1},
0
};
struct isa_device isa_devtab_net[] = {
/* driver iobase irq drq maddr msiz intr unit */
{ &nedriver, 0x320, IRQ9, -1, C 0, 0, V(ne0), 0},
0
};
struct isa_device isa_devtab_null[] = {
/* driver iobase irq drq maddr msiz intr unit */
0
};
In Figure 10(a), we have data structures that encode all the appropriate information to configure a device in 386BSD. Each driver, which may have many devices, is able to locate and configure a device if present. The isa_device structure also contains the characteristics of each device to be recognized. If found, hardware resources can then be assigned to each device as configured. A sample table of possible devices to search for within the kernel appears in Figure 10(b).
|