text: typedef struct Conf	Conf;
  typedef	struct FController	FController;
  typedef	struct FDrive		FDrive;
  typedef struct FPsave	FPsave;
  typedef struct FType		FType;
  typedef struct ISAConf	ISAConf;
  typedef struct Label	Label;
  typedef struct Lock	Lock;
  typedef struct MMU	MMU;
  typedef struct Mach	Mach;
  typedef struct PCArch	PCArch;
  typedef struct PCMmap	PCMmap;
  typedef struct Page	Page;
  typedef struct PMMU	PMMU;
  typedef struct Segdesc	Segdesc;
  typedef struct Ureg	Ureg;
  typedef struct User	User;
  
  #define	MACHP(n)	(n==0? &mach0 : *(Mach**)0)
  
  extern	Mach	mach0;
  extern  void	(*kprofp)(ulong);
  
  /*
   *  parameters for sysproc.c
   */
  #define AOUT_MAGIC	I_MAGIC
  
  struct Lock
  {
  	ulong	key;
  	ulong	pc;
  	ulong	sr;
  };
  
  struct Label
  {
  	ulong	sp;
  	ulong	pc;
  };
  
  
  /*
   * FPsave.status
   */
  enum
  {
  	FPinit,
  	FPactive,
  	FPinactive,
  };
  
  struct	FPsave
  {
  	ushort	control;
  	ushort	r1;
  	ushort	status;
  	ushort	r2;
  	ushort	tag;
  	ushort	r3;
  	ulong	pc;
  	ushort	selector;
  	ushort	r4;
  	ulong	operand;
  	ushort	oselector;
  	ushort	r5;
  	uchar	regs[80];	/* floating point registers */
  };
  
  struct Conf
  {
  	ulong	nmach;		/* processors */
  	ulong	nproc;		/* processes */
  	ulong	monitor;	/* has monitor? */
  	ulong	npage0;		/* total physical pages of memory */
  	ulong	npage1;		/* total physical pages of memory */
  	ulong	topofmem;	/* highest physical address + 1 */
  	ulong	npage;		/* total physical pages of memory */
  	ulong	upages;		/* user page pool */
  	ulong	nimage;		/* number of page cache image headers */
  	ulong	nswap;		/* number of swap pages */
  	ulong	base0;		/* base of bank 0 */
  	ulong	base1;		/* base of bank 1 */
  	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
  	ulong	nfloppy;	/* number of floppy drives */
  	ulong	nhard;		/* number of hard drives */
  	ulong	ldepth;		/* screen depth */
  	ulong	maxx;		/* screen width */
  	ulong	maxy;		/* screen length */
  };
  
  /*
   *  MMU stuff in proc
   */
  #define MAXMMU	4
  #define MAXSMMU	1
  struct PMMU
  {
  	Page	*mmutop;	/* 1st level table */
  	Page	*mmufree;	/* unused page table pages */
  	Page	*mmuused;	/* used page table pages */
  };
  
  #include "../port/portdat.h"
  
  /*
   *  machine dependent definitions not used by ../port/dat.h
   */
  
  /*
   *  task state segment.  Plan 9 ignores all the task switching goo and just
   *  uses the tss for esp0 and ss0 on gate's into the kernel, interrupts,
   *  and exceptions.  The rest is completely ignored.
   *
   *  We use one tss per CPU because we'll need to in Brazil.
   *  
   */
  typedef struct Tss	Tss;
  struct Tss
  {
  	ulong	backlink;	/* unused */
  	ulong	sp0;		/* pl0 stack pointer */
  	ulong	ss0;		/* pl0 stack selector */
  	ulong	sp1;		/* pl1 stack pointer */
  	ulong	ss1;		/* pl1 stack selector */
  	ulong	sp2;		/* pl2 stack pointer */
  	ulong	ss2;		/* pl2 stack selector */
  	ulong	cr3;		/* page table descriptor */
  	ulong	eip;		/* instruction pointer */
  	ulong	eflags;		/* processor flags */
  	ulong	eax;		/* general (hah?) registers */
  	ulong 	ecx;
  	ulong	edx;
  	ulong	ebx;
  	ulong	esp;
  	ulong	ebp;
  	ulong	esi;
  	ulong	edi;
  	ulong	es;		/* segment selectors */
  	ulong	cs;
  	ulong	ss;
  	ulong	ds;
  	ulong	fs;
  	ulong	gs;
  	ulong	ldt;		/* local descriptor table */
  	ulong	iomap;		/* io map base */
  };
  
  /*
   *  segment descriptor/gate
   */
  struct Segdesc
  {
  	ulong	d0;
  	ulong	d1;
  };
  
  struct Mach
  {
  	/* OFFSETS OF THE FOLLOWING KNOWN BY l.s */
  	int	machno;			/* physical id of processor */
  	ulong	splpc;			/* pc of last caller to splhi */
  
  	/* ordering from here on irrelevant */
  	int	mmask;			/* 1<<m->machno */
  	ulong	ticks;			/* of the clock since boot time */
  	Proc	*proc;			/* current process on this processor */
  	Label	sched;			/* scheduler wakeup */
  	Lock	alarmlock;		/* access to alarm list */
  	void	*alarm;			/* alarms bound to this clock */
  
  	int	tlbfault;
  	int	tlbpurge;
  	int	pfault;
  	int	cs;
  	int	syscall;
  	int	load;
  	int	intr;
  
  	Tss	tss;
  	Segdesc	gdt[N386SEG];
  
  	int	stack[1];
  };
  
  /*
   * Fake kmap
   */
  typedef void		KMap;
  #define	VA(k)		((ulong)(k))
  #define	kmap(p)		(KMap*)((p)->pa|KZERO)
  #define	kunmap(k)
  
  #define	NERR	15
  #define	NNOTE	5
  struct User
  {
  	Proc	*p;
  	FPsave	fpsave;			/* address of this is known by vdb */
  	int	scallnr;		/* sys call number - known by db */
  	Sargs	s;			/* address of this is known by db */
  	int	nerrlab;
  	Label	errlab[NERR];
  	char	error[ERRLEN];
  	char	elem[NAMELEN];		/* last name element from namec */
  	Chan	*slash;
  	Chan	*dot;
  	/*
  	 * Rest of structure controlled by devproc.c and friends.
  	 * lock(&p->debug) to modify.
  	 */
  	Note	note[NNOTE];
  	short	nnote;
  	short	notified;		/* sysnoted is due */
  	Note	lastnote;
  	int	(*notify)(void*, char*);
  	void	*ureg;
  	void	*dbgreg;		/* User registers for debugging in proc */
  	ulong	svcs;		/* cs before a notify */
  	ulong	svss;		/* ss before a notify */
  	ulong	svflags;		/* flags before a notify */
  };
  
  struct
  {
  	Lock;
  	short	machs;
  	short	exiting;
  }active;
  
  /*
   *  routines for things outside the PC model, like power management
   */
  struct PCArch
  {
  	char	*id;
  	void	(*reset)(void);		/* this should be in the model */
  	int	(*cpuspeed)(int);	/* 0 = low, 1 = high */
  	void	(*buzz)(int, int);	/* make a noise */
  	void	(*lights)(int);		/* turn lights or icons on/off */
  	int	(*serialpower)(int);	/* 1 == on, 0 == off */
  	int	(*modempower)(int);	/* 1 == on, 0 == off */
  	int	(*extvga)(int);		/* 1 == external, 0 == internal */
  	int	(*snooze)(ulong, int);
  };
  
  extern Mach	*m;
  extern User	*u;
  
  ulong boottime;
  
  extern int	flipD[];	/* for flipping bitblt destination polarity */
  
  #define BOOTLINE ((char *)0x80000100) /*  bootline passed by boot program */
  
  extern PCArch *arch;			/* PC architecture */
  
  struct ISAConf {
  	char	type[NAMELEN];
  	ulong	port;
  	ulong	irq;
  	int	dma;
  	ulong	mem;
  	ulong	size;
  	uchar	ea[6];
  	uchar	bus;
  };
  
  /*
   *  maps between ISA memory space and PCMCIA card memory space
   */
  struct PCMmap
  {
  	ulong	ca;		/* card address */
  	ulong	cea;		/* card end address */
  	ulong	isa;		/* ISA address */
  	int	len;		/* length of the ISA area */
  	int	attr;		/* attribute memory */
  	int	ref;
  };
  
  /*
   *  a floppy drive
   */
  struct FDrive
  {
  	FType	*t;		/* floppy type */
  	int	dt;		/* drive type */
  	int	dev;
  
  	ulong	lasttouched;	/* time last touched */
  	int	cyl;		/* current arm position */
  	int	confused;	/* needs to be recalibrated */
  	int	vers;
  
  	int	tcyl;		/* target cylinder */
  	int	thead;		/* target head */
  	int	tsec;		/* target sector */
  	long	len;		/* size of xfer */
  
  	uchar	*cache;	/* track cache */
  	int	ccyl;
  	int	chead;
  
  	Rendez	r;		/* waiting here for motor to spin up */
  };
  
  /*
   *  controller for 4 floppys
   */
  struct FController
  {
  	QLock;			/* exclusive access to the contoller */
  
  	FDrive	*d;		/* the floppy drives */
  	FDrive	*selected;
  	int	rate;		/* current rate selected */
  	uchar	cmd[14];	/* command */
  	int	ncmd;		  /* # command bytes */
  	uchar	stat[14];	/* command status */
  	int	nstat;		  /* # status bytes */
  	int	confused;	/* controler needs to be reset */
  	Rendez	r;		/* wait here for command termination */
  	int	motor;		/* bit mask of spinning disks */
  	Rendez	kr;		/* for motor watcher */
  };
  
  /*
   *  floppy types (all MFM encoding)
   */
  struct FType
  {
  	char	*name;
  	int	dt;		/* compatible drive type */
  	int	bytes;		/* bytes/sector */
  	int	sectors;	/* sectors/track */
  	int	heads;		/* number of heads */
  	int	steps;		/* steps per cylinder */
  	int	tracks;		/* tracks/disk */
  	int	gpl;		/* intersector gap length for read/write */	
  	int	fgpl;		/* intersector gap length for format */
  	int	rate;		/* rate code */
  
  	/*
  	 *  these depend on previous entries and are set filled in
  	 *  by floppyinit
  	 */
  	int	bcode;		/* coded version of bytes for the controller */
  	long	cap;		/* drive capacity in bytes */
  	long	tsize;		/* track size in bytes */
  };
  /* bits in the registers */
  enum
  {
  	/* status registers a & b */
  	Psra=		0x3f0,
  	Psrb=		0x3f1,
  
  	/* digital output register */
  	Pdor=		0x3f2,
  	Fintena=	0x8,	/* enable floppy interrupt */
  	Fena=		0x4,	/* 0 == reset controller */
  
  	/* main status register */
  	Pmsr=		0x3f4,
  	Fready=		0x80,	/* ready to be touched */
  	Ffrom=		0x40,	/* data from controller */
  	Ffloppybusy=	0x10,	/* operation not over */
  
  	/* data register */
  	Pfdata=		0x3f5,
  	Frecal=		0x07,	/* recalibrate cmd */
  	Fseek=		0x0f,	/* seek cmd */
  	Fsense=		0x08,	/* sense cmd */
  	Fread=		0x66,	/* read cmd */
  	Freadid=	0x4a,	/* read track id */
  	Fspec=		0x03,	/* set hold times */
  	Fwrite=		0x45,	/* write cmd */
  	Fformat=	0x4d,	/* format cmd */
  	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */
  	Fdumpreg=	0x0e,	/* dump internal registers */
  
  	/* digital input register */
  	Pdir=		0x3F7,	/* disk changed port (read only) */
  	Pdsr=		0x3F7,	/* data rate select port (write only) */
  	Fchange=	0x80,	/* disk has changed */
  
  	/* status 0 byte */
  	Drivemask=	3<<0,
  	Seekend=	1<<5,
  	Codemask=	(3<<6)|(3<<3),
  };
  
  