Pmsr= 0x3f4, /* controller main status port */
Fready= 0x80, /* ready to be touched */
Ffrom= 0x40, /* data from controller */
Fbusy= 0x10, /* operation not over */
Pdata= 0x3f5, /* controller data port */
Frecal= 0x7, /* recalibrate cmd */
Fseek= 0xf, /* seek cmd */
Fsense= 0x8, /* sense cmd */
Fread= 0x66, /* read cmd */
Fwrite= 0x45, /* write cmd */
Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
/* digital input register */
Pdir= 0x3F7, /* disk changed port (read only) */
Pdsr= 0x3F7, /* data rate select port (write only) */
Fchange= 0x80, /* disk has changed */
/*
* floppy types (all MFM encoding)
*/
struct Type
{
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 */
};
Type floppytype[] =
{
{ "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
{ "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
{ "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
{ "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
{ "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
{ "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },
};
#define NTYPES (sizeof(floppytype)/sizeof(Type))
/*
* bytes per sector encoding for the controller.
* - index for b2c is is (bytes per sector/128).
* - index for c2b is code from b2c
*/
static int b2c[] =
{
[1] 0,
[2] 1,
[4] 2,
[8] 3,
};
static int c2b[] =
{
128,
256,
512,
1024,
};
/*
* a floppy drive
*/
struct Floppy
{
Type *t;
int dt;
int dev;
ulong lasttouched; /* time last touched */
int cyl; /* current cylinder */
int confused; /* needs to be recalibrated (or worse) */
long offset; /* current offset */
int tcyl; /* target cylinder */
int thead; /* target head */
int tsec; /* target sector */
long len;
int maxtries;
};
/*
* NEC PD765A controller for 4 floppys
*/
struct Ctlr
{
QLock;
Rendez;
Floppy d[Maxfloppy]; /* the floppy drives */
int rw; /* true if a read or write in progress */
int seek; /* one bit for each seek in progress */
uchar stat[8]; /* status of an operation */
int intr;
int confused;
int motor;
Floppy *selected;
int rate;
int cdev;
uchar *ccache; /* cyclinder cache */
int ccyl;
int chead;
};
Ctlr fl;
static int floppysend(int);
static int floppyrcv(void);
static int floppyrdstat(int);
static void floppypos(Floppy*, long);
static void floppywait(char*);
static int floppysense(Floppy*);
static int floppyrecal(Floppy*);
static void floppyon(Floppy*);
static long floppyxfer(Floppy*, int, void*, long);
static void floppyrevive(void);
/*
* get floppy status
*/
if(floppysense(dp) < 0)
return -1;
/*
* see if it worked
*/
if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
DPRINT("seek failed\n");
dp->confused = 1;
return -1;
}
/*
* see what cylinder we got to
*/
dp->cyl = fl.stat[1]/dp->t->steps;
if(dp->cyl != dp->tcyl){
DPRINT("seek went to wrong cylinder %d instead of %d\n",
dp->cyl, dp->tcyl);
dp->confused = 1;
return -1;
}