|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Harris Corp. ! 7: * ! 8: * Redistribution is only permitted until one year after the first shipment ! 9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 10: * binary forms are permitted provided that: (1) source distributions retain ! 11: * this entire copyright notice and comment, and (2) distributions including ! 12: * binaries display the following acknowledgement: This product includes ! 13: * software developed by the University of California, Berkeley and its ! 14: * contributors'' in the documentation or other materials provided with the ! 15: * distribution and in all advertising materials mentioning features or use ! 16: * of this software. Neither the name of the University nor the names of ! 17: * its contributors may be used to endorse or promote products derived from ! 18: * this software without specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: * ! 23: * @(#)hd.c 7.9 (Berkeley) 6/30/90 ! 24: */ ! 25: ! 26: #include "sys/param.h" ! 27: #include "sys/time.h" ! 28: #include "sys/buf.h" ! 29: #include "sys/ioctl.h" ! 30: #include "sys/disklabel.h" ! 31: #include "saio.h" ! 32: #include "tahoe/mtpr.h" ! 33: #include "tahoevba/hdreg.h" ! 34: ! 35: static struct registers *hdc_regs[HDC_MAXCTLR][HDC_MAXBUS]; ! 36: static struct disklabel dklabel[HDC_MAXDRIVE][HDC_MAXCTLR][HDC_MAXBUS]; ! 37: ! 38: hdopen(io) ! 39: register struct iob *io; ! 40: { ! 41: register struct disklabel *dlp; ! 42: struct status status; ! 43: struct module_id id; ! 44: struct registers *hr; ! 45: struct mcb mcb; ! 46: long junk, dlbuf[DEV_BSIZE/sizeof(long)]; ! 47: ! 48: /* validate the device specification */ ! 49: if ((u_int)io->i_bus >= HDC_MAXBUS) ! 50: return(EADAPT); ! 51: if ((u_int)io->i_ctlr >= HDC_MAXCTLR) ! 52: return(ECTLR); ! 53: if ((u_int)io->i_unit >= HDC_MAXDRIVE) ! 54: return(EUNIT); ! 55: if ((u_int)io->i_part > 7) ! 56: return(EPART); ! 57: ! 58: /* init drive structure. */ ! 59: hdc_regs[io->i_ctlr][io->i_bus] = hr = (struct registers *)(io->i_bus ? ! 60: 0x80000000 | io->i_ctlr << 24 | HDC_MID << 16 : ! 61: 0xC0000000 | io->i_ctlr << 24 | HDC_MID << 16); ! 62: ! 63: /* insure that this is an hdc, then reset the hdc. */ ! 64: if (wbadaddr(&hr->module_id, 4, &junk)) { ! 65: printf("hd%d: %x: invalid csr\n", io->i_ctlr, (u_int)hr); ! 66: return(ENXIO); ! 67: } ! 68: hr->soft_reset = 0; ! 69: DELAY(1000000); ! 70: ! 71: /* ! 72: * read in the hdc module id word. The controller is bad if the ! 73: * hdc's writeable control store is not loaded or if the hdc failed ! 74: * the functional integrity test for any reason. ! 75: */ ! 76: hr->module_id = (u_long)&id; ! 77: DELAY(10000); ! 78: mtpr(PADC, 0); ! 79: if (id.module_id != (u_char)HDC_MID) { ! 80: printf("hdc: controller bad module id: id = %x\n", ! 81: id.module_id); ! 82: return(ENXIO); ! 83: } ! 84: if (id.code_rev == (u_char)0xff) { ! 85: printf("hdc: controller micro-code is not loaded.\n"); ! 86: return(ENXIO); ! 87: } ! 88: if (id.fit != (u_char)0xff) { ! 89: printf("hdc: controller FIT test failed: error= %x\n", ! 90: id.fit); ! 91: return(ENXIO); ! 92: } ! 93: ! 94: /* read the drive status */ ! 95: mcb.command = HCMD_STATUS; ! 96: mcb.drive = io->i_unit; ! 97: mcb.cyl = 0; ! 98: mcb.head = 0; ! 99: mcb.sector = 0; ! 100: mcb.chain[0].wcount = (long)(sizeof(struct status) / sizeof(long)); ! 101: mcb.chain[0].memadr = (long)&status; ! 102: if (hdimcb(&mcb, io)) ! 103: return(EIO); ! 104: ! 105: /* ! 106: * Report drive down if anything in the drive status is bad. ! 107: * If fault condition, reading will try to clear the fault. ! 108: */ ! 109: if (status.drs&DRS_FAULT) ! 110: printf("hdc: clearing drive fault.\n"); ! 111: if (!(status.drs&DRS_ONLINE)) { ! 112: printf("hdc: drive is not online.\n"); ! 113: return(EIO); ! 114: } ! 115: ! 116: /* read in the pack label */ ! 117: mcb.command = HCMD_READ; ! 118: mcb.drive = io->i_unit; ! 119: mcb.cyl = 0; ! 120: mcb.head = 0; ! 121: mcb.sector = LABELSECTOR; ! 122: mcb.chain[0].wcount = (long)(DEV_BSIZE / sizeof(long)); ! 123: mcb.chain[0].memadr = (long)dlbuf; ! 124: if (hdimcb(&mcb, io)) ! 125: return(ERDLAB); ! 126: dlp = (struct disklabel *)(dlbuf + (LABELOFFSET / sizeof(long))); ! 127: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) ! 128: #ifdef COMPAT_42 ! 129: { ! 130: int error; ! 131: ! 132: if (error = hdmaptype(io, dlp, &status, io->i_unit)) ! 133: return(error); ! 134: } ! 135: #else ! 136: return(EUNLAB); ! 137: #endif ! 138: dklabel[io->i_unit][io->i_ctlr][io->i_bus] = *dlp; ! 139: if (io->i_part >= dlp->d_npartitions || ! 140: dlp->d_partitions[io->i_part].p_size == 0) ! 141: return(EPART); ! 142: io->i_boff = (dlp->d_partitions[io->i_part].p_offset * ! 143: dlp->d_secsize) / DEV_BSIZE; ! 144: return(0); ! 145: } ! 146: ! 147: hdstrategy(io, cmd) ! 148: register struct iob *io; ! 149: int cmd; ! 150: { ! 151: register struct disklabel *dlp; ! 152: struct mcb mcb; ! 153: long sector; ! 154: ! 155: if (io->i_cc&3) { ! 156: printf("hd%d: i/o not a longword multiple.\n", io->i_unit); ! 157: return(0); ! 158: } ! 159: dlp = &dklabel[io->i_unit][io->i_ctlr][io->i_bus]; ! 160: sector = io->i_bn * HDC_SPB; ! 161: mcb.command = (cmd == READ) ? HCMD_READ : HCMD_WRITE; ! 162: mcb.drive = io->i_unit; ! 163: mcb.cyl = sector / dlp->d_secpercyl; ! 164: mcb.head = (sector / dlp->d_nsectors) % dlp->d_ntracks; ! 165: mcb.sector = sector % dlp->d_nsectors; ! 166: mcb.chain[0].wcount = io->i_cc / sizeof(long); ! 167: mcb.chain[0].memadr = (u_long)io->i_ma; ! 168: return(hdimcb(&mcb, io) ? -1 : io->i_cc); ! 169: } ! 170: ! 171: hdimcb(mcb, io) ! 172: register struct mcb *mcb; ! 173: register struct iob *io; ! 174: { ! 175: struct master_mcb master; ! 176: int timeout; ! 177: ! 178: /* fill in mcb */ ! 179: mcb->interrupt = 0; ! 180: mcb->forw_phaddr = 0; ! 181: ! 182: /* fill in master mcb */ ! 183: master.mcw = MCL_IMMEDIATE; ! 184: master.forw_phaddr = (u_long)mcb; ! 185: master.mcs = 0; ! 186: ! 187: hdc_regs[io->i_ctlr][io->i_bus]->master_mcb = (u_long)&master; ! 188: for (timeout = 15000; timeout; --timeout) { ! 189: DELAY(1000); ! 190: mtpr(PADC, 0); ! 191: if (master.mcs&MCS_FATALERROR) { ! 192: printf("hdc%d: fatal error.\n", io->i_ctlr); ! 193: return(1); ! 194: } ! 195: if (master.mcs&MCS_DONE) ! 196: return(0); ! 197: } ! 198: printf("hdc%d: timed out.\n", io->i_ctlr); ! 199: return(1); ! 200: } ! 201: ! 202: #ifdef COMPAT_42 ! 203: hdmaptype(io, dlp, status, unit) ! 204: register struct iob *io; ! 205: register struct disklabel *dlp; ! 206: struct status *status; ! 207: int unit; ! 208: { ! 209: geometry_sector geometry; ! 210: geometry_block *geo; ! 211: struct mcb mcb; ! 212: int cnt; ! 213: char *strcpy(); ! 214: ! 215: printf("hd%d: unlabeled\n", unit); ! 216: /* ! 217: * Read the geometry block (at head = 0 sector = 0 of the drive ! 218: * definition cylinder), validate it (must have the correct version ! 219: * number, header, and checksum). ! 220: */ ! 221: mcb.command = HCMD_READ; ! 222: mcb.drive = unit; ! 223: mcb.cyl = status->def_cyl; ! 224: mcb.head = 0; ! 225: mcb.sector = 0; ! 226: mcb.chain[0].wcount = (long)(sizeof(geometry_sector) / sizeof(long)); ! 227: mcb.chain[0].memadr = (long)&geometry; ! 228: if (hdimcb(&mcb, io)) { ! 229: printf("hd%d: can't read default geometry.\n", io->i_unit); ! 230: return(ERDLAB); ! 231: } ! 232: geo = &geometry.geometry_block; ! 233: if (geo->version > 64000 || geo->version < 0) { ! 234: printf("hd%d: bad default geometry version#.\n", io->i_unit); ! 235: return(ENXIO); ! 236: } ! 237: if (strcmp(&geo->id[0], GB_ID)) { ! 238: printf("hd%d: bad default geometry header.\n", io->i_unit); ! 239: return(ENXIO); ! 240: } ! 241: GB_CHECKSUM(geo, cnt); ! 242: if (geometry.checksum != cnt) { ! 243: printf("hd%d: bad default geometry checksum.\n", io->i_unit); ! 244: return(ENXIO); ! 245: } ! 246: for (cnt = 0; cnt < GB_MAXPART; cnt++) { ! 247: dlp->d_partitions[cnt].p_offset = geo->partition[cnt].start; ! 248: dlp->d_partitions[cnt].p_size = geo->partition[cnt].length; ! 249: } ! 250: #ifdef RAW_SIZE ! 251: dlp->d_secsize = status->bytes_per_sec; ! 252: #else ! 253: dlp->d_secsize = 512; ! 254: #endif ! 255: dlp->d_nsectors = status->max_sector + 1; ! 256: dlp->d_ncylinders = status->max_cyl + 1; ! 257: dlp->d_ntracks = status->max_head + 1; ! 258: dlp->d_secpercyl = dlp->d_ntracks * dlp->d_nsectors; ! 259: dlp->d_npartitions = GB_MAXPART; ! 260: dlp->d_rpm = status->rpm; ! 261: (void)strcpy(dlp->d_typename, "hdc (prom)"); ! 262: return(0); ! 263: } ! 264: #endif /* COMPAT_42 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.