static char SCCS_ID [] = "@(#)udd.c 3.7"; /* * UDD disk driver - ITDC */ #include #include #include #include "../saio.h" #define ALTBSY 0x20 #define UNS 0x10 #define UNREADY 0x08 #define SINC 0x02 #define OFFL 0x01 #define DISABLE 0x80 #define ENABLE 0x40 #define DISARM 0xc0 #define SETHEAD 0x20 #define SETCYL 0x10 #define SEEK 0x02 #define RELEASE 0xb0 #define CNTL_UNRCV 0xc1 #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 #ifdef NORMAL char uddaddr[4] = { 0xfc, 0xfd, 0xfe, 0xff }; char uddcntl = 0xfb; char uddselch = 0xf0; #else NORMAL char uddaddr[4] = { 0xec, 0xed, 0xee, 0xef }; char uddcntl = 0xeb; char uddselch = 0xf1; #endif NORMAL static int curcntl; /* controller address for uddidle */ #define NSECTORS 2 /* number of physical sectors per 512 bytes */ #define SECSHIFT 1 /* shift for NSECTORS */ #define NBPT 59 /* 256-byte blocks per track */ #define NUMCYL 815 /* number of cylinders 0..814 */ #define UDD_ITDC (59*5 ) /* 256-byte blocks per cylinder - ITDC */ uddstrategy(io, func) struct iob *io; { return uddfstrategy (io, func, UDD_ITDC,0); } static uddfstrategy(io, func, nbpc,headoffset) register struct iob *io; int headoffset; { register int drive, cntl, selch, stat; register offset; /* number of bytes already finished */ register int tn; /* track */ register int cn; /* cylinder */ register int sn; /* sector */ offset = 0; /* offset initialy zero */ if ((drive = io->i_deva) == 0) drive = uddaddr[io->i_unit]; if ((cntl = io->i_cntl) == 0) cntl = uddcntl; if ((selch = io->i_selch) == 0) selch = uddselch; curcntl = cntl; io->i_bn *= 2; /* block number in 256 byte blocks. */ cn = io->i_bn / nbpc; { register off_t bn; /* block number */ bn = io->i_bn % nbpc; tn = bn / NBPT; sn = (bn % NBPT); } findit: uddidle(); while (ss(drive) & ALTBSY) ; wh(drive, cn); uddidle(); oc(drive, SETCYL | DISARM) ; uddidle(); oc(drive, SEEK); uddidle(); while ((stat=ss(drive)) & UNREADY) ; if (stat & (UNS|SINC|OFFL|ALTBSY)) { printf("MSM seek 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[offset]); wdh(selch, &io->i_ma[io->i_cc - 1]); wh(drive, tn | headoffset ); oc(drive, SETHEAD); uddidle(); wd(cntl, sn); wh(cntl, (tn<<10) | cn); wh(drive, tn); oc(drive, SETHEAD); if (func == READ) { oc(cntl, CREAD); oc(selch, READ_GO); } else { oc(cntl, CWRITE); oc(selch, GO); } while (ss(selch) & SELCHBSY) ; oc(selch, STOP); uddidle(); /* check status */ stat = ss(cntl); if (stat & (CNTL_UNRCV|CYL_OV)) { if(stat & CYL_OV) /* cylinder overflow */ { oc(cntl,CRESET); offset = (rdh(selch) - io->i_ma +2) & 0x00FFFF00; sn = tn = 0; if(++cn < NUMCYL) goto findit; } printf("MSM %s error: cyl=%d track=%d sect=%d er=%x ad=%x\n", func == READ ? "read" : "write", cn, tn, sn, stat, cntl); return(-1); } return(io->i_cc); } uddidle() { while (! (ss(curcntl) & IDLE) ) continue; }