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