_PORTING UNIX TO THE 80386: A PRACTICAL APPROACH_ by William Frederick Jolitz and Lynne Greer Jolitz [FIGURE 6] /* Intel 386 process control block */ struct pcb { struct i386tss pcbtss; #define pcb_ksp pcbtss.tss_esp0 #define pcb_ptd pcbtss.tss_cr3 #define pcb_pc pcbtss.tss_eip #define pcb_psl pcbtss.tss_eflags #define pcb_usp pcbtss.tss_esp #define pcb_fp pcbtss.tss_ebp /* Software pcb (extension) */ int pcb_fpsav; #define FP_NEEDSAVE 0x1 /* need save on next context switch */ #define FP_NEEDRESTORE 0x2 /* need restore on next DNA fault */ struct save87 pcb_savefpu; struct pte *pcb_p0br; struct pte *pcb_p1br; int pcb_p0lr; int pcb_p1lr; int pcb_szpt; /* number of pages of user page table */ int pcb_cmap2; int *pcb_sswap; long pcb_sigc[8]; /* sigcode actually 19 bytes */ int pcb_iml; /* interrupt mask level */ }; /* Intel 386 Task Switch State */ struct i386tss { long tss_link; /* actually 16 bits: top 16 bits must be zero */ long tss_esp0; /* kernel stack pointer priviledge level 0 */ #define tss_ksp tss_esp0 long tss_ss0; /* actually 16 bits: top 16 bits must be zero */ long tss_esp1; /* kernel stack pointer priviledge level 1 */ long tss_ss1; /* actually 16 bits: top 16 bits must be zero */ long tss_esp2; /* kernel stack pointer priviledge level 2 */ long tss_ss2; /* actually 16 bits: top 16 bits must be zero */ long tss_cr3; /* page table directory physical address */ #define tss_ptd tss_cr3 long tss_eip; /* program counter */ #define tss_pc tss_eip long tss_eflags; /* program status longword */ #define tss_psl tss_eflags long tss_eax; long tss_ecx; long tss_edx; long tss_ebx; long tss_esp; /* user stack pointer */ #define tss_usp tss_esp long tss_ebp; /* user frame pointer */ #define tss_fp tss_ebp long tss_esi; long tss_edi; long tss_es; /* actually 16 bits: top 16 bits must be zero */ long tss_cs; /* actually 16 bits: top 16 bits must be zero */ long tss_ss; /* actually 16 bits: top 16 bits must be zero */ long tss_ds; /* actually 16 bits: top 16 bits must be zero */ long tss_fs; /* actually 16 bits: top 16 bits must be zero */ long tss_gs; /* actually 16 bits: top 16 bits must be zero */ long tss_ldt; /* actually 16 bits: top 16 bits must be zero */ long tss_ioopt; /* options & io offset bitmap: currently zero */ /* XXX unimplemented .. i/o permission bitmap */ }; [FIGURE 8] #include <syscall.h> globl _write, _errno #amtwritten = write(fildes, address, count); _write: # caller places arguments on stack lea SYS_write,%eax # select desired system call lcall $0x7,0 # call the system jb 1f # if system returns error, handle ret # otherwise return 1: movl %eax,_errno # save error in global variable movl $-1,%eax # indicate error has occured ret # and return [FIGURE 10a] /* 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 */ }; [FIGURE 10b] /* 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 };