Commit | Line | Data |
---|---|---|
2839b724 KB |
1 | /* |
2 | * Stand alone driver for the HDC controller | |
3b94e226 | 3 | * |
62e6d4ba | 4 | * @(#)hd.c 7.4 (Berkeley) %G% |
2839b724 | 5 | */ |
3b94e226 KB |
6 | #define KERNEL |
7 | ||
8 | #include "machine/mtpr.h" | |
9 | #include "param.h" | |
10 | #include "systm.h" | |
11 | #include "buf.h" | |
12 | #include "time.h" | |
13 | #include "inode.h" | |
14 | #include "fs.h" | |
15 | #include "ioctl.h" | |
16 | #include "tahoevba/dsk.h" | |
17 | #include "tahoevba/dskio.h" | |
18 | #include "tahoevba/hdc.h" | |
19 | #include "saio.h" | |
20 | ||
21 | #define NHD 4 | |
22 | #define NDRIVE 8 /* drives per controller */ | |
23 | #define HDSLAVE(x) ((x) % NDRIVE) | |
24 | #define HDCTLR(x) ((x) / NDRIVE) | |
25 | ||
26 | #define HDREG(x) (ctlr_addr->x) /* standalone io to an hdc register */ | |
27 | #define HID_HDC 0x01 /* hvme_id for HDC */ | |
2839b724 KB |
28 | |
29 | /* | |
30 | * hdc controller table. It contains information about the hdc controller. | |
31 | */ | |
2839b724 KB |
32 | typedef struct { |
33 | int ctlr; /* controller number (0-15) */ | |
34 | hdc_regs_type *registers; /* base address of hdc io registers */ | |
35 | hdc_mid_type mid; /* the module id is read to here */ | |
d1de3d34 | 36 | master_mcb_type master_mcb; /* the master mcb for this hdc */ |
2839b724 KB |
37 | mcb_type mcb; /* an mcb for i/o to the controller */ |
38 | } hdctlr_type; | |
39 | ||
40 | hdctlr_type hdc_ctlr[HDC_MAXCTLR][HDC_MAXBUS]; | |
41 | ||
42 | /* | |
43 | * hdc unit table. It contains information about the hdc drive. | |
44 | * Some information is obtained from the profile prom and geometry block. | |
45 | */ | |
2839b724 | 46 | typedef struct { |
d1de3d34 KB |
47 | par_tab partition[GB_MAXPART]; /* partition definitions */ |
48 | int ctlr; /* the controller number (0-15) */ | |
49 | int slave; /* the slave number (0-4) */ | |
50 | int unit; /* the unit number (0-31) */ | |
51 | int id; /* identifies the disk model */ | |
52 | int cylinders; /* number of logical cylinders */ | |
53 | int heads; /* number of logical heads */ | |
54 | int sectors; /* number of logical sectors/track */ | |
55 | int phys_cylinders; /* number of physical cylinders */ | |
56 | int phys_heads; /* number of physical heads */ | |
57 | int phys_sectors; /* number of physical sectors/track */ | |
58 | int def_cyl; /* logical cylinder of drive def */ | |
59 | int def_cyl_count; /* number of logical def cylinders */ | |
60 | int diag_cyl; /* logical cylinder of diag area */ | |
61 | int diag_cyl_count; /* number of logical diag cylinders */ | |
62 | int rpm; /* disk rpm */ | |
63 | int bytes_per_sec; /* bytes/sector -vendorflaw conversn*/ | |
64 | int format; /* format program is active */ | |
65 | u_long phio_data[HDC_PHIO_SIZE]; /* data for physical io */ | |
2839b724 KB |
66 | } hdunit_type; |
67 | ||
d1de3d34 | 68 | hdunit_type hdc_unit [HDC_MAXDRIVE] [HDC_MAXCTLR] [HDC_MAXBUS]; |
2839b724 KB |
69 | |
70 | /************************************************************************* | |
71 | * Procedure: hdopen | |
72 | * | |
d1de3d34 KB |
73 | * Description: The hdc open routine. Initializes the hdc and reads the |
74 | * hdc status and the geometry block. | |
2839b724 | 75 | * |
d1de3d34 KB |
76 | * Returns: 0 open was successful |
77 | * -1 this is not an hdc controller | |
2839b724 | 78 | **************************************************************************/ |
2839b724 | 79 | hdopen(io) |
d1de3d34 | 80 | register struct iob *io; /* i/o block */ |
2839b724 KB |
81 | { |
82 | mcb_type *mcb; /* an mcb to send commands to hdc */ | |
83 | hdunit_type *hu; /* disk unit information table */ | |
84 | hdctlr_type *hc; /* hdc ctlr information table */ | |
85 | hdc_mid_type *id; /* the hdc module id */ | |
d1de3d34 | 86 | geometry_sector geometry; /* the geometry block sector */ |
2839b724 KB |
87 | geometry_block *geo; /* the geometry block */ |
88 | drive_stat_type status; /* the hdc status is read to here */ | |
d1de3d34 | 89 | long ctlr; /* the controller number */ |
3b94e226 | 90 | long junk; /* badaddr will write junk here */ |
d1de3d34 KB |
91 | int par; /* partition number */ |
92 | int drive; /* the drive number */ | |
93 | int bus; /* the bus number */ | |
94 | int i; /* temp */ | |
2839b724 | 95 | hdc_regs_type *ctlr_addr; /* hdc i/o registers */ |
2839b724 | 96 | |
d1de3d34 KB |
97 | par = io->i_boff; /* io->i_part; */ |
98 | bus = 0; /* io->i_bus; */ | |
99 | ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ | |
100 | drive = HDSLAVE(io->i_unit); /* io->i_drive; */ | |
2839b724 KB |
101 | hu = &hdc_unit[drive][ctlr][bus]; |
102 | hc = &hdc_ctlr[ctlr][bus]; | |
103 | mcb = &hc->mcb; | |
104 | ||
105 | /* | |
106 | * Validate the device specification | |
107 | */ | |
3b94e226 KB |
108 | if (ctlr >= HDC_MAXCTLR) { |
109 | printf("invalid controller number\n"); | |
d1de3d34 | 110 | return(ENXIO); |
3b94e226 | 111 | } |
d1de3d34 | 112 | if (drive < 0 || drive > HDC_MAXDRIVE - 1) { |
2839b724 | 113 | printf("hdc: bad drive number.\n"); |
d1de3d34 | 114 | return(EUNIT); |
2839b724 KB |
115 | } |
116 | if (par < 0 || par > 7) { | |
117 | printf("hdc: bad partition number.\n"); | |
d1de3d34 | 118 | return(EUNIT); |
2839b724 | 119 | } |
3b94e226 | 120 | ctlr_addr = (hdc_regs_type *)(bus == 0 ? |
2839b724 | 121 | 0xC0000000 | ctlr << 24 | HDC_MID << 16 : |
3b94e226 | 122 | 0x80000000 | ctlr << 24 | HDC_MID << 16); |
2839b724 KB |
123 | |
124 | /* | |
125 | * Init drive structure. | |
126 | */ | |
2839b724 KB |
127 | hu->slave = drive; |
128 | hc->registers = ctlr_addr; | |
129 | ||
130 | /* | |
131 | * Insure that this is an hdc, then reset the hdc. | |
132 | */ | |
3b94e226 KB |
133 | junk = 0; |
134 | if (wbadaddr(&ctlr_addr->module_id_reg, 4, &junk)) { | |
d1de3d34 KB |
135 | printf("hd%d: %x: invalid csr\n", ctlr, (u_int)ctlr_addr); |
136 | return(ENXIO); | |
3b94e226 | 137 | } |
2839b724 KB |
138 | HDREG(soft_reset_reg) = 0; |
139 | DELAY(1000000); | |
140 | ||
141 | /* | |
d1de3d34 KB |
142 | * Read in the hdc module id word. The controller is bad if the |
143 | * hdc's writeable control store is not loaded or if the hdc failed | |
144 | * the functional integrity test for any reason. | |
2839b724 | 145 | */ |
2839b724 | 146 | id = &hc->mid; |
d1de3d34 | 147 | HDREG(module_id_reg) = (u_long)id; |
2839b724 | 148 | DELAY(10000); |
3b94e226 | 149 | mtpr(PADC, 0); |
d1de3d34 KB |
150 | if (id->module_id != (u_char)HDC_MID) { |
151 | printf("hdc: Controller bad module id: id = %x\n", | |
152 | id->module_id); | |
153 | return(-1); | |
2839b724 | 154 | } |
d1de3d34 KB |
155 | if (id->code_rev == (u_char)0xFF) { |
156 | printf("hdc: Controller micro-code is not loaded.\n"); | |
157 | return(ENXIO); | |
2839b724 | 158 | } |
d1de3d34 KB |
159 | if (id->fit != (u_char)0xFF) { |
160 | printf("hdc: Controller FIT test failed: error= %x\n", | |
161 | id->fit); | |
162 | return(ENXIO); | |
2839b724 KB |
163 | } |
164 | ||
165 | /* | |
166 | * Read the drive status. Save important info. | |
167 | */ | |
2839b724 KB |
168 | mcb->command = HCMD_STATUS; |
169 | mcb->drive = drive; | |
170 | mcb->cyl = 0; | |
171 | mcb->head = 0; | |
172 | mcb->sector = 0; | |
d1de3d34 KB |
173 | mcb->chain[0].lwc = (long)sizeof(drive_stat_type) / 4; |
174 | mcb->chain[0].ta = (long)&status; | |
2839b724 | 175 | if (hdmcb(mcb, io)) |
d1de3d34 | 176 | return(EIO); |
2839b724 KB |
177 | hu->cylinders = status.max_cyl+1; |
178 | hu->heads = status.max_head+1; | |
179 | hu->sectors = status.max_sector+1; | |
180 | hu->def_cyl = status.def_cyl; | |
181 | hu->def_cyl_count = status.def_cyl_count; | |
182 | hu->diag_cyl = status.diag_cyl; | |
183 | hu->diag_cyl_count = status.diag_cyl_count; | |
184 | hu->phys_cylinders = status.max_phys_cyl+1; | |
185 | hu->phys_heads = status.max_phys_head+1; | |
186 | hu->phys_sectors = status.max_phys_sector+1; | |
187 | hu->bytes_per_sec = status.bytes_per_sec; | |
188 | hu->id = status.id; | |
189 | hu->rpm = status.rpm; | |
190 | hu->partition[HDC_DEFPART].start= | |
191 | hu->def_cyl * hu->sectors * hu->heads / HDC_SPB; | |
192 | hu->partition[HDC_DEFPART].length = | |
193 | hu->def_cyl_count * hu->sectors * hu->heads / HDC_SPB; | |
d1de3d34 | 194 | io->i_boff = hu->partition[HDC_DEFPART].start; /* default */ |
2839b724 KB |
195 | |
196 | /* | |
197 | * Report drive down if anything in the drive status is bad. | |
198 | * If fault condition, reading geo will try to clear the fault. | |
199 | */ | |
2839b724 KB |
200 | if (status.drs & DRS_FAULT) |
201 | printf("hdc: clearing drive fault.\n"); | |
d1de3d34 | 202 | if (!(status.drs & DRS_ONLINE)) { |
2839b724 | 203 | printf("hdc: drive is not online.\n"); |
d1de3d34 | 204 | return(EIO); |
2839b724 KB |
205 | } |
206 | ||
207 | /* | |
208 | * Read the geometry block (at head=0 sector=0 of the drive | |
209 | * definition cylinder), validate it (must have the correct | |
210 | * version number, header, and checksum). | |
211 | */ | |
2839b724 KB |
212 | geo = &geometry.geometry_block; |
213 | mcb->command = HCMD_READ; | |
214 | mcb->drive = drive; | |
215 | mcb->cyl = status.def_cyl; | |
216 | mcb->head = 0; | |
217 | mcb->sector = 0; | |
218 | mcb->chain[0].lwc = sizeof(geometry_sector) / 4; | |
d1de3d34 | 219 | mcb->chain[0].ta = (long)&geometry; |
2839b724 KB |
220 | if (hdmcb(mcb, io)) { |
221 | printf("hdc: could not read geometry block\n"); | |
d1de3d34 | 222 | return(EIO); |
2839b724 KB |
223 | } |
224 | io->i_boff = 0; | |
d1de3d34 | 225 | if (geo->version > 64000 || geo->version < 0) { |
2839b724 | 226 | printf("hdc: bad geometry block version#\n"); |
d1de3d34 | 227 | return(ENXIO); |
2839b724 | 228 | } |
d1de3d34 | 229 | if (strcmp(&geo->id[0], GB_ID) != 0) { |
2839b724 | 230 | printf("hdc: bad geometry block header\n"); |
d1de3d34 | 231 | return(ENXIO); |
2839b724 | 232 | } |
d1de3d34 | 233 | GB_CHECKSUM(geo, i); |
2839b724 KB |
234 | if (geometry.checksum != i) { |
235 | printf("hdc: bad geometry block checksum\n"); | |
d1de3d34 | 236 | return(ENXIO); |
2839b724 KB |
237 | } |
238 | ||
239 | /* | |
240 | * Set the partition start/size info. | |
241 | * Note: this info was already defaulted to be the disk | |
242 | * definition partition. | |
243 | */ | |
d1de3d34 | 244 | if (par != HDC_DEFPART) |
3b94e226 | 245 | if (geo->partition[par].length == 0) { |
2839b724 | 246 | printf("hdc: null partition\n"); |
d1de3d34 | 247 | return(ENXIO); |
3b94e226 | 248 | } |
2839b724 KB |
249 | else { |
250 | hu->partition[par].start = geo->partition[par].start; | |
251 | hu->partition[par].length = geo->partition[par].length; | |
252 | io->i_boff = hu->partition[par].start; | |
253 | } | |
d1de3d34 | 254 | return(0); |
2839b724 KB |
255 | } |
256 | ||
257 | /************************************************************************* | |
258 | * Procedure: hdstrategy | |
259 | * | |
d1de3d34 KB |
260 | * Description: The hdc strategy routine. This routine does the disk |
261 | * reads/writes. If this is the format program, read/writes | |
262 | * are forced to be within the disk definition partition. | |
2839b724 | 263 | * |
d1de3d34 | 264 | * Returns: The number of bytes transfered. |
2839b724 | 265 | **************************************************************************/ |
d1de3d34 KB |
266 | hdstrategy(io, cmd) |
267 | register struct iob *io; /* i/o block */ | |
268 | int cmd; /* i/o operation to perform */ | |
2839b724 KB |
269 | { |
270 | mcb_type *mcb; /* mcb to send to the hdc */ | |
271 | hdunit_type *hu; /* disk unit information table */ | |
272 | hdctlr_type *hc; /* hdc ctlr information table */ | |
273 | long err; /* error code */ | |
274 | long sector; /* sector number for i/o */ | |
d1de3d34 KB |
275 | int partstart; /* block number of partition start */ |
276 | int partlen; /* number of blocks in partition */ | |
277 | int bytes; /* number of bytes to transfer */ | |
2839b724 | 278 | int bus; /* bus number */ |
d1de3d34 KB |
279 | int ctlr; /* the controller number */ |
280 | int drive; /* the drive number */ | |
2839b724 | 281 | |
d1de3d34 KB |
282 | bus = 0; /* io->i_bus; */ |
283 | ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ | |
284 | drive = HDSLAVE(io->i_unit); /* io->i_drive; */ | |
2839b724 KB |
285 | hu = &hdc_unit[drive][ctlr][bus]; |
286 | hc = &hdc_ctlr[ctlr][bus]; | |
287 | ||
288 | /* | |
289 | * Only the format program can access the disk definition tracks. | |
290 | */ | |
d1de3d34 KB |
291 | if (io->i_boff == HDC_DEFPART && !hu->format) { |
292 | printf("hdc: partition 7 is protected\n"); | |
293 | return(0); | |
294 | } | |
2839b724 KB |
295 | |
296 | /* | |
297 | * Insure the transfer fits in the partition. | |
298 | * Set and validate transfer size. | |
299 | */ | |
d1de3d34 KB |
300 | partstart = hu->partition[io->i_boff].start; |
301 | partlen = hu->partition[io->i_boff].length; | |
302 | if (io->i_bn < partstart || io->i_bn >= partstart + partlen) | |
303 | return(0); | |
304 | bytes = MIN(io->i_cc, DEV_BSIZE * (partstart + partlen-io->i_bn)); | |
2839b724 | 305 | if (io->i_cc & 3) { |
d1de3d34 KB |
306 | printf("hdc: i/o not a longword multiple\n"); |
307 | return(0); | |
2839b724 KB |
308 | } |
309 | ||
310 | /* | |
311 | * Set up the mcb and send it to the hdc. | |
312 | */ | |
2839b724 KB |
313 | mcb = &hc->mcb; |
314 | sector = io->i_bn * HDC_SPB; | |
d1de3d34 | 315 | mcb->command = (cmd == READ) ? HCMD_READ : HCMD_WRITE; |
2839b724 KB |
316 | mcb->drive = hu->slave; |
317 | mcb->cyl = sector / (hu->sectors * hu->heads); | |
d1de3d34 | 318 | mcb->head = (sector / hu->sectors) % hu->heads; |
2839b724 | 319 | mcb->sector = sector % hu->sectors; |
d1de3d34 | 320 | mcb->chain[0].ta = (u_long)io->i_ma; |
2839b724 KB |
321 | mcb->chain[0].lwc = (bytes + 3) / 4; |
322 | err = hdmcb(mcb, io); | |
323 | io->i_error = err; | |
d1de3d34 | 324 | return(err ? 0 : bytes); |
2839b724 KB |
325 | } |
326 | ||
327 | /************************************************************************* | |
328 | * Procedure: hdioctl | |
329 | * | |
d1de3d34 | 330 | * Description: ioctl routine. |
2839b724 | 331 | * |
d1de3d34 KB |
332 | * Returns: 0 no errors |
333 | * non-0 error | |
2839b724 | 334 | **************************************************************************/ |
2839b724 | 335 | hdioctl(io, command, arg) |
d1de3d34 KB |
336 | struct iob *io; /* i/o block */ |
337 | int command; /* The ioctl commmand */ | |
338 | int arg; /* Data. Format depends on ioctl */ | |
2839b724 | 339 | { |
2839b724 | 340 | register int i; |
d1de3d34 KB |
341 | mcb_type *mcb; |
342 | hdunit_type *hu; /* disk unit information table */ | |
343 | hdctlr_type *hc; /* hdc ctlr information table */ | |
344 | int bus; /* bus number */ | |
345 | int ctlr; /* the controller number */ | |
346 | int drive; /* the drive number */ | |
347 | ||
348 | bus = 0; /* io->i_bus; */ | |
349 | ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ | |
350 | drive = HDSLAVE(io->i_unit); /* io->i_drive; */ | |
2839b724 KB |
351 | hu = &hdc_unit[drive][ctlr][bus]; |
352 | hc = &hdc_ctlr[ctlr][bus]; | |
353 | ||
354 | switch (command) { | |
355 | ||
356 | case DSKIOCFORMAT: { | |
357 | ||
358 | /* | |
359 | * Format a disk track. The received argument is a pointer | |
360 | * to a "formatop" structure describing the track to format. | |
361 | * | |
362 | * Set up a buffer with each longword corresponding to a | |
363 | * sector on the track; a 1 means no flaw, a 0 means a flaw. | |
364 | * Send an mcb to the hdc to format the track. | |
365 | */ | |
366 | ||
367 | register struct formatop *track; | |
368 | ||
369 | if (!hu->format) | |
370 | return(1); | |
d1de3d34 | 371 | track = (struct formatop *)arg; |
2839b724 | 372 | mcb = &hc->mcb; |
d1de3d34 | 373 | for (i = 0; i < hu->phys_sectors; i++) |
2839b724 | 374 | hu->phio_data[i] = 1; |
d1de3d34 KB |
375 | for (i = 0; i < track->flaw_count; i++) |
376 | hu->phio_data[track->flaw[i]] = 0; | |
2839b724 KB |
377 | mcb->command = HCMD_FORMAT; |
378 | mcb->drive = hu->slave; | |
d1de3d34 | 379 | mcb->chain[0].ta = (u_long)hu->phio_data; |
2839b724 KB |
380 | mcb->chain[0].lwc = hu->phys_sectors; |
381 | mcb->cyl = track->cylinder; | |
382 | mcb->head = track->head; | |
383 | mcb->sector = 0; | |
384 | if (hdmcb(mcb, io)) | |
d1de3d34 | 385 | return(EIO); |
2839b724 KB |
386 | break; |
387 | } | |
388 | ||
389 | case DSKIOCCERTIFY: { | |
390 | ||
391 | /* | |
392 | * Certify a disk track. The received argument is a pointer | |
393 | * to a "formatop" structure describing the track to certify. | |
394 | * | |
395 | * Send an mcb to the hdc to certify the track. | |
396 | * The controller returns data in which each longword | |
397 | * corresponds to a sector on the track; a 1 means no flaw, | |
398 | * a 0 means a flaw. | |
399 | */ | |
400 | ||
401 | register struct formatop *track; | |
402 | ||
403 | if (!hu->format) | |
d1de3d34 KB |
404 | return(1); |
405 | track = (struct formatop *)arg; | |
2839b724 KB |
406 | mcb = &hc->mcb; |
407 | mcb->command = HCMD_CERTIFY; | |
408 | mcb->drive = hu->slave; | |
d1de3d34 | 409 | mcb->chain[0].ta = (u_long)hu->phio_data; |
2839b724 KB |
410 | mcb->chain[0].lwc = hu->phys_sectors; |
411 | mcb->cyl = track->cylinder; | |
412 | mcb->head = track->head; | |
413 | mcb->sector = 0; | |
414 | if (hdmcb(mcb, io)) | |
d1de3d34 | 415 | return(EIO); |
2839b724 | 416 | track->flaw_count = 0; |
d1de3d34 KB |
417 | for (i = 0; i < hu->phys_sectors; i++) { |
418 | if (track->flaw_count >= MAXVFLAW) | |
419 | break; | |
420 | if (hu->phio_data[i] == 0) { | |
2839b724 KB |
421 | track->flaw[track->flaw_count] = i; |
422 | track->flaw_count++; | |
423 | } | |
424 | } | |
425 | break; | |
426 | } | |
427 | ||
428 | case DSKIOCVERIFY: { | |
429 | ||
430 | /* | |
431 | * Verify a disk track. The received argument is a pointer | |
432 | * to a "formatop" structure describing the track to verify. | |
433 | */ | |
434 | ||
435 | register struct formatop *track; | |
436 | ||
437 | if (!hu->format) | |
438 | return(1); | |
d1de3d34 | 439 | track = (struct formatop *)arg; |
2839b724 KB |
440 | mcb = &hc->mcb; |
441 | mcb->command = HCMD_VERIFY; | |
442 | mcb->drive = hu->slave; | |
443 | mcb->chain[0].ta = 0; | |
444 | mcb->chain[0].lwc = 0; | |
445 | mcb->cyl = track->cylinder; | |
446 | mcb->head = track->head; | |
447 | mcb->sector = 0; | |
448 | if (hdmcb(mcb, io)) | |
d1de3d34 | 449 | return(EIO); |
2839b724 KB |
450 | break; |
451 | } | |
452 | ||
453 | case DSKIOCFORMATCTL: { | |
454 | ||
455 | /* | |
456 | * This ioctl provides special format control. | |
457 | * Currently the valid arguments are: | |
458 | * | |
d1de3d34 | 459 | * arg = 0 disable formatting; |
2839b724 | 460 | * |
d1de3d34 KB |
461 | * arg = 1 enable formatting (allow privileged access); |
462 | * formatting must not already be enabled; | |
463 | * For formatting, change to use partition 7. | |
2839b724 KB |
464 | */ |
465 | ||
d1de3d34 KB |
466 | if (arg < 0 || arg > 1) |
467 | return(1); | |
468 | if (arg == 1) { | |
469 | if (hu->format) | |
470 | return(1); | |
2839b724 | 471 | /* If not already formatting.... */ |
d1de3d34 | 472 | hu->format = 1; |
3b94e226 | 473 | /* io->i_part = HDC_DEFPART; */ |
2839b724 KB |
474 | io->i_boff = hu->partition[HDC_DEFPART].start; |
475 | } | |
476 | else | |
d1de3d34 | 477 | hu->format = 0; |
2839b724 KB |
478 | break; |
479 | } | |
480 | ||
481 | case DSKIOCSTATUS: { | |
482 | ||
483 | /* | |
484 | * Return info about the disk. Caller's parameter is a | |
485 | * pointer to a dsk_status structure. | |
486 | */ | |
487 | ||
488 | register dsk_status *status; | |
489 | ||
d1de3d34 KB |
490 | status = (dsk_status *)arg; |
491 | status->id = hu->id; | |
492 | status->drive_status = 0; | |
493 | status->rpm = hu->rpm; | |
2839b724 | 494 | status->bytes_per_sec = hu->bytes_per_sec; |
d1de3d34 KB |
495 | status->cylinders = hu->cylinders; |
496 | status->heads = hu->heads; | |
497 | status->sectors = hu->sectors; | |
498 | status->phys_cylinders = hu->phys_cylinders; | |
499 | status->phys_heads = hu->phys_heads; | |
500 | status->phys_sectors = hu->phys_sectors; | |
501 | status->diag_cyl = hu->diag_cyl; | |
502 | status->diag_cylinders = hu->diag_cyl_count; | |
503 | status->def_cyl = hu->def_cyl; | |
504 | status->def_cylinders = hu->def_cyl_count; | |
2839b724 KB |
505 | break; |
506 | } | |
507 | ||
508 | case DSKIOCVENDORFLAW: { | |
509 | ||
510 | /* | |
511 | * Return vendor flaw info. | |
512 | * | |
513 | * Read in the vendor data (data for each track is at | |
514 | * relative sector 0 of the track); then copy the | |
515 | * vendor flaw data to the caller's buffer. | |
516 | */ | |
517 | ||
518 | register vflaw_type *vflaw; | |
519 | register struct flaw *vendor; | |
520 | ||
521 | if (!hu->format) | |
522 | return(1); | |
d1de3d34 | 523 | vflaw = (vflaw_type *)arg; |
2839b724 KB |
524 | mcb = &hc->mcb; |
525 | mcb->command = HCMD_VENDOR; | |
526 | mcb->drive = hu->slave; | |
527 | mcb->chain[0].lwc = HDC_VDATA_SIZE; | |
d1de3d34 | 528 | mcb->chain[0].ta = (u_long)hu->phio_data; |
2839b724 KB |
529 | mcb->cyl = vflaw->cylinder; |
530 | mcb->head = vflaw->head; | |
531 | mcb->sector = 0; | |
532 | if (hdmcb(mcb, io)) | |
d1de3d34 KB |
533 | return(EIO); |
534 | vendor = (struct flaw *)&hu->phio_data[0]; | |
535 | for (i = 0; i < MAXVFLAW; i++) { | |
2839b724 KB |
536 | vflaw->flaw[i].offset = vendor[i].offset; |
537 | vflaw->flaw[i].length = vendor[i].length; | |
538 | } | |
539 | break; | |
540 | } | |
541 | } | |
d1de3d34 | 542 | return(0); |
2839b724 KB |
543 | } |
544 | ||
545 | /************************************************************************* | |
546 | * Procedure: hdmcb | |
547 | * | |
d1de3d34 | 548 | * Description: Internal routine used to send mcb's to the hdc. |
2839b724 | 549 | * |
d1de3d34 KB |
550 | * Returns: 0 normal |
551 | * non-zero error occurred | |
2839b724 | 552 | **************************************************************************/ |
2839b724 | 553 | hdmcb(mcb, io) |
d1de3d34 KB |
554 | register mcb_type *mcb; /* mcb to send to the hdc */ |
555 | register struct iob *io; /* i/o block */ | |
2839b724 | 556 | { |
d1de3d34 KB |
557 | master_mcb_type *master_mcb; /* the hdc's master mcb */ |
558 | hdctlr_type *hc; /* hdc ctlr information table */ | |
559 | hdc_regs_type *ctlr_addr; /* pointer to hdc i/o registers */ | |
560 | int timeout; /* used to timeout the mcb */ | |
561 | int bus; /* bus number */ | |
562 | int ctlr; /* the controller number */ | |
563 | int i, end; | |
564 | u_int *ptr; | |
565 | ||
566 | bus = 0; /* io->i_bus; */ | |
567 | ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ | |
2839b724 KB |
568 | hc = &hdc_ctlr[ctlr][bus]; |
569 | ||
570 | mcb->interrupt = FALSE; | |
571 | mcb->priority = 0; | |
572 | mcb->forw_phaddr = 0; | |
573 | mcb->context = 0; | |
574 | mcb->reserved[0] = 0; | |
575 | mcb->reserved[1] = 0; | |
576 | master_mcb = &hc->master_mcb; | |
d1de3d34 | 577 | master_mcb->forw_phaddr = (long)&mcb->forw_phaddr; |
2839b724 KB |
578 | master_mcb->mcs = 0; |
579 | master_mcb->interrupt = 0; | |
d1de3d34 KB |
580 | master_mcb->reserve1 = 0; |
581 | master_mcb->reserve2 = 0; | |
582 | master_mcb->context = 0; | |
2839b724 | 583 | master_mcb->mcl = MCL_IMMEDIATE; |
d1de3d34 KB |
584 | for (i = 0; i < HDC_XSTAT_SIZE; i++) |
585 | master_mcb->xstatus[i] = 0; | |
586 | ctlr_addr = hc->registers; | |
587 | HDREG(master_mcb_reg) = (u_long)master_mcb; | |
2839b724 | 588 | timeout = 15000; |
d1de3d34 | 589 | for (;;) { |
2839b724 | 590 | DELAY(1000); |
3b94e226 | 591 | mtpr(PADC, 0); |
d1de3d34 KB |
592 | if (master_mcb->mcs & MCS_DONE && |
593 | !(master_mcb->mcs & MCS_FATALERROR)) | |
594 | return(0); | |
2839b724 | 595 | timeout--; |
d1de3d34 KB |
596 | if (timeout > 0 && !(master_mcb->mcs & MCS_FATALERROR)) |
597 | continue; | |
598 | if (master_mcb->mcs & MCS_FATALERROR) | |
2839b724 KB |
599 | printf("hdc: controller fatal error\n"); |
600 | else | |
601 | printf("hdc: controller timed out\n"); | |
602 | ||
603 | printf("mmcb: "); | |
d1de3d34 KB |
604 | ptr = (u_int *)master_mcb; |
605 | for (i = 0; i < 8; i++) | |
606 | printf(" %x", ptr[i]); | |
607 | for (i = 7 + HDC_XSTAT_SIZE; i > 7; i--) { | |
2839b724 | 608 | end = i; |
d1de3d34 KB |
609 | if (ptr[i] != 0) |
610 | break; | |
2839b724 | 611 | } |
d1de3d34 KB |
612 | for (i = 8; i <= end; i++) |
613 | printf(" %x", ptr[i]); | |
2839b724 KB |
614 | printf("\n"); |
615 | ||
616 | printf("mcb: "); | |
d1de3d34 KB |
617 | ptr = (u_int *)&mcb->forw_phaddr; |
618 | for (i = 0; i < 6; i++) | |
619 | printf(" %x", ptr[i]); | |
620 | for (i = 6; i < 72; i += 2) { | |
2839b724 | 621 | printf(" %x %x", ptr[i], ptr[i+1]); |
d1de3d34 KB |
622 | if (!(ptr[i] & 0x80000000)) |
623 | break; | |
2839b724 KB |
624 | } |
625 | printf("\n"); | |
626 | return(1); | |
627 | } | |
628 | } |