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 offset; /* current offset */ int vers; int maxtries; 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 */ void *aux;}; /* * 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,}; /* * types of drive (from PC equipment byte) */enum{ Tnone= 0, T360kb= 1, T1200kb= 2, T720kb= 3, T1440kb= 4,}; static voidpcfloppyintr(Ureg *ur, void *a){ USED(a); floppyintr(ur);} voidfloppysetup0(FController *fl){ uchar equip; /* * Read nvram for types of floppies 0 & 1. * Always try floppy 0. */ equip = nvramread(0x10); fl->ndrive = 1; if(equip & 0xf) fl->ndrive++; /* * Allocate the drive storage. * There's always one. defend against * cruddy intel bios. */ fl->d = xalloc(fl->ndrive*sizeof(FDrive)); fl->d[0].dt = (equip >> 4) & 0xf; if(fl->d[0].dt == Tnone || fl->d[0].dt > T1440kb){ if(fl->d[0].dt > T1440kb) print("unknown fl0 type %d; assume el torrito\n", fl->d[0].dt); fl->d[0].dt = T1440kb; } if(fl->ndrive == 2){ fl->d[1].dt = equip & 0xf; if(fl->d[0].dt > T1440kb){ fl->d[0].dt = Tnone; fl->ndrive--; } }} voidfloppysetup1(FController*){// intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN); setvec(VectorFLOPPY, pcfloppyintr, 0);} static vlong pcfloppyseek(FDrive*, vlong);FController fl; vlongfloppyseek(Fs *fs, vlong off){ FDrive *dp; dp = &fl.d[fs->dev]; return pcfloppyseek(dp, off);}
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 offset; /* current offset */
int vers;
int maxtries;
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 */
void *aux;
};
/*
* 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,
};
/*
* types of drive (from PC equipment byte)
*/
enum
{
Tnone= 0,
T360kb= 1,
T1200kb= 2,
T720kb= 3,
T1440kb= 4,
};
static void
pcfloppyintr(Ureg *ur, void *a)
{
USED(a);
floppyintr(ur);
}
void
floppysetup0(FController *fl)
{
uchar equip;
/*
* Read nvram for types of floppies 0 & 1.
* Always try floppy 0.
*/
equip = nvramread(0x10);
fl->ndrive = 1;
if(equip & 0xf)
fl->ndrive++;
/*
* Allocate the drive storage.
* There's always one. defend against
* cruddy intel bios.
*/
fl->d = xalloc(fl->ndrive*sizeof(FDrive));
fl->d[0].dt = (equip >> 4) & 0xf;
if(fl->d[0].dt == Tnone || fl->d[0].dt > T1440kb){
if(fl->d[0].dt > T1440kb)
print("unknown fl0 type %d; assume el torrito\n", fl->d[0].dt);
fl->d[0].dt = T1440kb;
}
if(fl->ndrive == 2){
fl->d[1].dt = equip & 0xf;
if(fl->d[0].dt > T1440kb){
fl->d[0].dt = Tnone;
fl->ndrive--;
}
}
}
void
floppysetup1(FController*)
{
// intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
setvec(VectorFLOPPY, pcfloppyintr, 0);
}
static vlong pcfloppyseek(FDrive*, vlong);
FController fl;
vlong
floppyseek(Fs *fs, vlong off)
{
FDrive *dp;
dp = &fl.d[fs->dev];
return pcfloppyseek(dp, off);
}