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