minimal fixes to update 4.3 distribution
[unix-history] / usr / src / sys / tahoe / vba / vd.c
CommitLineData
7bae1a62 1/* vd.c 1.14 87/02/18 */
210a9f40 2
ad409ece 3#include "dk.h"
210a9f40
SL
4#if NVD > 0
5/*
7bae1a62 6 * Versabus VDDC/SMDE driver.
9d915fad 7 */
9d915fad
SL
8#include "param.h"
9#include "buf.h"
10#include "cmap.h"
11#include "conf.h"
12#include "dir.h"
ad409ece 13#include "dkstat.h"
7bae1a62 14#include "disklabel.h"
9d915fad 15#include "map.h"
7bae1a62 16#include "file.h"
9d915fad
SL
17#include "systm.h"
18#include "user.h"
19#include "vmmac.h"
20#include "proc.h"
21#include "uio.h"
82bc5dc5
MK
22#include "syslog.h"
23#include "kernel.h"
7bae1a62 24#include "ioctl.h"
9d915fad 25
997cf0e7
MK
26#include "../tahoe/cpu.h"
27#include "../tahoe/mtpr.h"
28#include "../tahoe/pte.h"
29
9d915fad 30#include "../tahoevba/vbavar.h"
c7c48d07 31#include "../tahoevba/vdreg.h"
9d915fad 32
7bae1a62 33#define COMPAT_42
210a9f40 34
7bae1a62 35#define VDMAXIO (MAXBPTE*NBPG)
9d915fad 36
7bae1a62
SL
37#define vdunit(dev) (minor(dev) >> 3)
38#define vdpart(dev) (minor(dev) & 0x07)
39#define vdminor(unit,part) (((unit) << 3) | (part))
210a9f40
SL
40
41struct vba_ctlr *vdminfo[NVD];
ad409ece 42struct vba_device *vddinfo[NDK];
9d915fad 43int vdprobe(), vdslave(), vdattach(), vddgo();
7bae1a62 44long vdaddr[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
9d915fad 45struct vba_driver vddriver =
7bae1a62
SL
46 { vdprobe, vdslave, vdattach, vddgo, vdaddr, "dk", vddinfo, "vd", vdminfo };
47
48/*
49 * Per-controller state.
50 */
51struct vdsoftc {
52 u_short vd_flags;
53#define VD_INIT 0x1 /* controller initialized */
54#define VD_STARTED 0x2 /* start command issued */
55#define VD_DOSEEKS 0x4 /* should overlap seeks */
56 u_short vd_type; /* controller type */
57 u_short vd_wticks; /* timeout */
58 u_short vd_offcyl; /* off cylinder bitmask */
59 struct mdcb vd_mdcb; /* master command block */
60 u_long vd_mdcbphys; /* physical address of vd_mdcb */
61 struct dcb vd_dcb; /* i/o command block */
62 u_long vd_dcbphys; /* physical address of vd_dcb */
63 struct pte *vd_map; /* i/o page map */
64 caddr_t vd_utl; /* mapped i/o space */
65 caddr_t vd_rawbuf; /* buffer for raw+swap i/o */
66} vdsoftc[NVD];
210a9f40
SL
67
68/*
9d915fad
SL
69 * Per-drive state.
70 */
7bae1a62
SL
71struct dksoftc {
72 u_short dk_state; /* open fsm */
73 u_short dk_openpart; /* units open on this drive */
74 u_short dk_bshift; /* shift for * (DEV_BSIZE / sectorsize) XXX */
75 u_short dk_curdaddr; /* last selected track & sector */
76 u_int dk_curcyl; /* last selected cylinder */
77 struct dcb dk_dcb; /* seek command block */
78 u_long dk_dcbphys; /* physical address of dk_dcb */
79} dksoftc[NDK];
210a9f40
SL
80
81/*
7bae1a62
SL
82 * Drive states. Used during steps of open/initialization.
83 * States < OPEN (> 0) are transient, during an open operation.
84 * OPENRAW is used for unabeled disks, to allow format operations.
9d915fad 85 */
7bae1a62
SL
86#define CLOSED 0 /* disk is closed */
87#define WANTOPEN 1 /* open requested, not started */
88#define WANTOPENRAW 2 /* open requested, no label */
89#define RDLABEL 3 /* reading pack label */
90#define OPEN 4 /* intialized and ready */
91#define OPENRAW 5 /* open, no label */
92
93struct buf rdkbuf[NDK]; /* raw i/o buffer headers */
94struct buf dkutab[NDK]; /* i/o queue headers */
95struct disklabel dklabel[NDK]; /* pack labels */
96
97#define b_cylin b_resid
98#define b_daddr b_error
99
100int vdwstart, vdwatch();
210a9f40
SL
101
102/*
9d915fad
SL
103 * See if the controller is really there; if so, initialize it.
104 */
336ca318
SL
105vdprobe(reg, vm)
106 caddr_t reg;
107 struct vba_ctlr *vm;
210a9f40 108{
336ca318 109 register br, cvec; /* must be r12, r11 */
7bae1a62
SL
110 register struct vddevice *vdaddr = (struct vddevice *)reg;
111 struct vdsoftc *vd;
336ca318 112
82bc5dc5
MK
113#ifdef lint
114 br = 0; cvec = br; br = cvec;
115 vdintr(0);
116#endif
336ca318 117 if (badaddr((caddr_t)reg, 2))
9d915fad 118 return (0);
7bae1a62
SL
119 vd = &vdsoftc[vm->um_ctlr];
120 vdaddr->vdreset = 0xffffffff;
9d915fad 121 DELAY(1000000);
7bae1a62
SL
122 if (vdaddr->vdreset != (unsigned)0xffffffff) {
123 vd->vd_type = VDTYPE_VDDC;
124 vd->vd_flags &= ~VD_DOSEEKS;
9d915fad
SL
125 DELAY(1000000);
126 } else {
7bae1a62
SL
127 vd->vd_type = VDTYPE_SMDE;
128 vd->vd_flags |= VD_DOSEEKS;
129 vdaddr->vdrstclr = 0;
9d915fad 130 DELAY(3000000);
7bae1a62
SL
131 vdaddr->vdcsr = 0;
132 vdaddr->vdtcf_mdcb = AM_ENPDA;
133 vdaddr->vdtcf_dcb = AM_ENPDA;
134 vdaddr->vdtcf_trail = AM_ENPDA;
135 vdaddr->vdtcf_data = AM_ENPDA;
136 vdaddr->vdccf = CCF_SEN | CCF_DER | CCF_STS |
227f7a3e 137 XMD_32BIT | BSZ_16WRD |
7c4f3479 138 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
210a9f40 139 }
7bae1a62
SL
140 vd->vd_mdcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_mdcb);
141 vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);
142 vm->um_addr = reg; /* XXX */
143 if (!vdcmd(vm, VDOP_INIT, 10) || !vdcmd(vm, VDOP_DIAG, 10)) {
144 printf("vd%d: %s cmd failed\n", vm->um_ctlr,
145 vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
146 return (0);
147 }
7c4f3479 148 /*
f60fa697 149 * Allocate page tables and i/o buffer.
7c4f3479 150 */
7bae1a62
SL
151 vbmapalloc(btoc(VDMAXIO)+1, &vd->vd_map, &vd->vd_utl);
152 vd->vd_rawbuf = calloc(VDMAXIO);
336ca318 153 br = 0x17, cvec = 0xe0 + vm->um_ctlr; /* XXX */
7bae1a62 154 return (sizeof (struct vddevice));
9d915fad 155}
210a9f40
SL
156
157/*
7bae1a62
SL
158 * See if a drive is really there.
159 *
160 * Can't read pack label here as various data structures
161 * aren't setup for doing a read in a straightforward
162 * manner. Instead just probe for the drive and leave
163 * the pack label stuff to the attach routine.
9d915fad
SL
164 */
165vdslave(vi, addr)
166 register struct vba_device *vi;
7bae1a62 167 struct vddevice *vdaddr;
210a9f40 168{
7bae1a62
SL
169 register struct disklabel *lp = &dklabel[vi->ui_unit];
170 struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
9d915fad 171
7bae1a62 172 if ((vd->vd_flags&VD_INIT) == 0) {
7c4f3479 173 printf("vd%d: %s controller\n", vi->ui_ctlr,
7bae1a62
SL
174 vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");
175 vd->vd_flags |= VD_INIT;
210a9f40 176 }
7bae1a62 177
210a9f40 178 /*
7bae1a62
SL
179 * Initialize label enough to do a reset on
180 * the drive. The remainder of the default
181 * label values will be filled in in vdinit
182 * at attach time.
210a9f40 183 */
7bae1a62
SL
184 lp->d_secsize = DEV_BSIZE / 2; /* XXX */
185 lp->d_nsectors = 32;
186 lp->d_ntracks = 24;
187 lp->d_ncylinders = 711;
188 lp->d_secpercyl = 32*24;
189 return (vdreset_drive(vi));
9d915fad
SL
190}
191
7bae1a62
SL
192/*
193 * Read pack label.
194 */
195vdattach(vi)
196 register struct vba_device *vi;
9d915fad 197{
7bae1a62
SL
198 register int unit = vi->ui_unit;
199 register struct dksoftc *dk = &dksoftc[unit];
200 register struct disklabel *lp;
201
202 if (vdwstart == 0) {
203 timeout(vdwatch, (caddr_t)0, hz);
204 vdwstart++;
9d915fad 205 }
7bae1a62
SL
206 /*
207 * Try to initialize device and read pack label.
208 */
209 if (vdinit(vdminor(unit, 0), 0) != 0) {
210 printf(": unknown drive type");
211 return;
9d915fad 212 }
7bae1a62
SL
213 /*
214 * Initialize invariant portion of
215 * dcb used for overlapped seeks.
216 */
217 dk->dk_dcb.opcode = VDOP_SEEK;
218 dk->dk_dcb.intflg = DCBINT_NONE | DCBINT_PBA;
219 dk->dk_dcb.devselect = vi->ui_slave;
220 dk->dk_dcb.trailcnt = sizeof (trseek) / sizeof (long);
221 dk->dk_dcb.trail.sktrail.skaddr.sector = 0;
222 dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);
223 lp = &dklabel[unit];
224 printf(": %s <ntrak %d, ncyl %d, nsec %d>",
225 lp->d_typename, lp->d_ntracks, lp->d_ncylinders, lp->d_nsectors);
226 /*
227 * (60 / rpm) / (sectors per track * (bytes per sector / 2))
228 */
229 if (vi->ui_dk >= 0)
230 dk_mspw[vi->ui_dk] = 120.0 /
231 (lp->d_rpm * lp->d_nsectors * lp->d_secsize);
232#ifdef notyet
233 addwap(makedev(VDMAJOR, vdminor(unit, 0)), &dklabel[unit]);
234#endif
9d915fad
SL
235}
236
7bae1a62
SL
237/*ARGSUSED*/
238vdopen(dev, flags)
239 dev_t dev;
240 int flags;
9d915fad 241{
7bae1a62
SL
242 register unit = vdunit(dev);
243 register struct disklabel *lp;
244 register struct dksoftc *dk;
245 register struct partition *pp;
246 struct vba_device *vi;
247 int s, error, part = vdpart(dev);
248 daddr_t start, end;
249
250 if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
251 return (ENXIO);
252 lp = &dklabel[unit];
253 dk = &dksoftc[unit];
9d915fad 254
7bae1a62
SL
255 s = spl7();
256 while (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
257 dk->dk_state != CLOSED)
258 sleep((caddr_t)dk, PZERO+1);
259 splx(s);
260 if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
261 if (error = vdinit(dev, flags))
262 return (error);
263 /*
264 * Warn if a partion is opened
265 * that overlaps another partition which is open
266 * unless one is the "raw" partition (whole disk).
267 */
268#define RAWPART 2 /* 'c' partition */ /* XXX */
269 if ((dk->dk_openpart & (1 << part)) == 0 &&
270 part != RAWPART) {
271 pp = &lp->d_partitions[part];
272 start = pp->p_offset;
273 end = pp->p_offset + pp->p_size;
274 for (pp = lp->d_partitions;
275 pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
276 if (pp->p_offset + pp->p_size <= start ||
277 pp->p_offset >= end)
278 continue;
279 if (pp - lp->d_partitions == RAWPART)
280 continue;
281 if (dk->dk_openpart & (1 << (pp - lp->d_partitions)))
282 log(LOG_WARNING,
283 "dk%d%c: overlaps open partition (%c)\n",
284 unit, part + 'a',
285 pp - lp->d_partitions + 'a');
286 }
9d915fad 287 }
7bae1a62
SL
288 if (part >= lp->d_npartitions)
289 return (ENXIO);
290 dk->dk_openpart |= 1 << part;
291 return (0);
9d915fad
SL
292}
293
7bae1a62
SL
294vdclose(dev, flags)
295 dev_t dev;
296 int flags;
9d915fad 297{
7bae1a62
SL
298 register int unit = vdunit(dev);
299 register struct dksoftc *dk = &dksoftc[unit];
300
301 dk->dk_openpart &= ~(1 << vdpart(dev));
302#ifdef notdef
303 /*
304 * Should wait for i/o to complete on this partition
305 * even if others are open, but wait for work on blkflush().
306 */
307 if (dk->dk_openpart == 0) {
308 struct vba_device *vi = vddinfo[unit];
309 int s;
310
311 s = spl7();
312 /* can't sleep on b_actf, it might be async. */
313 while (vi->ui_tab.b_actf)
314 sleep((caddr_t)&vi->ui_tab.b_actf, PZERO-1);
315 splx(s);
316 dk->dk_state = CLOSED;
210a9f40 317 }
7bae1a62 318#endif
210a9f40
SL
319}
320
7bae1a62
SL
321vdinit(dev, flags)
322 dev_t dev;
323 int flags;
210a9f40 324{
7bae1a62
SL
325 register struct buf *bp = NULL;
326 register struct disklabel *lp;
327 register struct dksoftc *dk;
328 struct vba_device *vi;
329 struct disklabel *dlp;
330 int unit = vdunit(dev), error = 0;
331 extern int cold;
332
333 dk = &dksoftc[unit];
334 if (flags & O_NDELAY) {
335 dk->dk_state = OPENRAW;
336 goto done;
337 }
338
339 /*
340 * Initialize portion of the label
341 * not set up in the slave routine.
342 */
343 dk->dk_bshift = 1; /* DEV_BSIZE / 512 */
344 dk->dk_state = RDLABEL;
345 lp = &dklabel[unit];
346 lp->d_secperunit = 0x1fffffff;
347 lp->d_npartitions = 1;
348 lp->d_partitions[0].p_size = 0x1fffffff;
349 lp->d_partitions[0].p_offset = 0;
350
351 bp = geteblk(DEV_BSIZE); /* max sector size */
352 bp->b_dev = dev;
353 bp->b_blkno = LABELSECTOR;
354 bp->b_bcount = DEV_BSIZE;
355 bp->b_flags = B_BUSY | B_READ;
356 bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
357 vdstrategy(bp);
358 biowait(bp);
359 if (bp->b_flags & B_ERROR) {
360 error = u.u_error; /* XXX */
361 u.u_error = 0;
362 dk->dk_state = CLOSED;
363 goto done;
364 }
365 vi = vddinfo[unit];
366 dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
367 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
368 dkcksum(dlp) == 0) {
369 *lp = *dlp;
370 /*
371 * Now that we have the label, configure
372 * the correct drive parameters.
373 */
374 if (!vdreset_drive(vi))
375 dk->dk_state = CLOSED;
376 else
377 dk->dk_state = OPEN;
9d915fad 378 } else {
7bae1a62
SL
379 if (cold)
380 printf(": no disk label");
381 else
382 log(LOG_ERR, "dk%d: no disk label\n", vi->ui_unit);
383#ifdef COMPAT_42
384 if (!vdmaptype(vi, lp)) {
385 error = ENXIO;
386 dk->dk_state = CLOSED;
387 } else
388 dk->dk_state = OPEN;
389#else
390 dk->dk_state = OPENRAW;
391#endif
9d915fad 392 }
7bae1a62 393done:
9d915fad 394 /*
7bae1a62
SL
395 * If open, calculate scaling shift for
396 * mapping DEV_BSIZE blocks to drive sectors.
9d915fad 397 */
7bae1a62
SL
398 if (dk->dk_state == OPEN || dk->dk_state == OPENRAW) {
399 int mul = DEV_BSIZE / lp->d_secsize;
400 dk->dk_bshift = 0;
401 while ((mul >>= 1) > 0)
402 dk->dk_bshift++;
403 }
404 if (bp) {
405 bp->b_flags = B_INVAL | B_AGE;
406 brelse(bp);
407 }
408 wakeup((caddr_t)dk);
409 return (error);
210a9f40
SL
410}
411
9d915fad 412/*ARGSUSED*/
7bae1a62
SL
413vddgo(vm)
414 struct vba_device *vm;
210a9f40 415{
9d915fad 416
210a9f40
SL
417}
418
419vdstrategy(bp)
9d915fad 420 register struct buf *bp;
210a9f40 421{
7bae1a62
SL
422 register struct vba_device *vi;
423 register struct disklabel *lp;
424 register struct dksoftc *dk;
425 register int unit;
426 struct buf *dp;
427 daddr_t sz, sn, maxsz;
428 int part, s;
429
430 sz = bp->b_bcount;
431 sz = (sz + DEV_BSIZE - 1) >> DEV_BSHIFT;
432 unit = vdunit(bp->b_dev);
433 if (unit > NDK) {
434 bp->b_error = ENXIO;
435 goto bad;
436 }
437 vi = vddinfo[unit];
438 lp = &dklabel[unit];
439 if (vi == 0 || vi->ui_alive == 0) {
1e9609f2 440 bp->b_error = ENXIO;
9d915fad 441 goto bad;
1e9609f2 442 }
7bae1a62
SL
443 dk = &dksoftc[unit];
444 if (dk->dk_state < OPEN)
445 goto q;
446 part = vdpart(bp->b_dev);
447 if ((dk->dk_openpart & (1 << part)) == 0) {
448 bp->b_error = ENODEV;
449 goto bad;
450 }
451 maxsz = lp->d_partitions[part].p_size;
452 sn = bp->b_blkno << dk->dk_bshift;
453 if (sn < 0 || sn + sz > maxsz) {
454 if (sn == maxsz) {
1e9609f2
MK
455 bp->b_resid = bp->b_bcount;
456 goto done;
457 }
7bae1a62
SL
458 bp->b_error = EINVAL;
459 goto bad;
210a9f40 460 }
7bae1a62
SL
461 bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
462q:
463 vbasetup(bp, lp->d_secsize);
9d915fad 464 s = spl7();
7bae1a62
SL
465 dp = &dkutab[vi->ui_unit];
466 disksort(dp, bp);
467 if (!dp->b_active) {
468 (void) vdustart(vi);
469 bp = &vi->ui_mi->um_tab;
470 if (bp->b_actf && !bp->b_active)
471 vdstart(vi->ui_mi);
9d915fad 472 }
7bae1a62 473 splx(s);
210a9f40 474 return;
9d915fad 475bad:
1e9609f2
MK
476 bp->b_flags |= B_ERROR;
477done:
7bae1a62
SL
478 biodone(bp);
479 return;
210a9f40
SL
480}
481
7bae1a62
SL
482vdustart(vi)
483 register struct vba_device *vi;
9d915fad 484{
7bae1a62
SL
485 register struct buf *bp, *dp;
486 register struct vba_ctlr *vm;
487 register int unit = vi->ui_unit;
488 register struct dksoftc *dk;
489 register struct vdsoftc *vd;
490 struct disklabel *lp;
491
492 dk_busy &= ~(1<<vi->ui_dk);
493 dp = &dkutab[unit];
494 /*
495 * If queue empty, nothing to do.
496 */
497 if ((bp = dp->b_actf) == NULL)
498 return;
499 /*
500 * If drive is off-cylinder, mark unit to force
501 * overlap seek with next transfer on this controller.
502 */
503 vd = &vdsoftc[vi->ui_ctlr];
504 dk = &dksoftc[unit];
505 if (bp->b_cylin != dk->dk_curcyl && vd->vd_flags&VD_DOSEEKS) {
506 int sn = bp->b_blkno << dk->dk_bshift;
507 lp = &dklabel[unit];
508 bp->b_daddr = (sn % lp->d_secpercyl) / lp->d_nsectors;
509 if (bp->b_daddr != dk->dk_curdaddr)
510 vd->vd_offcyl |= 1 << vi->ui_slave;
511 }
512 /*
513 * If controller is not busy, place request on the
514 * controller's ready queue (unless its already there).
515 */
516 if (!dp->b_active) {
517 dp->b_forw = NULL;
518 vm = vi->ui_mi;
519 if (vm->um_tab.b_actf == NULL)
520 vm->um_tab.b_actf = dp;
521 else
522 vm->um_tab.b_actl->b_forw = dp;
523 vm->um_tab.b_actl = dp;
524 dp->b_active++;
525 }
9d915fad
SL
526}
527
528/*
7bae1a62 529 * Start next transfer on a controller.
9d915fad 530 */
7bae1a62
SL
531vdstart(vm)
532 register struct vba_ctlr *vm;
9d915fad 533{
9d915fad 534 register struct buf *bp;
7bae1a62
SL
535 register struct vba_device *vi;
536 register struct vdsoftc *vd;
537 register struct dksoftc *dk;
538 register struct disklabel *lp;
539 register int slave;
540 register struct dcb **dcbp;
541 struct mdcb *mdcb;
542 struct buf *dp;
543 int sn, tn;
544
545loop:
546 /*
547 * Pull a request off the controller queue.
548 */
549 if ((dp = vm->um_tab.b_actf) == NULL)
550 return;
551 if ((bp = dp->b_actf) == NULL) {
552 vm->um_tab.b_actf = dp->b_forw;
553 goto loop;
554 }
9d915fad 555
210a9f40 556 /*
7bae1a62
SL
557 * Mark controller busy, and determine
558 * destination of this request.
210a9f40 559 */
7bae1a62
SL
560 vm->um_tab.b_active++;
561 vi = vddinfo[vdunit(bp->b_dev)];
562 dk = &dksoftc[vi->ui_unit];
563 sn = bp->b_blkno << dk->dk_bshift;
564 lp = &dklabel[vi->ui_unit];
565 sn %= lp->d_secpercyl;
566 tn = sn / lp->d_nsectors;
567 sn %= lp->d_nsectors;
210a9f40 568
7bae1a62
SL
569 /*
570 * Construct dcb for read/write command.
571 */
572 vd = &vdsoftc[vm->um_ctlr];
573 slave = vi->ui_slave;
574 vd->vd_dcb.opcode = (bp->b_flags & B_READ) ? VDOP_RD : VDOP_WD;
575 vd->vd_dcb.intflg = DCBINT_DONE;
576 vd->vd_dcb.devselect = slave;
577 vd->vd_dcb.operrsta = 0;
578 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
579 vd->vd_dcb.trailcnt = sizeof (trrw) / sizeof (long);
580 vd->vd_dcb.trail.rwtrail.memadr = (char *)
581 vbastart(bp, vd->vd_rawbuf, (long *)vd->vd_map, vd->vd_utl);
582 vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
583 vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
584 vd->vd_dcb.trail.rwtrail.disk.track = tn;
585 vd->vd_dcb.trail.rwtrail.disk.sector = sn;
9d915fad 586
7bae1a62
SL
587 /*
588 * Look for any seeks to be performed on other drives on this
589 * controller. If overlapped seeks exist, insert seek commands
590 * on the controller's command queue before the transfer.
591 */
592 dcbp = &vd->vd_mdcb.mdcb_head;
593 if (vd->vd_offcyl &~ (1<<slave)) {
594 register struct dksoftc *tdk;
595 register struct buf *tp;
596
597 for (dp = dp->b_forw; dp != NULL; dp = dp->b_forw) {
598 if ((tp = dp->b_actf) == NULL)
599 continue;
600 slave = (vi = vddinfo[vdunit(tp->b_dev)])->ui_slave;
601 if ((vd->vd_offcyl & (1<<slave)) == 0)
602 continue;
603 vd->vd_offcyl &= ~(1 << slave);
604 tdk = &dksoftc[vi->ui_unit];
605 if (tdk->dk_curcyl != tp->b_cylin) {
606 tdk->dk_curcyl = tp->b_cylin;
607 dk_seek[vi->ui_dk]++;
608 }
609 tdk->dk_curdaddr = tp->b_daddr;
610 tdk->dk_dcb.operrsta = 0;
611 tdk->dk_dcb.trail.sktrail.skaddr.cylinder = tp->b_cylin;
612 tdk->dk_dcb.trail.sktrail.skaddr.track = tp->b_daddr>>8;
613 tdk->dk_dcb.trail.sktrail.skaddr.sector =
614 tp->b_daddr & 0xff;
615 *dcbp = (struct dcb *)tdk->dk_dcbphys;
616 dcbp = &tdk->dk_dcb.nxtdcb;
617 }
618 } else {
619 dk->dk_curcyl = bp->b_cylin;
620 dk->dk_curdaddr = (tn << 8) | sn;
621 vd->vd_offcyl = 0;
9d915fad 622 }
7bae1a62
SL
623 *dcbp = (struct dcb *)vd->vd_dcbphys;
624
625 /*
626 * Initiate operation.
627 */
628 bp->b_daddr = 0; /* init overloaded field */
629 if (vi->ui_dk >= 0) {
630 dk_busy |= 1<<vi->ui_dk;
631 dk_xfer[vi->ui_dk]++;
632 dk_wds[vi->ui_dk] += bp->b_bcount>>6;
9d915fad 633 }
7bae1a62
SL
634 vd->vd_mdcb.mdcb_status = 0;
635 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
9d915fad 636}
210a9f40 637
7bae1a62 638#define DONTCARE (DCBS_DSE|DCBS_DSL|DCBS_TOP|DCBS_TOM|DCBS_FAIL|DCBS_DONE)
210a9f40
SL
639/*
640 * Handle a disk interrupt.
641 */
9d915fad 642vdintr(ctlr)
7bae1a62 643 register ctlr;
210a9f40 644{
7bae1a62
SL
645 register struct buf *bp, *dp;
646 register struct vba_ctlr *vm = vdminfo[ctlr];
647 register struct vba_device *vi;
648 register struct vdsoftc *vd = &vdsoftc[ctlr];
649 register status;
650
651 vd->vd_wticks = 0;
652 if (!vm->um_tab.b_active) {
9d915fad 653 printf("vd%d: stray interrupt\n", ctlr);
210a9f40
SL
654 return;
655 }
9d915fad 656 /*
7bae1a62
SL
657 * Get device and block structures, and a pointer
658 * to the vba_device for the drive.
9d915fad 659 */
7bae1a62
SL
660 dp = vm->um_tab.b_actf;
661 bp = dp->b_actf;
662 vi = vddinfo[vdunit(bp->b_dev)];
663 dk_busy &= ~(1<<vi->ui_dk);
664 /*
665 * Check for and process errors on
666 * either the drive or the controller.
667 */
668 uncache(&vd->vd_dcb.operrsta);
669 status = vd->vd_dcb.operrsta;
670 if (status & VDERR_HARD) {
671 if (status & DCBS_WPT) {
672 /*
673 * Give up on write locked devices immediately.
674 */
675 printf("dk%d: write locked\n", vdunit(bp->b_dev));
676 bp->b_flags |= B_ERROR;
677 } else if (status & VDERR_SOFT) {
678 if (status & VDERR_DRIVE) {
679 if (!vdreset_drive(vi))
680 vi->ui_alive = 0;
681 } else if (status & VDERR_CTLR)
682 vdreset_ctlr(vm);
683 /*
684 * Retry transfer once, unless reset failed.
685 */
686 if (!vi->ui_alive || bp->b_errcnt++ >= 2)
687 goto hard;
688 vm->um_tab.b_active = 0; /* force retry */
689 } else {
690 hard:
691 bp->b_flags |= B_ERROR;
692 /* NEED TO ADJUST b_blkno to failed sector */
693 harderr(bp, "dk");
694 printf("status %x (%b)", status,
695 status &~ DONTCARE, VDERRBITS);
696 if (vd->vd_type == VDTYPE_SMDE) {
697 uncache(&vd->vd_dcb.err_code);
698 printf(" ecode %x", vd->vd_dcb.err_code);
699 }
700 printf("\n");
9d915fad 701 }
7bae1a62
SL
702 } else if (status & DCBS_SOFT)
703 vdsofterr(vd, bp, &vd->vd_dcb);
704 if (vm->um_tab.b_active) {
705 vm->um_tab.b_active = 0;
706 vm->um_tab.b_errcnt = 0;
707 vm->um_tab.b_actf = dp->b_forw;
708 dp->b_active = 0;
709 dp->b_errcnt = 0;
710 dp->b_actf = bp->av_forw;
9d915fad 711 bp->b_resid = 0;
7bae1a62
SL
712 vbadone(bp, vd->vd_rawbuf, (long *)vd->vd_map, vd->vd_utl);
713 biodone(bp);
714 /*
715 * If this unit has more work to do,
716 * then start it up right away.
717 */
718 if (dp->b_actf)
719 vdustart(vi);
210a9f40 720 }
9d915fad 721 /*
7bae1a62
SL
722 * If there are devices ready to
723 * transfer, start the controller.
9d915fad 724 */
7bae1a62
SL
725 if (vm->um_tab.b_actf)
726 vdstart(vm);
210a9f40
SL
727}
728
7bae1a62
SL
729vdsofterr(vd, bp, dcb)
730 struct vdsoftc *vd;
9d915fad 731 register struct buf *bp;
7bae1a62 732 register struct dcb *dcb;
9d915fad 733{
7bae1a62
SL
734 int unit = vdunit(bp->b_dev), status = dcb->operrsta;
735 char part = 'a' + vdpart(bp->b_dev);
82bc5dc5 736
7bae1a62
SL
737 if (status != (DCBS_DCE|DCBS_CCD|DCBS_SOFT|DCBS_ERR)) {
738 if (vd->vd_type == VDTYPE_SMDE)
739 uncache(&dcb->err_code);
740 log(LOG_WARNING, "dk%d%c: soft error sn%d status %b ecode %x\n",
741 unit, part, bp->b_blkno, status, VDERRBITS, dcb->err_code);
742 } else
82bc5dc5
MK
743 log(LOG_WARNING, "dk%d%c: soft ecc sn%d\n",
744 unit, part, bp->b_blkno);
9d915fad 745}
210a9f40
SL
746
747vdread(dev, uio)
9d915fad
SL
748 dev_t dev;
749 struct uio *uio;
210a9f40 750{
7bae1a62 751 register int unit = vdunit(dev);
210a9f40 752
ad409ece 753 if (unit >= NDK)
9d915fad 754 return (ENXIO);
7bae1a62 755 return (physio(vdstrategy, &rdkbuf[unit], dev, B_READ, minphys, uio));
210a9f40
SL
756}
757
758vdwrite(dev, uio)
9d915fad
SL
759 dev_t dev;
760 struct uio *uio;
210a9f40 761{
7bae1a62 762 register int unit = vdunit(dev);
210a9f40 763
ad409ece 764 if (unit >= NDK)
9d915fad 765 return (ENXIO);
7bae1a62 766 return (physio(vdstrategy, &rdkbuf[unit], dev, B_WRITE, minphys, uio));
210a9f40
SL
767}
768
7bae1a62 769vdioctl(dev, cmd, data, flag)
9d915fad 770 dev_t dev;
7bae1a62
SL
771 int cmd;
772 caddr_t data;
773 int flag;
210a9f40 774{
7bae1a62
SL
775 int unit = vdunit(dev);
776 register struct disklabel *lp = &dklabel[unit];
777 int error = 0;
778
779 switch (cmd) {
780
781 case DIOCGDINFO:
782 *(struct disklabel *)data = *lp;
783 break;
784
785 case DIOCGDINFOP:
786 *(struct disklabel **)data = lp;
787 break;
788
789 case DIOCSDINFO:
790 if ((flag & FWRITE) == 0)
791 error = EBADF;
792 else
793 *lp = *(struct disklabel *)data;
794 break;
795
796 case DIOCWDINFO: {
797 struct buf *bp;
798 struct disklabel *dlp;
799
800 if ((flag & FWRITE) == 0) {
801 error = EBADF;
802 break;
803 }
804 *lp = *(struct disklabel *)data;
805 bp = geteblk(lp->d_secsize);
806 bp->b_dev = dev;
807 bp->b_blkno = LABELSECTOR;
808 bp->b_bcount = lp->d_secsize;
809 bp->b_flags = B_READ;
810 dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
811 vdstrategy(bp);
812 biowait(bp);
813 if (bp->b_flags & B_ERROR) {
814 error = u.u_error; /* XXX */
815 u.u_error = 0;
816 goto bad;
817 }
818 *dlp = *lp;
819 bp->b_flags = B_WRITE;
820 vdstrategy(bp);
821 biowait(bp);
822 if (bp->b_flags & B_ERROR) {
823 error = u.u_error; /* XXX */
824 u.u_error = 0;
825 }
826bad:
827 brelse(bp);
828 break;
829 }
830
831 default:
832 error = ENOTTY;
833 break;
210a9f40 834 }
9d915fad 835 return (0);
210a9f40
SL
836}
837
9d915fad 838/*
7bae1a62 839 * Watch for lost interrupts.
9d915fad 840 */
7bae1a62 841vdwatch()
210a9f40 842{
7bae1a62
SL
843 register struct vdsoftc *vd;
844 register struct vba_ctlr *vm;
845 register int ctlr, unit;
846
847 timeout(vdwatch, (caddr_t)0, hz);
848 for (ctlr = 0; ctlr < NVD; ctlr++) {
849 vm = vdminfo[ctlr];
850 if (vm == 0 || vm->um_alive == 0)
851 continue;
852 vd = &vdsoftc[ctlr];
853 if (!vm->um_tab.b_active) {
854 for (unit = 0; unit < NDK; unit++)
855 if (dkutab[unit].b_active &&
856 vddinfo[unit]->ui_mi == vm)
857 goto active;
858 vd->vd_wticks = 0;
859 continue;
860 }
861active:
862 vd->vd_wticks++;
863 if (vd->vd_wticks >= 20) {
864 vd->vd_wticks = 0;
865 printf("vd%d: lost interrupt\n", ctlr);
866 /* abort pending dcb's and restart controller */
867 }
9d915fad 868 }
7bae1a62
SL
869}
870
871#define DBSIZE 64 /* controller limit with 1K sectors */
872/*
873 * Crash dump.
874 */
875vddump(dev)
876 dev_t dev;
877{
878 register struct vba_device *vi;
879 register struct vba_ctlr *vm;
880 register struct disklabel *lp;
881 register struct vdsoftc *vd;
882 struct dksoftc *dk;
883 int part, unit, num;
884 caddr_t start;
885
886 start = 0;
887 unit = vdunit(dev);
888 if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
889 return (ENXIO);
890 dk = &dksoftc[unit];
891 if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
892 return (ENXIO);
893 lp = &dklabel[unit];
894 part = vdpart(dev);
895 if (part >= lp->d_npartitions)
896 return (ENXIO);
897 vm = vdminfo[vi->ui_ctlr];
898 vdreset_ctlr(vm);
899 if (dumplo < 0)
900 return (EINVAL);
901 /*
902 * Dumplo and maxfree are in pages;
903 * dumplo will change soon (XXX).
904 */
905 num = maxfree * (NBPG / lp->d_secsize);
906 dumplo *= NBPG / lp->d_secsize; /* XXX */
907 if (dumplo + num >= lp->d_partitions[vdpart(dev)].p_size)
908 num = lp->d_partitions[vdpart(dev)].p_size - dumplo;
909 vd = &vdsoftc[vm->um_ctlr];
910 vd->vd_dcb.intflg = DCBINT_NONE;
911 vd->vd_dcb.opcode = VDOP_WD;
912 vd->vd_dcb.devselect = vi->ui_slave;
913 vd->vd_dcb.trailcnt = sizeof (trrw) / sizeof (long);
914 while (num > 0) {
915 int nsec, cn, sn, tn;
916
917 nsec = MIN(num, DBSIZE);
918 sn = dumplo + (unsigned)start / lp->d_secsize;
919 cn = (sn + lp->d_partitions[vdpart(dev)].p_offset) /
920 lp->d_secpercyl;
921 sn %= lp->d_secpercyl;
922 tn = sn / lp->d_nsectors;
923 sn %= lp->d_nsectors;
924 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
925 vd->vd_dcb.trail.rwtrail.memadr = start;
926 vd->vd_dcb.trail.rwtrail.wcount = (nsec * lp->d_secsize) >> 1;
927 vd->vd_dcb.trail.rwtrail.disk.cylinder = cn;
928 vd->vd_dcb.trail.rwtrail.disk.track = tn;
929 vd->vd_dcb.trail.rwtrail.disk.sector = sn;
930 vd->vd_dcb.operrsta = 0;
931 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
932 if (!vdpoll(vm, 5)) {
933 printf(" during dump\n");
934 return (EIO);
935 }
936 if (vd->vd_dcb.operrsta & VDERR_HARD) {
937 printf("dk%d: hard error, status=%b\n", unit,
938 vd->vd_dcb.operrsta, VDERRBITS);
939 return (EIO);
940 }
941 start += nsec * lp->d_secsize;
942 num -= nsec;
9d915fad 943 }
7bae1a62 944 return (0);
210a9f40
SL
945}
946
947vdsize(dev)
9d915fad 948 dev_t dev;
210a9f40 949{
7bae1a62
SL
950 register int unit = vdunit(dev);
951 register struct dksoftc *dk;
952 struct vba_device *vi;
953 struct disklabel *lp;
210a9f40 954
7bae1a62
SL
955 if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0 ||
956 (dk = &dksoftc[unit])->dk_state != OPEN)
9d915fad 957 return (-1);
7bae1a62
SL
958 lp = &dklabel[unit];
959 return ((int)lp->d_partitions[vdpart(dev)].p_size >> dk->dk_bshift);
210a9f40
SL
960}
961
9d915fad
SL
962/*
963 * Perform a controller reset.
964 */
7bae1a62
SL
965vdreset_ctlr(vm)
966 register struct vba_ctlr *vm;
210a9f40 967{
7bae1a62
SL
968 register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
969 register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
970 register int unit;
971 struct vba_device *vi;
9d915fad 972
7bae1a62
SL
973 VDRESET(vdaddr, vd->vd_type);
974 if (vd->vd_type == VDTYPE_SMDE) {
975 vdaddr->vdcsr = 0;
976 vdaddr->vdtcf_mdcb = AM_ENPDA;
977 vdaddr->vdtcf_dcb = AM_ENPDA;
978 vdaddr->vdtcf_trail = AM_ENPDA;
979 vdaddr->vdtcf_data = AM_ENPDA;
980 vdaddr->vdccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
9d915fad
SL
981 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
982 }
7bae1a62
SL
983 if (!vdcmd(vm, VDOP_INIT, 10) || !vdcmd(vm, VDOP_DIAG, 10)) {
984 printf("%s cmd failed\n",
985 vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
82bc5dc5 986 return;
9d915fad 987 }
7bae1a62
SL
988 for (unit = 0; unit < NDK; unit++)
989 if ((vi = vddinfo[unit])->ui_mi == vm && vi->ui_alive)
990 (void) vdreset_drive(vi);
991}
992
993vdreset_drive(vi)
994 register struct vba_device *vi;
995{
996 register struct disklabel *lp = &dklabel[vi->ui_unit];
997 struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
998 struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
999 struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
1000
1001top:
1002 vd->vd_dcb.opcode = VDOP_CONFIG; /* command */
1003 vd->vd_dcb.intflg = DCBINT_NONE;
1004 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
1005 vd->vd_dcb.operrsta = 0;
1006 vd->vd_dcb.devselect = vi->ui_slave;
1007 vd->vd_dcb.trail.rstrail.ncyl = lp->d_ncylinders;
1008 vd->vd_dcb.trail.rstrail.nsurfaces = lp->d_ntracks;
1009 if (vd->vd_type == VDTYPE_SMDE) {
1010 vd->vd_dcb.trailcnt = sizeof (treset) / sizeof (long);
1011 vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
1012 vd->vd_dcb.trail.rstrail.slip_sec = lp->d_trackskew;
1013 vd->vd_dcb.trail.rstrail.recovery = 0x18f;
1014 } else
1015 vd->vd_dcb.trailcnt = 2; /* XXX */
1016 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1017 vd->vd_mdcb.mdcb_status = 0;
1018 VDGO(vdaddr, vd->vd_mdcbphys, vd->vd_type);
1019 if (!vdpoll(vm, 5)) {
1020 printf(" during config\n");
1021 return (0);
9d915fad 1022 }
7bae1a62
SL
1023 if (vd->vd_dcb.operrsta & VDERR_HARD) {
1024 if (vd->vd_type == VDTYPE_SMDE &&
1025 (vdaddr->vdstatus[vi->ui_slave]&STA_US) == 0)
1026 return (0);
1027 if ((vd->vd_dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0)
1028 printf("dk%d: config error\n", vi->ui_unit);
1029 else if ((vd->vd_flags&VD_STARTED) == 0) {
1030 int started;
1031
1032 printf("vd%d: starting drives, wait ... ", vm->um_ctlr);
1033 vd->vd_flags |= VD_STARTED;
1034 started = (vdcmd(vm, VDOP_START, 10) == 1);
1035 DELAY(62000000);
1036 printf("\n");
1037 if (started)
1038 goto top;
1039 }
1040 return (0);
1041 }
1042 return (1);
9d915fad 1043}
210a9f40 1044
9d915fad 1045/*
7bae1a62 1046 * Perform a command w/o trailer.
9d915fad 1047 */
7bae1a62
SL
1048vdcmd(vm, cmd, t)
1049 register struct vba_ctlr *vm;
9d915fad 1050{
7bae1a62
SL
1051 register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
1052
1053 vd->vd_dcb.opcode = cmd; /* command */
1054 vd->vd_dcb.intflg = DCBINT_NONE;
1055 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
1056 vd->vd_dcb.operrsta = 0;
1057 vd->vd_dcb.devselect = 0;
1058 vd->vd_dcb.trailcnt = 0;
1059 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1060 vd->vd_mdcb.mdcb_status = 0;
1061 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
1062 if (!vdpoll(vm, t)) {
1063 printf(" during init\n");
82bc5dc5
MK
1064 return (0);
1065 }
7bae1a62 1066 return ((vd->vd_dcb.operrsta&VDERR_HARD) == 0);
9d915fad
SL
1067}
1068
7c4f3479 1069/*
7bae1a62
SL
1070 * Poll controller until operation
1071 * completes or timeout expires.
7c4f3479 1072 */
7bae1a62
SL
1073vdpoll(vm, t)
1074 register struct vba_ctlr *vm;
7c4f3479
SL
1075 register int t;
1076{
7bae1a62
SL
1077 register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
1078 register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
7c4f3479
SL
1079
1080 t *= 1000;
82bc5dc5 1081 for (;;) {
7bae1a62
SL
1082 uncache(&vd->vd_dcb.operrsta);
1083 if (vd->vd_dcb.operrsta & (DCBS_DONE|DCBS_ABORT))
82bc5dc5 1084 break;
7c4f3479 1085 if (--t <= 0) {
7bae1a62
SL
1086 printf("vd%d: controller timeout", vm->um_ctlr);
1087 VDABORT(vdaddr, vd->vd_type);
7c4f3479 1088 DELAY(30000);
7c4f3479
SL
1089 return (0);
1090 }
82bc5dc5 1091 DELAY(1000);
7c4f3479 1092 }
7bae1a62
SL
1093 if (vd->vd_type == VDTYPE_SMDE) {
1094 do {
82bc5dc5 1095 DELAY(50);
7bae1a62
SL
1096 uncache(&vdaddr->vdcsr);
1097 } while (vdaddr->vdcsr & CS_GO);
7c4f3479
SL
1098 DELAY(300);
1099 }
1100 DELAY(200);
7bae1a62 1101 uncache(&vd->vd_dcb.operrsta);
7c4f3479
SL
1102 return (1);
1103}
1104
7bae1a62
SL
1105#ifdef COMPAT_42
1106struct vdst {
1107 int nsec; /* sectors/track */
1108 int ntrack; /* tracks/cylinder */
1109 int ncyl; /* cylinders */
1110 char *name; /* type name */
1111 struct {
1112 int off; /* partition offset in sectors */
1113 int size; /* partition size in sectors */
1114 } parts[3];
1115} vdst[] = {
1116 { 48, 24, 711, "xsd", {0,61056}, {61056,61056}, {122112,691200} },
1117 { 44, 20, 842, "egl", {0,52800}, {52800,66000}, {118800,617760} },
1118 { 64, 10, 823, "fuj", {0,38400}, {38400,48000}, { 86400,437120} },
1119 { 32, 24, 711, "xfd", {0,40704}, {40704,40704}, { 81408,460800} },
1120 { 32, 19, 823, "smd", {0,40128}, {40128,27360}, { 67488,429856} },
1121 { 32, 10, 823, "fsd", {0,19200}, {19200,24000}, { 43200,218560} }
1122};
1123#define NVDST (sizeof (vdst) / sizeof (vdst[0]))
1124
9d915fad 1125/*
7bae1a62
SL
1126 * Construct a label for an unlabeled pack. We
1127 * deduce the drive type by reading from the last
1128 * track on successively smaller drives until we
1129 * don't get an error.
9d915fad 1130 */
7bae1a62
SL
1131vdmaptype(vi, lp)
1132 register struct vba_device *vi;
1133 register struct disklabel *lp;
9d915fad 1134{
7bae1a62
SL
1135 register struct vdsoftc *vd;
1136 register struct vdst *p;
1137 struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
1138 int i;
9d915fad 1139
7bae1a62
SL
1140 vd = &vdsoftc[vi->ui_ctlr];
1141 for (p = vdst; p < &vdst[NVDST]; p++) {
1142 if (vd->vd_type == VDTYPE_VDDC && p->nsec != 32)
1143 continue;
1144 lp->d_nsectors = p->nsec;
1145 lp->d_ntracks = p->ntrack;
1146 lp->d_ncylinders = p->ncyl;
1147 if (!vdreset_drive(vi))
1148 return (0);
1149 vd->vd_dcb.opcode = VDOP_RD;
1150 vd->vd_dcb.intflg = DCBINT_NONE;
1151 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
1152 vd->vd_dcb.devselect = vi->ui_slave;
1153 vd->vd_dcb.trailcnt = sizeof (trrw) / sizeof (long);
1154 vd->vd_dcb.trail.rwtrail.memadr = (char *)
1155 vtoph((struct proc *)0, (unsigned)vd->vd_rawbuf);
1156 vd->vd_dcb.trail.rwtrail.wcount = 512 / sizeof(short);
1157 vd->vd_dcb.operrsta = 0;
1158 vd->vd_dcb.trail.rwtrail.disk.cylinder = p->ncyl - 2;
1159 vd->vd_dcb.trail.rwtrail.disk.track = p->ntrack - 1;
1160 vd->vd_dcb.trail.rwtrail.disk.sector = p->nsec - 1;
1161 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1162 vd->vd_mdcb.mdcb_status = 0;
1163 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
1164 if (!vdpoll(vm, 60))
1165 printf(" during probe\n");
1166 if ((vd->vd_dcb.operrsta & VDERR_HARD) == 0)
1167 break;
210a9f40 1168 }
7bae1a62
SL
1169 if (p >= &vdst[NVDST]) {
1170 printf("dk%d: unknown drive type\n", vi->ui_unit);
1171 return (0);
1172 }
1173 for (i = 0; i < 3; i++) {
1174 lp->d_partitions[i].p_offset = p->parts[i].off;
1175 lp->d_partitions[i].p_size = p->parts[i].size;
1176 }
1177 lp->d_npartitions = 3;
1178 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
1179 lp->d_rpm = 3600;
1180 lp->d_secsize = 512;
1181 bcopy(p->name, lp->d_typename, 4);
1182 return (1);
210a9f40 1183}
7bae1a62 1184#endif COMPAT_42
9d915fad 1185#endif