_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
};