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.5 (Berkeley) 11/01/88 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); 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: controller timed out.\n"); 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 */ 263