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