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