typedef struct FController FController; typedef struct FDrive FDrive; typedef struct FType FType; static void floppyintr(Ureg*); static int floppyon(FDrive*); static void floppyoff(FDrive*); static void floppysetdef(FDrive*); /* * 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 maxtries; /* max read attempts before Eio */ 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 */ int ndrive; 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), Cmdexec= 1<<6, /* status 1 byte */ Overrun= 0x10, }; static void pcfloppyintr(Ureg *ur, void *a) { USED(a); floppyintr(ur); } void floppysetup0(FController *fl) { fl->ndrive = 0; if(ioalloc(Psra, 6, 0, "floppy") < 0) return; if(ioalloc(Pdir, 1, 0, "floppy") < 0){ iofree(Psra); return; } fl->ndrive = 1; } void floppysetup1(FController *fl) { if(fl->ndrive > 0){ fl->d[0].dt = 4; floppysetdef(&fl->d[0]); } if(fl->ndrive > 1){ fl->d[1].dt = 4; floppysetdef(&fl->d[1]); } intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy"); } /* * eject disk */ void floppyeject(FDrive *dp) { floppyon(dp); dp->vers++; floppyoff(dp); } int floppyexec(char *a, long b, int c) { USED(a, b, c); return b; }