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