## diffname pc/devfloppy.c 1991/0727
## diff -e /dev/null /n/bootesdump/1991/0727/sys/src/9/safari/devfloppy.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
typedef struct Drive Drive;
typedef struct Controller Controller;
typedef struct Type Type;
enum
{
Fmotor= 0x3f2, /* motor port */
Fintena= 0x4, /* enable floppy interrupt */
Fena= 0x8, /* 0 == reset controller */
Fstatus= 0x3f4, /* controller main status port */
Fready= 0x80, /* ready to be touched */
Ffrom= 0x40, /* data from controller */
Fbusy= 0x10, /* operation not over */
Fdata= 0x3f5, /* controller data port */
Frecal= 0x7, /* recalibrate cmd */
Fseek= 0xf, /* seek cmd */
Fsense= 0x8, /* sense cmd */
Fread= 0x66, /* read cmd */
Fwrite= 0x47, /* write cmd */
Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
DMAmode0= 0xb,
DMAmode1= 0xc,
DMAaddr= 0x4,
DMAtop= 0x81,
DMAinit= 0xa,
DMAcount= 0x5,
Nfloppy= 4, /* floppies/controller */
/* sector size encodings */
S128= 0,
S256= 1,
S512= 2,
S1024= 3,
/* status 0 byte */
Drivemask= 3<<0,
Seekend= 1<<5,
Codemask= (3<<6)|(3<<3),
};
/*
* floppy types
*/
struct Type
{
char *name;
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 */
long cap; /* drive capacity in bytes */
};
Type floppytype[] =
{
{ "MF2HD", S512, 18, 2, 1, 80, 0x1B, 0x54, 512*2*18*80 },
{ "MF2DD", S512, 9, 2, 1, 80, 0x1B, 0x54, 512*2*9*80 },
{ "F2HD", S512, 15, 2, 1, 80, 0x2A, 0x50, 512*15*2*80 },
{ "F2DD", S512, 8, 2, 1, 40, 0x2A, 0x50, 512*8*2*40 },
{ "F1DD", S512, 8, 1, 1, 40, 0x2A, 0x50, 512*8*1*40 },
};
static int secbytes[] =
{
128,
256,
512,
1024
};
/*
* a floppy drive
*/
struct Drive
{
QLock;
Type *t;
int dev;
ulong lasttouched; /* time last touched */
int motoron; /* motor is on */
int cyl; /* current cylinder */
long offset; /* current offset */
int confused; /* needs to be recalibrated (or worse) */
int tcyl; /* target cylinder */
int thead; /* target head */
int tsec; /* target sector */
long len;
int busy; /* true if drive is seeking */
Rendez r; /* waiting for operation termination */
};
/*
* NEC PD765A controller for 4 floppys
*/
struct Controller
{
QLock;
Drive d[Nfloppy]; /* the floppy drives */
int busy; /* true if a read or write in progress */
uchar stat[8]; /* status of an operation */
int confused;
};
Controller floppy[1];
/*
* start a floppy drive's motor. set an alarm for 1 second later to
* mark it as started (we get no interrupt to tell us).
*
* assume the caller qlocked the drive.
*/
void
floppystart(Drive *dp)
{
int cmd;
dp->lasttouched = m->ticks;
if(dp->motoron)
return;
cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev;
outb(Fmotor, cmd);
dp->busy = 1;
tsleep(&dp->r, noreturn, 0, 1000);
dp->motoron = 1;
dp->busy = 0;
dp->lasttouched = m->ticks;
}
/*
* stop the floppy if it hasn't been used in 5 seconds
*/
void
floppystop(Drive *dp)
{
int cmd;
if(!canqlock(dp))
return;
cmd = Fintena | Fena | dp->dev;
outb(Fmotor, cmd);
dp->motoron = 0;
}
void
floppykproc(Alarm* a)
{
Drive *dp;
if(waserror())
for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5)
floppystop(dp);
}
alarm(5*1000, floppyalarm, 0);
cancel(a);
}
int
floppysend(int data)
{
int tries;
uchar c;
for(tries = 0; tries < 100; tries++){
/*
* see if its ready for data
*/
c = inb(Fstatus);
if((c&(Ffrom|Fready)) != Fready)
continue;
/*
* send the data
*/
outb(Fdata, data);
return 0;
}
return -1;
}
int
floppyrcv(void)
{
int tries;
uchar c;
for(tries = 0; tries < 100; tries++){
/*
* see if its ready for data
*/
c = inb(Fstatus);
if((c&(Ffrom|Fready)) != (Ffrom|Fready))
continue;
/*
* get data
*/
return inb(Fdata)&0xff;
}
return -1;
}
int
floppyrdstat(int n)
{
int i;
int c;
for(i = 0; i < n; i++){
c = floppyrcv();
if(c < 0)
return -1;
floppy.stat[i] = c;
}
return 0;
}
void
floppypos(Drive *dp, long off)
{
int lsec;
int end;
int cyl;
lsec = off/secbytes[dp->t->bytes];
dp->tcyl = lsec/(dp->t->sectors*dp->t->heads);
dp->tsec = (lsec % dp->t->sectors) + 1;
dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
/*
* can't read across cylinder boundaries.
* if so, decrement the bytes to be read.
*/
lsec = (off+dp->len)/secbytes[dp->t->bytes];
cyl = lsec/(dp->t->sectors*dp->t->heads);
if(cyl != dp->tcyl){
dp->len -= (lsec % dp->t->sectors)*secbytes[dp->t->bytes];
dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*secbytes[dp->t->bytes]
*dp->t->sectors;
}
dp->lasttouched = m->ticks;
floppy.intr = 0;
}
void
floppywait(void)
{
int tries;
for(tries = 0; tries < 100 && floppy.intr == 0; tries++)
delay(5);
if(tries >= 100)
print("tired floopy\n");
floppy.intr = 0;
}
int
floppysense(Drive *dp)
{
/*
* ask for floppy status
*/
if(floppysend(Fsense) < 0){
floppy.confused = 1;
return -1;
}
if(floppyrdstat(2) < 0){
floppy.confused = 1;
dp->confused = 1;
return -1;
}
/*
* make sure it's the right drive
*/
if((floppy.stat[0] & Drivemask) != dp-floppy.d){
print("sense failed\n");
dp->confused = 1;
return -1;
}
return 0;
}
int
floppyrecal(Drive *dp)
{
floppy.intr = 0;
if(floppysend(Frecal) < 0
|| floppysend(dp - floppy.d) < 0){
floppy.confused = 0;
return -1;
}
floppywait();
/*
* get return values
*/
if(floppysense(dp) < 0)
return -1;
/*
* see if it worked
*/
if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
print("recalibrate failed\n");
dp->confused = 1;
return -1;
}
/*
* see what cylinder we got to
*/
dp->tcyl = 0;
dp->cyl = floppy.stat[1]/dp->t->steps;
if(dp->cyl != dp->tcyl){
print("recalibrate went to wrong cylinder %d\n", dp->cyl);
dp->confused = 1;
return -1;
}
dp->confused = 0;
return 0;
}
void
floppyinit(void)
{
Drive *dp;
for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
dp->t = &floppytype[0];
dp->cyl = -1;
dp->motoron = 1;
floppystop(dp);
}
setvec(22, floppyintr);
alarm(5*1000, floppyalarm, (void *)0);
}
void
floppyreset(void)
{
Drive *dp;
/*
* reset the floppy if'n it's confused
*/
if(floppy.confused){
/* reset controller and turn all motors off */
floppy.intr = 0;
splhi();
outb(Fmotor, 0);
delay(1);
outb(Fmotor, Fintena|Fena);
spllo();
for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
dp->motoron = 0;
dp->confused = 1;
}
floppywait();
floppy.confused = 0;
}
/*
* recalibrate any confused drives
*/
for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Nfloppy]; dp++){
if(dp->confused == 0)
floppyrecal(dp);
}
}
long
floppyseek(int dev, long off)
{
Drive *dp;
dp = &floppy.d[dev];
if(floppy.confused || dp->confused)
floppyreset();
floppystart(dp);
floppypos(dp, off);
if(dp->cyl == dp->tcyl){
dp->offset = off;
return off;
}
/*
* tell floppy to seek
*/
if(floppysend(Fseek) < 0
|| floppysend((dp->thead<<2) | dev) < 0
|| floppysend(dp->tcyl * dp->t->steps) < 0){
print("seek cmd failed\n");
floppy.confused = 1;
return -1;
}
/*
* wait for interrupt
*/
floppywait();
/*
* get floppy status
*/
if(floppysense(dp) < 0)
return -1;
/*
* see if it worked
*/
if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
print("seek failed\n");
dp->confused = 1;
return -1;
}
/*
* see what cylinder we got to
*/
dp->cyl = floppy.stat[1]/dp->t->steps;
if(dp->cyl != dp->tcyl){
print("seek went to wrong cylinder %d instead of %d\n", dp->cyl, dp->tcyl);
dp->confused = 1;
return -1;
}
dp->offset = off;
return dp->offset;
}
long
floppyxfer(Drive *dp, int cmd, void *a, long n)
{
int dev;
ulong addr;
long offset;
addr = (ulong)a;
dev = dp - floppy.d;
/*
* dma can't cross 64 k boundaries
*/
if((addr & 0xffff0000) != ((addr+n) & 0xffff0000))
n -= (addr+n)&0xffff;
dp->len = n;
floppyseek(dev, dp->offset);
/* print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
dp->tcyl, dp->thead, dp->tsec, addr, n);/**/
/*
* set up the dma
*/
outb(DMAmode1, cmd==Fread ? 0x46 : 0x4a);
outb(DMAmode0, cmd==Fread ? 0x46 : 0x4a);
outb(DMAaddr, addr);
outb(DMAaddr, addr>>8);
outb(DMAtop, addr>>16);
outb(DMAcount, n-1);
outb(DMAcount, (n-1)>>8);
outb(DMAinit, 2);
/*
* tell floppy to go
*/
cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
if(floppysend(cmd) < 0
|| floppysend((dp->thead<<2) | dev) < 0
|| floppysend(dp->tcyl * dp->t->steps) < 0
|| floppysend(dp->thead) < 0
|| floppysend(dp->tsec) < 0
|| floppysend(dp->t->bytes) < 0
|| floppysend(dp->t->sectors) < 0
|| floppysend(dp->t->gpl) < 0
|| floppysend(0xFF) < 0){
print("xfer cmd failed\n");
floppy.confused = 1;
return -1;
}
floppywait();
/*
* get status
*/
if(floppyrdstat(7) < 0){
print("xfer status failed\n");
floppy.confused = 1;
return -1;
}
if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){
print("xfer failed %lux %lux %lux\n", floppy.stat[0],
floppy.stat[1], floppy.stat[2]);
dp->confused = 1;
return -1;
}
offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4];
offset = offset*dp->t->sectors + floppy.stat[5] - 1;
offset = offset * secbytes[floppy.stat[6]];
if(offset != dp->offset+n){
print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
dp->confused = 1;
return -1;/**/
}
dp->offset += dp->len;
return dp->len;
}
long
floppyread(int dev, void *a, long n)
{
Drive *dp;
long rv, i;
uchar *aa = a;
dp = &floppy.d[dev];
for(rv = 0; rv < n; rv += i){
i = floppyxfer(dp, Fread, aa+rv, n-rv);
if(i <= 0)
break;
}
return rv;
}
void
floppyintr(Ureg *ur)
{
floppy.intr = 1;
}
.
## diffname pc/devfloppy.c 1991/0728
## diff -e /n/bootesdump/1991/0727/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0728/sys/src/9/safari/devfloppy.c
354,355c
}
void
floppyinit(void)
{
kproc(floppykproc, 0);
.
351a
dp->cyl = -1;
.
349,350c
dp->dev = dp - floppy.d;
dp->t = &floppytype[0]; /* default type */
.
344c
floppyreset(void)
.
170,172d
168a
qunlock(dp);
}
.
167c
if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5
&& canqlock(dp)){
.
165d
154,155d
120c
Controller floppy;
.
50a
/* file types */
Qdir= 0,
Qdata= 16,
Qstruct= 32,
.
40a
DMAchan= 2, /* floppy dma channel */
.
32,38d
## diffname pc/devfloppy.c 1991/0729
## diff -e /n/bootesdump/1991/0728/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0729/sys/src/9/safari/devfloppy.c
166c
if(TK2SEC(m->ticks - dp->lasttouched) > 5)
floppystop(dp);
.
## diffname pc/devfloppy.c 1991/0730
## diff -e /n/bootesdump/1991/0729/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0730/sys/src/9/safari/devfloppy.c
256,270d
## diffname pc/devfloppy.c 1991/0731
## diff -e /n/bootesdump/1991/0730/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0731/sys/src/9/safari/devfloppy.c
546a
wakeup(&floppy.r);
.
527,543c
static void
.
522a
qunlock(&floppy);
qunlock(dp);
poperror();
.
520c
errors("floppy drive lost");
.
518c
print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
.
516c
offset = offset * c2b[floppy.stat[6]];
.
511c
errors("floppy drive lost");
.
504c
errors("floppy result failed");
.
501,502c
if(floppyresult(7) < 0){
print("xfer status failed\n");
.
496c
sleep(&floppy.r, interrupted, 0);
.
493c
errors("floppy command failed");
.
487c
|| floppysend(dp->t->bcode) < 0
.
479c
* start operation
.
469,476c
dp->len = dmasetup(2, a, dp->len, cmd==Fread);
.
467c
* set up the dma (dp->len may be trimmed)
.
463c
print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
.
461c
floppypos(dp);
if(floppyseek(dp) < 0)
errors("seeking floppy");
.
459a
/*
* calculate new position and seek to it (dp->len may be trimmed)
*/
.
457,458c
if(floppy.confused || dp->confused)
floppyrevive();
if(!dp->motoron)
motoron(dp);
.
455c
* get floppy reset and spinning
.
453a
qlock(&floppy);
qlock(dp);
if(waserror){
qunlock(&floppy);
qunlock(dp);
}
.
452d
447d
444c
static long
.
413c
sleep(&floppy.r, interrupted, 0);
.
403c
|| floppysend((dp->thead<<2) | dp->dev) < 0
.
384,393d
381,382c
static long
floppyseek(Drive *dp)
.
373c
for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Ndrive]; dp++){
.
366c
sleep(&floppy.r, interrupted, 0);
.
362c
for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
.
352c
* reset the floppy if it's confused
.
331,350d
327c
floppyrevive(void)
.
325a
/*
* if the controller or a specific drive is in a confused state,
* reset it and get back to a kown state
*/
.
294c
sleep(&floppy.r, interrupted, 0);
.
285c
/*
* return true if interrupt occurred
*/
static int
interrupted(void *a)
{
return floppy.intr;
}
/*
* we've lost the floppy position, go to cylinder 0.
*/
static int
.
268c
if(floppyresult(2) < 0){
.
258c
/*
* get the interrupt cause from the floppy. we need to do this
* after seeks and recalibrations since they don't return results.
*/
static int
.
252,253c
dp->len -= (lsec % dp->t->sectors)*dp->t->bytes;
dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes
.
249c
lsec = (dp->off+dp->len)/dp->t->bytes;
.
240c
lsec = dp->off/dp->t->bytes;
.
233,234c
/*
* calculate physical address of a logical byte offset into the disk
*
* truncate dp->length if it crosses a cylinder boundary
*/
static void
floppypos(Drive *dp)
.
218,219c
/*
* read a command result message from the floppy
*/
static int
floppyresult(int n)
.
196c
/*
* get a byte from the floppy
*/
static int
.
173c
/*
* send a byte to the floppy
*/
static int
.
167c
motoroff(dp);
.
163c
for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
.
158,159c
static void
floppykproc(void *a)
.
149,150c
static void
motoroff(Drive *dp)
.
133,136d
128,129c
static void
motoron(Drive *dp)
.
122a
* predeclared
*/
static void motoron(Drive*);
static void motoroff(Drive*);
static void floppykproc(void*);
static int floppysend(int);
static int floppyrcv(void);
static int floppyresult(int);
static void floppypos(Drive*);
static int floppysense(Drive*);
static int interrupted(void*);
static int floppyrecal(Drive*);
static void floppyrevive(void);
static long floppyseek(Drive*);
static long floppyxfer(Drive*, int, void*, long);
static void floppyintr(Ureg*);
static int
floppygen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
{
long l;
Drive *dp;
if(s >= ntab)
return -1;
if(c->dev >= Ndrive)
return -1;
tab += s;
dp = &floppy.d[c->dev];
if((tab->qid.path&~Mask) == Qdata)
l = dp->t->cap;
else
l = 8;
devdir(c, tab->qid, tab->name, l, tab->perm, dp);
return 1;
}
void
floppyreset(void)
{
Drive *dp;
for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
dp->dev = dp - floppy.d;
dp->t = &floppytype[0]; /* default type */
dp->motoron = 1;
dp->cyl = -1;
motoroff(dp);
}
setvec(Floppyvec, floppyintr);
}
void
floppyinit(void)
{
Type *t;
/*
* init dependent parameters
*/
for(t = floppytype; t < &floppytype[NTYPES], t++){
t->cap = t->bytes * t->heads * t->sectors * t->tracks;
t->bcode = bcode[t->bytes/128];
}
/*
* watchdog to turn off the motors
*/
kproc(floppykproc, 0);
}
long
floppyread(Chan *c, void *a, long n)
{
Drive *dp;
long rv, i;
uchar *aa = a;
dp = &floppy.d[c->dev];
for(rv = 0; rv < n; rv += i){
i = floppyxfer(dp, Fread, aa+rv, n-rv);
if(i <= 0)
break;
}
return rv;
}
long
floppywrite(Chan *c, void *a, long n)
{
Drive *dp;
long rv, i;
uchar *aa = a;
dp = &floppy.d[c->dev];
for(rv = 0; rv < n; rv += i){
i = floppyxfer(dp, Fwrite, aa+rv, n-rv);
if(i <= 0)
break;
}
return rv;
}
/*
.
117a
int intr; /* true if interrupt occured */
Rendez r; /* wait here for command termination */
.
113,114c
QLock; /* exclusive access to the contoller */
Drive d[Ndrive]; /* the floppy drives */
.
105c
Rendez r; /* waiting here for motor to spin up */
.
102c
long len; /* size of xfer */
.
89c
QLock; /* exclusive access to the drive */
.
81c
1024,
.
77a
[1] 0,
[2] 1,
[4] 2,
[8] 3,
};
static int c2b[] =
{
.
76c
#define NTYPES (sizeof(floppytype)/sizeof(Type))
/*
* bytes/sector encoding for the controller, index is (bytes per sector/128)
*/
static int b2c[] =
.
70,74c
{ "MF2HD", 512, 18, 2, 1, 80, 0x1B, 0x54, },
{ "MF2DD", 512, 9, 2, 1, 80, 0x1B, 0x54, },
{ "F2HD", 512, 15, 2, 1, 80, 0x2A, 0x50, },
{ "F2DD", 512, 8, 2, 2, 40, 0x2A, 0x50, },
{ "F1DD", 512, 8, 1, 2, 40, 0x2A, 0x50, },
.
65c
int fgpl; /* intersector gap length for format */
/*
* these depend on previous entries and are set filled in
* by floppyinit
*/
int bcode; /* coded version of bytes for the controller */
.
49,50c
Qdata= 1,
Qstruct= 2,
.
32c
Ndrive= 4, /* floppies/controller */
.
## diffname pc/devfloppy.c 1991/0802
## diff -e /n/bootesdump/1991/0731/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0802/sys/src/9/safari/devfloppy.c
658d
653a
dp->lasttouched = m->ticks;
.
648,649c
if(offset != off+dp->len){
print("new offset %d instead of %d\n", offset, off+dp->len);
.
626d
614c
|| floppysend((dp->thead<<2) | dp->dev) < 0
.
611a
floppy.intr = 0;
.
597c
floppypos(dp, off);
.
580c
if(waserror()){
.
571c
floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
.
566,567c
return dp->cyl;
.
535,538d
527a
floppy.intr = 0;
dp->cyl = -1; /* once the seek starts it could end anywhere */
.
520,523c
if(dp->cyl == dp->tcyl)
return dp->cyl;
.
417c
if((floppy.stat[0] & Drivemask) != dp->dev){
.
385c
lsec = (off+dp->len)/dp->t->bytes;
.
376c
lsec = off/dp->t->bytes;
.
370c
floppypos(Drive *dp, long off)
.
291a
tsleep(&floppy.kr, return0, 0, 5*1000);
.
285,290c
waserror();
for(;;){
for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5
&& canqlock(dp)){
if(TK2SEC(m->ticks - dp->lasttouched) > 5)
motoroff(dp);
qunlock(dp);
}
.
264d
261,262c
tsleep(&dp->r, return0, 0, 750);
.
249c
* start a floppy drive's motor. set an alarm for .75 second later to
.
239,243c
rv = 0;
dp = &floppy.d[c->qid.path & ~Qmask];
switch ((int)(c->qid.path & Qmask)) {
case Qdata:
for(rv = 0; rv < n; rv += i){
i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv);
if(i <= 0)
break;
}
break;
case Qstruct:
error(Eperm);
break;
default:
panic("floppywrite: bad qid");
.
223,227c
if(c->qid.path == CHDIR)
return devdirread(c, a, n, floppydir, NFDIR, devgen);
rv = 0;
dp = &floppy.d[c->qid.path & ~Qmask];
switch ((int)(c->qid.path & Qmask)) {
case Qdata:
for(rv = 0; rv < n; rv += i){
i = floppyxfer(dp, Fread, aa+rv, c->offset+rv, n-rv);
if(i <= 0)
break;
}
break;
case Qstruct:
if (n < 2*sizeof(ulong))
error(Ebadarg);
if (c->offset >= 2*sizeof(ulong))
return 0;
rv = 2*sizeof(ulong);
ul2user((uchar*)a, dp->t->cap);
ul2user((uchar*)a+sizeof(ulong), dp->t->bytes);
break;
default:
panic("floppyread: bad qid");
.
215a
Chan*
floppyattach(char *spec)
{
return devattach('f', spec);
}
Chan*
floppyclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
floppywalk(Chan *c, char *name)
{
return devwalk(c, name, floppydir, NFDIR, devgen);
}
void
floppystat(Chan *c, char *dp)
{
devstat(c, dp, floppydir, NFDIR, devgen);
}
Chan*
floppyopen(Chan *c, int omode)
{
return devopen(c, omode, floppydir, NFDIR, devgen);
}
void
floppycreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
floppyclose(Chan *c)
{
}
void
floppyremove(Chan *c)
{
error(Eperm);
}
void
floppywstat(Chan *c, char *dp)
{
error(Eperm);
}
static void
ul2user(uchar *a, ulong x)
{
a[0] = x >> 24;
a[1] = x >> 16;
a[2] = x >> 8;
a[3] = x;
}
.
214c
kproc("floppy", floppykproc, 0);
.
204,211d
201,202d
192c
dp->cyl = -1; /* because we don't know */
.
190a
floppydir[2*dp->dev].length = dp->t->cap;
.
187a
/*
* init dependent parameters
*/
for(t = floppytype; t < &floppytype[NTYPES]; t++){
t->cap = t->bytes * t->heads * t->sectors * t->tracks;
t->bcode = b2c[t->bytes/128];
}
/*
* stop the motors
*/
.
186a
Type *t;
.
168,182d
162,166c
Dirtab floppydir[]={
"fd0data", {Qdata + 0}, 0, 0600,
"fd0struct", {Qstruct + 0}, 8, 0600,
"fd1data", {Qdata + 1}, 0, 0600,
"fd1struct", {Qstruct + 1}, 8, 0600,
"fd2data", {Qdata + 2}, 0, 0600,
"fd2struct", {Qstruct + 2}, 8, 0600,
"fd3data", {Qdata + 3}, 0, 0600,
"fd3struct", {Qstruct + 3}, 8, 0600,
};
#define NFDIR (sizeof(floppydir)/sizeof(Dirtab))
.
159c
static long floppyxfer(Drive*, int, void*, long, long);
.
153c
static void floppypos(Drive*,long);
.
139a
Rendez kr; /* for motor watcher */
.
135d
123d
115d
85c
* bytes per sector encoding for the controller.
* - index for b2c is is (bytes per sector/128).
* - index for c2b is code from b2c
.
49,50c
Qdata= (1<<2),
Qstruct= (2<<2),
Qmask= (3<<2),
.
11c
typedef struct Type Type;
.
9c
typedef struct Drive Drive;
.
7c
#include "errno.h"
.
## diffname pc/devfloppy.c 1991/0803
## diff -e /n/bootesdump/1991/0802/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0803/sys/src/9/safari/devfloppy.c
381a
.
380a
disp++;
if(owl(disp&1) < 0)
print("owl failed\n");
if(mail((disp>>1)&1) < 0)
print("mail failed\n");
.
369a
int disp = 0;
.
## diffname pc/devfloppy.c 1991/0806
## diff -e /n/bootesdump/1991/0803/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0806/sys/src/9/safari/devfloppy.c
756a
print("floppy intr\n");
.
## diffname pc/devfloppy.c 1991/0809
## diff -e /n/bootesdump/1991/0806/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0809/sys/src/9/safari/devfloppy.c
606c
for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[conf.nfloppy]; dp++){
.
595c
for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
.
385,386d
374c
for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
.
289,292c
if(c->offset % dp->t->bytes)
errors("bad offset");
if(n % dp->t->bytes)
errors("bad len");
nn = dp->t->bytes * dp->t->sectors * dp->t->heads;
for(rv = 0; rv < n; rv += len){
/*
* truncate xfer at cylinder boundary
*/
dp->len = n - rv;
floppypos(dp, c->offset+rv);
cyl = dp->tcyl;
len = dp->len;
sec = dp->tsec + dp->thead * dp->t->sectors;
/*
* read the cylinder
*/
if(dp->ccyl != cyl){
dp->ccyl = -1;
if(floppyxfer(dp, Fread, dp->ccache, cyl * nn, nn) != nn)
errors("floppy read err");
dp->ccyl = cyl;
}
memmove(aa+rv, dp->ccache + (sec-1)*dp->t->bytes, len);
.
279c
long rv, nn, len, cyl;
int sec;
.
274a
/*
* the floppy is so slow, we always read a cylinder
* at a time and cache the extra bytes.
*/
.
200a
/*
* allocate cylinder caches that don't cross 64k boundaries
*/
for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
do {
dp->ccache = ialloc(dp->t->cap, 1);
} while(k64(dp->ccache) != k64(dp->ccache+dp->t->cap));
dp->ccyl = -1;
}
.
193c
for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
.
190a
* allocate the drive storage
*/
floppy.d = ialloc(conf.nfloppy*sizeof(Drive), 0);
/*
.
175a
#define k64(x) (((ulong)(x))>>16)
.
135c
Drive *d; /* the floppy drives */
.
125a
uchar *ccache; /* cylinder cache (always read a whole cyl) */
int ccyl; /* number of cached cylinder */
.
32,33d
## diffname pc/devfloppy.c 1991/0810
## diff -e /n/bootesdump/1991/0809/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0810/sys/src/9/safari/devfloppy.c
214,215c
n = 512 * 18 * 2; /* MF2HD cylinder size */
dp->ccache = ialloc(n, 1);
} while(k64(dp->ccache) != k64(dp->ccache+n));
.
182a
int n;
.
## diffname pc/devfloppy.c 1991/0811
## diff -e /n/bootesdump/1991/0810/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0811/sys/src/9/safari/devfloppy.c
307c
return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen);
.
259c
return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
.
253c
devstat(c, dp, floppydir, conf.nfloppy*NFDIR, devgen);
.
247c
return devwalk(c, name, floppydir, conf.nfloppy*NFDIR, devgen);
.
204c
floppydir[NFDIR*dp->dev].length = dp->t->cap;
.
175c
#define NFDIR 2 /* directory entries/drive */
.
## diffname pc/devfloppy.c 1991/0823
## diff -e /n/bootesdump/1991/0811/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0823/sys/src/9/safari/devfloppy.c
800c
/*print("floppy intr\n");/**/
.
736c
/*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
.
372,374d
340,348d
166,173c
"fd0disk", {Qdata + 0}, 0, 0600,
"fd1disk", {Qdata + 1}, 0, 0600,
"fd2disk", {Qdata + 2}, 0, 0600,
"fd3disk", {Qdata + 3}, 0, 0600,
.
48d
34,39d
## diffname pc/devfloppy.c 1991/0831
## diff -e /n/bootesdump/1991/0823/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0831/sys/src/9/safari/devfloppy.c
345a
floppychanged(dp);
dp->ccyl = -1;
.
301a
floppychanged(dp);
.
283a
* look for a floppy change
*/
void
floppychange(Drive *dp)
{
if((inb(Fchanged) & Fchange) == 0)
return;
}
/*
.
31a
Fchanged= 0x3F7, /* disk changed register */
Fchange= 0x80, /* disk has changed */
.
29c
Fwrite= 0x45, /* write cmd */
.
## diffname pc/devfloppy.c 1991/0902
## diff -e /n/bootesdump/1991/0831/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0902/sys/src/9/safari/devfloppy.c
290c
floppychanged(Drive *dp)
.
## diffname pc/devfloppy.c 1991/0906
## diff -e /n/bootesdump/1991/0902/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0906/sys/src/9/safari/devfloppy.c
732c
dp->tcyl, dp->thead, dp->tsec, a, n);/**/
.
730a
.
706,707d
703d
## diffname pc/devfloppy.c 1991/0913
## diff -e /n/bootesdump/1991/0906/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0913/sys/src/9/safari/devfloppy.c
423,424d
## diffname pc/devfloppy.c 1991/0919
## diff -e /n/bootesdump/1991/0913/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0919/sys/src/9/safari/devfloppy.c
412c
while(waserror())
;
.
## diffname pc/devfloppy.c 1991/0920
## diff -e /n/bootesdump/1991/0919/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0920/sys/src/9/safari/devfloppy.c
295c
print("floppy has changed\n");
.
277,285d
226a
static int kstarted;
if(kstarted == 0){
/*
* watchdog to turn off the motors
*/
kstarted = 1;
kproc("floppy", floppykproc, 0);
}
.
218,221d
165a
"fd3ctl", {Qctl + 3}, 0, 0600,
.
164a
"fd2ctl", {Qctl + 2}, 0, 0600,
.
163a
"fd1ctl", {Qctl + 1}, 0, 0600,
.
162a
"fd0ctl", {Qctl + 0}, 0, 0600,
.
44a
Qctl= (2<<2),
.
8a
/* NEC PD765A (8272A compatible) floppy controller */
.
## diffname pc/devfloppy.c 1991/0921
## diff -e /n/bootesdump/1991/0920/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0921/sys/src/9/safari/devfloppy.c
719,720c
motoron(dp);
.
638a
floppy.motor = 0;
.
636d
432a
* start a floppy drive's motor. set an alarm for .75 second later to
* mark it as started (we get no interrupt to tell us).
*
* assume the caller qlocked the drive.
*
* this also selects the drive for subsequent operations
*/
static void
motoron(Drive *dp)
{
int alreadyon;
alreadyon = floppy.motor & MOTORBIT(dp->dev);
floppy.motor |= MOTORBIT(dp->dev);
driveselect(dp);
if(!alreadyon)
tsleep(&dp->r, return0, 0, 750);
dp->lasttouched = m->ticks;
}
/*
* stop the floppy if it hasn't been used in 5 seconds
*/
static void
motoroff(Drive *dp)
{
floppy.motor &= ~MOTORBIT(dp->dev);
driveselect(dp);
}
/*
.
431a
static void
driveselect(Drive *dp)
{
int cmd;
cmd = floppy.motor | Fintena | Fena | dp->dev;
outb(Fmotor, cmd);
}
.
419c
if((floppy.motor&MOTORBIT(dp->dev))
&& TK2SEC(m->ticks - dp->lasttouched) > 5
.
386,409d
379,384d
204c
floppy.motor |= MOTORBIT(dp->dev);
.
145a
#define MOTORBIT(i) (1<<((i)+4))
.
139a
int motor;
.
113d
## diffname pc/devfloppy.c 1991/0924
## diff -e /n/bootesdump/1991/0921/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0924/sys/src/9/safari/devfloppy.c
807,809c
switch(fl.cmd[0]&~Fmulti){
case Fread:
case Fwrite:
floppyresult();
break;
case Freadid:
floppyresult();
break;
case Fseek:
case Frecal:
default:
floppysense(); /* to clear interrupt */
break;
}
fl.ncmd = 0;
wakeup(&fl.r);
.
804,805c
void
floppyintr(void)
.
797c
qunlock(&fl);
.
791c
print("new offset %d instead of %d\n", offset, off+dp->len);
.
787,789c
/*
* check for correct cylinder
*/
offset = (fl.stat[3]/dp->t->steps) * dp->t->heads + fl.stat[4];
offset = offset*dp->t->sectors + fl.stat[5] - 1;
offset = offset * c2b[fl.stat[6]];
.
779,784c
if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
if(fl.stat[1] != 0x80){
print("xfer failed %lux %lux %lux\n", fl.stat[0],
fl.stat[1], fl.stat[2]);
print("offset %lud len %d\n", off, dp->len);
dp->confused = 1;
errors("floppy drive lost");
} else
fl.stat[5]++;
.
772,776c
* give bus to DMA, floppyintr() will read result
*/
floppywait();
dmaend(DMAchan);
/*
* check for errors
*/
if(fl.nstat < 7){
print("xfer result failed %lux\n", inb(Pmsr));
fl.confused = 1;
.
769d
766d
754,764c
/* cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/
fl.ncmd = 0;
fl.cmd[fl.ncmd++] = cmd;
fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
fl.cmd[fl.ncmd++] = dp->thead;
fl.cmd[fl.ncmd++] = dp->tsec;
fl.cmd[fl.ncmd++] = dp->t->bcode;
fl.cmd[fl.ncmd++] = dp->tsec + dp->len/dp->t->bytes - 1;
fl.cmd[fl.ncmd++] = dp->t->gpl;
fl.cmd[fl.ncmd++] = 0xFF;
if(floppycmd() < 0){
spllo();
.
749c
dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
.
744c
dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/
.
741d
738,739c
if(floppyseek(dp, off) < 0)
.
728,734d
724a
fl.confused = 1;
nexterror();
.
723c
dmaend(DMAchan);
qunlock(&fl);
.
720c
if(off >= dp->t->cap)
return 0;
if(off + n > dp->t->cap)
n = dp->t->cap - off;
qlock(&fl);
.
718a
ulong up;
.
702,711c
dp->cyl = dp->tcyl;
.
692,696c
}
if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
.
685,690c
floppywait();
if(fl.nstat < 2){
fl.confused = 1;
.
682d
673,680c
/* print("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); /**/
fl.ncmd = 0;
fl.cmd[fl.ncmd++] = Fseek;
fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
if(floppycmd() < 0){
.
669a
floppyon(dp);
floppypos(dp, off);
.
668c
floppyseek(Drive *dp, long off)
.
666a
/*
* seek to the target cylinder
*
* interrupt, no results
*/
.
655,664d
650,653c
fl.motor = 0;
floppywait();
fl.confused = 0;
/* devp->dsr = 0;
devp->ccr = 0; /**/
.
648c
for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
.
646c
outb(Pdor, Fintena|Fena);
.
644c
fl.cmd[0] = 0;
outb(Pdor, 0);
.
642d
640c
if(fl.confused){
.
638c
* reset the controller if it's confused
.
612,618c
dp->cyl = fl.stat[1]/dp->t->steps;
if(dp->cyl != 0){
.
604,608c
fl.ncmd = 0;
fl.cmd[fl.ncmd++] = Frecal;
fl.cmd[fl.ncmd++] = dp->dev;
if(floppycmd() < 0)
return -1;
floppywait();
if(fl.nstat < 2){
fl.confused = 1;
return -1;
}
if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
.
598,602c
dp->ccyl = -1;
.
590,596c
int type;
.
581c
tsleep(&fl.r, cmddone, 0, 2000);
.
578,579c
static void
floppywait(void)
.
576c
* wait for a floppy interrupt
.
574a
static int
cmddone(void *a)
{
return fl.ncmd == 0;
}
.
563,571d
557,560c
if(floppyresult() < 2){
print("can't read sense response\n");
fl.confused = 1;
.
551,555c
fl.ncmd = 0;
fl.cmd[fl.ncmd++] = Fsense;
if(floppycmd() < 0)
.
549c
floppysense(void)
.
545,546c
* get the interrupt cause from the floppy.
.
535,541c
end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
if(off+dp->len > end)
dp->len = end - off;
.
532c
* can't read across track boundaries.
.
527c
ltrack = lsec/dp->t->sectors;
dp->tcyl = ltrack/dp->t->heads;
.
524a
int track;
.
522a
int ltrack;
.
517c
* truncate dp->length if it crosses a track boundary
.
511c
fl.nstat = i;
return i;
.
505,509c
for(i = 0; i < sizeof(fl.stat); i++){
for(tries = 0; ; tries++){
if(tries > 1000){
fl.confused = 1;
return -1;
}
s = inb(Pmsr)&(Ffrom|Fready);
if(s == Fready){
fl.nstat = i;
return i;
}
if(s == (Ffrom|Fready))
break;
}
fl.stat[i] = inb(Pdata);
.
502,503c
int i, s;
int tries;
.
500c
floppyresult(void)
.
497c
* get a command result from the floppy
*
* when the controller goes ready waiting for a command
* (instead of sending results), we're done
*
.
493c
return 0;
.
480,491c
for(i = 0; i < fl.ncmd; i++){
for(tries = 0; ; tries++){
if(tries > 1000){
print("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
fl.confused = 1;
return -1;
}
if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
break;
}
outb(Pdata, fl.cmd[i]);
.
478d
476a
int i;
.
475c
floppycmd(void)
.
472c
* send a command to the floppy
.
451,468c
floppyon(dp);
floppyoff(dp);
.
448,449c
static void
floppyeject(Drive *dp)
.
446c
* eject disk ( unknown on safari )
.
441,442c
fl.motor &= ~MOTORBIT(dp->dev);
outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
.
439c
floppyoff(Drive *dp)
.
431a
/* get drive to a known cylinder */
if(dp->confused)
for(tries = 0; tries < 4; tries++)
if(floppyrecal(dp) >= 0)
break;
.
427,429c
if(fl.confused)
floppyrevive();
/* start motor and select drive */
alreadyon = fl.motor & MOTORBIT(dp->dev);
fl.motor |= MOTORBIT(dp->dev);
outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
.
425a
int tries;
.
423c
floppyon(Drive *dp)
.
415,420c
* start a floppy drive's motor.
.
405,413d
399,401c
tsleep(&fl.kr, return0, 0, 5*100);
.
395c
floppyoff(dp);
.
390,391c
i = inb(Pdir) & 0x80;
if(i != last)
print("fromn %d to %d\n", last, i);
last = i;
for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
if((fl.motor&MOTORBIT(dp->dev))
.
385c
int i;
static int last;
.
377a
.
374a
case Qctl:
if(SNCMP(aa, "eject") == 0){
floppyeject(dp);
} else if(SNCMP(aa, "seek") == 0){
aa += 5;
floppyseek(dp, strtoul(aa, 0, 0));
} else if(SNCMP(aa, "den") == 0){
aa += 4;
i = strtoul(aa, 0, 0);
USED(i);
/* devp->dsr = i;
devp->ccr = i;/**/
} else if(SNCMP(aa, "reset") == 0){
floppyon(dp);
}
break;
.
370c
floppypos(dp, c->offset+rv);
if(dp->tcyl == dp->ccyl)
dp->ccyl = -1;
i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv,
n-rv);
.
367,368c
if(c->offset % dp->t->bytes)
errors("bad offset");
if(n % dp->t->bytes)
errors("bad len");
.
364c
dp = &fl.d[c->qid.path & ~Qmask];
.
361c
char *aa = a;
int dev;
.
355a
#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)
.
352a
.
349a
case Qctl:
break;
.
347c
memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
.
345a
dp->chead = head;
.
344a
}
.
343c
i = floppyxfer(dp, Fread, dp->cache,
(cyl*dp->t->heads+head)*nn, nn);
if(i != nn){
if(i == 0)
break;
.
341c
if(dp->ccyl!=cyl || dp->chead!=head){
.
339c
* read the track
.
336c
sec = dp->tsec;
.
334a
head = dp->thead;
.
330c
* truncate xfer at track boundary
.
327c
aa = a;
nn = dp->t->tsize;
.
322d
319c
dp = &fl.d[c->qid.path & ~Qmask];
.
311,313c
long rv, i;
int nn, sec, head, cyl;
long len;
long noff;
uchar *aa;
.
291,306d
214,221c
fl.confused = 1;
.
212c
* first operation will recalibrate
.
208c
dp->cache = (uchar*)ialloc(dp->t->tsize, 1);
dp->ccyl = -1;
.
206d
202,203c
fl.motor = 0;
delay(10);
outb(Pdor, fl.motor | Fintena | Fena);
delay(10);
/*
* init drives
*/
for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
dp->dev = dp - fl.d;
.
197c
fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0);
.
191a
t->tsize = t->bytes * t->sectors;
.
184a
ulong p;
long l;
.
178d
164c
static int cmddone(void*);
void Xdelay(int);
.
162c
static long floppyseek(Drive*, long);
static int floppysense(void);
static void floppywait(void);
.
160a
static int floppyresult(void);
.
158,159d
154,156c
static void floppyon(Drive*);
static void floppyoff(Drive*);
.
151,152c
static int floppycmd(void);
static void floppyeject(Drive*);
.
144c
Controller fl;
.
139,140c
int motor; /* bit mask of spinning disks */
.
135,137c
uchar cmd[14]; /* command */
int ncmd; /* # command bytes */
uchar stat[14]; /* command status */
int nstat; /* # status bytes */
int confused; /* controler needs to be reset */
.
128c
* controller for 4 floppys
.
123,124c
Rendez r; /* waiting here for motor to spin up */
.
121c
uchar *cache; /* track cache */
int ccyl;
int chead;
.
114c
int confused; /* needs to be recalibrated */
.
75c
{ "MF1DD", 512, 9, 2, 1, 80, 0x1B, 0x54, },
{ "MF4HD", 1024, 18, 2, 1, 80, 0x1B, 0x54, },
.
70a
long tsize; /* track size in bytes */
.
48a
DMAchan= 2, /* floppy dma channel */
.
37,38d
34,35c
/* digital input register */
Pdir= 0x3F7, /* disk changed port */
Fchange= 0x80, /* disk has changed */
.
26,32c
/* data register */
Pdata= 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 */
Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
Fdumpreg= 0x0e, /* dump internal registers */
.
21,24c
/* main status register */
Pmsr= 0x3f4,
Fready= 0x80, /* ready to be touched */
Ffrom= 0x40, /* data from controller */
Fbusy= 0x10, /* operation not over */
.
17,19c
/* digital output register */
Pdor= 0x3f2,
Fintena= 0x8, /* enable floppy interrupt */
Fena= 0x4, /* 0 == reset controller */
.
14a
/* bits in the registers */
.
9c
/* Intel 82077A (8272A compatible) floppy controller */
.
## diffname pc/devfloppy.c 1991/0925
## diff -e /n/bootesdump/1991/0924/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0925/sys/src/9/safari/devfloppy.c
816,817c
static void
floppyintr(Ureg *ur)
.
809,812d
803a
print(" %d %d %d\n", fl.stat[3], fl.stat[4], fl.stat[5]);
.
786,793c
print("xfer failed %lux %lux %lux\n", fl.stat[0],
fl.stat[1], fl.stat[2]);
print("offset %lud len %d\n", off, dp->len);
dp->confused = 1;
errors("floppy drive lost");
.
754c
cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
.
742c
.
726,735d
686d
673,674c
outb(Pdsr, 0);
.
490a
dp->vers++;
.
481a
fl.selected = dp;
.
471a
fl.selected = dp;
.
443c
tsleep(&fl.kr, return0, 0, 1000);
.
440c
qunlock(&fl);
.
437c
&& canqlock(&fl)){
.
430,433d
424,425d
411a
qunlock(&fl);
.
409a
fl.confused = 1;
.
400,408d
397a
qlock(&fl);
.
395a
qunlock(&fl);
poperror();
.
383,386c
islegal(c, n, dp);
qlock(&fl);
if(waserror()){
qunlock(&fl);
nexterror();
}
floppyon(dp);
changed(c, dp);
.
380d
358a
qunlock(&fl);
poperror();
.
330a
qlock(&fl);
if(waserror()){
qunlock(&fl);
nexterror();
}
floppyon(dp);
changed(c, dp);
.
325,328c
islegal(c, n, dp);
.
322d
306a
static void
islegal(Chan *c, long n, Drive *dp)
{
if(c->offset % dp->t->bytes)
errors("bad offset");
if(n % dp->t->bytes)
errors("bad len");
}
/*
* check if the floppy has been replaced under foot
*
* a seek and a read clears the condition. this was determined experimentally,
* there has to be a better way.
*/
static void
changed(Chan *c, Drive *dp)
{
ulong old;
if(inb(Pdir)&Fchange)
dp->vers++;
old = c->qid.vers;
c->qid.vers = dp->vers;
if(old && old!=dp->vers){
dp->ccyl = -1;
if(dp->cyl)
floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
else
floppyxfer(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize);
errors("disk changed");
}
}
.
281c
devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
.
237a
setvec(Floppyvec, floppyintr);
.
231a
dp->vers = 1;
.
212a
fl.selected = fl.d;
.
164a
static void floppyintr(Ureg*);
.
145a
Drive *selected;
.
124a
int vers;
.
117,118d
42c
Pdir= 0x3F7, /* disk changed port (read only) */
Pdsr= 0x3F7, /* data rate select port (write only) */
.
## diffname pc/devfloppy.c 1991/0927
## diff -e /n/bootesdump/1991/0925/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0927/sys/src/9/safari/devfloppy.c
454a
} else if(SNCMP(aa, "v") == 0){
vgaset(aa+1);
.
422a
extern void vgaset(char*);
.
## diffname pc/devfloppy.c 1991/1001
## diff -e /n/bootesdump/1991/0927/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1001/sys/src/9/safari/devfloppy.c
795c
fl.cmd[fl.ncmd++] = dp->t->sectors;
.
## diffname pc/devfloppy.c 1991/1003
## diff -e /n/bootesdump/1991/1001/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1003/sys/src/9/safari/devfloppy.c
343a
old = c->qid.vers;
c->qid.vers = dp->vers;
if(old && old!=dp->vers)
errors("disk changed");
.
342d
334,336d
332c
if(inb(Pdir)&Fchange){
.
## diffname pc/devfloppy.c 1991/1005
## diff -e /n/bootesdump/1991/1003/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1005/sys/src/9/safari/devfloppy.c
636c
/*print("can't read sense response\n");/**/
.
## diffname pc/devfloppy.c 1991/1006
## diff -e /n/bootesdump/1991/1005/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1006/sys/src/9/safari/devfloppy.c
833,834d
758a
floppythrice(Drive *dp, int cmd, void *a, long off, long n)
{
int tries;
long rv;
for(tries = 0; ; tries++){
if(waserror()){
if(strcmp(u->error, errstrtab[Eintr])==0 || tries > 3)
nexterror();
} else {
rv = floppyxfer(dp, cmd, a, off, n);
poperror();
return rv;
}
}
}
static long
.
757a
/*
* since floppies are so flakey, try 3 times before giving up
*/
.
456,457d
444a
if(i == 0)
error(Eio);
.
443c
if(i < 0)
.
441c
i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv,
.
423d
390c
i = floppythrice(dp, Fread, dp->cache,
.
177a
static long floppythrice(Drive*, int, void*, long, long);
.
## diffname pc/devfloppy.c 1991/1029
## diff -e /n/bootesdump/1991/1006/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1029/sys/src/9/safari/devfloppy.c
457a
} else if(SNCMP(aa, "fast") == 0){
cpuspeed(1);
} else if(SNCMP(aa, "slow") == 0){
cpuspeed(0);
.
## diffname pc/devfloppy.c 1991/1112
## diff -e /n/bootesdump/1991/1029/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1112/sys/src/9/safari/devfloppy.c
183,190c
"fd0disk", {Qdata + 0}, 0, 0666,
"fd0ctl", {Qctl + 0}, 0, 0666,
"fd1disk", {Qdata + 1}, 0, 0666,
"fd1ctl", {Qctl + 1}, 0, 0666,
"fd2disk", {Qdata + 2}, 0, 0666,
"fd2ctl", {Qctl + 2}, 0, 0666,
"fd3disk", {Qdata + 3}, 0, 0666,
"fd3ctl", {Qctl + 3}, 0, 0666,
.
## diffname pc/devfloppy.c 1991/1203
## diff -e /n/bootesdump/1991/1112/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1203/sys/src/9/safari/devfloppy.c
287c
return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
.
## diffname pc/devfloppy.c 1992/0111
## diff -e /n/bootesdump/1991/1203/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0111/sys/src/9/safari/devfloppy.c
773c
if(strcmp(u->error, Eintr)==0 || tries > 3)
.
7c
#include "../port/error.h"
.
## diffname pc/devfloppy.c 1992/0114
## diff -e /n/bootesdump/1992/0111/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0114/sys/src/9/safari/devfloppy.c
859c
error(Eio);
.
848c
error(Eio);
.
841c
error(Eio);
.
826c
error(Eio);
.
799c
error(Eio);
.
396c
error(Eio);
.
344c
error(Eio);
.
319c
error(Ebadarg);
.
317c
error(Ebadarg);
.
## diffname pc/devfloppy.c 1992/0321
## diff -e /n/bootesdump/1992/0114/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0321/sys/src/9/safari/devfloppy.c
2c
#include "../port/lib.h"
.
## diffname pc/devfloppy.c 1992/0625
## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0625/sys/src/9/safari/devfloppy.c
234c
dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 0);
.
215c
fl.d = xalloc(conf.nfloppy*sizeof(Drive));
.
## diffname pc/devfloppy.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0711/sys/src/9/safari/devfloppy.c
868a
USED(ur);
.
787d
668,669d
649a
USED(a);
.
611,612d
476a
USED(a);
.
423d
354d
309a
USED(c, dp);
.
303a
USED(c);
.
298a
USED(c);
.
292a
USED(c, name, omode, perm);
.
199,201d
## diffname pc/devfloppy.c 1992/0829
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0829/sys/src/9/pc/devfloppy.c
835c
/* print("xfer result failed %lux\n", inb(Pmsr));/**/
.
821c
/* print("xfer cmd failed\n");/**/
.
## diffname pc/devfloppy.c 1992/0901
## diff -e /n/bootesdump/1992/0829/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/0901/sys/src/9/pc/devfloppy.c
842c
DPRINT("offset %lud len %d\n", off, dp->len);
.
840c
DPRINT("xfer failed %lux %lux %lux\n", fl.stat[0],
.
835c
DPRINT("xfer result failed %lux\n", inb(Pmsr));
.
821c
DPRINT("xfer cmd failed\n");
.
797,798c
DPRINT("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
dp->tcyl, dp->thead, dp->tsec, a, dp->len);
.
750c
DPRINT("seek failed\n");
.
741c
DPRINT("seek cmd failed\n");
.
735c
DPRINT("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead);
.
685c
DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
.
638c
DPRINT("can't read sense response\n");
.
555c
DPRINT("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
.
14a
#define DPRINT if(0)print
.
## diffname pc/devfloppy.c 1992/1002
## diff -e /n/bootesdump/1992/0901/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1002/sys/src/9/pc/devfloppy.c
762c
* since floppies are so flakey, automaticly retry failed attempts.
* every 3 tries switch to a different density
.
342c
floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize);
.
340c
floppythrice(dp, Fread, dp->cache, 0, dp->t->tsize);
.
326c
* check if the floppy has been replaced under foot. cause a read error if it has.
.
86,91c
[0] { "MF2HD", 512, 18, 2, 1, 80, 0x1B, 0x54, 1, },
[1] { "MF1DD", 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
[2] { "MF4HD", 1024, 18, 2, 1, 80, 0x1B, 0x54, 0, },
[3] { "F2HD", 512, 15, 2, 1, 80, 0x2A, 0x50, 4, },
[4] { "F2DD", 512, 8, 2, 2, 40, 0x2A, 0x50, 5, },
[5] { "F1DD", 512, 8, 1, 2, 40, 0x2A, 0x50, 3, },
.
74a
int ring; /* ring of compatible floppy types */
.
## diffname pc/devfloppy.c 1992/1003
## diff -e /n/bootesdump/1992/1002/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1003/sys/src/9/pc/devfloppy.c
857a
DPRINT("xfer ends on wrong cyl\n");
.
854c
offset = ((fl.stat[3]+dp->t->steps-1)/dp->t->steps) * dp->t->heads + fl.stat[4];
.
775a
/* walk through the compatible types */
if(tries == 3){
if(++dp->t == &floppytype[NTYPES])
dp->t = floppytype;
floppydir[NFDIR*dp->dev].length = dp->t->cap;
if(dp->t == start)
nexterror();
tries = 0;
floppyon(dp);
}
.
774c
if(cmd != Fread || strcmp(u->error, Eintr)==0)
.
771a
start = dp->t;
.
770a
Type *start;
.
758,759c
dp->arm = dp->tcyl*dp->t->steps;
return dp->tcyl;
.
748a
DPRINT("seek cmd confused\n");
.
735,736c
if(dp->arm*dp->t->steps == dp->tcyl)
return dp->tcyl;
.
722a
fl.rate = 0;
.
686,688c
dp->arm = fl.stat[1];
if(dp->arm != 0){
DPRINT("recalibrate went to wrong cylinder %d\n", dp->arm);
.
514a
/* set transfer rate */
if(fl.rate != dp->t->rate){
fl.rate = dp->t->rate;
outb(Pdsr, fl.rate);
}
.
399c
len = 0;
continue;
.
387a
nn = dp->t->tsize;
.
369d
348a
}
.
347c
if(old && old!=dp->vers){
.
343c
floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize,
dp->t->tsize);
.
340c
if(dp->arm)
.
233c
dp->arm = -1; /* because we don't know */
.
149a
int rate; /* current rate selected */
.
125c
int arm; /* current arm position */
.
87,92c
{ "3½HD", 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
{ "3½DD", 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
{ "5¼HD", 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
{ "5¼DD2", 512, 9, 2, 2, 40, 0x2A, 0x50, 2, },
{ "5¼DD1", 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
{ "3½ED", 1024, 18, 2, 1, 80, 0x1B, 0x54, 3, },
.
75c
int rate; /* rate code */
.
63c
* floppy types (all MFM encoding)
.
## diffname pc/devfloppy.c 1992/1006
## diff -e /n/bootesdump/1992/1003/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1006/sys/src/9/pc/devfloppy.c
899,901c
case Fformat:
.
891a
/*
* format a track
*/
static int
floppyformat(Chan *c, Drive *dp, int track, char filler)
{
int cyl, h, sec;
uchar *buf, *bp;
Type *t;
t = dp->t;
cyl = track/t->heads;
h = track % t->heads;
if(track >= t->tracks * t->heads)
return 0;
buf = smalloc(t->sectors*4);
qlock(&fl);
if(waserror()){
qunlock(&fl);
free(buf);
nexterror();
}
floppyon(dp);
changed(c, dp);
if(floppyseek(dp, track*t->tsize) < 0)
error(Eio);
/*
* set up the dma (dp->len may be trimmed)
*/
bp = buf;
for(sec = 1; sec <= t->sectors; sec++){
*bp++ = cyl;
*bp++ = h;
*bp++ = sec;
*bp++ = t->bcode;
}
dmasetup(DMAchan, buf, bp-buf, 0);
/*
* start operation
*/
fl.ncmd = 0;
fl.cmd[fl.ncmd++] = Fformat;
fl.cmd[fl.ncmd++] = (h<<2) | dp->dev;
fl.cmd[fl.ncmd++] = t->bcode;
fl.cmd[fl.ncmd++] = t->sectors;
fl.cmd[fl.ncmd++] = t->fgpl;
fl.cmd[fl.ncmd++] = filler;
if(floppycmd() < 0){
DPRINT("xfer cmd failed\n");
error(Eio);
}
/*
* give bus to DMA, floppyintr() will read result
*/
floppywait();
dmaend(DMAchan);
/*
* check for errors
*/
if(fl.nstat < 7){
DPRINT("format result failed %lux\n", inb(Pmsr));
fl.confused = 1;
error(Eio);
}
if((fl.stat[0]&Codemask)!=0 || fl.stat[1] || fl.stat[2]){
DPRINT("format failed %lux %lux %lux\n",
fl.stat[0], fl.stat[1], fl.stat[2]);
dp->confused = 1;
error(Eio);
}
qunlock(&fl);
free(buf);
return 1;
}
.
879c
offset = fl.stat[3] * dp->t->heads + fl.stat[4];
.
841c
fl.cmd[fl.ncmd++] = dp->tcyl;
.
793,794c
while(++dp->t){
if(dp->t == &floppytype[NTYPES])
dp->t = floppytype;
if(dp->dt == Tnone)
break;
if(dp->dt == dp->t->dt)
break;
}
.
770c
dp->cyl = dp->tcyl;
.
746c
if(dp->cyl == dp->tcyl)
.
696,698c
dp->cyl = fl.stat[1];
if(dp->cyl != 0){
DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
.
464,467c
} else if(SNCMP(ctlmsg, "format") == 0){
if(getfields(ctlmsg, f, 3, ' ') != 3)
error(Ebadarg);
rv = n*floppyformat(c, dp, atoi(f[1]), *f[2]);
.
461c
} else if(SNCMP(ctlmsg, "reset") == 0){
.
459c
if(n >= sizeof(ctlmsg))
n = sizeof(ctlmsg) - 1;
memmove(ctlmsg, aa, n);
ctlmsg[n] = 0;
if(SNCMP(ctlmsg, "eject") == 0){
.
447,448c
i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, n-rv);
.
429a
char *f[3];
char ctlmsg[64];
.
340,341c
dp->confused = 1;
floppyon(dp);
if(dp->cyl)
.
338a
setdef(dp);
.
240a
* read nvram for types of floppies 0 & 1
*/
equip = nvramread(0x10);
if(conf.nfloppy > 0){
fl.d[0].dt = (equip >> 4) & 0xf;
setdef(&fl.d[0]);
}
if(conf.nfloppy > 1){
fl.d[1].dt = equip & 0xf;
setdef(&fl.d[1]);
}
/*
.
232,234c
dp->dt = T1440kb;
setdef(dp);
dp->cyl = -1; /* because we don't know */
.
202a
uchar equip;
.
197a
/*
* set floppy drive to its default type
*/
static void
setdef(Drive *dp)
{
Type *t;
for(t = floppytype; t < &floppytype[NTYPES]; t++)
if(dp->dt == t->dt){
dp->t = t;
floppydir[NFDIR*dp->dev].length = dp->t->cap;
break;
}
}
.
181a
static int floppyformat(Chan*, Drive*, int, char);
.
125c
int cyl; /* current arm position */
.
121c
Type *t; /* floppy type */
int dt; /* drive type */
.
87,92c
{ "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, },
.
67a
int dt; /* compatible drive type */
.
62a
* types of drive (from PC equipment byte)
*/
enum
{
Tnone= 0,
T360kb= 1,
T1200kb= 2,
T720kb= 3,
T1440kb= 4,
};
/*
.
39a
Fformat= 0x4d, /* format cmd */
.
## diffname pc/devfloppy.c 1992/1007
## diff -e /n/bootesdump/1992/1006/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1007/sys/src/9/pc/devfloppy.c
1027a
poperror();
.
1026d
974,977c
if(!waserror()){
floppyon(dp);
poperror();
}
floppyseek(dp, track*t->tsize);
dp->cyl = cyl;
dp->confused = 0;
.
970d
967,968d
965a
setdef(dp);
.
955c
floppyformat(Drive *dp, ulong track, ulong filler)
.
521a
poperror();
.
520c
rv = n*floppyformat(dp, strtoul(f[1], 0, 0), strtoul(f[2], 0, 0));
.
507a
if(waserror()){
qunlock(&fl);
nexterror();
}
.
463c
return readstr(offset, a, n, dp->t->name);
.
197c
static int floppyformat(Drive*, ulong, ulong);
.
## diffname pc/devfloppy.c 1992/1009
## diff -e /n/bootesdump/1992/1007/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1009/sys/src/9/pc/devfloppy.c
1034d
1026,1031d
1018,1024c
/*
* seek to track, ignore errors
*/
if(!waserror()){
floppyon(dp);
poperror();
}
floppyseek(dp, track*t->tsize);
dp->cyl = cyl;
dp->confused = 0;
/*
* set up the dma (dp->len may be trimmed)
*/
bp = buf;
for(sec = 1; sec <= t->sectors; sec++){
*bp++ = cyl;
*bp++ = h;
*bp++ = sec;
*bp++ = t->bcode;
}
dmasetup(DMAchan, buf, bp-buf, 0);
/*
* start operation
*/
fl.ncmd = 0;
fl.cmd[fl.ncmd++] = Fformat;
fl.cmd[fl.ncmd++] = (h<<2) | dp->dev;
fl.cmd[fl.ncmd++] = t->bcode;
fl.cmd[fl.ncmd++] = t->sectors;
fl.cmd[fl.ncmd++] = t->fgpl;
fl.cmd[fl.ncmd++] = 0x5a;
if(floppycmd() < 0){
DPRINT("xfer cmd failed\n");
error(Eio);
}
/*
* give bus to DMA, floppyintr() will read result
*/
floppywait();
dmaend(DMAchan);
/*
* check for errors
*/
if(fl.nstat < 7){
DPRINT("format result failed %lux\n",inb(Pmsr));
fl.confused = 1;
error(Eio);
}
if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){
DPRINT("format failed %lux %lux %lux\n",
fl.stat[0], fl.stat[1], fl.stat[2]);
dp->confused = 1;
error(Eio);
}
.
1015,1016c
for(track = 0; track < t->tracks*t->heads; track++){
cyl = track/t->heads;
h = track % t->heads;
.
1013c
* format a track at time
.
1000,1009c
buf = smalloc(t->sectors*4);
if(waserror()){
free(buf);
nexterror();
.
998c
* buffer for per track info
.
995d
988,993c
if(getfields(params, f, 3, ' ') > 1){
for(t = floppytype; t < &floppytype[NTYPES]; t++)
if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){
dp->t = t;
floppydir[NFDIR*dp->dev].length = dp->t->cap;
break;
}
} else {
setdef(dp);
t = dp->t;
.
986c
* set the type
.
966,984d
964a
char *f[3];
.
962a
ulong track;
.
959,960c
static void
floppyformat(Drive *dp, char *params)
.
522,524c
floppyformat(dp, ctlmsg);
.
506a
rv = n;
.
497c
i = floppythrice(dp, Fwrite, aa+rv, offset+rv, n-rv);
.
494c
floppypos(dp, offset+rv);
.
485c
islegal(offset, n, dp);
.
478d
473c
floppywrite(Chan *c, void *a, long n, ulong offset)
.
433c
floppypos(dp, offset+rv);
.
418c
islegal(offset, n, dp);
.
403c
floppyread(Chan *c, void *a, long n, ulong offset)
.
367c
if(offset % dp->t->bytes)
.
365c
islegal(ulong offset, long n, Drive *dp)
.
197c
static void floppyformat(Drive*, char*);
.
7a
#include "devtab.h"
.
## diffname pc/devfloppy.c 1992/1013
## diff -e /n/bootesdump/1992/1009/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1013/sys/src/9/pc/devfloppy.c
1057a
dp->confused = 1;
.
1040a
poperror();
.
1018a
if(waserror()){
dmaend(DMAchan);
nexterror();
}
.
949a
poperror();
.
921a
poperror();
.
894a
if(waserror()){
dmaend(DMAchan);
nexterror();
}
.
882,884c
/* retry on error 3 times */
while(waserror())
if(tries++ >= 3)
nexterror();
.
875a
int tries = 0;
.
836,872d
832,833c
* read or write to floppy. try up to three times.
.
755a
dp->cyl = -1;
.
497c
i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv);
.
446c
i = floppyxfer(dp, Fread, dp->cache,
.
400d
398c
if(old && old != dp->vers)
.
395a
.
390,394c
floppyseek(dp, dp->t->heads*dp->t->tsize);
while(waserror()){
while(++dp->t){
if(dp->t == &floppytype[NTYPES])
dp->t = floppytype;
if(dp->dt == dp->t->dt)
break;
}
floppydir[NFDIR*dp->dev].length = dp->t->cap;
if(dp->t == start)
nexterror();
floppyon(dp);
}
floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
poperror();
.
388c
setdef(dp);
start = dp->t;
dp->confused = 1; /* make floppyon recal */
.
385,386c
/*
* if floppy has changed or first time through
*/
if((inb(Pdir)&Fchange) || dp->vers == 0){
.
383a
Type *start;
.
377,378c
* a seek and a read clears the condition. this was determined
* experimentally, there has to be a better way.
*
* if the read fails, cycle through the possible floppy
* density till one works or we've cycled through all
* possibilities.
.
375c
* check if the floppy has been replaced under foot. cause
* an error if it has.
.
199d
## diffname pc/devfloppy.c 1992/1016
## diff -e /n/bootesdump/1992/1013/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1016/sys/src/9/pc/devfloppy.c
1047c
DPRINT("format: failed %lux %lux %lux\n",
.
1042c
DPRINT("format: confused\n");
.
1029d
1026,1027c
if(floppycmd() < 0)
.
992,995d
981a
/* force a recalibrate to cylinder 0 */
dp->confused = 1;
if(!waserror()){
floppyon(dp);
poperror();
}
.
936c
DPRINT("xfer: ends on wrong cyl\n");
.
922c
DPRINT("xfer: failed %lux %lux %lux\n", fl.stat[0],
.
917c
DPRINT("xfer: confused\n");
.
904d
900,902c
if(floppycmd() < 0)
.
874c
DPRINT("floppyxfer: tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
.
872a
}
.
871c
if(floppyseek(dp, off) < 0){
DPRINT("xfer: seek failed\n");
dp->confused = 1;
.
868a
}
.
866c
tries = 0;
while(waserror()){
DPRINT("floppyxfer: retrying\n");
.
858c
int tries;
.
842c
DPRINT("seek: failed\n");
.
837c
DPRINT("seek: confused\n");
.
834d
831,832c
if(floppycmd() < 0)
.
826c
DPRINT("seek: tcyl %d, thead %d\n", dp->tcyl, dp->thead);
.
824a
dp->cyl = -1;
.
774c
DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
.
768a
DPRINT("recalibrate: failed\n");
.
764a
DPRINT("recalibrate: confused\n");
.
756a
dp->cyl = -1;
.
644c
DPRINT("cmd %ux can't be sent (%d %ux)\n",
fl.cmd[0], i, inb(Pmsr));
.
640a
fl.nstat = 0;
.
542a
} else if(SNCMP(ctlmsg, "debug") == 0){
floppydebug = 1;
.
410a
DPRINT("changed: trying %s\n", dp->t->name);
.
16c
#define DPRINT if(floppydebug)print
int floppydebug;
.
## diffname pc/devfloppy.c 1992/1113
## diff -e /n/bootesdump/1992/1016/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1113/sys/src/9/pc/devfloppy.c
269c
dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 64*1024);
.
## diffname pc/devfloppy.c 1992/1120
## diff -e /n/bootesdump/1992/1113/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1120/sys/src/9/pc/devfloppy.c
819c
fl.rate = -1;
.
772c
DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
.
648c
if(tries > 10000){
.
## diffname pc/devfloppy.c 1992/1216
## diff -e /n/bootesdump/1992/1120/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1216/sys/src/9/pc/devfloppy.c
819c
fl.rate = 0;
DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
805a
DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
764a
DPRINT("floppyrecal: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
753a
if(!cmddone(0))
floppyintr(0);
.
411d
408a
floppyon(dp);
.
394a
DPRINT("changed: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
## diffname pc/devfloppy.c 1992/1217
## diff -e /n/bootesdump/1992/1216/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1217/sys/src/9/pc/devfloppy.c
893,895d
842d
825c
DPRINT("floppyrevive out\n");
fldump();
.
822a
floppywait();
/* mark all drives in an unknown state */
for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
dp->confused = 1;
/* set rate to a known value */
.
821d
818,819d
812a
fl.ncmd = 1;
.
810c
DPRINT("floppyrevive in\n");
fldump();
.
768d
754c
tsleep(&fl.r, cmddone, 0, 5000);
.
749c
* Wait for a floppy interrupt. If none occurs in 5 seconds, we
* may have missed one. This only happens on some portables which
* do power management behind our backs. Call the interrupt
* routine to try to clear any conditions.
.
734a
fldump();
.
692,693c
fl.nstat = sizeof(fl.stat);
return fl.nstat;
.
685c
return fl.nstat;
.
678a
DPRINT("floppyresult: %d stats\n", i);
fldump();
.
676a
/* wait for status byte */
.
675a
/* get the result of the operation */
.
649,652c
if(tries > 1000){
DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
fldump();
/* empty fifo, might have been a bad command */
floppyresult();
.
599a
/* clear any pending interrupts */
floppysense();
}
.
597c
if(!alreadyon){
/* wait for drive to spin up */
.
413d
410a
DPRINT("changed: trying %s\n", dp->t->name);
fldump();
.
395c
DPRINT("changed\n");
fldump();
.
383c
* possibilities for this drive.
.
214a
static void
fldump(void)
{
DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
inb(Pdor), inb(Pmsr), inb(Pdir));
}
.
21a
/* status registers a & b */
Psra= 0x3f0,
Psrb= 0x3f1,
.
16c
#define DPRINT if(floppydebug)kprint
.
## diffname pc/devfloppy.c 1992/1218
## diff -e /n/bootesdump/1992/1217/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1218/sys/src/9/pc/devfloppy.c
846a
delay(10);
.
845c
delay(10);
.
784a
fl.confused = 1;
}
.
783c
if(!cmddone(0)){
.
614a
setvec(Floppyvec, floppyintr);
.
280c
dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
.
255a
if(maxtsize < t->tsize)
maxtsize = t->tsize;
.
251a
maxtsize = 0;
.
247a
ulong maxtsize;
.
## diffname pc/devfloppy.c 1993/0219
## diff -e /n/bootesdump/1992/1218/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0219/sys/src/9/pc/devfloppy.c
619d
## diffname pc/devfloppy.c 1993/0410
## diff -e /n/bootesdump/1993/0219/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0410/sys/src/9/pc/devfloppy.c
112a
{ "ATT3B1", T360kb, 512, 8, 2, 1, 48, 0x2A, 0x50, 2, },
.
## diffname pc/devfloppy.c 1993/0430
## diff -e /n/bootesdump/1993/0410/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0430/sys/src/9/pc/devfloppy.c
113d
111a
{ "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },
.
## diffname pc/devfloppy.c 1993/0915
## diff -e /n/bootesdump/1993/0430/sys/src/9/pc/devfloppy.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devfloppy.c
479,496c
if(readtrack(dp, cyl, head) < 0)
break;
.
471c
* all xfers come out of the track cache
.
447,448c
long rv;
int sec, head, cyl;
.
442a
static int
readtrack(Drive *dp, int cyl, int head)
{
int i, nn, sofar;
ulong pos;
nn = dp->t->tsize;
if(dp->ccyl==cyl && dp->chead==head)
return nn;
pos = (cyl*dp->t->heads+head) * nn;
for(sofar = 0; sofar < nn; sofar += i){
dp->ccyl = -1;
i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
if(i <= 0)
return -1;
}
dp->ccyl = cyl;
dp->chead = head;
return nn;
}
.
## diffname pc/devfloppy.c 1993/1124
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devfloppy.c
1124c
USED(ur, arg);
.
1122c
floppyintr(Ureg *ur, void *arg)
.
794c
floppyintr(0, 0);
.
307c
setvec(Floppyvec, floppyintr, 0);
.
192c
static void floppyintr(Ureg*, void*);
.
## diffname pc/devfloppy.c 1994/1017
## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1994/1017/sys/src/brazil/pc/devfloppy.c
377,378c
Dirtab *dt;
Dir d;
if(!iseve())
error(Eperm);
if(CHDIR & c->qid.path)
error(Eperm);
convM2D(dp, &d);
d.mode &= 0x666;
dt = &floppydir[2 * (c->qid.path & ~Qmask)];
dt[0].perm = dt[1].perm = d.mode;
.
209,216c
"fd0disk", {Qdata + 0}, 0, 0660,
"fd0ctl", {Qctl + 0}, 0, 0660,
"fd1disk", {Qdata + 1}, 0, 0660,
"fd1ctl", {Qctl + 1}, 0, 0660,
"fd2disk", {Qdata + 2}, 0, 0660,
"fd2ctl", {Qctl + 2}, 0, 0660,
"fd3disk", {Qdata + 3}, 0, 0660,
"fd3ctl", {Qctl + 3}, 0, 0660,
.
## diffname pc/devfloppy.c 1995/0105
## diff -e /n/fornaxdump/1994/1017/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0105/sys/src/brazil/pc/devfloppy.c
16c
#define DPRINT if(floppydebug)print
.
## diffname pc/devfloppy.c 1995/0108
## diff -e /n/fornaxdump/1995/0105/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devfloppy.c
589a
}
long
floppybwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
.
526a
Block*
floppybread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
## diffname pc/devfloppy.c 1995/0117
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devfloppy.c
1045c
if(getfields(params, f, 3, " ") > 1){
.
## diffname pc/devfloppy.c 1995/0218
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0218/sys/src/brazil/pc/devfloppy.c
1051a
}
if(t >= &floppytype[NTYPES])
error(Ebadarg);
.
1046c
for(t = floppytype; t < &floppytype[NTYPES]; t++){
.
240a
}
.
239c
return;
.
235c
for(t = floppytype; t < &floppytype[NTYPES]; t++){
.
## diffname pc/devfloppy.c 1995/0726
## diff -e /n/fornaxdump/1995/0218/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devfloppy.c
358d
356c
floppycreate(Chan*, char*, int, ulong)
.
## diffname pc/devfloppy.c 1995/0728
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0728/sys/src/brazil/pc/devfloppy.c
978c
fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
.
976c
cmd = cmd;
.
953c
if(tries++ > 20)
.
949c
/* retry on error */
.
## diffname pc/devfloppy.c 1995/0818
## diff -e /n/fornaxdump/1995/0728/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0818/sys/src/brazil/pc/devfloppy.c
1009c
if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun)
DPRINT("DMA overrun: retry\n");
else
dp->confused = 1;
.
59a
/* status 1 byte */
Overrun= 0x10,
.
58a
Cmdexec= 1<<6,
.
## diffname pc/devfloppy.c 1995/1121
## diff -e /n/fornaxdump/1995/0818/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/1121/sys/src/brazil/pc/devfloppy.c
866c
static void
.
## diffname pc/devfloppy.c 1996/0223
## diff -e /n/fornaxdump/1995/1121/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1996/0223/sys/src/brazil/pc/devfloppy.c
8d
## diffname pc/devfloppy.c 1996/0315
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1996/0315/sys/src/brazil/pc/devfloppy.c
1051c
if(parsefields(params, f, 3, " ") > 1){
.
## diffname pc/devfloppy.c 1997/0327
## diff -e /n/fornaxdump/1996/0315/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devfloppy.c
1170a
Dev floppydevtab = {
floppyreset,
devinit,
floppyattach,
devclone,
floppywalk,
floppystat,
floppyopen,
devcreate,
floppyclose,
floppyread,
devbread,
floppywrite,
devbwrite,
devremove,
devwstat,
};
.
1159a
case Fdumpreg:
.
1155c
USED(ur);
.
1153c
floppyintr(Ureg *ur)
.
1124a
/* Poll ready bits and transfer data */
floppyexec((char *)buf, bp-buf, 0);
.
1062c
floppysetdef(dp);
.
1059c
if(t >= &floppytype[nelem(floppytype)])
.
1052c
for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
.
1045c
FType *t;
.
1040c
floppyformat(FDrive *dp, char *params)
.
1014c
} else
.
1012c
if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
.
992a
/* Poll ready bits and transfer data */
floppyexec((char*)a, dp->len, cmd==Fread);
.
979d
957a
DPRINT("floppyxfer: retrying\n");
/*floppyon(dp);*/
.
955d
952c
/* retry on error (until it gets ridiculous) */
.
942c
floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
.
909c
floppyseek(FDrive *dp, long off)
.
891c
for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
.
868c
FDrive *dp;
.
828c
floppyrecal(FDrive *dp)
.
819c
floppyintr(0);
.
761c
floppypos(FDrive *dp, long off)
.
749c
fl.stat[i] = inb(Pfdata);
.
747a
if(tries > 1000){
DPRINT("floppyresult: %d stats\n", i);
fldump();
fl.confused = 1;
return -1;
}
microdelay(8); /* for machine independence */
.
735,740d
713c
outb(Pfdata, fl.cmd[i]);
.
710,711c
microdelay(8); /* for machine independence */
.
701a
if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
break;
.
680,690d
676d
672c
floppyoff(FDrive *dp)
.
633c
floppyon(FDrive *dp)
.
616c
for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
.
610c
FDrive *dp;
.
601,606d
590c
} else
error(Ebadctl);
.
540c
FDrive *dp;
.
537c
static long
.
530,535d
487c
return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen);
.
480c
FDrive *dp;
.
477c
static long
.
457c
readtrack(FDrive *dp, int cyl, int head)
.
434c
if(dp->t == &floppytype[nelem(floppytype)])
.
427c
floppysetdef(dp);
.
418c
FType *start;
.
415c
changed(Chan *c, FDrive *dp)
.
395c
islegal(ulong offset, long n, FDrive *dp)
.
370,393d
358,364c
static void
.
355c
return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen);
.
352c
static Chan*
.
349c
devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen);
.
346c
static void
.
343c
return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen);
.
334,340c
static int
.
319c
static Chan*
.
314,316c
floppysetup1(&fl);
.
311,312d
295,307d
287c
floppysetdef(dp);
.
284c
for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
.
270c
fl.d = xalloc(fl.ndrive*sizeof(FDrive));
.
259c
for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
.
253a
floppysetup0(&fl);
.
250,252c
FDrive *dp;
FType *t;
.
247c
static void
.
244d
242c
break;
.
238c
for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
.
236c
FType *t;
.
234c
floppysetdef(FDrive *dp)
.
212,219c
"fd0disk", {Qdata + 0}, 0, 0666,
"fd0ctl", {Qctl + 0}, 0, 0666,
"fd1disk", {Qdata + 1}, 0, 0666,
"fd1ctl", {Qctl + 1}, 0, 0666,
"fd2disk", {Qdata + 2}, 0, 0666,
"fd2ctl", {Qctl + 2}, 0, 0666,
"fd3disk", {Qdata + 3}, 0, 0666,
"fd3ctl", {Qctl + 3}, 0, 0666,
.
206,209c
static long floppyxfer(FDrive*, int, void*, long, long);
.
203c
static long floppyseek(FDrive*, long);
.
197,200c
static void floppypos(FDrive*,long);
static int floppyrecal(FDrive*);
.
193,195c
static int cmddone(void*);
static void floppyformat(FDrive*, char*);
.
149,187d
140,147c
FController fl;
.
118d
89,109d
84,87c
FType floppytype[] =
.
71a
#define DPRINT if(floppydebug)iprint
int floppydebug;
.
64c
Qdir= 0,
.
15,62c
enum {
.
11,13c
/* This module expects the following functions to be defined
* elsewhere:
*
* inb()
* outb()
* floppyexec()
* floppyeject()
* floppysetup0()
* floppysetup1()
* dmasetup()
* dmaend()
*
* On DMA systems, floppyexec() should be an empty function;
* on non-DMA systems, dmaend() should be an empty function;
* dmasetup() may enforce maximum transfer sizes.
*/
.
8a
#include "floppy.h"
.
## diffname pc/devfloppy.c 1997/0404
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0404/sys/src/brazil/pc/devfloppy.c
933c
if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)
error(Eio);
.
795a
if(dp->len < 0)
error(Eio);
.
145a
dmainit(DMAchan);
.
21a
* dmainit()
.
## diffname pc/devfloppy.c 1997/0408
## diff -e /n/emeliedump/1997/0404/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devfloppy.c
1005a
'f',
"floppy",
.
## diffname pc/devfloppy.c 1997/0910
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0910/sys/src/brazil/pc/devfloppy.c
107,114c
"fd0disk", {Qdata + 0}, 0, 0660,
"fd0ctl", {Qctl + 0}, 0, 0660,
"fd1disk", {Qdata + 1}, 0, 0660,
"fd1ctl", {Qctl + 1}, 0, 0660,
"fd2disk", {Qdata + 2}, 0, 0660,
"fd2ctl", {Qctl + 2}, 0, 0660,
"fd3disk", {Qdata + 3}, 0, 0660,
"fd3ctl", {Qctl + 3}, 0, 0660,
.
## diffname pc/devfloppy.c 1998/0120
## diff -e /n/emeliedump/1997/0910/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0120/sys/src/brazil/pc/devfloppy.c
188c
dp->vers = 0;
.
41,42c
#define DPRINT if(floppydebug)print
int floppydebug = 1;
.
## diffname pc/devfloppy.c 1998/0213
## diff -e /n/emeliedump/1998/0120/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0213/sys/src/brazil/pc/devfloppy.c
42c
int floppydebug = 0;
.
## diffname pc/devfloppy.c 1998/0319
## diff -e /n/emeliedump/1998/0213/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devfloppy.c
987d
985c
floppyintr(Ureg *)
.
627d
625c
cmddone(void *)
.
445d
441c
floppykproc(void *)
.
381a
ulong offset = off;
.
376c
floppywrite(Chan *c, void *a, long n, vlong off)
.
328a
ulong offset = off;
.
322c
floppyread(Chan *c, void *a, long n, vlong off)
.
235d
233c
floppyclose(Chan *)
.
## diffname pc/devfloppy.c 1998/0825
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0825/sys/src/brazil/pc/devfloppy.c
972c
DPRINT("format: failed %ux %ux %ux\n",
.
838c
DPRINT("offset %lud len %ld\n", off, dp->len);
.
836c
DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
.
## diffname pc/devfloppy.c 1999/0403
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0403/sys/src/brazil/pc/devfloppy.c
162a
dmainit(DMAchan, maxtsize);
.
147,148d
## diffname pc/devfloppy.c 1999/0507
## diff -e /n/emeliedump/1999/0403/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0507/sys/src/brazil/pc/devfloppy.c
685c
* reset it and get back to a known state
.
## diffname pc/devfloppy.c 1999/0714
## diff -e /n/emeliedump/1999/0507/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devfloppy.c
202a
if(fl.ndrive == 0)
error(Enodev);
.
148a
if(fl.ndrive == 0)
return;
.
## diffname pc/devfloppy.c 2000/0308
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devfloppy.c /n/emeliedump/2000/0308/sys/src/9/pc/devfloppy.c
883c
if(getfields(params, f, 3, 1, " ") > 1){
.
## diffname pc/devfloppy.c 2000/0813
## diff -e /n/emeliedump/2000/0308/sys/src/9/pc/devfloppy.c /n/emeliedump/2000/0813/sys/src/9/pc/devfloppy.c
964c
floppywait(1);
.
828c
floppywait(0);
.
785d
782c
if(tries++ >= dp->maxtries)
.
749c
floppywait(1);
.
715c
floppywait(0);
.
665c
floppywait(1);
.
644c
tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000);
.
642c
floppywait(int slow)
.
503a
/* return -1 if this didn't work */
if(dp->confused)
return -1;
return 0;
.
470c
static int
.
295a
dp->maxtries = 20;
.
293a
/* if the read succeeds, we've got the density right */
.
288c
/* floppyon will fail if there's a controller but no drive */
if(floppyon(dp) < 0)
error(Eio);
.
280a
/*
* if first attempt doesn't reset changed bit, there's
* no floppy there
*/
if(inb(Pdir)&Fchange)
nexterror();
.
278c
if(floppyon(dp) < 0)
error(Eio);
/* seek to the first track */
.
276a
dp->maxtries = 3; /* limit it when we're probing */
/* floppyon will fail if there's a controller but no drive */
.
275d
103c
static void floppywait(int);
.
## diffname pc/devfloppy.c 2001/0527
## diff -e /n/emeliedump/2000/0813/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/0527/sys/src/9/pc/devfloppy.c
1038d
354c
if(c->qid.type & QTDIR)
.
228c
return devstat(c, dp, n, floppydir, fl.ndrive*NFDIR, devgen);
.
225,226c
static int
floppystat(Chan *c, uchar *dp, int n)
.
222c
return devwalk(c, nc, name, nname, floppydir, fl.ndrive*NFDIR, devgen);
.
219,220c
static Walkqid*
floppywalk(Chan *c, Chan *nc, char **name, int nname)
.
106a
".", {Qdir, 0, QTDIR}, 0, 0550,
.
## diffname pc/devfloppy.c 2001/0716
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/0716/sys/src/9/pc/devfloppy.c
911c
floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
.
356c
return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
300c
floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
.
235c
return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
229c
return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
223c
return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
137c
floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
.
## diffname pc/devfloppy.c 2001/1117
## diff -e /n/emeliedump/2001/0716/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/1117/sys/src/9/pc/devfloppy.c
907c
if(tokenize(params, f, 3) > 1){
.
## diffname pc/devfloppy.c 2001/1120
## diff -e /n/emeliedump/2001/1117/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/1120/sys/src/9/pc/devfloppy.c
919a
} else {
cmderror(cb, "invalid floppy format command");
SET(t);
.
917c
} else if(cb->nf == 1){
.
909c
if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){
.
907c
if(cb->nf == 2){
.
902d
896c
floppyformat(FDrive *dp, Cmdbuf *cb)
.
457a
poperror();
free(cb);
.
454,455c
break;
}
.
450,452c
break;
case CMdebug:
.
447c
break;
case CMformat:
floppyformat(dp, cb);
break;
case CMreset:
.
441,445c
ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg));
switch(ct->index){
case CMeject:
.
435a
cb = parsecmd(a, n);
if(waserror()){
free(cb);
nexterror();
}
.
406c
Cmdbuf *cb;
Cmdtab *ct;
.
399d
118a
enum
{
CMdebug,
CMeject,
CMformat,
CMreset,
};
static Cmdtab floppyctlmsg[] =
{
CMdebug, "debug", 1,
CMeject, "eject", 1,
CMformat, "format", 0,
CMreset, "reset", 1,
};
.
95c
static void floppyformat(FDrive*, Cmdbuf*);
.
## diffname pc/devfloppy.c 2002/0109
## diff -e /n/emeliedump/2001/1120/sys/src/9/pc/devfloppy.c /n/emeliedump/2002/0109/sys/src/9/pc/devfloppy.c
1063a
devshutdown,
.
## diffname pc/devfloppy.c 2003/0325
## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devfloppy.c /n/emeliedump/2003/0325/sys/src/9/pc/devfloppy.c
475a
break;
case CMnodebug:
floppydebug = 0;
.
129a
CMnodebug, "nodebug", 1,
.
121a
CMnodebug,
.
## diffname pc/devfloppy.c 2003/0407
## diff -e /n/emeliedump/2003/0325/sys/src/9/pc/devfloppy.c /n/emeliedump/2003/0407/sys/src/9/pc/devfloppy.c
534c
tsleep(&up->sleep, return0, 0, 750);
.
512c
tsleep(&up->sleep, return0, 0, 1000);
.
|