1*41480Smckusick /* 2*41480Smckusick * Copyright (c) 1988 University of Utah. 3*41480Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 4*41480Smckusick * All rights reserved. 5*41480Smckusick * 6*41480Smckusick * This code is derived from software contributed to Berkeley by 7*41480Smckusick * the Systems Programming Group of the University of Utah Computer 8*41480Smckusick * Science Department. 9*41480Smckusick * 10*41480Smckusick * %sccs.include.redist.c% 11*41480Smckusick * 12*41480Smckusick * from: Utah $Hdr: rd.c 1.30 89/09/17$ 13*41480Smckusick * 14*41480Smckusick * @(#)rd.c 7.1 (Berkeley) 05/08/90 15*41480Smckusick */ 16*41480Smckusick 17*41480Smckusick /* 18*41480Smckusick * CS80/SS80 disk driver 19*41480Smckusick */ 20*41480Smckusick #include "rd.h" 21*41480Smckusick #if NRD > 0 22*41480Smckusick 23*41480Smckusick #include "param.h" 24*41480Smckusick #include "systm.h" 25*41480Smckusick #include "errno.h" 26*41480Smckusick #include "dkstat.h" 27*41480Smckusick #include "disklabel.h" 28*41480Smckusick #include "buf.h" 29*41480Smckusick #include "uio.h" 30*41480Smckusick 31*41480Smckusick #include "device.h" 32*41480Smckusick #include "rdreg.h" 33*41480Smckusick 34*41480Smckusick int rdinit(), rdstart(), rdgo(), rdintr(); 35*41480Smckusick struct driver rddriver = { 36*41480Smckusick rdinit, "rd", rdstart, rdgo, rdintr, 37*41480Smckusick }; 38*41480Smckusick 39*41480Smckusick struct rd_softc { 40*41480Smckusick struct hp_device *sc_hd; 41*41480Smckusick struct rd_iocmd sc_ioc; 42*41480Smckusick struct rd_rscmd sc_rsc; 43*41480Smckusick struct rd_stat sc_stat; 44*41480Smckusick struct rd_ssmcmd sc_ssmc; 45*41480Smckusick struct rd_srcmd sc_src; 46*41480Smckusick struct rd_clearcmd sc_clear; 47*41480Smckusick int sc_resid; 48*41480Smckusick char *sc_addr; 49*41480Smckusick struct rdinfo *sc_info; 50*41480Smckusick int sc_flags; 51*41480Smckusick short sc_type; 52*41480Smckusick short sc_punit; 53*41480Smckusick struct devqueue sc_dq; 54*41480Smckusick } rd_softc[NRD]; 55*41480Smckusick 56*41480Smckusick /* sc_flags values */ 57*41480Smckusick #define RDF_ALIVE 0x1 58*41480Smckusick #define RDF_SEEK 0x2 59*41480Smckusick #define RDF_SWAIT 0x4 60*41480Smckusick 61*41480Smckusick struct size { 62*41480Smckusick daddr_t nblocks; 63*41480Smckusick int cyloff; 64*41480Smckusick }; 65*41480Smckusick 66*41480Smckusick #ifdef DEBUG 67*41480Smckusick int rddebug = 0x80; 68*41480Smckusick #define RDB_FOLLOW 0x01 69*41480Smckusick #define RDB_STATUS 0x02 70*41480Smckusick #define RDB_IDENT 0x04 71*41480Smckusick #define RDB_IO 0x08 72*41480Smckusick #define RDB_ASYNC 0x10 73*41480Smckusick #define RDB_ERROR 0x80 74*41480Smckusick #define RDB_DUMP 0x80000000 75*41480Smckusick 76*41480Smckusick struct rdstats { 77*41480Smckusick long rdretries; 78*41480Smckusick long rdresets; 79*41480Smckusick long rdtimeouts; 80*41480Smckusick long rdpolltries; 81*41480Smckusick long rdpollwaits; 82*41480Smckusick } rdstats[NRD]; 83*41480Smckusick 84*41480Smckusick /* error message tables */ 85*41480Smckusick char *err_reject[] = { 86*41480Smckusick 0, 0, 87*41480Smckusick "channel parity error", /* 0x2000 */ 88*41480Smckusick 0, 0, 89*41480Smckusick "illegal opcode", /* 0x0400 */ 90*41480Smckusick "module addressing", /* 0x0200 */ 91*41480Smckusick "address bounds", /* 0x0100 */ 92*41480Smckusick "parameter bounds", /* 0x0080 */ 93*41480Smckusick "illegal parameter", /* 0x0040 */ 94*41480Smckusick "message sequence", /* 0x0020 */ 95*41480Smckusick 0, 96*41480Smckusick "message length", /* 0x0008 */ 97*41480Smckusick 0, 0, 0 98*41480Smckusick }; 99*41480Smckusick 100*41480Smckusick char *err_fault[] = { 101*41480Smckusick 0, 102*41480Smckusick "cross unit", /* 0x4000 */ 103*41480Smckusick 0, 104*41480Smckusick "controller fault", /* 0x1000 */ 105*41480Smckusick 0, 0, 106*41480Smckusick "unit fault", /* 0x0200 */ 107*41480Smckusick 0, 108*41480Smckusick "diagnostic result", /* 0x0080 */ 109*41480Smckusick 0, 110*41480Smckusick "operator release request", /* 0x0020 */ 111*41480Smckusick "diagnostic release request", /* 0x0010 */ 112*41480Smckusick "internal maintenance release request", /* 0x0008 */ 113*41480Smckusick 0, 114*41480Smckusick "power fail", /* 0x0002 */ 115*41480Smckusick "retransmit" /* 0x0001 */ 116*41480Smckusick }; 117*41480Smckusick 118*41480Smckusick char *err_access[] = { 119*41480Smckusick "illegal parallel operation", /* 0x8000 */ 120*41480Smckusick "uninitialized media", /* 0x4000 */ 121*41480Smckusick "no spares available", /* 0x2000 */ 122*41480Smckusick "not ready", /* 0x1000 */ 123*41480Smckusick "write protect", /* 0x0800 */ 124*41480Smckusick "no data found", /* 0x0400 */ 125*41480Smckusick 0, 0, 126*41480Smckusick "unrecoverable data overflow", /* 0x0080 */ 127*41480Smckusick "unrecoverable data", /* 0x0040 */ 128*41480Smckusick 0, 129*41480Smckusick "end of file", /* 0x0010 */ 130*41480Smckusick "end of volume", /* 0x0008 */ 131*41480Smckusick 0, 0, 0 132*41480Smckusick }; 133*41480Smckusick 134*41480Smckusick char *err_info[] = { 135*41480Smckusick "operator release request", /* 0x8000 */ 136*41480Smckusick "diagnostic release request", /* 0x4000 */ 137*41480Smckusick "internal maintenance release request", /* 0x2000 */ 138*41480Smckusick "media wear", /* 0x1000 */ 139*41480Smckusick "latency induced", /* 0x0800 */ 140*41480Smckusick 0, 0, 141*41480Smckusick "auto sparing invoked", /* 0x0100 */ 142*41480Smckusick 0, 143*41480Smckusick "recoverable data overflow", /* 0x0040 */ 144*41480Smckusick "marginal data", /* 0x0020 */ 145*41480Smckusick "recoverable data", /* 0x0010 */ 146*41480Smckusick 0, 147*41480Smckusick "maintenance track overflow", /* 0x0004 */ 148*41480Smckusick 0, 0 149*41480Smckusick }; 150*41480Smckusick #endif 151*41480Smckusick 152*41480Smckusick /* 153*41480Smckusick * CS/80 partitions. We reserve the first cylinder for a LIF 154*41480Smckusick * style boot directory (the 8k allowed in the BSD filesystem 155*41480Smckusick * is just way too small). This boot area is outside of all but 156*41480Smckusick * the C partition. This implies that you cannot use the C 157*41480Smckusick * partition on a bootable disk since the filesystem would overlay 158*41480Smckusick * the boot area. You must use the A partition. 159*41480Smckusick * 160*41480Smckusick * These maps support four basic layouts: 161*41480Smckusick * 162*41480Smckusick * A/B/G: This is the "traditional" setup for a bootable disk. 163*41480Smckusick * A is the root partition, B the swap, and G a user partition. 164*41480Smckusick * A/D/H: This is a setup for bootable systems requiring more swap 165*41480Smckusick * (e.g. those who use HPCL). It has A as the root, D as a 166*41480Smckusick * larger swap, and H as a smaller user partition. 167*41480Smckusick * A/D/E/F: Similar to A/D/H with E and F breaking H into two partitions. 168*41480Smckusick * E could be used for /usr and F for users. 169*41480Smckusick * C: This gives a single, non-bootable, large user filesystem. 170*41480Smckusick * Good for second drives on a machine (e.g. /usr/src). 171*41480Smckusick */ 172*41480Smckusick struct size rd7945A_sizes[8] = { 173*41480Smckusick RDSZ(15904), 1, /* A=cyl 1 thru 142 */ 174*41480Smckusick RDSZ(20160), 143, /* B=cyl 143 thru 322 */ 175*41480Smckusick RDSZ(108416), 0, /* C=cyl 0 thru 967 */ 176*41480Smckusick RDSZ(40320), 143, /* D=cyl 143 thru 502 */ 177*41480Smckusick RDSZ(0), 0, /* E=<undefined> */ 178*41480Smckusick RDSZ(0), 0, /* F=<undefined> */ 179*41480Smckusick RDSZ(72240), 323, /* G=cyl 323 thru 967 */ 180*41480Smckusick RDSZ(52080), 503, /* H=cyl 503 thru 967 */ 181*41480Smckusick }, rd9134D_sizes[8] = { 182*41480Smckusick RDSZ(15936), 1, /* A=cyl 1 thru 166 */ 183*41480Smckusick RDSZ(13056), 167, /* B=cyl 167 thru 302 */ 184*41480Smckusick RDSZ(29088), 0, /* C=cyl 0 thru 302 */ 185*41480Smckusick RDSZ(0), 0, /* D=<undefined> */ 186*41480Smckusick RDSZ(0), 0, /* E=<undefined> */ 187*41480Smckusick RDSZ(0), 0, /* F=<undefined> */ 188*41480Smckusick RDSZ(0), 0, /* G=<undefined> */ 189*41480Smckusick RDSZ(0), 0, /* H=<undefined> */ 190*41480Smckusick }, rd9122S_sizes[8] = { 191*41480Smckusick RDSZ(0), 0, /* A=<undefined> */ 192*41480Smckusick RDSZ(0), 0, /* B=<undefined> */ 193*41480Smckusick RDSZ(1232), 0, /* C=cyl 0 thru 76 */ 194*41480Smckusick RDSZ(0), 0, /* D=<undefined> */ 195*41480Smckusick RDSZ(0), 0, /* E=<undefined> */ 196*41480Smckusick RDSZ(0), 0, /* F=<undefined> */ 197*41480Smckusick RDSZ(0), 0, /* G=<undefined> */ 198*41480Smckusick RDSZ(0), 0, /* H=<undefined> */ 199*41480Smckusick }, rd7912P_sizes[8] = { 200*41480Smckusick RDSZ(15904), 0, /* A=cyl 1 thru 71 */ 201*41480Smckusick RDSZ(22400), 72, /* B=cyl 72 thru 171 */ 202*41480Smckusick RDSZ(128128), 0, /* C=cyl 0 thru 571 */ 203*41480Smckusick RDSZ(42560), 72, /* D=cyl 72 thru 261 */ 204*41480Smckusick RDSZ(0), 292, /* E=<undefined> */ 205*41480Smckusick RDSZ(0), 542, /* F=<undefined> */ 206*41480Smckusick RDSZ(89600), 172, /* G=cyl 221 thru 571 */ 207*41480Smckusick RDSZ(69440), 262, /* H=cyl 262 thru 571 */ 208*41480Smckusick }, rd7914P_sizes[8] = { 209*41480Smckusick RDSZ(15904), 1, /* A=cyl 1 thru 71 */ 210*41480Smckusick RDSZ(40320), 72, /* B=cyl 72 thru 251 */ 211*41480Smckusick RDSZ(258048), 0, /* C=cyl 0 thru 1151 */ 212*41480Smckusick RDSZ(64960), 72, /* D=cyl 72 thru 361 */ 213*41480Smckusick RDSZ(98560), 362, /* E=cyl 362 thru 801 */ 214*41480Smckusick RDSZ(78400), 802, /* F=cyl 802 thru 1151 */ 215*41480Smckusick RDSZ(201600), 252, /* G=cyl 221 thru 1151 */ 216*41480Smckusick RDSZ(176960), 362, /* H=cyl 362 thru 1151 */ 217*41480Smckusick }, rd7933H_sizes[8] = { 218*41480Smckusick RDSZ(16146), 1, /* A=cyl 1 thru 27 */ 219*41480Smckusick RDSZ(66976), 28, /* B=cyl 28 thru 139 */ 220*41480Smckusick RDSZ(789958), 0, /* C=cyl 0 thru 1320 */ 221*41480Smckusick RDSZ(16146), 140, /* D=cyl 140 thru 166 */ 222*41480Smckusick RDSZ(165646), 167, /* E=cyl 167 thru 443 */ 223*41480Smckusick RDSZ(165646), 444, /* F=cyl 444 thru 720 */ 224*41480Smckusick RDSZ(706238), 140, /* G=cyl 140 thru 1320 */ 225*41480Smckusick RDSZ(358800), 721, /* H=cyl 721 thru 1320 */ 226*41480Smckusick }, rd9134L_sizes[8] = { 227*41480Smckusick RDSZ(15920), 1, /* A=cyl 1 thru 199 */ 228*41480Smckusick RDSZ(20000), 200, /* B=cyl 200 thru 449 */ 229*41480Smckusick RDSZ(77840), 0, /* C=cyl 0 thru 972 */ 230*41480Smckusick RDSZ(32000), 200, /* D=cyl 200 thru 599 */ 231*41480Smckusick RDSZ(0), 0, /* E=<undefined> */ 232*41480Smckusick RDSZ(0), 0, /* F=<undefined> */ 233*41480Smckusick RDSZ(41840), 450, /* G=cyl 450 thru 972 */ 234*41480Smckusick RDSZ(29840), 600, /* H=cyl 600 thru 972 */ 235*41480Smckusick }, rd7957A_sizes[8] = { 236*41480Smckusick RDSZ(16016), 1, /* A=cyl 1 thru 104 */ 237*41480Smckusick RDSZ(24640), 105, /* B=cyl 105 thru 264 */ 238*41480Smckusick RDSZ(159544), 0, /* C=cyl 0 thru 1035 */ 239*41480Smckusick RDSZ(42350), 105, /* D=cyl 105 thru 379 */ 240*41480Smckusick RDSZ(54824), 380, /* E=cyl 380 thru 735 */ 241*41480Smckusick RDSZ(46200), 736, /* F=cyl 736 thru 1035 */ 242*41480Smckusick RDSZ(118734), 265, /* G=cyl 265 thru 1035 */ 243*41480Smckusick RDSZ(101024), 380, /* H=cyl 380 thru 1035 */ 244*41480Smckusick }, rd7958A_sizes[8] = { 245*41480Smckusick RDSZ(16128), 1, /* A=cyl 1 thru 64 */ 246*41480Smckusick RDSZ(32256), 65, /* B=cyl 65 thru 192 */ 247*41480Smckusick RDSZ(255276), 0, /* C=cyl 0 thru 1012 */ 248*41480Smckusick RDSZ(48384), 65, /* D=cyl 65 thru 256 */ 249*41480Smckusick RDSZ(100800), 257, /* E=cyl 257 thru 656 */ 250*41480Smckusick RDSZ(89712), 657, /* F=cyl 657 thru 1012 */ 251*41480Smckusick RDSZ(206640), 193, /* G=cyl 193 thru 1012 */ 252*41480Smckusick RDSZ(190512), 257, /* H=cyl 257 thru 1012 */ 253*41480Smckusick }, rd7957B_sizes[8] = { 254*41480Smckusick RDSZ(16002), 1, /* A=cyl 1 thru 127 */ 255*41480Smckusick RDSZ(32760), 128, /* B=cyl 128 thru 387 */ 256*41480Smckusick RDSZ(159894), 0, /* C=cyl 0 thru 1268 */ 257*41480Smckusick RDSZ(49140), 128, /* D=cyl 128 thru 517 */ 258*41480Smckusick RDSZ(50400), 518, /* E=cyl 518 thru 917 */ 259*41480Smckusick RDSZ(44226), 918, /* F=cyl 918 thru 1268 */ 260*41480Smckusick RDSZ(111006), 388, /* G=cyl 388 thru 1268 */ 261*41480Smckusick RDSZ(94626), 518, /* H=cyl 518 thru 1268 */ 262*41480Smckusick }, rd7958B_sizes[8] = { 263*41480Smckusick RDSZ(16254), 1, /* A=cyl 1 thru 43 */ 264*41480Smckusick RDSZ(32886), 44, /* B=cyl 44 thru 130 */ 265*41480Smckusick RDSZ(297108), 0, /* C=cyl 0 thru 785 */ 266*41480Smckusick RDSZ(49140), 44, /* D=cyl 44 thru 173 */ 267*41480Smckusick RDSZ(121716), 174, /* E=cyl 174 thru 495 */ 268*41480Smckusick RDSZ(109620), 496, /* F=cyl 496 thru 785 */ 269*41480Smckusick RDSZ(247590), 131, /* G=cyl 131 thru 785 */ 270*41480Smckusick RDSZ(231336), 174, /* H=cyl 174 thru 785 */ 271*41480Smckusick }, rd7959B_sizes[8] = { 272*41480Smckusick RDSZ(16254), 1, /* A=cyl 1 thru 43 */ 273*41480Smckusick RDSZ(49140), 44, /* B=cyl 44 thru 173 */ 274*41480Smckusick RDSZ(594216), 0, /* C=cyl 0 thru 1571 */ 275*41480Smckusick RDSZ(65772), 44, /* D=cyl 44 thru 217 */ 276*41480Smckusick RDSZ(303912), 218, /* E=cyl 218 thru 1021 */ 277*41480Smckusick RDSZ(207900), 1022, /* F=cyl 1022 thru 1571 */ 278*41480Smckusick RDSZ(528444), 174, /* G=cyl 174 thru 1571 */ 279*41480Smckusick RDSZ(511812), 218, /* H=cyl 218 thru 1571 */ 280*41480Smckusick 281*41480Smckusick #if DEV_BSIZE == 512 282*41480Smckusick /* 283*41480Smckusick * These values would not work for 1k, 284*41480Smckusick * since the number of cylinders would be different. 285*41480Smckusick */ 286*41480Smckusick }, rd7936H_sizes[8] = { 287*41480Smckusick RDSZ(16359), 1, /* A=cyl 1 thru 19 */ 288*41480Smckusick RDSZ(67158), 20, /* B=cyl 20 thru 97 */ 289*41480Smckusick RDSZ(600978), 0, /* C=cyl 0 thru 697 */ 290*41480Smckusick RDSZ(16359), 98, /* D=cyl 98 thru 116 */ 291*41480Smckusick RDSZ(120540), 117, /* E=cyl 117 thru 256 */ 292*41480Smckusick RDSZ(120540), 256, /* F=cyl 256 thru 396 */ 293*41480Smckusick RDSZ(516600), 98, /* G=cyl 98 thru 697 */ 294*41480Smckusick RDSZ(259161), 397, /* H=cyl 397 thru 697 */ 295*41480Smckusick }, rd7937H_sizes[8] = { 296*41480Smckusick #ifdef UTAH 297*41480Smckusick RDSZ(15990), 1, /* A=cyl 1 thru 10 */ 298*41480Smckusick RDSZ(67158), 11, /* B=cyl 11 thru 52 */ 299*41480Smckusick RDSZ(1116102), 0, /* C=cyl 0 thru 697 */ 300*41480Smckusick RDSZ(124722), 53, /* D=cyl 53 thru 130 */ 301*41480Smckusick RDSZ(163098), 131, /* E=cyl 131 thru 232 */ 302*41480Smckusick RDSZ(287820), 233, /* F=cyl 233 thru 412 */ 303*41480Smckusick RDSZ(1031355), 53, /* G=cyl 53 thru 697 */ 304*41480Smckusick RDSZ(455715), 413, /* H=cyl 413 thru 697 */ 305*41480Smckusick #else 306*41480Smckusick RDSZ(15990), 1, /* A=cyl 1 thru 10 */ 307*41480Smckusick RDSZ(67158), 11, /* B=cyl 11 thru 52 */ 308*41480Smckusick RDSZ(1116102), 0, /* C=cyl 0 thru 697 */ 309*41480Smckusick RDSZ(15990), 53, /* D=cyl 53 thru 62 */ 310*41480Smckusick RDSZ(246246), 63, /* E=cyl 63 thru 216 */ 311*41480Smckusick RDSZ(246246), 217, /* F=cyl 217 thru 370 */ 312*41480Smckusick RDSZ(1031355), 53, /* G=cyl 53 thru 697 */ 313*41480Smckusick RDSZ(522873), 371, /* H=cyl 371 thru 697 */ 314*41480Smckusick #endif 315*41480Smckusick #endif 316*41480Smckusick }; 317*41480Smckusick 318*41480Smckusick struct rdinfo { 319*41480Smckusick int nbpt; /* DEV_BSIZE blocks per track */ 320*41480Smckusick int ntpc; /* tracks per cylinder */ 321*41480Smckusick int nbpc; /* blocks per cylinder */ 322*41480Smckusick struct size *sizes; /* default partition info (if no disklabel) */ 323*41480Smckusick short hwid; /* 2 byte HW id */ 324*41480Smckusick short maxunum; /* maximum allowed unit number */ 325*41480Smckusick char *desc; /* drive type description */ 326*41480Smckusick }; 327*41480Smckusick 328*41480Smckusick struct rdinfo rdinfo[] = { 329*41480Smckusick NRD7945ABPT, NRD7945ATRK, NRD7945ABPT * NRD7945ATRK, 330*41480Smckusick rd7945A_sizes, RD7946AID, 0, "7945A", 331*41480Smckusick NRD9134DBPT, NRD9134DTRK, NRD9134DBPT * NRD9134DTRK, 332*41480Smckusick rd9134D_sizes, RD9134DID, 1, "9134D", 333*41480Smckusick NRD9122SBPT, NRD9122STRK, NRD9122SBPT * NRD9122STRK, 334*41480Smckusick rd9122S_sizes, RD9134LID, 1, "9122S", 335*41480Smckusick NRD7912PBPT, NRD7912PTRK, NRD7912PBPT * NRD7912PTRK, 336*41480Smckusick rd7912P_sizes, RD7912PID, 0, "7912P", 337*41480Smckusick NRD7914PBPT, NRD7914PTRK, NRD7914PBPT * NRD7914PTRK, 338*41480Smckusick rd7914P_sizes, RD7914PID, 0, "7914P", 339*41480Smckusick NRD7958ABPT, NRD7958ATRK, NRD7958ABPT * NRD7958ATRK, 340*41480Smckusick rd7958A_sizes, RD7958AID, 0, "7958A", 341*41480Smckusick NRD7957ABPT, NRD7957ATRK, NRD7957ABPT * NRD7957ATRK, 342*41480Smckusick rd7957A_sizes, RD7957AID, 0, "7957A", 343*41480Smckusick NRD7933HBPT, NRD7933HTRK, NRD7933HBPT * NRD7933HTRK, 344*41480Smckusick rd7933H_sizes, RD7933HID, 0, "7933H", 345*41480Smckusick NRD9134LBPT, NRD9134LTRK, NRD9134LBPT * NRD9134LTRK, 346*41480Smckusick rd9134L_sizes, RD9134LID, 1, "9134L", 347*41480Smckusick NRD7936HBPT, NRD7936HTRK, NRD7936HBPT * NRD7936HTRK, 348*41480Smckusick rd7936H_sizes, RD7936HID, 0, "7936H", 349*41480Smckusick NRD7937HBPT, NRD7937HTRK, NRD7937HBPT * NRD7937HTRK, 350*41480Smckusick rd7937H_sizes, RD7937HID, 0, "7937H", 351*41480Smckusick NRD7914PBPT, NRD7914PTRK, NRD7914PBPT * NRD7914PTRK, 352*41480Smckusick rd7914P_sizes, RD7914CTID, 0, "7914CT", 353*41480Smckusick NRD7945ABPT, NRD7945ATRK, NRD7945ABPT * NRD7945ATRK, 354*41480Smckusick rd7945A_sizes, RD7946AID, 0, "7946A", 355*41480Smckusick NRD9122SBPT, NRD9122STRK, NRD9122SBPT * NRD9122STRK, 356*41480Smckusick rd9122S_sizes, RD9134LID, 1, "9122D", 357*41480Smckusick NRD7957BBPT, NRD7957BTRK, NRD7957BBPT * NRD7957BTRK, 358*41480Smckusick rd7957B_sizes, RD7957BID, 0, "7957B", 359*41480Smckusick NRD7958BBPT, NRD7958BTRK, NRD7958BBPT * NRD7958BTRK, 360*41480Smckusick rd7958B_sizes, RD7958BID, 0, "7958B", 361*41480Smckusick NRD7959BBPT, NRD7959BTRK, NRD7959BBPT * NRD7959BTRK, 362*41480Smckusick rd7959B_sizes, RD7959BID, 0, "7959B", 363*41480Smckusick }; 364*41480Smckusick int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]); 365*41480Smckusick 366*41480Smckusick struct buf rdtab[NRD]; 367*41480Smckusick struct buf rdbuf[NRD]; 368*41480Smckusick 369*41480Smckusick #define rdunit(x) ((minor(x) >> 3) & 0xf) 370*41480Smckusick #define rdpart(x) (minor(x) & 0x7) 371*41480Smckusick #define rdpunit(x) ((x) & 7) 372*41480Smckusick #define b_cylin b_resid 373*41480Smckusick #define RDRETRY 5 374*41480Smckusick #define RDWAITC 1 /* min time for timeout in seconds */ 375*41480Smckusick 376*41480Smckusick rdinit(hd) 377*41480Smckusick register struct hp_device *hd; 378*41480Smckusick { 379*41480Smckusick register struct rd_softc *rs = &rd_softc[hd->hp_unit]; 380*41480Smckusick 381*41480Smckusick rs->sc_hd = hd; 382*41480Smckusick rs->sc_punit = rdpunit(hd->hp_flags); 383*41480Smckusick rs->sc_type = rdident(rs, hd); 384*41480Smckusick if (rs->sc_type < 0) 385*41480Smckusick return(0); 386*41480Smckusick rs->sc_dq.dq_ctlr = hd->hp_ctlr; 387*41480Smckusick rs->sc_dq.dq_unit = hd->hp_unit; 388*41480Smckusick rs->sc_dq.dq_slave = hd->hp_slave; 389*41480Smckusick rs->sc_dq.dq_driver = &rddriver; 390*41480Smckusick rs->sc_info = &rdinfo[rs->sc_type]; 391*41480Smckusick rs->sc_flags = RDF_ALIVE; 392*41480Smckusick return(1); 393*41480Smckusick } 394*41480Smckusick 395*41480Smckusick rdident(rs, hd) 396*41480Smckusick struct rd_softc *rs; 397*41480Smckusick struct hp_device *hd; 398*41480Smckusick { 399*41480Smckusick struct rd_describe desc; 400*41480Smckusick u_char stat, cmd[3]; 401*41480Smckusick int unit, lunit; 402*41480Smckusick char name[7]; 403*41480Smckusick register int ctlr, slave, id, i; 404*41480Smckusick 405*41480Smckusick ctlr = hd->hp_ctlr; 406*41480Smckusick slave = hd->hp_slave; 407*41480Smckusick unit = rs->sc_punit; 408*41480Smckusick lunit = hd->hp_unit; 409*41480Smckusick 410*41480Smckusick /* 411*41480Smckusick * Grab device id and make sure: 412*41480Smckusick * 1. It is a CS80 device. 413*41480Smckusick * 2. It is one of the types we support. 414*41480Smckusick * 3. If it is a 7946, we are accessing the disk unit (0) 415*41480Smckusick */ 416*41480Smckusick id = hpibid(ctlr, slave); 417*41480Smckusick if ((id & 0x200) == 0) 418*41480Smckusick return(-1); 419*41480Smckusick for (i = 0; i < nrdinfo; i++) 420*41480Smckusick if (id == rdinfo[i].hwid) 421*41480Smckusick break; 422*41480Smckusick if (i == nrdinfo || unit > rdinfo[i].maxunum) 423*41480Smckusick return(-1); 424*41480Smckusick id = i; 425*41480Smckusick 426*41480Smckusick /* 427*41480Smckusick * Reset drive and collect device description. 428*41480Smckusick * Don't really use the description info right now but 429*41480Smckusick * might come in handy in the future (for disk labels). 430*41480Smckusick */ 431*41480Smckusick rdreset(rs, hd); 432*41480Smckusick cmd[0] = C_SUNIT(unit); 433*41480Smckusick cmd[1] = C_SVOL(0); 434*41480Smckusick cmd[2] = C_DESC; 435*41480Smckusick hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd)); 436*41480Smckusick hpibrecv(ctlr, slave, C_EXEC, &desc, 37); 437*41480Smckusick hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); 438*41480Smckusick bzero(name, sizeof(name)); 439*41480Smckusick if (!stat) { 440*41480Smckusick register int n = desc.d_name; 441*41480Smckusick for (i = 5; i >= 0; i--) { 442*41480Smckusick name[i] = (n & 0xf) + '0'; 443*41480Smckusick n >>= 4; 444*41480Smckusick } 445*41480Smckusick } 446*41480Smckusick #ifdef DEBUG 447*41480Smckusick if (rddebug & RDB_IDENT) { 448*41480Smckusick printf("rd%d: name: %x ('%s')\n", 449*41480Smckusick lunit, desc.d_name, name); 450*41480Smckusick printf(" iuw %x, maxxfr %d, ctype %d\n", 451*41480Smckusick desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype); 452*41480Smckusick printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n", 453*41480Smckusick desc.d_utype, desc.d_sectsize, 454*41480Smckusick desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime); 455*41480Smckusick printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n", 456*41480Smckusick desc.d_uavexfr, desc.d_retry, desc.d_access, 457*41480Smckusick desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte); 458*41480Smckusick printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n", 459*41480Smckusick desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect, 460*41480Smckusick desc.d_maxvsectl, desc.d_interleave); 461*41480Smckusick } 462*41480Smckusick #endif 463*41480Smckusick /* 464*41480Smckusick * Take care of a couple of anomolies: 465*41480Smckusick * 1. 7945A and 7946A both return same HW id 466*41480Smckusick * 2. 9122S and 9134D both return same HW id 467*41480Smckusick * 3. 9122D and 9134L both return same HW id 468*41480Smckusick */ 469*41480Smckusick switch (rdinfo[id].hwid) { 470*41480Smckusick case RD7946AID: 471*41480Smckusick if (bcmp(name, "079450", 6) == 0) 472*41480Smckusick id = RD7945A; 473*41480Smckusick else 474*41480Smckusick id = RD7946A; 475*41480Smckusick break; 476*41480Smckusick 477*41480Smckusick case RD9134LID: 478*41480Smckusick if (bcmp(name, "091340", 6) == 0) 479*41480Smckusick id = RD9134L; 480*41480Smckusick else 481*41480Smckusick id = RD9122D; 482*41480Smckusick break; 483*41480Smckusick 484*41480Smckusick case RD9134DID: 485*41480Smckusick if (bcmp(name, "091220", 6) == 0) 486*41480Smckusick id = RD9122S; 487*41480Smckusick else 488*41480Smckusick id = RD9134D; 489*41480Smckusick break; 490*41480Smckusick } 491*41480Smckusick printf("rd%d: %s\n", lunit, rdinfo[id].desc); 492*41480Smckusick return(id); 493*41480Smckusick } 494*41480Smckusick 495*41480Smckusick rdreset(rs, hd) 496*41480Smckusick register struct rd_softc *rs; 497*41480Smckusick register struct hp_device *hd; 498*41480Smckusick { 499*41480Smckusick u_char stat; 500*41480Smckusick 501*41480Smckusick rs->sc_clear.c_unit = C_SUNIT(rs->sc_punit); 502*41480Smckusick rs->sc_clear.c_cmd = C_CLEAR; 503*41480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &rs->sc_clear, 504*41480Smckusick sizeof(rs->sc_clear)); 505*41480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 506*41480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 507*41480Smckusick rs->sc_src.c_unit = C_SUNIT(RDCTLR); 508*41480Smckusick rs->sc_src.c_nop = C_NOP; 509*41480Smckusick rs->sc_src.c_cmd = C_SREL; 510*41480Smckusick rs->sc_src.c_param = C_REL; 511*41480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_src, 512*41480Smckusick sizeof(rs->sc_src)); 513*41480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 514*41480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 515*41480Smckusick rs->sc_ssmc.c_unit = C_SUNIT(rs->sc_punit); 516*41480Smckusick rs->sc_ssmc.c_cmd = C_SSM; 517*41480Smckusick rs->sc_ssmc.c_refm = REF_MASK; 518*41480Smckusick rs->sc_ssmc.c_fefm = FEF_MASK; 519*41480Smckusick rs->sc_ssmc.c_aefm = AEF_MASK; 520*41480Smckusick rs->sc_ssmc.c_iefm = IEF_MASK; 521*41480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_ssmc, 522*41480Smckusick sizeof(rs->sc_ssmc)); 523*41480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 524*41480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 525*41480Smckusick #ifdef DEBUG 526*41480Smckusick rdstats[hd->hp_unit].rdresets++; 527*41480Smckusick #endif 528*41480Smckusick } 529*41480Smckusick 530*41480Smckusick /*ARGSUSED*/ 531*41480Smckusick rdopen(dev, flags) 532*41480Smckusick dev_t dev; 533*41480Smckusick { 534*41480Smckusick register int unit = rdunit(dev); 535*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 536*41480Smckusick 537*41480Smckusick if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0) 538*41480Smckusick return(ENXIO); 539*41480Smckusick if (rs->sc_hd->hp_dk >= 0) 540*41480Smckusick dk_wpms[rs->sc_hd->hp_dk] = 60 * rs->sc_info->nbpt * DEV_BSIZE / 2; 541*41480Smckusick return(0); 542*41480Smckusick } 543*41480Smckusick 544*41480Smckusick rdstrategy(bp) 545*41480Smckusick register struct buf *bp; 546*41480Smckusick { 547*41480Smckusick register int part = rdpart(bp->b_dev); 548*41480Smckusick register int unit = rdunit(bp->b_dev); 549*41480Smckusick register int bn, sz; 550*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 551*41480Smckusick register struct buf *dp = &rdtab[unit]; 552*41480Smckusick int s; 553*41480Smckusick 554*41480Smckusick #ifdef DEBUG 555*41480Smckusick if (rddebug & RDB_FOLLOW) 556*41480Smckusick printf("rdstrategy(%x): dev %x, bn %x, bcount %x, %c\n", 557*41480Smckusick bp, bp->b_dev, bp->b_blkno, bp->b_bcount, 558*41480Smckusick (bp->b_flags & B_READ) ? 'R' : 'W'); 559*41480Smckusick #endif 560*41480Smckusick bn = bp->b_blkno; 561*41480Smckusick sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT; 562*41480Smckusick if (bn < 0 || bn + sz > rs->sc_info->sizes[part].nblocks) { 563*41480Smckusick if (bn == rs->sc_info->sizes[part].nblocks) { 564*41480Smckusick bp->b_resid = bp->b_bcount; 565*41480Smckusick goto done; 566*41480Smckusick } 567*41480Smckusick bp->b_error = EINVAL; 568*41480Smckusick goto bad; 569*41480Smckusick } 570*41480Smckusick bp->b_cylin = bn / rs->sc_info->nbpc + rs->sc_info->sizes[part].cyloff; 571*41480Smckusick s = splbio(); 572*41480Smckusick disksort(dp, bp); 573*41480Smckusick if (dp->b_active == 0) { 574*41480Smckusick dp->b_active = 1; 575*41480Smckusick rdustart(unit); 576*41480Smckusick } 577*41480Smckusick splx(s); 578*41480Smckusick return; 579*41480Smckusick bad: 580*41480Smckusick bp->b_flags |= B_ERROR; 581*41480Smckusick done: 582*41480Smckusick biodone(bp); 583*41480Smckusick } 584*41480Smckusick 585*41480Smckusick /* 586*41480Smckusick * Called from timeout() when handling maintenance releases 587*41480Smckusick */ 588*41480Smckusick rdrestart(unit) 589*41480Smckusick int unit; 590*41480Smckusick { 591*41480Smckusick int s = splbio(); 592*41480Smckusick rdustart(unit); 593*41480Smckusick splx(s); 594*41480Smckusick } 595*41480Smckusick 596*41480Smckusick rdustart(unit) 597*41480Smckusick register int unit; 598*41480Smckusick { 599*41480Smckusick register struct buf *bp; 600*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 601*41480Smckusick 602*41480Smckusick bp = rdtab[unit].b_actf; 603*41480Smckusick rs->sc_addr = bp->b_un.b_addr; 604*41480Smckusick rs->sc_resid = bp->b_bcount; 605*41480Smckusick if (hpibreq(&rs->sc_dq)) 606*41480Smckusick rdstart(unit); 607*41480Smckusick } 608*41480Smckusick 609*41480Smckusick rdstart(unit) 610*41480Smckusick register int unit; 611*41480Smckusick { 612*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 613*41480Smckusick register struct buf *bp = rdtab[unit].b_actf; 614*41480Smckusick register struct hp_device *hp = rs->sc_hd; 615*41480Smckusick register int part; 616*41480Smckusick 617*41480Smckusick again: 618*41480Smckusick #ifdef DEBUG 619*41480Smckusick if (rddebug & RDB_FOLLOW) 620*41480Smckusick printf("rdstart(%d): bp %x, %c\n", unit, bp, 621*41480Smckusick (bp->b_flags & B_READ) ? 'R' : 'W'); 622*41480Smckusick #endif 623*41480Smckusick part = rdpart(bp->b_dev); 624*41480Smckusick rs->sc_flags |= RDF_SEEK; 625*41480Smckusick rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit); 626*41480Smckusick rs->sc_ioc.c_volume = C_SVOL(0); 627*41480Smckusick rs->sc_ioc.c_saddr = C_SADDR; 628*41480Smckusick rs->sc_ioc.c_hiaddr = 0; 629*41480Smckusick rs->sc_ioc.c_addr = RDBTOS(bp->b_blkno + rs->sc_info->nbpc * 630*41480Smckusick rs->sc_info->sizes[part].cyloff); 631*41480Smckusick rs->sc_ioc.c_nop2 = C_NOP; 632*41480Smckusick rs->sc_ioc.c_slen = C_SLEN; 633*41480Smckusick rs->sc_ioc.c_len = rs->sc_resid; 634*41480Smckusick rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE; 635*41480Smckusick #ifdef DEBUG 636*41480Smckusick if (rddebug & RDB_IO) 637*41480Smckusick printf("rdstart: hpibsend(%x, %x, %x, %x, %x)\n", 638*41480Smckusick hp->hp_ctlr, hp->hp_slave, C_CMD, 639*41480Smckusick &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2); 640*41480Smckusick #endif 641*41480Smckusick if (hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, &rs->sc_ioc.c_unit, 642*41480Smckusick sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) { 643*41480Smckusick if (hp->hp_dk >= 0) { 644*41480Smckusick dk_busy |= 1 << hp->hp_dk; 645*41480Smckusick dk_seek[hp->hp_dk]++; 646*41480Smckusick } 647*41480Smckusick #ifdef DEBUG 648*41480Smckusick if (rddebug & RDB_IO) 649*41480Smckusick printf("rdstart: hpibawait(%x)\n", hp->hp_ctlr); 650*41480Smckusick #endif 651*41480Smckusick hpibawait(hp->hp_ctlr); 652*41480Smckusick return; 653*41480Smckusick } 654*41480Smckusick /* 655*41480Smckusick * Experience has shown that the hpibwait in this hpibsend will 656*41480Smckusick * occasionally timeout. It appears to occur mostly on old 7914 657*41480Smckusick * drives with full maintenance tracks. We should probably 658*41480Smckusick * integrate this with the backoff code in rderror. 659*41480Smckusick */ 660*41480Smckusick #ifdef DEBUG 661*41480Smckusick if (rddebug & RDB_ERROR) 662*41480Smckusick printf("rd%d: rdstart: cmd %x adr %d blk %d len %d ecnt %d\n", 663*41480Smckusick unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr, 664*41480Smckusick bp->b_blkno, rs->sc_resid, rdtab[unit].b_errcnt); 665*41480Smckusick rdstats[unit].rdretries++; 666*41480Smckusick #endif 667*41480Smckusick rs->sc_flags &= ~RDF_SEEK; 668*41480Smckusick rdreset(rs, hp); 669*41480Smckusick if (rdtab[unit].b_errcnt++ < RDRETRY) 670*41480Smckusick goto again; 671*41480Smckusick printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n", 672*41480Smckusick unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr, 673*41480Smckusick bp->b_blkno, rs->sc_resid); 674*41480Smckusick rdtab[unit].b_errcnt = 0; 675*41480Smckusick rdtab[unit].b_actf = bp->b_actf; 676*41480Smckusick bp->b_flags |= B_ERROR; 677*41480Smckusick bp->b_error = EIO; 678*41480Smckusick bp->b_resid = 0; 679*41480Smckusick biodone(bp); 680*41480Smckusick hpibfree(&rs->sc_dq); 681*41480Smckusick bp = rdtab[unit].b_actf; 682*41480Smckusick if (bp == NULL) { 683*41480Smckusick rdtab[unit].b_active = 0; 684*41480Smckusick return; 685*41480Smckusick } 686*41480Smckusick rs->sc_addr = bp->b_un.b_addr; 687*41480Smckusick rs->sc_resid = bp->b_bcount; 688*41480Smckusick if (hpibreq(&rs->sc_dq)) 689*41480Smckusick goto again; 690*41480Smckusick } 691*41480Smckusick 692*41480Smckusick rdgo(unit) 693*41480Smckusick register int unit; 694*41480Smckusick { 695*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 696*41480Smckusick register struct hp_device *hp = rs->sc_hd; 697*41480Smckusick struct buf *bp = rdtab[unit].b_actf; 698*41480Smckusick 699*41480Smckusick if (hp->hp_dk >= 0) { 700*41480Smckusick dk_busy |= 1 << hp->hp_dk; 701*41480Smckusick dk_xfer[hp->hp_dk]++; 702*41480Smckusick dk_wds[hp->hp_dk] += rs->sc_resid >> 6; 703*41480Smckusick } 704*41480Smckusick hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC, 705*41480Smckusick rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ); 706*41480Smckusick } 707*41480Smckusick 708*41480Smckusick rdintr(unit) 709*41480Smckusick register int unit; 710*41480Smckusick { 711*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 712*41480Smckusick register struct buf *bp = rdtab[unit].b_actf; 713*41480Smckusick register struct hp_device *hp = rs->sc_hd; 714*41480Smckusick u_char stat = 13; /* in case hpibrecv fails */ 715*41480Smckusick int restart; 716*41480Smckusick 717*41480Smckusick #ifdef DEBUG 718*41480Smckusick if (rddebug & RDB_FOLLOW) 719*41480Smckusick printf("rdintr(%d): bp %x, %c, flags %x\n", unit, bp, 720*41480Smckusick (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags); 721*41480Smckusick if (bp == NULL) { 722*41480Smckusick printf("rd%d: bp == NULL\n", unit); 723*41480Smckusick return; 724*41480Smckusick } 725*41480Smckusick #endif 726*41480Smckusick if (hp->hp_dk >= 0) 727*41480Smckusick dk_busy &= ~(1 << hp->hp_dk); 728*41480Smckusick if (rs->sc_flags & RDF_SEEK) { 729*41480Smckusick rs->sc_flags &= ~RDF_SEEK; 730*41480Smckusick if (hpibustart(hp->hp_ctlr)) 731*41480Smckusick rdgo(unit); 732*41480Smckusick return; 733*41480Smckusick } 734*41480Smckusick if ((rs->sc_flags & RDF_SWAIT) == 0) { 735*41480Smckusick #ifdef DEBUG 736*41480Smckusick rdstats[unit].rdpolltries++; 737*41480Smckusick #endif 738*41480Smckusick if (hpibpptest(hp->hp_ctlr, hp->hp_slave) == 0) { 739*41480Smckusick #ifdef DEBUG 740*41480Smckusick rdstats[unit].rdpollwaits++; 741*41480Smckusick #endif 742*41480Smckusick if (hp->hp_dk >= 0) 743*41480Smckusick dk_busy |= 1 << hp->hp_dk; 744*41480Smckusick rs->sc_flags |= RDF_SWAIT; 745*41480Smckusick hpibawait(hp->hp_ctlr); 746*41480Smckusick return; 747*41480Smckusick } 748*41480Smckusick } else 749*41480Smckusick rs->sc_flags &= ~RDF_SWAIT; 750*41480Smckusick if (!hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1) || stat) { 751*41480Smckusick #ifdef DEBUG 752*41480Smckusick if (rddebug & RDB_ERROR) 753*41480Smckusick printf("rdintr: recv failed or bad stat %d\n", stat); 754*41480Smckusick #endif 755*41480Smckusick restart = rderror(unit); 756*41480Smckusick #ifdef DEBUG 757*41480Smckusick rdstats[unit].rdretries++; 758*41480Smckusick #endif 759*41480Smckusick if (rdtab[unit].b_errcnt++ < RDRETRY) { 760*41480Smckusick if (restart) 761*41480Smckusick rdstart(unit); 762*41480Smckusick return; 763*41480Smckusick } 764*41480Smckusick bp->b_flags |= B_ERROR; 765*41480Smckusick bp->b_error = EIO; 766*41480Smckusick } 767*41480Smckusick rdtab[unit].b_errcnt = 0; 768*41480Smckusick rdtab[unit].b_actf = bp->b_actf; 769*41480Smckusick bp->b_resid = 0; 770*41480Smckusick biodone(bp); 771*41480Smckusick hpibfree(&rs->sc_dq); 772*41480Smckusick if (rdtab[unit].b_actf) 773*41480Smckusick rdustart(unit); 774*41480Smckusick else 775*41480Smckusick rdtab[unit].b_active = 0; 776*41480Smckusick } 777*41480Smckusick 778*41480Smckusick rdstatus(rs) 779*41480Smckusick register struct rd_softc *rs; 780*41480Smckusick { 781*41480Smckusick register int c, s; 782*41480Smckusick u_char stat; 783*41480Smckusick int rv; 784*41480Smckusick 785*41480Smckusick c = rs->sc_hd->hp_ctlr; 786*41480Smckusick s = rs->sc_hd->hp_slave; 787*41480Smckusick rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit); 788*41480Smckusick rs->sc_rsc.c_sram = C_SRAM; 789*41480Smckusick rs->sc_rsc.c_ram = C_RAM; 790*41480Smckusick rs->sc_rsc.c_cmd = C_STATUS; 791*41480Smckusick bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat)); 792*41480Smckusick rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc)); 793*41480Smckusick if (rv != sizeof(rs->sc_rsc)) { 794*41480Smckusick #ifdef DEBUG 795*41480Smckusick if (rddebug & RDB_STATUS) 796*41480Smckusick printf("rdstatus: send C_CMD failed %d != %d\n", 797*41480Smckusick rv, sizeof(rs->sc_rsc)); 798*41480Smckusick #endif 799*41480Smckusick return(1); 800*41480Smckusick } 801*41480Smckusick rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat)); 802*41480Smckusick if (rv != sizeof(rs->sc_stat)) { 803*41480Smckusick #ifdef DEBUG 804*41480Smckusick if (rddebug & RDB_STATUS) 805*41480Smckusick printf("rdstatus: send C_EXEC failed %d != %d\n", 806*41480Smckusick rv, sizeof(rs->sc_stat)); 807*41480Smckusick #endif 808*41480Smckusick return(1); 809*41480Smckusick } 810*41480Smckusick rv = hpibrecv(c, s, C_QSTAT, &stat, 1); 811*41480Smckusick if (rv != 1 || stat) { 812*41480Smckusick #ifdef DEBUG 813*41480Smckusick if (rddebug & RDB_STATUS) 814*41480Smckusick printf("rdstatus: recv failed %d or bad stat %d\n", 815*41480Smckusick rv, stat); 816*41480Smckusick #endif 817*41480Smckusick return(1); 818*41480Smckusick } 819*41480Smckusick return(0); 820*41480Smckusick } 821*41480Smckusick 822*41480Smckusick /* 823*41480Smckusick * Deal with errors. 824*41480Smckusick * Returns 1 if request should be restarted, 825*41480Smckusick * 0 if we should just quietly give up. 826*41480Smckusick */ 827*41480Smckusick rderror(unit) 828*41480Smckusick int unit; 829*41480Smckusick { 830*41480Smckusick struct rd_softc *rs = &rd_softc[unit]; 831*41480Smckusick register struct rd_stat *sp; 832*41480Smckusick struct buf *bp; 833*41480Smckusick daddr_t bn, pbn; 834*41480Smckusick 835*41480Smckusick if (rdstatus(rs)) { 836*41480Smckusick #ifdef DEBUG 837*41480Smckusick printf("rd%d: couldn't get status\n", unit); 838*41480Smckusick #endif 839*41480Smckusick rdreset(rs, rs->sc_hd); 840*41480Smckusick return(1); 841*41480Smckusick } 842*41480Smckusick sp = &rs->sc_stat; 843*41480Smckusick if (sp->c_fef & FEF_REXMT) 844*41480Smckusick return(1); 845*41480Smckusick if (sp->c_fef & FEF_PF) { 846*41480Smckusick rdreset(rs, rs->sc_hd); 847*41480Smckusick return(1); 848*41480Smckusick } 849*41480Smckusick /* 850*41480Smckusick * Unit requests release for internal maintenance. 851*41480Smckusick * We just delay awhile and try again later. Use expontially 852*41480Smckusick * increasing backoff ala ethernet drivers since we don't really 853*41480Smckusick * know how long the maintenance will take. With RDWAITC and 854*41480Smckusick * RDRETRY as defined, the range is 1 to 32 seconds. 855*41480Smckusick */ 856*41480Smckusick if (sp->c_fef & FEF_IMR) { 857*41480Smckusick extern int hz; 858*41480Smckusick int rdtimo = RDWAITC << rdtab[unit].b_errcnt; 859*41480Smckusick #ifdef DEBUG 860*41480Smckusick printf("rd%d: internal maintenance, %d second timeout\n", 861*41480Smckusick unit, rdtimo); 862*41480Smckusick rdstats[unit].rdtimeouts++; 863*41480Smckusick #endif 864*41480Smckusick hpibfree(&rs->sc_dq); 865*41480Smckusick timeout(rdrestart, unit, rdtimo*hz); 866*41480Smckusick return(0); 867*41480Smckusick } 868*41480Smckusick bp = rdtab[unit].b_actf; 869*41480Smckusick /* 870*41480Smckusick * First conjure up the block number at which the error occured. 871*41480Smckusick * Note that not all errors report a block number, in that case 872*41480Smckusick * we just use b_blkno. 873*41480Smckusick */ 874*41480Smckusick pbn = RDSTOB(rs->sc_info->nbpc * 875*41480Smckusick rs->sc_info->sizes[rdpart(bp->b_dev)].cyloff); 876*41480Smckusick if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) || 877*41480Smckusick (sp->c_ief & IEF_RRMASK)) { 878*41480Smckusick bn = pbn + bp->b_blkno; 879*41480Smckusick pbn = bp->b_blkno; 880*41480Smckusick } else { 881*41480Smckusick bn = RDSTOB(sp->c_blk); 882*41480Smckusick pbn = bn - pbn; 883*41480Smckusick } 884*41480Smckusick /* 885*41480Smckusick * Now output a generic message suitable for badsect. 886*41480Smckusick * Note that we don't use harderr cuz it just prints 887*41480Smckusick * out b_blkno which is just the beginning block number 888*41480Smckusick * of the transfer, not necessary where the error occured. 889*41480Smckusick */ 890*41480Smckusick printf("rd%d%c: hard error sn%d\n", 891*41480Smckusick rdunit(bp->b_dev), 'a'+rdpart(bp->b_dev), pbn); 892*41480Smckusick /* 893*41480Smckusick * Now report the status as returned by the hardware with 894*41480Smckusick * attempt at interpretation (unless debugging). 895*41480Smckusick */ 896*41480Smckusick printf("rd%d %s error:", 897*41480Smckusick unit, (bp->b_flags & B_READ) ? "read" : "write"); 898*41480Smckusick #ifdef DEBUG 899*41480Smckusick if (rddebug & RDB_ERROR) { 900*41480Smckusick /* status info */ 901*41480Smckusick printf("\n volume: %d, unit: %d\n", 902*41480Smckusick (sp->c_vu>>4)&0xF, sp->c_vu&0xF); 903*41480Smckusick rdprinterr("reject", sp->c_ref, err_reject); 904*41480Smckusick rdprinterr("fault", sp->c_fef, err_fault); 905*41480Smckusick rdprinterr("access", sp->c_aef, err_access); 906*41480Smckusick rdprinterr("info", sp->c_ief, err_info); 907*41480Smckusick printf(" block: %d, P1-P10: ", bn); 908*41480Smckusick printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8)); 909*41480Smckusick printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8)); 910*41480Smckusick printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4)); 911*41480Smckusick /* command */ 912*41480Smckusick printf(" ioc: "); 913*41480Smckusick printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_pad, 8)); 914*41480Smckusick printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_hiaddr, 4)); 915*41480Smckusick printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_addr, 8)); 916*41480Smckusick printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_nop2, 4)); 917*41480Smckusick printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_len, 8)); 918*41480Smckusick printf("%s\n", hexstr(*(u_short *)&rs->sc_ioc.c_cmd, 4)); 919*41480Smckusick return(1); 920*41480Smckusick } 921*41480Smckusick #endif 922*41480Smckusick printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n", 923*41480Smckusick (sp->c_vu>>4)&0xF, sp->c_vu&0xF, 924*41480Smckusick sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief); 925*41480Smckusick printf("P1-P10: "); 926*41480Smckusick printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8)); 927*41480Smckusick printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8)); 928*41480Smckusick printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4)); 929*41480Smckusick return(1); 930*41480Smckusick } 931*41480Smckusick 932*41480Smckusick rdread(dev, uio) 933*41480Smckusick dev_t dev; 934*41480Smckusick struct uio *uio; 935*41480Smckusick { 936*41480Smckusick register int unit = rdunit(dev); 937*41480Smckusick 938*41480Smckusick return(physio(rdstrategy, &rdbuf[unit], dev, B_READ, minphys, uio)); 939*41480Smckusick } 940*41480Smckusick 941*41480Smckusick rdwrite(dev, uio) 942*41480Smckusick dev_t dev; 943*41480Smckusick struct uio *uio; 944*41480Smckusick { 945*41480Smckusick register int unit = rdunit(dev); 946*41480Smckusick 947*41480Smckusick return(physio(rdstrategy, &rdbuf[unit], dev, B_WRITE, minphys, uio)); 948*41480Smckusick } 949*41480Smckusick 950*41480Smckusick /*ARGSUSED*/ 951*41480Smckusick rdioctl(dev, cmd, data, flag) 952*41480Smckusick dev_t dev; 953*41480Smckusick int cmd; 954*41480Smckusick caddr_t data; 955*41480Smckusick int flag; 956*41480Smckusick { 957*41480Smckusick return(EINVAL); 958*41480Smckusick } 959*41480Smckusick 960*41480Smckusick rdsize(dev) 961*41480Smckusick dev_t dev; 962*41480Smckusick { 963*41480Smckusick register int unit = rdunit(dev); 964*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 965*41480Smckusick 966*41480Smckusick if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0) 967*41480Smckusick return(-1); 968*41480Smckusick return(rs->sc_info->sizes[rdpart(dev)].nblocks); 969*41480Smckusick } 970*41480Smckusick 971*41480Smckusick #ifdef DEBUG 972*41480Smckusick rdprinterr(str, err, tab) 973*41480Smckusick char *str; 974*41480Smckusick short err; 975*41480Smckusick char *tab[]; 976*41480Smckusick { 977*41480Smckusick register int i; 978*41480Smckusick int printed; 979*41480Smckusick 980*41480Smckusick if (err == 0) 981*41480Smckusick return; 982*41480Smckusick printf(" %s error field:", str, err); 983*41480Smckusick printed = 0; 984*41480Smckusick for (i = 0; i < 16; i++) 985*41480Smckusick if (err & (0x8000 >> i)) 986*41480Smckusick printf("%s%s", printed++ ? " + " : " ", tab[i]); 987*41480Smckusick printf("\n"); 988*41480Smckusick } 989*41480Smckusick #endif 990*41480Smckusick 991*41480Smckusick #include "machine/pte.h" 992*41480Smckusick #include "machine/vmparam.h" 993*41480Smckusick #include "../h/vmmac.h" 994*41480Smckusick 995*41480Smckusick /* 996*41480Smckusick * Non-interrupt driven, non-dma dump routine. 997*41480Smckusick */ 998*41480Smckusick rddump(dev) 999*41480Smckusick dev_t dev; 1000*41480Smckusick { 1001*41480Smckusick int part = rdpart(dev); 1002*41480Smckusick int unit = rdunit(dev); 1003*41480Smckusick register struct rd_softc *rs = &rd_softc[unit]; 1004*41480Smckusick register struct hp_device *hp = rs->sc_hd; 1005*41480Smckusick register daddr_t baddr; 1006*41480Smckusick register int maddr; 1007*41480Smckusick register int pages, i; 1008*41480Smckusick char stat; 1009*41480Smckusick extern int lowram, dumpsize; 1010*41480Smckusick 1011*41480Smckusick pages = dumpsize; 1012*41480Smckusick #ifdef DEBUG 1013*41480Smckusick if (rddebug & RDB_DUMP) 1014*41480Smckusick printf("rddump(%x): u %d p %d dumplo %d ram %x pmem %d\n", 1015*41480Smckusick dev, unit, part, dumplo, lowram, ctod(pages)); 1016*41480Smckusick #endif 1017*41480Smckusick /* is drive ok? */ 1018*41480Smckusick if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0) 1019*41480Smckusick return (ENXIO); 1020*41480Smckusick /* HPIB idle? */ 1021*41480Smckusick if (!hpibreq(&rs->sc_dq)) { 1022*41480Smckusick #ifdef DEBUG 1023*41480Smckusick /* is this a safe thing to do?? */ 1024*41480Smckusick hpibreset(hp->hp_ctlr); 1025*41480Smckusick rdreset(rs, rs->sc_hd); 1026*41480Smckusick printf("[ drive %d reset ] ", unit); 1027*41480Smckusick #else 1028*41480Smckusick return (EFAULT); 1029*41480Smckusick #endif 1030*41480Smckusick } 1031*41480Smckusick /* dump parameters in range? */ 1032*41480Smckusick if (dumplo < 0 || dumplo >= rs->sc_info->sizes[part].nblocks) 1033*41480Smckusick return (EINVAL); 1034*41480Smckusick if (dumplo + ctod(pages) > rs->sc_info->sizes[part].nblocks) 1035*41480Smckusick pages = dtoc(rs->sc_info->sizes[part].nblocks - dumplo); 1036*41480Smckusick maddr = lowram; 1037*41480Smckusick baddr = dumplo + rs->sc_info->nbpc * rs->sc_info->sizes[part].cyloff; 1038*41480Smckusick #ifdef DEBUG 1039*41480Smckusick if (rddebug & RDB_DUMP) 1040*41480Smckusick printf("rddump: dumping %d pages from %x to disk block %d\n", 1041*41480Smckusick pages, maddr, baddr); 1042*41480Smckusick #endif 1043*41480Smckusick for (i = 0; i < pages; i++) { 1044*41480Smckusick #ifdef DEBUG 1045*41480Smckusick #define NPGMB (1024*1024/NBPG) 1046*41480Smckusick /* print out how many Mbs we have dumped */ 1047*41480Smckusick if (i && (i % NPGMB) == 0) 1048*41480Smckusick printf("%d ", i / NPGMB); 1049*41480Smckusick #undef NPBMG 1050*41480Smckusick #endif 1051*41480Smckusick rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit); 1052*41480Smckusick rs->sc_ioc.c_volume = C_SVOL(0); 1053*41480Smckusick rs->sc_ioc.c_saddr = C_SADDR; 1054*41480Smckusick rs->sc_ioc.c_hiaddr = 0; 1055*41480Smckusick rs->sc_ioc.c_addr = RDBTOS(baddr); 1056*41480Smckusick rs->sc_ioc.c_nop2 = C_NOP; 1057*41480Smckusick rs->sc_ioc.c_slen = C_SLEN; 1058*41480Smckusick rs->sc_ioc.c_len = NBPG; 1059*41480Smckusick rs->sc_ioc.c_cmd = C_WRITE; 1060*41480Smckusick hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, 1061*41480Smckusick &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2); 1062*41480Smckusick if (hpibswait(hp->hp_ctlr, hp->hp_slave)) { 1063*41480Smckusick #ifdef DEBUG 1064*41480Smckusick if (rddebug & RDB_DUMP) 1065*41480Smckusick printf("rddump: IOC wait timeout\n"); 1066*41480Smckusick #endif 1067*41480Smckusick return (EIO); 1068*41480Smckusick } 1069*41480Smckusick mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V); 1070*41480Smckusick hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG); 1071*41480Smckusick if (hpibswait(hp->hp_ctlr, hp->hp_slave)) { 1072*41480Smckusick #ifdef DEBUG 1073*41480Smckusick if (rddebug & RDB_DUMP) 1074*41480Smckusick printf("rddump: write wait timeout\n"); 1075*41480Smckusick #endif 1076*41480Smckusick } 1077*41480Smckusick hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1); 1078*41480Smckusick if (stat) { 1079*41480Smckusick #ifdef DEBUG 1080*41480Smckusick if (rddebug & RDB_DUMP) 1081*41480Smckusick printf("rddump: write failed, status %x\n", 1082*41480Smckusick stat); 1083*41480Smckusick #endif 1084*41480Smckusick return (EIO); 1085*41480Smckusick } 1086*41480Smckusick maddr += NBPG; 1087*41480Smckusick baddr += ctod(1); 1088*41480Smckusick } 1089*41480Smckusick return (0); 1090*41480Smckusick } 1091*41480Smckusick #endif 1092