/* * 40MB disk driver */ #include #include #include #include "../saio.h" #define NBPC 200 /* blocks per cylinder */ #define NBPT 10 /* blocks per track */ #define NTPC 20 /* tracks per cylinder */ #define UNS 0x10 #define UNREADY 0x08 #define SINC 0x02 #define OFFL 0x01 #define DISABLE 0x80 #define ENABLE 0x40 #define SETHEAD 0x20 #define SETCYL 0x10 #define RSTGATN 0x08 #define RSTHEAD 0x04 #define SEEK 0x02 #define DISARM 0xc0 #define CNTL_UNRCV 0x61 #define CYL_OV 0x10 #define IDLE 0x02 #define CREAD 0x01 #define CWRITE 0x02 #define CRESET 0x08 #define STOP 0x48 #define GO 0x50 #define READ_GO 0x70 #define SELCHBSY 0x08 char d40addr[4] = { 0xfc, 0xfd, 0xfe, 0xff }; char d40cntl = 0xfb; char d40selch = 0xf0; static int curcntl; /* controller address for d40idle */ d40strategy(io, func) register struct iob *io; { register drive, cntl, selch, stat; register bn, tn, cn, sn; if ((drive = io->i_deva) == 0) drive = d40addr[io->i_unit]; if ((cntl = io->i_cntl) == 0) cntl = d40cntl; if ((selch = io->i_selch) == 0) selch = d40selch; curcntl = cntl; cn = io->i_bn / NBPC; bn = io->i_bn % NBPC; tn = bn / NBPT; sn = (bn % NBPT) << 1; d40idle(); wh(drive, cn); d40idle(); oc(drive, SETCYL | DISARM) ; d40idle(); oc(drive, RSTGATN); d40idle(); oc(drive, RSTHEAD); d40idle(); wh(drive, tn); oc(drive, SETHEAD); d40idle(); oc(drive, SEEK); d40idle(); while ((stat=ss(drive)) & UNREADY) ; if (stat & (UNS|SINC|OFFL)) { printf("d40 error: cyl=%d track=%d sect=%d er=%x ad=%x\n", cn, tn, sn, stat, drive); return(-1); } oc(selch, STOP); wdh(selch, io->i_ma); wdh(selch, io->i_ma + io->i_cc - 1); wd(cntl, sn); wh(cntl, (tn<<10) | cn); if (func == READ) { oc(cntl, CREAD); oc(selch, READ_GO); } else { oc(cntl, CWRITE); oc(selch, GO); } while (ss(selch) & SELCHBSY) ; oc(selch, STOP); d40idle(); if ((stat=ss(cntl)) & (CNTL_UNRCV|CYL_OV)) { printf("MSM error: cyl=%d track=%d sect=%d er=%x ad=%x\n", cn, tn, sn, stat, cntl); return(-1); } return(io->i_cc); } d40idle() { while (! (ss(curcntl) & IDLE) ) ; }