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