static char SCCS_ID [] = "@(#)msm.c 1.3"; /* * MSM disk driver - 67MB and 256MB */ #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 msmaddr[4] = { 0xfc, 0xfd, 0xfe, 0xff }; char msmcntl = 0xfb; char msmselch = 0xf0; #else NORMAL char msmaddr[4] = { 0xec, 0xed, 0xee, 0xef }; char msmcntl = 0xeb; char msmselch = 0xf1; #endif NORMAL static int curcntl; /* controller address for msmidle */ #define NSECTORS 2 /* number of physical sectors per 512 bytes */ #define SECSHIFT 1 /* shift for NSECTORS */ #define NBPT 32 /* 512-byte blocks per track */ #define D67_NBPC (32*5) /* 512-byte blocks per cylinder - 67MB */ #define D256_NBPC (32*19) /* 512-byte blocks per cylinder - 256MB */ #define C13R_NBPC (32*1 ) /* 512-byte blocks per cylinder - 13MBR */ #define C13F_NBPC (32*1 ) /* 512-byte blocks per cylinder - 13MBF */ #define C40F_NBPC (32*3 ) /* 512-byte blocks per cylinder - 40MBF */ #define C67F_NBPC (32*5 ) /* 512-byte blocks per cylinder - 67MBF */ d67strategy(io, func) struct iob *io; { return msmstrategy (io, func, D67_NBPC,0); } d256strategy(io, func) struct iob *io; { return msmstrategy (io, func, D256_NBPC,0); } c13rstrategy(io, func) struct iob *io; { return msmstrategy (io, func, C13R_NBPC,0); } c13fstrategy(io, func) struct iob *io; { return msmstrategy (io, func, C13F_NBPC,0x10); } c40fstrategy(io, func) struct iob *io; { return msmstrategy (io, func, C40F_NBPC,0x10); } c67fstrategy(io, func) struct iob *io; { return msmstrategy (io, func, C67F_NBPC,0x10); } static msmstrategy(io, func, nbpc,headoffset) register struct iob *io; int headoffset; { register int drive, cntl, selch, stat; register int tn; /* track */ register int cn; /* cylinder */ register int sn; /* sector */ if ((drive = io->i_deva) == 0) drive = msmaddr[io->i_unit]; if ((cntl = io->i_cntl) == 0) cntl = msmcntl; if ((selch = io->i_selch) == 0) selch = msmselch; curcntl = cntl; cn = io->i_bn / nbpc; { register off_t bn; /* block number */ bn = io->i_bn % nbpc; tn = bn / NBPT; sn = (bn % NBPT) << SECSHIFT; } msmidle(); while (ss(drive) & ALTBSY) ; wh(drive, cn); msmidle(); oc(drive, SETCYL | DISARM) ; msmidle(); oc(drive, SEEK); msmidle(); 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); wdh(selch, &io->i_ma[io->i_cc - 1]); wh(drive, tn | headoffset ); oc(drive, SETHEAD); msmidle(); wd(cntl, sn); wh(cntl, ((tn | headoffset) <<10) | cn); wh(drive, tn | headoffset ); oc(drive, SETHEAD); msmidle(); if (func == READ) { oc(cntl, CREAD); oc(selch, READ_GO); } else { oc(cntl, CWRITE); oc(selch, GO); } while (ss(selch) & SELCHBSY) ; oc(selch, STOP); msmidle(); if ((stat=ss(cntl)) & (CNTL_UNRCV|CYL_OV)) { 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); } msmidle() { while (! (ss(curcntl) & IDLE) ) continue; }