BSD 4_3_Reno development
[unix-history] / .ref-fdb8e4aac282b72d4670aa3a26d9bba07afc7e6f / usr / src / sys / tahoe / vba / vd.c
CommitLineData
2149e3ac
MK
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
677067f0
MK
5 * This code is derived from software contributed to Berkeley by
6 * Computer Consoles Inc.
7 *
b702c21d 8 * %sccs.include.redist.c%
2149e3ac 9 *
b28b3a13 10 * @(#)vd.c 7.13 (Berkeley) %G%
2149e3ac 11 */
210a9f40 12
ad409ece 13#include "dk.h"
210a9f40
SL
14#if NVD > 0
15/*
7bae1a62 16 * Versabus VDDC/SMDE driver.
9d915fad 17 */
b28b3a13
KB
18#include "sys/param.h"
19#include "sys/buf.h"
20#include "sys/cmap.h"
21#include "sys/conf.h"
22#include "sys/dkstat.h"
23#include "sys/disklabel.h"
24#include "sys/map.h"
25#include "sys/file.h"
26#include "sys/systm.h"
27#include "sys/user.h"
28#include "sys/vmmac.h"
29#include "sys/proc.h"
30#include "sys/syslog.h"
31#include "sys/kernel.h"
32#include "sys/ioctl.h"
33#include "sys/stat.h"
9d915fad 34
b28b3a13
KB
35#include "../include/cpu.h"
36#include "../include/mtpr.h"
37#include "../include/pte.h"
997cf0e7 38
b28b3a13
KB
39#include "../vba/vbavar.h"
40#include "../vba/vdreg.h"
9d915fad 41
f9e93bbe 42#ifndef COMPAT_42
7bae1a62 43#define COMPAT_42
f9e93bbe 44#endif
81304755 45#define B_FORMAT B_XXX /* XXX */
210a9f40 46
7bae1a62
SL
47#define vdunit(dev) (minor(dev) >> 3)
48#define vdpart(dev) (minor(dev) & 0x07)
49#define vdminor(unit,part) (((unit) << 3) | (part))
210a9f40
SL
50
51struct vba_ctlr *vdminfo[NVD];
ad409ece 52struct vba_device *vddinfo[NDK];
d99b7c9d 53int vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();
2149e3ac 54long vdstd[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
9d915fad 55struct vba_driver vddriver =
2149e3ac 56 { vdprobe, vdslave, vdattach, vddgo, vdstd, "dk", vddinfo, "vd", vdminfo };
7bae1a62
SL
57
58/*
59 * Per-controller state.
60 */
61struct vdsoftc {
62 u_short vd_flags;
261c73f6 63#define VD_PRINT 0x1 /* controller info printed */
7bae1a62
SL
64#define VD_STARTED 0x2 /* start command issued */
65#define VD_DOSEEKS 0x4 /* should overlap seeks */
d99b7c9d 66#define VD_SCATGATH 0x8 /* can do scatter-gather commands (correctly) */
2d1c4664
MK
67#define VD_LOCKED 0x10 /* locked for direct controller access */
68#define VD_WAIT 0x20 /* someone needs direct controller access */
7bae1a62
SL
69 u_short vd_type; /* controller type */
70 u_short vd_wticks; /* timeout */
261c73f6 71 u_short vd_secsize; /* sector size for controller */
7bae1a62
SL
72 struct mdcb vd_mdcb; /* master command block */
73 u_long vd_mdcbphys; /* physical address of vd_mdcb */
74 struct dcb vd_dcb; /* i/o command block */
75 u_long vd_dcbphys; /* physical address of vd_dcb */
1f9a1539 76 struct vb_buf vd_rbuf; /* vba resources */
7bae1a62 77} vdsoftc[NVD];
210a9f40 78
81304755
MK
79#define VDMAXTIME 20 /* max time for operation, sec. */
80
210a9f40 81/*
9d915fad
SL
82 * Per-drive state.
83 */
7bae1a62 84struct dksoftc {
60d9b6a0 85 int dk_state; /* open fsm */
d99b7c9d
MK
86#ifndef SECSIZE
87 u_short dk_bshift; /* shift for * (DEV_BSIZE / sectorsize) XXX */
88#endif SECSIZE
60d9b6a0 89 int dk_wlabel; /* label sector is currently writable */
7e9892e0
MK
90 u_long dk_copenpart; /* character units open on this drive */
91 u_long dk_bopenpart; /* block units open on this drive */
92 u_long dk_openpart; /* all units open on this drive */
7bae1a62 93 u_int dk_curcyl; /* last selected cylinder */
d99b7c9d 94 struct skdcb dk_dcb; /* seek command block */
7bae1a62 95 u_long dk_dcbphys; /* physical address of dk_dcb */
81304755 96 int df_reg[3]; /* for formatting, in-out parameters */
7bae1a62 97} dksoftc[NDK];
210a9f40
SL
98
99/*
7bae1a62
SL
100 * Drive states. Used during steps of open/initialization.
101 * States < OPEN (> 0) are transient, during an open operation.
60d9b6a0 102 * OPENRAW is used for unlabeled disks, to allow format operations.
9d915fad 103 */
7bae1a62
SL
104#define CLOSED 0 /* disk is closed */
105#define WANTOPEN 1 /* open requested, not started */
106#define WANTOPENRAW 2 /* open requested, no label */
107#define RDLABEL 3 /* reading pack label */
108#define OPEN 4 /* intialized and ready */
109#define OPENRAW 5 /* open, no label */
110
7bae1a62
SL
111struct buf dkutab[NDK]; /* i/o queue headers */
112struct disklabel dklabel[NDK]; /* pack labels */
113
114#define b_cylin b_resid
2bb994d6
MK
115#define b_track b_error /* used for seek commands */
116#define b_seekf b_forw /* second queue on um_tab */
117#define b_seekl b_back /* second queue on um_tab */
7bae1a62
SL
118
119int vdwstart, vdwatch();
210a9f40
SL
120
121/*
9d915fad
SL
122 * See if the controller is really there; if so, initialize it.
123 */
336ca318
SL
124vdprobe(reg, vm)
125 caddr_t reg;
126 struct vba_ctlr *vm;
210a9f40 127{
336ca318 128 register br, cvec; /* must be r12, r11 */
7bae1a62
SL
129 register struct vddevice *vdaddr = (struct vddevice *)reg;
130 struct vdsoftc *vd;
4f42a6a1 131 int s;
336ca318 132
82bc5dc5
MK
133#ifdef lint
134 br = 0; cvec = br; br = cvec;
135 vdintr(0);
136#endif
336ca318 137 if (badaddr((caddr_t)reg, 2))
9d915fad 138 return (0);
7bae1a62
SL
139 vd = &vdsoftc[vm->um_ctlr];
140 vdaddr->vdreset = 0xffffffff;
9d915fad 141 DELAY(1000000);
7bae1a62
SL
142 if (vdaddr->vdreset != (unsigned)0xffffffff) {
143 vd->vd_type = VDTYPE_VDDC;
144 vd->vd_flags &= ~VD_DOSEEKS;
9d915fad
SL
145 DELAY(1000000);
146 } else {
7bae1a62
SL
147 vd->vd_type = VDTYPE_SMDE;
148 vd->vd_flags |= VD_DOSEEKS;
149 vdaddr->vdrstclr = 0;
9d915fad 150 DELAY(3000000);
210a9f40 151 }
7bae1a62
SL
152 vd->vd_mdcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_mdcb);
153 vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);
154 vm->um_addr = reg; /* XXX */
4f42a6a1 155 s = spl7();
261c73f6 156 if (vdinit_ctlr(vm, vd) == 0) {
4f42a6a1 157 splx(s);
7bae1a62
SL
158 return (0);
159 }
d99b7c9d 160 if (vd->vd_type == VDTYPE_SMDE) {
261c73f6
MK
161#ifdef notdef
162 /*
163 * Attempt PROBE to get all drive status;
164 * we take advantage of this in vdreset_drive
165 * to try to avoid guessing games.
166 */
167 (void) vdcmd(vm, VDOP_PROBE, 5, 0);
168#endif
169 /*
170 * Check for scatter-gather by checking firmware date
171 * with IDENT command. The date is printed when
172 * vdslave is first called, thus this must be
173 * the last controller operation in vdprobe.
174 */
d99b7c9d 175 vd->vd_dcb.trail.idtrail.date = 0;
07cd2d63 176 if (vdcmd(vm, VDOP_IDENT, 10, 0)) {
d99b7c9d
MK
177 uncache(&vd->vd_dcb.trail.idtrail.date);
178 if (vd->vd_dcb.trail.idtrail.date != 0)
179 vd->vd_flags |= VD_SCATGATH;
180 }
181 }
4f42a6a1 182 splx(s);
7c4f3479 183 /*
f60fa697 184 * Allocate page tables and i/o buffer.
7c4f3479 185 */
f9e93bbe
MK
186 if (vbainit(&vd->vd_rbuf, MAXPHYS,
187 vd->vd_type == VDTYPE_VDDC ? VB_24BIT : VB_32BIT) == 0) {
188 printf("vd%d: vbainit failed\n", vm->um_ctlr);
189 return (0);
190 }
336ca318 191 br = 0x17, cvec = 0xe0 + vm->um_ctlr; /* XXX */
7bae1a62 192 return (sizeof (struct vddevice));
9d915fad 193}
210a9f40
SL
194
195/*
7bae1a62
SL
196 * See if a drive is really there.
197 *
198 * Can't read pack label here as various data structures
199 * aren't setup for doing a read in a straightforward
200 * manner. Instead just probe for the drive and leave
201 * the pack label stuff to the attach routine.
9d915fad 202 */
60d9b6a0
MK
203/* ARGSUSED */
204vdslave(vi, vdaddr)
9d915fad 205 register struct vba_device *vi;
7bae1a62 206 struct vddevice *vdaddr;
210a9f40 207{
7bae1a62 208 register struct disklabel *lp = &dklabel[vi->ui_unit];
f9e93bbe 209 register struct dksoftc *dk = &dksoftc[vi->ui_unit];
7bae1a62 210 struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
261c73f6 211 int bcd();
9d915fad 212
261c73f6 213 if ((vd->vd_flags&VD_PRINT) == 0) {
07cd2d63
MK
214 printf("vd%d: %s controller", vi->ui_ctlr,
215 vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");
216 if (vd->vd_flags & VD_SCATGATH) {
217 char rev[5];
218
219 bcopy((caddr_t)&vd->vd_dcb.trail.idtrail.rev, rev,
220 sizeof(vd->vd_dcb.trail.idtrail.rev));
221 printf(" firmware rev %s (%d-%d-%d)", rev,
261c73f6
MK
222 bcd((vd->vd_dcb.trail.idtrail.date >> 8) & 0xff),
223 bcd(vd->vd_dcb.trail.idtrail.date & 0xff),
224 bcd((vd->vd_dcb.trail.idtrail.date >> 16)&0xffff));
07cd2d63
MK
225 }
226 printf("\n");
261c73f6 227 vd->vd_flags |= VD_PRINT;
210a9f40 228 }
7bae1a62 229
210a9f40 230 /*
7bae1a62
SL
231 * Initialize label enough to do a reset on
232 * the drive. The remainder of the default
233 * label values will be filled in in vdinit
234 * at attach time.
210a9f40 235 */
f9e93bbe
MK
236 if (vd->vd_type == VDTYPE_SMDE)
237 lp->d_secsize = VD_MAXSECSIZE;
238 else
239 lp->d_secsize = VDDC_SECSIZE;
81304755 240 lp->d_nsectors = 66; /* only used on smd-e */
60d9b6a0 241 lp->d_ntracks = 23;
81304755
MK
242 lp->d_ncylinders = 850;
243 lp->d_secpercyl = 66*23;
07cd2d63 244 lp->d_rpm = 3600;
35841c05
MK
245 lp->d_npartitions = 1;
246 lp->d_partitions[0].p_offset = 0;
247 lp->d_partitions[0].p_size = LABELSECTOR + 1;
7bae1a62 248
7bae1a62
SL
249 /*
250 * Initialize invariant portion of
251 * dcb used for overlapped seeks.
252 */
253 dk->dk_dcb.opcode = VDOP_SEEK;
254 dk->dk_dcb.intflg = DCBINT_NONE | DCBINT_PBA;
255 dk->dk_dcb.devselect = vi->ui_slave;
d99b7c9d 256 dk->dk_dcb.trailcnt = sizeof (struct trseek) / sizeof (long);
7bae1a62
SL
257 dk->dk_dcb.trail.sktrail.skaddr.sector = 0;
258 dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);
f9e93bbe
MK
259#ifndef SECSIZE
260 vd_setsecsize(dk, lp);
261#endif
262 return (vdreset_drive(vi));
263}
264
261c73f6
MK
265static int
266bcd(n)
267 register u_int n;
268{
269 register int bin = 0;
270 register int mul = 1;
271
272 while (n) {
273 bin += (n & 0xf) * mul;
274 n >>= 4;
275 mul *= 10;
276 }
277 return (bin);
278}
279
f9e93bbe
MK
280vdattach(vi)
281 register struct vba_device *vi;
282{
283 register int unit = vi->ui_unit;
284 register struct disklabel *lp = &dklabel[unit];
285
1f9a1539
MK
286 /*
287 * Try to initialize device and read pack label.
288 */
289 if (vdinit(vdminor(unit, 0), 0) != 0) {
290 printf(": unknown drive type");
291 return;
292 }
f9e93bbe
MK
293 if (dksoftc[unit].dk_state == OPEN)
294 printf(": %s <secsize %d, ntrak %d, ncyl %d, nsec %d>",
295 lp->d_typename, lp->d_secsize,
296 lp->d_ntracks, lp->d_ncylinders, lp->d_nsectors);
7bae1a62
SL
297 /*
298 * (60 / rpm) / (sectors per track * (bytes per sector / 2))
299 */
300 if (vi->ui_dk >= 0)
80b6b780
KM
301 dk_wpms[vi->ui_dk] =
302 (lp->d_rpm * lp->d_nsectors * lp->d_secsize) / 120;
7bae1a62 303#ifdef notyet
4f42a6a1 304 addswap(makedev(VDMAJOR, vdminor(unit, 0)), lp);
7bae1a62 305#endif
9d915fad
SL
306}
307
d99b7c9d 308vdopen(dev, flags, fmt)
7bae1a62 309 dev_t dev;
d99b7c9d 310 int flags, fmt;
9d915fad 311{
7bae1a62
SL
312 register unit = vdunit(dev);
313 register struct disklabel *lp;
314 register struct dksoftc *dk;
315 register struct partition *pp;
316 struct vba_device *vi;
261c73f6 317 int s, error = 0, part = vdpart(dev), mask = 1 << part;
7bae1a62
SL
318 daddr_t start, end;
319
320 if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
321 return (ENXIO);
322 lp = &dklabel[unit];
323 dk = &dksoftc[unit];
9d915fad 324
7bae1a62
SL
325 s = spl7();
326 while (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
327 dk->dk_state != CLOSED)
261c73f6
MK
328 if (error = tsleep((caddr_t)dk, (PZERO+1) | PCATCH, devopn, 0))
329 break;
7bae1a62 330 splx(s);
261c73f6
MK
331 if (error)
332 return (error);
7bae1a62
SL
333 if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
334 if (error = vdinit(dev, flags))
335 return (error);
4f42a6a1
MK
336
337 if (vdwstart == 0) {
338 timeout(vdwatch, (caddr_t)0, hz);
339 vdwstart++;
340 }
7bae1a62
SL
341 /*
342 * Warn if a partion is opened
343 * that overlaps another partition which is open
344 * unless one is the "raw" partition (whole disk).
345 */
f9e93bbe 346#define RAWPART 8 /* 'x' partition */ /* XXX */
7e9892e0 347 if ((dk->dk_openpart & mask) == 0 && part != RAWPART) {
7bae1a62
SL
348 pp = &lp->d_partitions[part];
349 start = pp->p_offset;
350 end = pp->p_offset + pp->p_size;
351 for (pp = lp->d_partitions;
352 pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
353 if (pp->p_offset + pp->p_size <= start ||
354 pp->p_offset >= end)
355 continue;
356 if (pp - lp->d_partitions == RAWPART)
357 continue;
358 if (dk->dk_openpart & (1 << (pp - lp->d_partitions)))
359 log(LOG_WARNING,
360 "dk%d%c: overlaps open partition (%c)\n",
361 unit, part + 'a',
362 pp - lp->d_partitions + 'a');
363 }
9d915fad 364 }
7bae1a62
SL
365 if (part >= lp->d_npartitions)
366 return (ENXIO);
d99b7c9d
MK
367 dk->dk_openpart |= mask;
368 switch (fmt) {
369 case S_IFCHR:
370 dk->dk_copenpart |= mask;
371 break;
372 case S_IFBLK:
373 dk->dk_bopenpart |= mask;
374 break;
375 }
7bae1a62 376 return (0);
9d915fad
SL
377}
378
2149e3ac 379/* ARGSUSED */
d99b7c9d 380vdclose(dev, flags, fmt)
7bae1a62 381 dev_t dev;
d99b7c9d 382 int flags, fmt;
9d915fad 383{
7bae1a62
SL
384 register int unit = vdunit(dev);
385 register struct dksoftc *dk = &dksoftc[unit];
d99b7c9d 386 int part = vdpart(dev), mask = 1 << part;
7bae1a62 387
d99b7c9d
MK
388 switch (fmt) {
389 case S_IFCHR:
390 dk->dk_copenpart &= ~mask;
391 break;
392 case S_IFBLK:
393 dk->dk_bopenpart &= ~mask;
394 break;
395 }
396 if (((dk->dk_copenpart | dk->dk_bopenpart) & mask) == 0)
397 dk->dk_openpart &= ~mask;
7bae1a62
SL
398 /*
399 * Should wait for i/o to complete on this partition
400 * even if others are open, but wait for work on blkflush().
401 */
402 if (dk->dk_openpart == 0) {
4f42a6a1
MK
403 int s = spl7();
404 while (dkutab[unit].b_actf)
405 sleep((caddr_t)dk, PZERO-1);
7bae1a62
SL
406 splx(s);
407 dk->dk_state = CLOSED;
60d9b6a0 408 dk->dk_wlabel = 0;
210a9f40 409 }
d99b7c9d 410 return (0);
210a9f40
SL
411}
412
7bae1a62
SL
413vdinit(dev, flags)
414 dev_t dev;
415 int flags;
210a9f40 416{
7bae1a62
SL
417 register struct disklabel *lp;
418 register struct dksoftc *dk;
419 struct vba_device *vi;
7bae1a62 420 int unit = vdunit(dev), error = 0;
d99b7c9d 421 char *msg, *readdisklabel();
7bae1a62
SL
422 extern int cold;
423
424 dk = &dksoftc[unit];
425 if (flags & O_NDELAY) {
426 dk->dk_state = OPENRAW;
2149e3ac 427 return (0);
7bae1a62 428 }
7bae1a62
SL
429 dk->dk_state = RDLABEL;
430 lp = &dklabel[unit];
7bae1a62 431 vi = vddinfo[unit];
d99b7c9d 432 if (msg = readdisklabel(dev, vdstrategy, lp)) {
60d9b6a0 433 if (cold) {
1f9a1539 434 printf(": %s", msg);
60d9b6a0
MK
435 dk->dk_state = CLOSED;
436 } else {
f9e93bbe 437 log(LOG_ERR, "dk%d: %s\n", unit, msg);
d99b7c9d 438 dk->dk_state = OPENRAW;
60d9b6a0
MK
439 }
440#ifdef COMPAT_42
2d1c4664 441 vdlock(vi->ui_ctlr);
60d9b6a0 442 if (vdmaptype(vi, lp))
7bae1a62 443 dk->dk_state = OPEN;
2d1c4664 444 vdunlock(vi->ui_ctlr);
7bae1a62 445#endif
d99b7c9d
MK
446 } else {
447 /*
448 * Now that we have the label, configure
449 * the correct drive parameters.
450 */
2d1c4664 451 vdlock(vi->ui_ctlr);
f9e93bbe
MK
452 if (vdreset_drive(vi))
453 dk->dk_state = OPEN;
454 else {
d99b7c9d
MK
455 dk->dk_state = CLOSED;
456 error = ENXIO;
f9e93bbe 457 }
2d1c4664 458 vdunlock(vi->ui_ctlr);
9d915fad 459 }
d99b7c9d 460#ifndef SECSIZE
f9e93bbe
MK
461 vd_setsecsize(dk, lp);
462#endif
7bae1a62
SL
463 wakeup((caddr_t)dk);
464 return (error);
210a9f40
SL
465}
466
f9e93bbe
MK
467#ifndef SECSIZE
468vd_setsecsize(dk, lp)
469 register struct dksoftc *dk;
470 register struct disklabel *lp;
471{
472 int mul;
473
474 /*
475 * Calculate scaling shift for mapping
476 * DEV_BSIZE blocks to drive sectors.
477 */
478 mul = DEV_BSIZE / lp->d_secsize;
479 dk->dk_bshift = 0;
480 while ((mul >>= 1) > 0)
481 dk->dk_bshift++;
482}
483#endif SECSIZE
484
9d915fad 485/*ARGSUSED*/
7bae1a62
SL
486vddgo(vm)
487 struct vba_device *vm;
210a9f40 488{
9d915fad 489
210a9f40
SL
490}
491
492vdstrategy(bp)
9d915fad 493 register struct buf *bp;
210a9f40 494{
7bae1a62
SL
495 register struct vba_device *vi;
496 register struct disklabel *lp;
497 register struct dksoftc *dk;
498 register int unit;
4f42a6a1 499 register daddr_t sn;
7bae1a62 500 struct buf *dp;
4f42a6a1 501 daddr_t sz, maxsz;
7bae1a62
SL
502 int part, s;
503
7bae1a62 504 unit = vdunit(bp->b_dev);
f9e93bbe 505 if (unit >= NDK) {
7bae1a62
SL
506 bp->b_error = ENXIO;
507 goto bad;
508 }
509 vi = vddinfo[unit];
510 lp = &dklabel[unit];
511 if (vi == 0 || vi->ui_alive == 0) {
1e9609f2 512 bp->b_error = ENXIO;
9d915fad 513 goto bad;
1e9609f2 514 }
7bae1a62 515 dk = &dksoftc[unit];
261c73f6
MK
516 if (dk->dk_state < OPEN) {
517 if (dk->dk_state == CLOSED) {
518 bp->b_error = EIO;
519 goto bad;
520 }
7bae1a62 521 goto q;
261c73f6 522 }
60d9b6a0
MK
523 if (dk->dk_state != OPEN && (bp->b_flags & B_READ) == 0) {
524 bp->b_error = EROFS;
525 goto bad;
526 }
7bae1a62
SL
527 part = vdpart(bp->b_dev);
528 if ((dk->dk_openpart & (1 << part)) == 0) {
529 bp->b_error = ENODEV;
530 goto bad;
531 }
f9e93bbe 532 sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
7bae1a62 533 maxsz = lp->d_partitions[part].p_size;
d99b7c9d
MK
534#ifndef SECSIZE
535 sn = bp->b_blkno << dk->dk_bshift;
536#else SECSIZE
4f42a6a1 537 sn = bp->b_blkno;
d99b7c9d 538#endif SECSIZE
60d9b6a0
MK
539 if (sn + lp->d_partitions[part].p_offset <= LABELSECTOR &&
540#if LABELSECTOR != 0
541 sn + lp->d_partitions[part].p_offset + sz > LABELSECTOR &&
542#endif
543 (bp->b_flags & B_READ) == 0 && dk->dk_wlabel == 0) {
544 bp->b_error = EROFS;
545 goto bad;
546 }
7bae1a62
SL
547 if (sn < 0 || sn + sz > maxsz) {
548 if (sn == maxsz) {
1e9609f2
MK
549 bp->b_resid = bp->b_bcount;
550 goto done;
551 }
d99b7c9d 552 sz = maxsz - sn;
4f42a6a1
MK
553 if (sz <= 0) {
554 bp->b_error = EINVAL;
555 goto bad;
556 }
557 bp->b_bcount = sz * lp->d_secsize;
210a9f40 558 }
7bae1a62 559 bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
d99b7c9d
MK
560#ifdef SECSIZE
561if (bp->b_blksize != lp->d_secsize && (bp->b_flags & B_PGIN) == 0)
562panic("vdstrat blksize");
563#endif SECSIZE
7bae1a62 564q:
9d915fad 565 s = spl7();
7bae1a62
SL
566 dp = &dkutab[vi->ui_unit];
567 disksort(dp, bp);
568 if (!dp->b_active) {
569 (void) vdustart(vi);
4f42a6a1 570 if (!vi->ui_mi->um_tab.b_active)
7bae1a62 571 vdstart(vi->ui_mi);
9d915fad 572 }
7bae1a62 573 splx(s);
210a9f40 574 return;
9d915fad 575bad:
1e9609f2
MK
576 bp->b_flags |= B_ERROR;
577done:
7bae1a62
SL
578 biodone(bp);
579 return;
210a9f40
SL
580}
581
7bae1a62
SL
582vdustart(vi)
583 register struct vba_device *vi;
9d915fad 584{
7bae1a62
SL
585 register struct buf *bp, *dp;
586 register struct vba_ctlr *vm;
587 register int unit = vi->ui_unit;
588 register struct dksoftc *dk;
589 register struct vdsoftc *vd;
590 struct disklabel *lp;
591
7bae1a62
SL
592 dp = &dkutab[unit];
593 /*
594 * If queue empty, nothing to do.
595 */
596 if ((bp = dp->b_actf) == NULL)
597 return;
598 /*
2bb994d6
MK
599 * If drive is off-cylinder and controller supports seeks,
600 * place drive on seek queue for controller.
601 * Otherwise, place on transfer queue.
7bae1a62
SL
602 */
603 vd = &vdsoftc[vi->ui_ctlr];
604 dk = &dksoftc[unit];
2bb994d6 605 vm = vi->ui_mi;
7bae1a62 606 if (bp->b_cylin != dk->dk_curcyl && vd->vd_flags&VD_DOSEEKS) {
7bae1a62 607 lp = &dklabel[unit];
2bb994d6
MK
608 bp->b_track = (bp->b_blkno % lp->d_secpercyl) / lp->d_nsectors;
609 if (vm->um_tab.b_seekf == NULL)
610 vm->um_tab.b_seekf = dp;
611 else
612 vm->um_tab.b_seekl->b_forw = dp;
613 vm->um_tab.b_seekl = dp;
614 } else {
615 if (vm->um_tab.b_actf == NULL)
616 vm->um_tab.b_actf = dp;
617 else
618 vm->um_tab.b_actl->b_forw = dp;
619 vm->um_tab.b_actl = dp;
7bae1a62 620 }
4f42a6a1 621 dp->b_forw = NULL;
4f42a6a1 622 dp->b_active++;
9d915fad
SL
623}
624
625/*
7bae1a62 626 * Start next transfer on a controller.
2bb994d6
MK
627 * There are two queues of drives, the first on-cylinder
628 * and the second off-cylinder from their next transfers.
629 * Perform the first transfer for the first drive on the on-cylinder
630 * queue, if any, otherwise the first transfer for the first drive
631 * on the second queue. Initiate seeks on remaining drives on the
632 * off-cylinder queue, then move them all to the on-cylinder queue.
9d915fad 633 */
7bae1a62
SL
634vdstart(vm)
635 register struct vba_ctlr *vm;
9d915fad 636{
9d915fad 637 register struct buf *bp;
7bae1a62
SL
638 register struct vba_device *vi;
639 register struct vdsoftc *vd;
640 register struct dksoftc *dk;
641 register struct disklabel *lp;
7bae1a62 642 register struct dcb **dcbp;
7bae1a62
SL
643 struct buf *dp;
644 int sn, tn;
645
646loop:
647 /*
648 * Pull a request off the controller queue.
649 */
2bb994d6
MK
650 if ((dp = vm->um_tab.b_actf) == NULL &&
651 (dp = vm->um_tab.b_seekf) == NULL)
7bae1a62
SL
652 return;
653 if ((bp = dp->b_actf) == NULL) {
1f9a1539
MK
654 if (dp == vm->um_tab.b_actf)
655 vm->um_tab.b_actf = dp->b_forw;
656 else
657 vm->um_tab.b_seekf = dp->b_forw;
7bae1a62
SL
658 goto loop;
659 }
9d915fad 660
210a9f40 661 /*
7bae1a62
SL
662 * Mark controller busy, and determine
663 * destination of this request.
210a9f40 664 */
7bae1a62
SL
665 vm->um_tab.b_active++;
666 vi = vddinfo[vdunit(bp->b_dev)];
667 dk = &dksoftc[vi->ui_unit];
d99b7c9d
MK
668#ifndef SECSIZE
669 sn = bp->b_blkno << dk->dk_bshift;
670#else SECSIZE
4f42a6a1 671 sn = bp->b_blkno;
d99b7c9d 672#endif SECSIZE
7bae1a62
SL
673 lp = &dklabel[vi->ui_unit];
674 sn %= lp->d_secpercyl;
675 tn = sn / lp->d_nsectors;
676 sn %= lp->d_nsectors;
210a9f40 677
7bae1a62
SL
678 /*
679 * Construct dcb for read/write command.
680 */
681 vd = &vdsoftc[vm->um_ctlr];
7bae1a62 682 vd->vd_dcb.intflg = DCBINT_DONE;
f9e93bbe 683 vd->vd_dcb.devselect = dk->dk_dcb.devselect;
7bae1a62
SL
684 vd->vd_dcb.operrsta = 0;
685 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
7bae1a62
SL
686 vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
687 vd->vd_dcb.trail.rwtrail.disk.track = tn;
688 vd->vd_dcb.trail.rwtrail.disk.sector = sn;
2bb994d6
MK
689 dk->dk_curcyl = bp->b_cylin;
690 bp->b_track = 0; /* init overloaded field */
d99b7c9d 691 vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
81304755
MK
692 if (bp->b_flags & B_FORMAT)
693 vd->vd_dcb.opcode = dk->dk_op;
694 else if (vd->vd_flags & VD_SCATGATH &&
695 ((int)bp->b_un.b_addr & (sizeof(long) - 1)) == 0)
d99b7c9d 696 vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RAS : VDOP_GAW;
81304755 697 else
d99b7c9d 698 vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RD : VDOP_WD;
81304755
MK
699
700 switch (vd->vd_dcb.opcode) {
701 case VDOP_FSECT:
261c73f6 702 vd->vd_dcb.trailcnt = sizeof (struct trfmt) / sizeof (long);
81304755
MK
703 vd->vd_dcb.trail.fmtrail.nsectors = bp->b_bcount /
704 lp->d_secsize;
705 vd->vd_dcb.trail.fmtrail.hdr = *(dskadr *)&dk->dk_althdr;
706 vd->vd_dcb.trail.rwtrail.disk.cylinder |= dk->dk_fmtflags;
707 goto setupaddr;
708
709 case VDOP_RDRAW:
710 case VDOP_RD:
261c73f6 711 case VDOP_RHDE:
81304755
MK
712 case VDOP_WD:
713 vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
714setupaddr:
d99b7c9d 715 vd->vd_dcb.trail.rwtrail.memadr =
2149e3ac 716 vbasetup(bp, &vd->vd_rbuf, (int)lp->d_secsize);
81304755
MK
717 break;
718
719 case VDOP_RAS:
720 case VDOP_GAW:
d44a0516 721 vd->vd_dcb.trailcnt += vd_sgsetup(bp, &vd->vd_rbuf,
81304755
MK
722 &vd->vd_dcb.trail.sgtrail);
723 break;
d99b7c9d 724 }
2bb994d6
MK
725 if (vi->ui_dk >= 0) {
726 dk_busy |= 1<<vi->ui_dk;
727 dk_xfer[vi->ui_dk]++;
728 dk_wds[vi->ui_dk] += bp->b_bcount>>6;
729 }
9d915fad 730
7bae1a62
SL
731 /*
732 * Look for any seeks to be performed on other drives on this
733 * controller. If overlapped seeks exist, insert seek commands
734 * on the controller's command queue before the transfer.
735 */
736 dcbp = &vd->vd_mdcb.mdcb_head;
7bae1a62 737
2bb994d6
MK
738 if (dp == vm->um_tab.b_seekf)
739 dp = dp->b_forw;
740 else
741 dp = vm->um_tab.b_seekf;
742 for (; dp != NULL; dp = dp->b_forw) {
743 if ((bp = dp->b_actf) == NULL)
744 continue;
745 vi = vddinfo[vdunit(bp->b_dev)];
746 dk = &dksoftc[vi->ui_unit];
7bae1a62 747 dk->dk_curcyl = bp->b_cylin;
2bb994d6
MK
748 if (vi->ui_dk >= 0)
749 dk_seek[vi->ui_dk]++;
750 dk->dk_dcb.operrsta = 0;
751 dk->dk_dcb.trail.sktrail.skaddr.cylinder = bp->b_cylin;
2bb994d6 752 dk->dk_dcb.trail.sktrail.skaddr.track = bp->b_track;
2bb994d6
MK
753 *dcbp = (struct dcb *)dk->dk_dcbphys;
754 dcbp = &dk->dk_dcb.nxtdcb;
9d915fad 755 }
7bae1a62 756 *dcbp = (struct dcb *)vd->vd_dcbphys;
2bb994d6
MK
757 if (vm->um_tab.b_actf)
758 vm->um_tab.b_actl->b_forw = vm->um_tab.b_seekf;
759 else
760 vm->um_tab.b_actf = vm->um_tab.b_seekf;
1f9a1539
MK
761 if (vm->um_tab.b_seekf)
762 vm->um_tab.b_actl = vm->um_tab.b_seekl;
2bb994d6 763 vm->um_tab.b_seekf = 0;
7bae1a62
SL
764
765 /*
766 * Initiate operation.
767 */
7bae1a62
SL
768 vd->vd_mdcb.mdcb_status = 0;
769 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
9d915fad 770}
210a9f40 771
2d1c4664
MK
772/*
773 * Wait for controller to finish current operation
774 * so that direct controller accesses can be done.
775 */
776vdlock(ctlr)
777{
778 register struct vba_ctlr *vm = vdminfo[ctlr];
779 register struct vdsoftc *vd = &vdsoftc[ctlr];
780 int s;
781
782 s = spl7();
783 while (vm->um_tab.b_active || vd->vd_flags & VD_LOCKED) {
784 vd->vd_flags |= VD_WAIT;
785 sleep((caddr_t)vd, PRIBIO);
786 }
787 vd->vd_flags |= VD_LOCKED;
788 splx(s);
789}
790
791/*
792 * Continue normal operations after pausing for
793 * munging the controller directly.
794 */
795vdunlock(ctlr)
796{
797 register struct vba_ctlr *vm = vdminfo[ctlr];
798 register struct vdsoftc *vd = &vdsoftc[ctlr];
799
800 vd->vd_flags &= ~VD_LOCKED;
801 if (vd->vd_flags & VD_WAIT) {
802 vd->vd_flags &= ~VD_WAIT;
803 wakeup((caddr_t)vd);
804 } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
805 vdstart(vm);
806}
807
7bae1a62 808#define DONTCARE (DCBS_DSE|DCBS_DSL|DCBS_TOP|DCBS_TOM|DCBS_FAIL|DCBS_DONE)
210a9f40
SL
809/*
810 * Handle a disk interrupt.
811 */
9d915fad 812vdintr(ctlr)
7bae1a62 813 register ctlr;
210a9f40 814{
7bae1a62
SL
815 register struct buf *bp, *dp;
816 register struct vba_ctlr *vm = vdminfo[ctlr];
817 register struct vba_device *vi;
818 register struct vdsoftc *vd = &vdsoftc[ctlr];
819 register status;
2149e3ac 820 int timedout;
4f42a6a1 821 struct dksoftc *dk;
7bae1a62 822
7bae1a62 823 if (!vm->um_tab.b_active) {
9d915fad 824 printf("vd%d: stray interrupt\n", ctlr);
210a9f40
SL
825 return;
826 }
9d915fad 827 /*
7bae1a62
SL
828 * Get device and block structures, and a pointer
829 * to the vba_device for the drive.
9d915fad 830 */
7bae1a62
SL
831 dp = vm->um_tab.b_actf;
832 bp = dp->b_actf;
833 vi = vddinfo[vdunit(bp->b_dev)];
2149e3ac 834 dk = &dksoftc[vi->ui_unit];
2bb994d6
MK
835 if (vi->ui_dk >= 0)
836 dk_busy &= ~(1<<vi->ui_dk);
81304755 837 timedout = (vd->vd_wticks >= VDMAXTIME);
7bae1a62
SL
838 /*
839 * Check for and process errors on
840 * either the drive or the controller.
841 */
842 uncache(&vd->vd_dcb.operrsta);
843 status = vd->vd_dcb.operrsta;
81304755
MK
844 if (bp->b_flags & B_FORMAT) {
845 dk->dk_operrsta = status;
846 uncache(&vd->vd_dcb.err_code);
261c73f6
MK
847 /* ecodecnt gets err_code + err_wcnt from the same longword */
848 dk->dk_ecodecnt = *(long *)&vd->vd_dcb.err_code;
849 uncache(&vd->vd_dcb.err_trk);
850 /* erraddr gets error trk/sec/cyl from the same longword */
851 dk->dk_erraddr = *(long *)&vd->vd_dcb.err_trk;
852 } else if (status & VDERR_HARD || timedout) {
2149e3ac 853 if (vd->vd_type == VDTYPE_SMDE)
1f9a1539 854 uncache(&vd->vd_dcb.err_code);
7bae1a62
SL
855 if (status & DCBS_WPT) {
856 /*
857 * Give up on write locked devices immediately.
858 */
4f42a6a1 859 printf("dk%d: write locked\n", vi->ui_unit);
7bae1a62 860 bp->b_flags |= B_ERROR;
81304755 861 } else if (status & VDERR_RETRY || timedout) {
81304755 862 if (status & VDERR_CTLR || timedout) {
261c73f6
MK
863 vdharderr(timedout ?
864 "controller timeout" : "controller err",
81304755
MK
865 vd, bp, &vd->vd_dcb);
866 printf("; resetting controller...");
867 vdreset_ctlr(vm);
868 } else if (status & VDERR_DRIVE) {
869 vdharderr("drive err", vd, bp, &vd->vd_dcb);
870 printf("; resetting drive...");
7bae1a62 871 if (!vdreset_drive(vi))
261c73f6 872 dk->dk_state = CLOSED;
f9e93bbe 873 } else
261c73f6 874 vdharderr("data err", vd, bp, &vd->vd_dcb);
7bae1a62
SL
875 /*
876 * Retry transfer once, unless reset failed.
877 */
261c73f6
MK
878 if (!vi->ui_alive || dp->b_errcnt++ >= 1) {
879 printf("\n");
7bae1a62 880 goto hard;
f9e93bbe
MK
881 }
882
261c73f6 883 printf(" retrying\n");
7bae1a62
SL
884 vm->um_tab.b_active = 0; /* force retry */
885 } else {
81304755 886 vdharderr("hard error", vd, bp, &vd->vd_dcb);
7bae1a62 887 printf("\n");
261c73f6
MK
888 hard:
889 bp->b_flags |= B_ERROR;
9d915fad 890 }
7bae1a62 891 } else if (status & DCBS_SOFT)
2149e3ac 892 vdsofterr(bp, &vd->vd_dcb);
261c73f6
MK
893if (vd->vd_wticks > 3) {
894vd->vd_dcb.err_code = vd->vd_wticks;
895vdharderr("slow transfer (ecode is sec.)", vd, bp, &vd->vd_dcb);
896printf("\n");
897}
81304755 898 vd->vd_wticks = 0;
7bae1a62
SL
899 if (vm->um_tab.b_active) {
900 vm->um_tab.b_active = 0;
7bae1a62
SL
901 vm->um_tab.b_actf = dp->b_forw;
902 dp->b_active = 0;
903 dp->b_errcnt = 0;
904 dp->b_actf = bp->av_forw;
9d915fad 905 bp->b_resid = 0;
1f9a1539 906 vbadone(bp, &vd->vd_rbuf);
7bae1a62
SL
907 biodone(bp);
908 /*
909 * If this unit has more work to do,
910 * then start it up right away.
911 */
912 if (dp->b_actf)
913 vdustart(vi);
2149e3ac 914 else if (dk->dk_openpart == 0)
4f42a6a1 915 wakeup((caddr_t)dk);
210a9f40 916 }
9d915fad 917 /*
7bae1a62
SL
918 * If there are devices ready to
919 * transfer, start the controller.
9d915fad 920 */
2d1c4664
MK
921 if (vd->vd_flags & VD_WAIT) {
922 vd->vd_flags &= ~VD_WAIT;
923 wakeup((caddr_t)vd);
924 } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
7bae1a62 925 vdstart(vm);
210a9f40
SL
926}
927
81304755
MK
928vdharderr(what, vd, bp, dcb)
929 char *what;
930 struct vdsoftc *vd;
931 register struct buf *bp;
932 register struct dcb *dcb;
933{
934 int unit = vdunit(bp->b_dev), status = dcb->operrsta;
81304755 935 register struct disklabel *lp = &dklabel[unit];
2149e3ac 936 int blkdone;
81304755
MK
937
938 if (vd->vd_wticks < VDMAXTIME)
939 status &= ~DONTCARE;
a3074845
MK
940 blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
941 lp->d_nsectors + dcb->err_sec -
942 lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
943 dksoftc[unit].dk_bshift) - bp->b_blkno;
2149e3ac
MK
944 diskerr(bp, "dk", what, LOG_PRINTF, blkdone, lp);
945 printf(", status %b", status, VDERRBITS);
81304755
MK
946 if (vd->vd_type == VDTYPE_SMDE)
947 printf(" ecode %x", dcb->err_code);
81304755
MK
948}
949
2149e3ac 950vdsofterr(bp, dcb)
9d915fad 951 register struct buf *bp;
7bae1a62 952 register struct dcb *dcb;
9d915fad 953{
f9d2ea8f
MK
954 int unit = vdunit(bp->b_dev);
955 struct disklabel *lp = &dklabel[unit];
2149e3ac
MK
956 int status = dcb->operrsta;
957 int blkdone;
958
a3074845
MK
959 blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
960 lp->d_nsectors + dcb->err_sec -
961 lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
962 dksoftc[unit].dk_bshift) - bp->b_blkno;
2149e3ac
MK
963
964 if (status != (DCBS_CCD|DCBS_SOFT|DCBS_ERR|DCBS_DONE)) {
965 diskerr(bp, "dk", "soft error", LOG_WARNING, blkdone, lp);
966 addlog(", status %b ecode %x\n", status, VDERRBITS,
81304755 967 dcb->err_code);
2149e3ac
MK
968 } else {
969 diskerr(bp, "dk", "soft ecc", LOG_WARNING, blkdone, lp);
970 addlog("\n");
971 }
9d915fad 972}
210a9f40 973
7bae1a62 974vdioctl(dev, cmd, data, flag)
9d915fad 975 dev_t dev;
7bae1a62
SL
976 int cmd;
977 caddr_t data;
978 int flag;
210a9f40 979{
7e9892e0 980 register int unit = vdunit(dev);
7bae1a62 981 register struct disklabel *lp = &dklabel[unit];
60d9b6a0 982 register struct dksoftc *dk = &dksoftc[unit];
045442ab 983 int error = 0, vdformat();
7bae1a62
SL
984
985 switch (cmd) {
986
987 case DIOCGDINFO:
988 *(struct disklabel *)data = *lp;
989 break;
990
4f42a6a1
MK
991 case DIOCGPART:
992 ((struct partinfo *)data)->disklab = lp;
993 ((struct partinfo *)data)->part =
994 &lp->d_partitions[vdpart(dev)];
7bae1a62
SL
995 break;
996
997 case DIOCSDINFO:
998 if ((flag & FWRITE) == 0)
999 error = EBADF;
1000 else
7e9892e0 1001 error = setdisklabel(lp, (struct disklabel *)data,
60d9b6a0 1002 (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart);
81304755
MK
1003 if (error == 0 && dk->dk_state == OPENRAW &&
1004 vdreset_drive(vddinfo[unit]))
60d9b6a0
MK
1005 dk->dk_state = OPEN;
1006 break;
1007
1008 case DIOCWLABEL:
1009 if ((flag & FWRITE) == 0)
1010 error = EBADF;
1011 else
1012 dk->dk_wlabel = *(int *)data;
7bae1a62
SL
1013 break;
1014
7e9892e0
MK
1015 case DIOCWDINFO:
1016 if ((flag & FWRITE) == 0)
7bae1a62 1017 error = EBADF;
7e9892e0 1018 else if ((error = setdisklabel(lp, (struct disklabel *)data,
60d9b6a0 1019 (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {
045442ab
MK
1020 int wlab;
1021
07cd2d63
MK
1022 if (error == 0 && dk->dk_state == OPENRAW &&
1023 vdreset_drive(vddinfo[unit]))
1024 dk->dk_state = OPEN;
045442ab
MK
1025 /* simulate opening partition 0 so write succeeds */
1026 dk->dk_openpart |= (1 << 0); /* XXX */
1027 wlab = dk->dk_wlabel;
1028 dk->dk_wlabel = 1;
7e9892e0 1029 error = writedisklabel(dev, vdstrategy, lp);
045442ab
MK
1030 dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
1031 dk->dk_wlabel = wlab;
60d9b6a0 1032 }
7bae1a62 1033 break;
7bae1a62 1034
81304755
MK
1035 case DIOCWFORMAT:
1036 {
1037 register struct format_op *fop;
1038 struct uio auio;
1039 struct iovec aiov;
1040
1041 if ((flag & FWRITE) == 0) {
1042 error = EBADF;
1043 break;
1044 }
1045 fop = (struct format_op *)data;
1046 aiov.iov_base = fop->df_buf;
1047 aiov.iov_len = fop->df_count;
1048 auio.uio_iov = &aiov;
1049 auio.uio_iovcnt = 1;
1050 auio.uio_resid = fop->df_count;
1051 auio.uio_segflg = UIO_USERSPACE;
1052 auio.uio_offset = fop->df_startblk * lp->d_secsize;
261c73f6
MK
1053 /* This assumes one active format operation per disk... */
1054 dk->dk_op = fop->dk_op;
1055 dk->dk_althdr = fop->dk_althdr;
1056 dk->dk_fmtflags = fop->dk_fmtflags;
81304755
MK
1057 /*
1058 * Don't return errors, as the format op won't get copied
1059 * out if we return nonzero. Callers must check the returned
261c73f6 1060 * registers and count.
81304755 1061 */
261c73f6
MK
1062 error = physio(vdformat, (struct buf *)NULL, dev,
1063 B_WRITE, minphys, &auio);
1064 if (error == EIO)
1065 error = 0;
81304755 1066 fop->df_count -= auio.uio_resid;
261c73f6 1067 /* This assumes one active format operation per disk... */
81304755 1068 fop->dk_operrsta = dk->dk_operrsta;
261c73f6
MK
1069 fop->dk_ecodecnt = dk->dk_ecodecnt;
1070 fop->dk_erraddr = dk->dk_erraddr;
81304755
MK
1071 break;
1072 }
1073
7bae1a62
SL
1074 default:
1075 error = ENOTTY;
1076 break;
210a9f40 1077 }
2322c6bc 1078 return (error);
210a9f40
SL
1079}
1080
81304755
MK
1081vdformat(bp)
1082 struct buf *bp;
1083{
1084 bp->b_flags |= B_FORMAT;
1085 vdstrategy(bp);
1086}
1087
9d915fad 1088/*
7bae1a62 1089 * Watch for lost interrupts.
9d915fad 1090 */
7bae1a62 1091vdwatch()
210a9f40 1092{
7bae1a62
SL
1093 register struct vdsoftc *vd;
1094 register struct vba_ctlr *vm;
2149e3ac 1095 register int ctlr;
81304755 1096 int s;
7bae1a62
SL
1097
1098 timeout(vdwatch, (caddr_t)0, hz);
1099 for (ctlr = 0; ctlr < NVD; ctlr++) {
1100 vm = vdminfo[ctlr];
1101 if (vm == 0 || vm->um_alive == 0)
1102 continue;
1103 vd = &vdsoftc[ctlr];
81304755
MK
1104 s = spl7();
1105 if (vm->um_tab.b_active && vd->vd_wticks++ >= VDMAXTIME) {
7bae1a62 1106 printf("vd%d: lost interrupt\n", ctlr);
81304755
MK
1107#ifdef maybe
1108 VDABORT((struct vddevice *)vm->um_addr, vd->vd_type);
1109#endif
1110 vdintr(ctlr);
7bae1a62 1111 }
81304755 1112 splx(s);
9d915fad 1113 }
7bae1a62
SL
1114}
1115
1116#define DBSIZE 64 /* controller limit with 1K sectors */
1117/*
1118 * Crash dump.
1119 */
1120vddump(dev)
1121 dev_t dev;
1122{
1123 register struct vba_device *vi;
1124 register struct vba_ctlr *vm;
1125 register struct disklabel *lp;
1126 register struct vdsoftc *vd;
1127 struct dksoftc *dk;
1128 int part, unit, num;
1f9a1539 1129 u_long start;
7bae1a62
SL
1130
1131 start = 0;
1132 unit = vdunit(dev);
1133 if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
1134 return (ENXIO);
1135 dk = &dksoftc[unit];
60d9b6a0
MK
1136 if (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
1137 vdinit(vdminor(unit, 0), 0) != 0)
7bae1a62
SL
1138 return (ENXIO);
1139 lp = &dklabel[unit];
1140 part = vdpart(dev);
1141 if (part >= lp->d_npartitions)
1142 return (ENXIO);
f9e93bbe 1143 vm = vi->ui_mi;
7bae1a62
SL
1144 vdreset_ctlr(vm);
1145 if (dumplo < 0)
1146 return (EINVAL);
1147 /*
d99b7c9d 1148 * Maxfree is in pages, dumplo is in DEV_BSIZE units.
7bae1a62
SL
1149 */
1150 num = maxfree * (NBPG / lp->d_secsize);
d99b7c9d 1151 dumplo *= DEV_BSIZE / lp->d_secsize;
7bae1a62
SL
1152 if (dumplo + num >= lp->d_partitions[vdpart(dev)].p_size)
1153 num = lp->d_partitions[vdpart(dev)].p_size - dumplo;
1154 vd = &vdsoftc[vm->um_ctlr];
1155 vd->vd_dcb.intflg = DCBINT_NONE;
1156 vd->vd_dcb.opcode = VDOP_WD;
f9e93bbe 1157 vd->vd_dcb.devselect = dk->dk_dcb.devselect;
d99b7c9d 1158 vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
7bae1a62
SL
1159 while (num > 0) {
1160 int nsec, cn, sn, tn;
1161
1162 nsec = MIN(num, DBSIZE);
1f9a1539 1163 sn = dumplo + start / lp->d_secsize;
7bae1a62
SL
1164 cn = (sn + lp->d_partitions[vdpart(dev)].p_offset) /
1165 lp->d_secpercyl;
1166 sn %= lp->d_secpercyl;
1167 tn = sn / lp->d_nsectors;
1168 sn %= lp->d_nsectors;
1169 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1170 vd->vd_dcb.trail.rwtrail.memadr = start;
1171 vd->vd_dcb.trail.rwtrail.wcount = (nsec * lp->d_secsize) >> 1;
1172 vd->vd_dcb.trail.rwtrail.disk.cylinder = cn;
1173 vd->vd_dcb.trail.rwtrail.disk.track = tn;
1174 vd->vd_dcb.trail.rwtrail.disk.sector = sn;
1175 vd->vd_dcb.operrsta = 0;
1176 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
1177 if (!vdpoll(vm, 5)) {
1178 printf(" during dump\n");
1179 return (EIO);
1180 }
1181 if (vd->vd_dcb.operrsta & VDERR_HARD) {
1182 printf("dk%d: hard error, status=%b\n", unit,
1183 vd->vd_dcb.operrsta, VDERRBITS);
1184 return (EIO);
1185 }
1186 start += nsec * lp->d_secsize;
1187 num -= nsec;
9d915fad 1188 }
7bae1a62 1189 return (0);
210a9f40
SL
1190}
1191
1192vdsize(dev)
9d915fad 1193 dev_t dev;
210a9f40 1194{
7bae1a62
SL
1195 register int unit = vdunit(dev);
1196 register struct dksoftc *dk;
1197 struct vba_device *vi;
1198 struct disklabel *lp;
210a9f40 1199
7bae1a62
SL
1200 if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0 ||
1201 (dk = &dksoftc[unit])->dk_state != OPEN)
9d915fad 1202 return (-1);
7bae1a62 1203 lp = &dklabel[unit];
d99b7c9d 1204#ifdef SECSIZE
4f42a6a1 1205 return ((int)lp->d_partitions[vdpart(dev)].p_size);
d99b7c9d
MK
1206#else SECSIZE
1207 return ((int)lp->d_partitions[vdpart(dev)].p_size >> dk->dk_bshift);
1208#endif SECSIZE
210a9f40
SL
1209}
1210
9d915fad 1211/*
261c73f6 1212 * Initialize controller.
9d915fad 1213 */
261c73f6
MK
1214vdinit_ctlr(vm, vd)
1215 struct vba_ctlr *vm;
1216 struct vdsoftc *vd;
210a9f40 1217{
7bae1a62 1218 register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
261c73f6 1219
7bae1a62
SL
1220 if (vd->vd_type == VDTYPE_SMDE) {
1221 vdaddr->vdcsr = 0;
1222 vdaddr->vdtcf_mdcb = AM_ENPDA;
1223 vdaddr->vdtcf_dcb = AM_ENPDA;
1224 vdaddr->vdtcf_trail = AM_ENPDA;
1225 vdaddr->vdtcf_data = AM_ENPDA;
261c73f6
MK
1226 vdaddr->vdccf = CCF_SEN | CCF_DIU | CCF_STS | CCF_RFE |
1227 XMD_32BIT | BSZ_16WRD |
9d915fad
SL
1228 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
1229 }
07cd2d63 1230 if (!vdcmd(vm, VDOP_INIT, 10, 0) || !vdcmd(vm, VDOP_DIAG, 10, 0)) {
261c73f6 1231 printf("vd%d: %s cmd failed\n", vm->um_ctlr,
7bae1a62 1232 vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
261c73f6 1233 return (0);
9d915fad 1234 }
261c73f6
MK
1235 vd->vd_secsize = vdaddr->vdsecsize << 1;
1236 return (1);
1237}
1238
1239/*
1240 * Perform a controller reset.
1241 */
1242vdreset_ctlr(vm)
1243 register struct vba_ctlr *vm;
1244{
1245 register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
1246 register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
1247 register int unit;
1248 struct vba_device *vi;
1249
1250 VDRESET(vdaddr, vd->vd_type);
1251 if (vdinit_ctlr(vm, vd) == 0)
1252 return;
7bae1a62
SL
1253 for (unit = 0; unit < NDK; unit++)
1254 if ((vi = vddinfo[unit])->ui_mi == vm && vi->ui_alive)
1255 (void) vdreset_drive(vi);
1256}
1257
1258vdreset_drive(vi)
1259 register struct vba_device *vi;
1260{
1261 register struct disklabel *lp = &dklabel[vi->ui_unit];
1262 struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
1263 struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
f9e93bbe
MK
1264 register struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
1265 register struct dksoftc *dk = &dksoftc[vi->ui_unit];
261c73f6 1266 int config_status, config_ecode, saw_drive = 0;
7bae1a62 1267
261c73f6
MK
1268#ifdef notdef
1269 /*
1270 * check for ESDI distribution panel already configured,
1271 * e.g. on boot drive, or if PROBE on controller actually
1272 * worked. Status will be zero if drive hasn't
1273 * been probed yet.
1274 */
1275#if STA_ESDI != 0
1276 if ((vdaddr->vdstatus[vi->ui_slave] & STA_TYPE) == STA_ESDI)
1277 lp->d_devflags |= VD_ESDI;
1278#endif
1279#endif
7bae1a62
SL
1280top:
1281 vd->vd_dcb.opcode = VDOP_CONFIG; /* command */
1282 vd->vd_dcb.intflg = DCBINT_NONE;
1283 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
1284 vd->vd_dcb.operrsta = 0;
f9e93bbe 1285 vd->vd_dcb.devselect = vi->ui_slave | lp->d_devflags;
7bae1a62
SL
1286 vd->vd_dcb.trail.rstrail.ncyl = lp->d_ncylinders;
1287 vd->vd_dcb.trail.rstrail.nsurfaces = lp->d_ntracks;
1288 if (vd->vd_type == VDTYPE_SMDE) {
d99b7c9d 1289 vd->vd_dcb.trailcnt = sizeof (struct treset) / sizeof (long);
7bae1a62 1290 vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
1f9a1539 1291 vd->vd_dcb.trail.rstrail.slip_sec = lp->d_sparespertrack;
261c73f6
MK
1292 vd->vd_dcb.trail.rstrail.recovery =
1293 (lp->d_flags & D_REMOVABLE) ? VDRF_NORMAL :
1294 (VDRF_NORMAL &~ (VDRF_OSP|VDRF_OSM));
7bae1a62
SL
1295 } else
1296 vd->vd_dcb.trailcnt = 2; /* XXX */
1297 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1298 vd->vd_mdcb.mdcb_status = 0;
1299 VDGO(vdaddr, vd->vd_mdcbphys, vd->vd_type);
1300 if (!vdpoll(vm, 5)) {
1301 printf(" during config\n");
1302 return (0);
9d915fad 1303 }
261c73f6
MK
1304 config_status = vd->vd_dcb.operrsta;
1305 config_ecode = (u_char)vd->vd_dcb.err_code;
1306 if (config_status & VDERR_HARD) {
f9e93bbe 1307 if (vd->vd_type == VDTYPE_SMDE) {
261c73f6
MK
1308 /*
1309 * If drive status was updated successfully,
1310 * STA_US (unit selected) should be set
1311 * if the drive is attached and powered up.
1312 * (But only if we've guessed right on SMD
1313 * vs. ESDI; if that flag is wrong, we won't
1314 * see the drive.) If we don't see STA_US
1315 * with either SMD or ESDI set for the unit,
1316 * we assume that the drive doesn't exist,
1317 * and don't wait for it to spin up.
1318 */
1319 (void) vdcmd(vm, VDOP_STATUS, 5, vi->ui_slave);
1320 uncache(&vdaddr->vdstatus[vi->ui_slave]);
1321 if (vdaddr->vdstatus[vi->ui_slave] & STA_US)
1322 saw_drive = 1;
1323 else if (lp->d_devflags == 0) {
f9e93bbe
MK
1324 lp->d_devflags = VD_ESDI;
1325 goto top;
1326 }
261c73f6
MK
1327 } else
1328 saw_drive = 1;
1329 if ((config_status & (DCBS_OCYL|DCBS_NRDY)) == 0)
f9e93bbe 1330 printf("dk%d: config error %b ecode %x\n", vi->ui_unit,
261c73f6
MK
1331 config_status, VDERRBITS, config_ecode);
1332 else if ((vd->vd_flags & VD_STARTED) == 0 && saw_drive) {
7bae1a62
SL
1333 int started;
1334
f9e93bbe 1335 printf(" starting drives, wait ... ");
7bae1a62
SL
1336 vd->vd_flags |= VD_STARTED;
1337 started = (vdcmd(vm, VDOP_START, 10) == 1);
1338 DELAY(62000000);
07cd2d63 1339 printf("done\n");
f9e93bbe 1340 lp->d_devflags = 0;
7bae1a62
SL
1341 if (started)
1342 goto top;
1343 }
1344 return (0);
1345 }
f9e93bbe 1346 dk->dk_dcb.devselect |= lp->d_devflags;
7bae1a62 1347 return (1);
9d915fad 1348}
210a9f40 1349
9d915fad 1350/*
7bae1a62 1351 * Perform a command w/o trailer.
9d915fad 1352 */
07cd2d63 1353vdcmd(vm, cmd, t, slave)
7bae1a62 1354 register struct vba_ctlr *vm;
9d915fad 1355{
7bae1a62
SL
1356 register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
1357
1358 vd->vd_dcb.opcode = cmd; /* command */
1359 vd->vd_dcb.intflg = DCBINT_NONE;
1360 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
1361 vd->vd_dcb.operrsta = 0;
07cd2d63 1362 vd->vd_dcb.devselect = slave;
7bae1a62
SL
1363 vd->vd_dcb.trailcnt = 0;
1364 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1365 vd->vd_mdcb.mdcb_status = 0;
1366 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
1367 if (!vdpoll(vm, t)) {
1368 printf(" during init\n");
82bc5dc5
MK
1369 return (0);
1370 }
7bae1a62 1371 return ((vd->vd_dcb.operrsta&VDERR_HARD) == 0);
9d915fad
SL
1372}
1373
7c4f3479 1374/*
7bae1a62
SL
1375 * Poll controller until operation
1376 * completes or timeout expires.
7c4f3479 1377 */
7bae1a62
SL
1378vdpoll(vm, t)
1379 register struct vba_ctlr *vm;
7c4f3479
SL
1380 register int t;
1381{
7bae1a62
SL
1382 register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
1383 register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
7c4f3479
SL
1384
1385 t *= 1000;
82bc5dc5 1386 for (;;) {
7bae1a62
SL
1387 uncache(&vd->vd_dcb.operrsta);
1388 if (vd->vd_dcb.operrsta & (DCBS_DONE|DCBS_ABORT))
82bc5dc5 1389 break;
7c4f3479 1390 if (--t <= 0) {
7bae1a62
SL
1391 printf("vd%d: controller timeout", vm->um_ctlr);
1392 VDABORT(vdaddr, vd->vd_type);
7c4f3479
SL
1393 return (0);
1394 }
82bc5dc5 1395 DELAY(1000);
7c4f3479 1396 }
7bae1a62
SL
1397 if (vd->vd_type == VDTYPE_SMDE) {
1398 do {
82bc5dc5 1399 DELAY(50);
7bae1a62
SL
1400 uncache(&vdaddr->vdcsr);
1401 } while (vdaddr->vdcsr & CS_GO);
f9e93bbe
MK
1402 DELAY(300);
1403 uncache(&vd->vd_dcb.err_code);
7c4f3479
SL
1404 }
1405 DELAY(200);
7bae1a62 1406 uncache(&vd->vd_dcb.operrsta);
7c4f3479
SL
1407 return (1);
1408}
1409
7bae1a62
SL
1410#ifdef COMPAT_42
1411struct vdst {
1412 int nsec; /* sectors/track */
1413 int ntrack; /* tracks/cylinder */
1414 int ncyl; /* cylinders */
f9e93bbe 1415 int secsize; /* sector size */
7bae1a62
SL
1416 char *name; /* type name */
1417 struct {
1418 int off; /* partition offset in sectors */
1419 int size; /* partition size in sectors */
4f42a6a1 1420 } parts[8];
7bae1a62 1421} vdst[] = {
f9e93bbe
MK
1422 { 66, 23, 850, 512, "NEC 800",
1423 {0, 1290300}, /* a cyl 0 - 849 */
1424 },
ef960e6f
KB
1425 { 64, 20, 842, 512, "2361a",
1426 {0, 61440}, /* a cyl 0 - 47 */
1427 {61440, 67840}, /* b cyl 48 - 100 */
1428 {129280, 942080}, /* c cyl 101 - 836 */
1429 {0, 1071360}, /* d cyl 0 - 836 */
1430 {449280, 311040}, /* e cyl 351 - 593 */
1431 {760320, 311040}, /* f cyl 594 - 836 */
1432 {449280, 622080}, /* g cyl 351 - 836 */
1433 {129280, 320000} /* h cyl 101 - 350 */
1434 },
f9e93bbe 1435 { 48, 24, 711, 512, "xsd",
451160eb
MK
1436 {0, 61056}, /* a cyl 0 - 52 */
1437 {61056, 61056}, /* b cyl 53 - 105 */
1438 {122112, 691200}, /* c cyl 106 - 705 */
1439 {237312, 576000}, /* d cyl 206 - 705 */
1440 {352512, 460800}, /* e cyl 306 - 705 */
1441 {467712, 345600}, /* f cyl 406 - 705 */
1442 {582912, 230400}, /* g cyl 506 - 705 */
1443 {698112, 115200} /* h cyl 606 - 705 */
4f42a6a1 1444 },
f9e93bbe 1445 { 44, 20, 842, 512, "eagle",
1f9a1539
MK
1446 {0, 52800}, /* egl0a cyl 0 - 59 */
1447 {52800, 66000}, /* egl0b cyl 60 - 134 */
1448 {118800, 617760}, /* egl0c cyl 135 - 836 */
d99b7c9d 1449 {736560, 4400}, /* egl0d cyl 837 - 841 */
451160eb
MK
1450 {0, 736560}, /* egl0e cyl 0 - 836 */
1451 {0, 740960}, /* egl0f cyl 0 - 841 */
1f9a1539
MK
1452 {118800, 310640}, /* egl0g cyl 135 - 487 */
1453 {429440, 307120} /* egl0h cyl 488 - 836 */
4f42a6a1 1454 },
f9e93bbe 1455 { 64, 10, 823, 512, "fuj",
451160eb
MK
1456 {0, 38400}, /* fuj0a cyl 0 - 59 */
1457 {38400, 48000}, /* fuj0b cyl 60 - 134 */
1458 {86400, 437120}, /* fuj0c cyl 135 - 817 */
1459 {159360, 364160}, /* fuj0d cyl 249 - 817 */
1460 {232320, 291200}, /* fuj0e cyl 363 - 817 */
1461 {305280, 218240}, /* fuj0f cyl 477 - 817 */
1462 {378240, 145280}, /* fuj0g cyl 591 - 817 */
1463 {451200, 72320} /* fug0h cyl 705 - 817 */
4f42a6a1 1464 },
f9e93bbe 1465 { 32, 24, 711, 512, "xfd",
d99b7c9d
MK
1466 { 0, 40704 }, /* a cyl 0 - 52 */
1467 { 40704, 40704 }, /* b cyl 53 - 105 */
1468 { 81408, 460800 }, /* c cyl 106 - 705 */
1469 { 0, 81408 }, /* d cyl 709 - 710 (a & b) */
1470 { 0, 542208 }, /* e cyl 0 - 705 */
1471 { 40704, 501504 }, /* f cyl 53 - 705 (b & c) */
1472 { 81408, 230400 }, /* g cyl 106 - 405 (1/2 of c) */
1473 { 311808,230400 } /* h cyl 406 - 705 (1/2 of c) */
4f42a6a1 1474 },
f9e93bbe 1475 { 32, 19, 823, 512, "smd",
451160eb
MK
1476 {0, 40128}, /* a cyl 0-65 */
1477 {40128, 27360}, /* b cyl 66-110 */
1478 {67488, 429856}, /* c cyl 111-817 */
1479 {139232, 358112}, /* d cyl 229 - 817 */
1480 {210976, 286368}, /* e cyl 347 - 817 */
1481 {282720, 214624}, /* f cyl 465 - 817 */
1482 {354464, 142880}, /* g cyl 583 - 817 */
1483 {426208, 71136} /* h cyl 701 - 817 */
4f42a6a1 1484 },
f9e93bbe
MK
1485 { 18, 15, 1224, 1024, "mxd",
1486 {0, 21600}, /* a cyl 0-79 */
1487 {21600, 22410}, /* b cyl 80-162 */
1488 {44010, 285120}, /* c cyl 163-1217 */
1489#ifdef notyet
1490 {x, 237600}, /* d cyl y - 1217 */
1491 {x, 190080}, /* e cyl y - 1217 */
1492 {x, 142560}, /* f cyl y - 1217 */
1493 {x, 95040}, /* g cyl y - 1217 */
1494 {x, 47520} /* h cyl 701 - 817 */
1495#endif
1496 },
1497 { 32, 10, 823, 512, "fsd",
d99b7c9d
MK
1498 {0, 19200}, /* a cyl 0 - 59 */
1499 {19200, 24000}, /* b cyl 60 - 134 */
1500 {43200, 218560}, /* c cyl 135 - 817 */
4f42a6a1 1501 }
7bae1a62
SL
1502};
1503#define NVDST (sizeof (vdst) / sizeof (vdst[0]))
1504
9d915fad 1505/*
7bae1a62
SL
1506 * Construct a label for an unlabeled pack. We
1507 * deduce the drive type by reading from the last
1508 * track on successively smaller drives until we
1509 * don't get an error.
9d915fad 1510 */
7bae1a62
SL
1511vdmaptype(vi, lp)
1512 register struct vba_device *vi;
1513 register struct disklabel *lp;
9d915fad 1514{
7bae1a62
SL
1515 register struct vdsoftc *vd;
1516 register struct vdst *p;
f9e93bbe 1517 struct vba_ctlr *vm = vi->ui_mi;
7bae1a62 1518 int i;
9d915fad 1519
7bae1a62
SL
1520 vd = &vdsoftc[vi->ui_ctlr];
1521 for (p = vdst; p < &vdst[NVDST]; p++) {
1522 if (vd->vd_type == VDTYPE_VDDC && p->nsec != 32)
1523 continue;
1524 lp->d_nsectors = p->nsec;
1525 lp->d_ntracks = p->ntrack;
1526 lp->d_ncylinders = p->ncyl;
f9e93bbe 1527 lp->d_secsize = p->secsize;
07cd2d63 1528 DELAY(100000);
7bae1a62
SL
1529 if (!vdreset_drive(vi))
1530 return (0);
07cd2d63 1531 DELAY(100000);
7bae1a62
SL
1532 vd->vd_dcb.opcode = VDOP_RD;
1533 vd->vd_dcb.intflg = DCBINT_NONE;
1534 vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */
f9e93bbe 1535 vd->vd_dcb.devselect = dksoftc[vi->ui_unit].dk_dcb.devselect;
d99b7c9d 1536 vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
1f9a1539
MK
1537 vd->vd_dcb.trail.rwtrail.memadr =
1538 vtoph((struct proc *)0, (unsigned)vd->vd_rbuf.vb_rawbuf);
f9e93bbe 1539 vd->vd_dcb.trail.rwtrail.wcount = lp->d_secsize / sizeof(short);
7bae1a62
SL
1540 vd->vd_dcb.operrsta = 0;
1541 vd->vd_dcb.trail.rwtrail.disk.cylinder = p->ncyl - 2;
1542 vd->vd_dcb.trail.rwtrail.disk.track = p->ntrack - 1;
1543 vd->vd_dcb.trail.rwtrail.disk.sector = p->nsec - 1;
1544 vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
1545 vd->vd_mdcb.mdcb_status = 0;
1546 VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
1547 if (!vdpoll(vm, 60))
1548 printf(" during probe\n");
1549 if ((vd->vd_dcb.operrsta & VDERR_HARD) == 0)
1550 break;
210a9f40 1551 }
f9e93bbe 1552 if (p >= &vdst[NVDST])
7bae1a62 1553 return (0);
f9e93bbe 1554
4f42a6a1 1555 for (i = 0; i < 8; i++) {
7bae1a62
SL
1556 lp->d_partitions[i].p_offset = p->parts[i].off;
1557 lp->d_partitions[i].p_size = p->parts[i].size;
1558 }
4f42a6a1 1559 lp->d_npartitions = 8;
7bae1a62 1560 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
7bae1a62
SL
1561 bcopy(p->name, lp->d_typename, 4);
1562 return (1);
210a9f40 1563}
7bae1a62 1564#endif COMPAT_42
9d915fad 1565#endif