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
hdopen(io)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
hdstrategy(io,cmd)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
hdimcb(mcb,io)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
hdmaptype(io,dlp,status,unit)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