get rid of unused queue() and dequeue() (from sun!shannon)
[unix-history] / usr / src / sys / tahoe / vba / vd.c
CommitLineData
210a9f40
SL
1/* vd.c 1.1 85/07/21 */
2
3#include "fsd.h"
4#if NVD > 0
5/*
6** VDDC Driver - Versabus to SMD direct interface version.
7** Written for TAHOE vmunix, CCI-WDC 9/1/83.
8*/
9
10#include "../h/param.h"
11#include "../h/buf.h"
12#include "../h/cmap.h"
13#include "../h/conf.h"
14#include "../h/dir.h"
15#include "../h/dk.h"
16#include "../h/map.h"
17#include "../machine/mtpr.h"
18#include "../machine/pte.h"
19#include "../h/systm.h"
20#include "../vba/vbavar.h"
21#include "../h/user.h"
22#include "../h/vmmac.h"
23#include "../h/proc.h"
24#include "../h/uio.h"
25#include "../vba/vddc.h"
26
27int vddebug = 1; /* if = 1, error messages are printed on the console */
28int vdintflg = 0; /* if = 1, interrupts are handled by the driver,
29 * otherwise they are just ignored. (during setup) */
30
31static struct size FSD[] = {
32 9600, 0, /* minor 0/ 8/16/24 = fsd0a - fsd3a - cyl 0 - 59*/
33 12000, 9600, /* minor 1/ 9/17/25 = fsd0b - fsd3b - cyl 60 - 134*/
34 108480, 21600, /* minor 2/10/18/26 = fsd0c - fsd3c - cyl 135 - 812*/
35 1600, 130080, /* minor 3/11/19/27 = fsd0d - fsd3d - cyl 813 - 822*/
36 130080, 0, /* minor 4/12/20/28 = fsd0e - fsd3e - cyl 0 - 812*/
37 131680, 0, /* minor 5/13/21/29 = fsd0f - fsd3f - cyl 0 - 822*/
38 0, 0, /* Non existent minor device */
39 0, 0, /* Non existent minor device */
40 0, 0, /* Non existent minor device */
41 0, 0, /* Non existent minor device */
42 0, 0, /* Non existent minor device */
43 0, 0, /* Non existent minor device */
44 0, 0, /* Non existent minor device */
45 0, 0, /* Non existent minor device */
46 0, 0, /* Non existent minor device */
47 0, 0, /* Non existent minor device */
48};
49
50static struct size SMD[]= {
51 20064, 0, /* minor 32/40/48/56 = smd0a - smd3a cyl 0- 65 */
52 13680, 20064, /* minor 33/41/49/57 = smd0b - smd3b cyl 66- 110 */
53 214928, 33744, /* minor 34/42/50/58 = smd0c - smd3c cyl 111-817 */
54 1520, 248672, /* minor 35/43/51/59 = smd0d - smd3d cyl 818-822 */
55 248672, 0, /* minor 36/44/52/60 = smd0e - smd3e cyl 0-817 */
56 250192, 0, /* minor 37/45/53/61 = smd0f - smd3f cyl 0-822 */
57 0, 0, /* minor 38/46/54/62 = smd0g - smd3g */
58 0, 0, /* minor 39/47/55/63 = smd0h - smd3h */
59 0, 0, /* Non existent minor device */
60 0, 0, /* Non existent minor device */
61 0, 0, /* Non existent minor device */
62 0, 0, /* Non existent minor device */
63 0, 0, /* Non existent minor device */
64 0, 0, /* Non existent minor device */
65 0, 0, /* Non existent minor device */
66 0, 0, /* Non existent minor device */
67};
68
69static struct size XFSD[] = {
70 20352, 0, /* minor 64/72/80/88 = xfsd0a - xfsd3a cyl 0- 52 */
71 20352, 20352, /* minor 65/73/81/89 = xfsd0b - xfsd3b cyl 53- 105 */
72 230400, 40704, /* minor 66/74/82/90 = xfsd0c - xfsd3c cyl 106-705 */
73 1920, 271104, /* minor 67/75/83/91 = xfsd0d - xfsd3d cyl 706-710 */
74 271104, 0, /* minor 68/76/84/92 = xfsd0e - xfsd3e cyl 0-705 */
75 273024, 0, /* minor 69/77/85/93 = xfsd0f - xfsd3f cyl 0-710 */
76 0, 0, /* minor 70/78/86/94 = xfsd0g - xfsd3g */
77 0, 0, /* minor 71/79/87/95 = xfsd0h - xfsd3h */
78 0, 0, /* Non existent minor device */
79 0, 0, /* Non existent minor device */
80 0, 0, /* Non existent minor device */
81 0, 0, /* Non existent minor device */
82 0, 0, /* Non existent minor device */
83 0, 0, /* Non existent minor device */
84 0, 0, /* Non existent minor device */
85 0, 0, /* Non existent minor device */
86};
87
88/*
89/*
90/* Layout of minor number assignments for the VDDC devices.
91/*
92/* 1
93/* 5 3 2 0
94/* +---------------------------+-----+
95/* | Unit number | FLS |
96/* +---------------------------+-----+
97/* | |_____ File system # ( 0-7 )
98/* |__________ Unit # in the system
99/*
100/********************************************************/
101
102#define VDUNIT(x) (minor(x) >> 3)
103#define FLSYS(x) (minor(x) & 0x07)
104#define PHYS(x) ( vtoph( 0, (int) (x) ) )
105
106
107/* Drive types should be in order of drive capacity for auto-configuration */
108/* e.g: smallest capacity = drive type 0, highest capacity = type NXPDRV-1 */
109
110struct vdst {
111 short nsect;
112 short ntrak;
113 short nspc;
114 short ncyl;
115 struct size *sizes;
116 short dtype; /* type as in byte 5 (drive) of iopb */
117 char *name; /* drive name for autoconf */
118} vdst[] = {
119
12016, 10, 16*10, 823, FSD, 0, "fsd",
12116, 19, 16*19, 823, SMD, 1, "smd",
12216, 24, 16*24, 711, XFSD, 2, "xfd"
123};
124
125
126struct vba_ctlr *vdminfo[NVD];
127struct vba_device *vddinfo[NFSD];
128
129/*
130** Internal Functions
131*/
132int vdopen();
133int vdclose();
134int vdprobe(); /* See if VDDC is really there */
135int vd_setup(); /* Called from vdprobe */
136int vdslave(); /* See if drive is really there */
137int vdattach();
138int vddgo();
139int vdstrategy(); /* VDDC strategy routine */
140int vdstart(); /* Top level interface to device queue */
141int vdintr(); /* Top Level ISR */
142int vdread(); /* raw i/o read routine */
143int vdwrite(); /* raw i/o write routine */
144int vddump(); /* dump routine */
145int vdsize(); /* sizes for swapconfig */
146int dskrst(); /* reset a drive after hard error */
147
148long vdstd[] = {
149 0x0f2000 };
150
151struct vba_driver vddriver = {
152 vdprobe, vdslave, vdattach, vddgo, vdstd,
153 "smd/fsd", vddinfo, "vd", vdminfo
154};
155
156struct buf vdutab[NFSD];
157struct buf rvdbuf[NFSD];
158char vdbuf[NVD][MAXBPTE * NBPG]; /* internal buffer for raw/swap i/o */
159long vdbufused[NVD];
160extern char vd0utl[],vd1utl[],vd2utl[],vd3utl[];
161
162/*
163** Disk Address
164*/
165struct dskadr {
166 char track; /* all 8 bits */
167 char sector; /* low order 5 bits */
168 short cylinder; /* low order 12 bits */
169};
170
171/*
172** DCB Trailer Formats
173**********************************/
174
175/*
176** Read / Write Trailer
177*/
178struct trrw {
179 char *memadr; /* memory address */
180 long wcount; /* 16 bit word count */
181 struct dskadr disk; /* disk address */
182};
183
184/*
185** Format Trailer
186*/
187struct trfmt {
188 char *addr; /* data buffer to be filled on sector*/
189 long nsectors; /* # of sectors to be formatted */
190 struct dskadr disk;
191 struct dskadr hdr;
192};
193
194/*
195** Reset / Configure Trailer
196*/
197struct treset {
198 long ncyl; /* # cylinders */
199 long nsurfaces; /* # surfaces */
200}; /* # of sectors is defined by VDDC */
201 /* to be 32/track of 512 data bytes each */
202
203/*
204** Seek Trailer
205*/
206struct trseek {
207 struct dskadr disk;
208};
209
210/*
211** DCB Format
212*/
213struct fmt_dcb {
214 struct fmt_dcb *nxtdcb; /* next dcb in chain or End of Chain */
215 short intflg; /* interrupt settings and flags */
216 short opcode; /* DCB Command code etc... */
217 long operrsta; /* Error & Status info */
218 short fill; /* not used */
219 char devselect; /* Drive selection */
220 char trailcnt; /* Trailer Word Count */
221 long err_memadr; /* Error memory address */
222 short fill2;
223 short err_wcount; /* Error word count */
224 short err_track; /* Error track/sector */
225 short err_cyl; /* Error cylinder adr */
226 union {
227 struct trrw rwtrail; /* read/write trailer */
228 struct trfmt fmtrail; /* format trailer */
229 struct treset resetrail; /* reset/configure trailer */
230 struct trseek seektrail; /* seek trailer */
231 } trail;
232};
233
234/*
235** MDCB Format
236*/
237struct fmt_mdcb {
238 struct fmt_dcb *firstdcb; /* first dcb in chain */
239 struct fmt_dcb *procdcb; /* dcb being processed */
240 struct fmt_dcb *intdcb; /* dcb causing interrupt */
241 long vddcstat; /* VDDC status */
242}mdcbx[NVD];
243
244/*
245** DCB
246*/
247
248struct fmt_dcb dcbx[NVD];
249
250int vdtimeout;
251#define POLLTILLDONE(x, name) { \
252 vdtimeout = 1000*(x); \
253 uncache((char *)&dcb->operrsta); \
254 while (! (dcb->operrsta & DCBCMP)) { \
255 DELAY(1000); \
256 vdtimeout--; \
257 uncache((char *)&dcb->operrsta); \
258 if (vdtimeout <=0) { \
259 printf("vd: timeout on %s\n", name);\
260 return(0); \
261 } \
262 } \
263}
264
265/*
266** See if the controller is really there.
267** if TRUE - initialize the controller.
268*/
269vdprobe(cntrl_vaddr)
270caddr_t cntrl_vaddr;
271{
272 if ( badaddr(cntrl_vaddr,2) ) return(0); /* no controller */
273 else
274 if (vd_setup(cntrl_vaddr)) /* initialize the controller */
275 return(1);
276 else return(0); /* initialization error */
277}
278
279vd_setup(cntrl_vaddr)
280caddr_t cntrl_vaddr;
281{
282 register struct fmt_dcb *dcb = &dcbx[0];
283 register struct fmt_mdcb *mdcb = &mdcbx[0];
284 int j;
285
286 VDDC_RESET(cntrl_vaddr); /* Reset the controller */
287 /* Burn some time ...... needed after accessing reset port */
288 for (j=0; j<20; j++)
289 DELAY(1000);
290
291 /* setup & issue INIT to initialize VDDC */
292
293 dcb->opcode = INIT;
294 dcb->nxtdcb = (struct fmt_dcb *)0;
295 dcb->intflg = NOINT;
296 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
297 dcb->operrsta = 0;
298 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ); /* do it */
299 POLLTILLDONE(1,"INIT"); /* poll till done */
300 if (dcb->operrsta & HRDERR) {
301 if (vddebug)
302 printf("vd: init error, err=%b\n",
303 dcb->operrsta, ERRBITS);
304 return(0);
305 }
306 /* setup & issue DIAGNOSE */
307
308 dcb->opcode = DIAG;
309 dcb->nxtdcb = (struct fmt_dcb *)0;
310 dcb->intflg = NOINT;
311 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
312 dcb->operrsta = 0;
313 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */
314 POLLTILLDONE(1,"DIAG") /* poll till done */
315 if (dcb->operrsta & HRDERR) {
316 if (vddebug)
317 printf("vd: diagnose error, err=%b\n",
318 dcb->operrsta, ERRBITS);
319 return(0);
320 }
321 /* Start drives command */
322#ifdef notdef
323 dcb->opcode = VDSTART;
324 dcb->nxtdcb = (struct fmt_dcb *)0;
325 dcb->intflg = NOINT;
326 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
327 dcb->operrsta = 0;
328 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */
329 POLLTILLDONE(20,"VDSTART") /* poll till done */
330 if (dcb->operrsta & HRDERR) {
331 if (vddebug)
332 printf("vd: start error, err=%b\n",
333 dcb->operrsta, ERRBITS);
334 return(0);
335 }
336#endif
337 return(1);
338 }
339
340/*
341 * See if a drive is really there
342 * Try to Reset/Configure the drive, then test its status.
343*/
344vdslave(ui,cntrl_vaddr)
345register struct vba_device *ui;
346register caddr_t cntrl_vaddr;
347{
348 register struct fmt_dcb *dcb = &dcbx[0];
349 register struct fmt_mdcb *mdcb = &mdcbx[ui->ui_ctlr];
350 register struct vdst *st;
351 int dsktype;
352
353 /*
354 ** check drive status - see if drive exists.
355 */
356 dcb->opcode = VDSTATUS;
357 dcb->intflg = NOINT;
358 dcb->operrsta = 0;
359 dcb->devselect = (char)ui->ui_slave;
360 dcb->trailcnt = (char)0;
361 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
362 mdcb->vddcstat = 0;
363 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb)) /* do it */
364 POLLTILLDONE(5,"VDSTATUS")
365#ifdef notdef
366 if (dcb->operrsta & HRDERR) {
367 if (vddebug)
368 printf("vd%d: status error, err=%b\n", ui->ui_unit,
369 dcb->operrsta, ERRBITS);
370 return(0);
371 }
372#endif
373 uncache((char *)&mdcb->vddcstat);
374 if (mdcb->vddcstat & DRVNRDY) return(0); /* not ready-> non existent */
375
376 /*
377 * drive is alive, now get its type!
378 * Seek on all drive types starting from the largest one.
379 * a sucessful seek to the last sector/cylinder/track verifies
380 * the drive type connected to this port.
381 */
382 for (dsktype = NVDDRV-1; dsktype >= 0; dsktype--) {
383 st = &vdst[dsktype];
384 dcb->opcode = RSTCFG; /* configure drive command */
385 dcb->intflg = NOINT;
386 dcb->operrsta = 0;
387 dcb->trail.resetrail.ncyl = st->ncyl;
388 dcb->trail.resetrail.nsurfaces = st->ntrak;
389 dcb->devselect = (char)ui->ui_slave;
390 dcb->trailcnt = (char)2;
391 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
392 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */
393 POLLTILLDONE(3,"RSTCFG")
394 if (dcb->operrsta & HRDERR) {
395 if (vddebug)
396 printf("vd%d: reset error, err=%b\n",
397 ui->ui_unit, dcb->operrsta, ERRBITS);
398 return(0);
399 }
400 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
401 dcb->intflg = NOINT;
402 dcb->opcode = RD;
403 dcb->operrsta = 0;
404 dcb->devselect = (char)ui->ui_slave;
405 dcb->trailcnt = (char)3;
406 dcb->trail.rwtrail.memadr = (char *)PHYS(vdbuf);
407 dcb->trail.rwtrail.wcount = 256;
408 dcb->trail.rwtrail.disk.cylinder = st->ncyl -4;
409 dcb->trail.rwtrail.disk.track = st->ntrak -1;
410 dcb->trail.rwtrail.disk.sector = 0;
411 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */
412 POLLTILLDONE(5,"RD")
413if (vddebug)
414 printf("vd%d: cyl %d, trk %d, sec %d, operrsta err=%b\n",
415 ui->ui_unit,
416 dcb->trail.rwtrail.disk.cylinder,
417 dcb->trail.rwtrail.disk.track,
418 dcb->trail.rwtrail.disk.sector,
419 dcb->operrsta, ERRBITS);
420 if ( (dcb->operrsta & HRDERR) == 0)
421 /* found the drive type! */
422 break;
423 }
424 if (dsktype < 0) {
425 /* If reached here, a drive which is not defined in the
426 * 'vdst' tables is connected. Cannot set it's type.
427 */
428 printf("vd%d: unrecognized drive type\n", ui->ui_unit);
429 return(0);
430 }
431 ui->ui_type = dsktype;
432 vddriver.ud_dname = st->name;
433 return(1);
434}
435
436vdattach(ui)
437struct vba_device *ui;
438{
439 if (ui->ui_dk >= 0)
440 dk_mspw[ui->ui_dk] = .0000020345; /* BAD VALUE */
441}
442
443vddgo(um)
444struct vba_ctlr *um;
445{
446}
447
448vdstrategy(bp)
449register struct buf *bp;
450{
451 register struct vba_device *ui;
452 register struct vba_ctlr *um;
453 register int unit;
454 register struct buf *dp;
455 register struct size *sizep;
456 int index, blocks, s;
457
458 vdintflg = 1; /* enable interrupts handling by the driver */
459 blocks = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
460 unit = VDUNIT(bp->b_dev);
461 ui = vddinfo[unit];
462 if (ui == 0 || ui->ui_alive == 0) goto bad1;
463 index = FLSYS(bp->b_dev); /* get file system index */
464 sizep = vdst[ui->ui_type].sizes;
465 if (bp->b_blkno < 0 ||
466 (dkblock(bp)+blocks > sizep[index].nblocks)) /* disk overflow */
467 goto bad1;
468 s = spl8();
469 dp = &vdutab[ui->ui_unit];
470 bp->b_resid = bp->b_blkno + sizep[index].block0;
471 /* block # plays same role as
472 cylinder # for disksort, as long
473 as increasing blocks correspond to
474 increasing cylinders on disk */
475
476 buf_setup (bp, SECTSIZ);
477
478 disksort(dp, bp);
479 if (dp->b_active == 0) { /* unit is on controller queue */
480 /* put the device on the controller queue */
481 dp->b_forw = NULL; /* end of queue indicator */
482 um = ui->ui_mi; /* get controller structure !! */
483 if (um->um_tab.b_actf == NULL) /* controller queue is empty */
484 um->um_tab.b_actf = dp;
485 else
486 um->um_tab.b_actl->b_forw = dp; /* add into queue */
487 um->um_tab.b_actl = dp; /* update queue tail */
488 dp->b_active ++;
489 }
490 bp = &ui->ui_mi->um_tab; /* controller structure addr */
491 if (bp->b_actf && /* cntrl queue not empty */
492 bp->b_active == 0) /* controller not active */
493 (void) vdstart(ui->ui_mi);/* go start I/O */
494 splx(s);
495 return;
496
497bad1:
498 bp->b_flags |= B_ERROR;
499 iodone(bp);
500 return;
501}
502
503
504/*
505 * Start up a transfer on a drive.
506 */
507vdstart(um)
508register struct vba_ctlr *um;
509{
510 register struct buf *bp, *dp;
511 register struct fmt_dcb *dcb = &dcbx[um->um_ctlr];
512 register struct fmt_mdcb *mdcb;
513 register struct size *sizep; /* Pointer to one of the tables */
514 register struct vdst *st;
515 register int index ; /* Index in the relevant table */
516 register int phadr; /* Buffer's physical address */
517 register caddr_t cntrl_vaddr = um->um_addr;
518 int sblock, unit;
519 int ct;
520
521loop:
522 /*
523 * Pull a request off the controller queue
524 */
525 if ((dp = um->um_tab.b_actf) == NULL)
526 return ;
527 if ((bp = dp->b_actf) == NULL) {
528 dp->b_active = 0; /* device removed from ctlr queue */
529 um->um_tab.b_actf = dp->b_forw;
530 goto loop;
531 }
532 /*
533 * Mark controller busy, and
534 * prepare a command packet for the controller.
535 */
536 um->um_tab.b_active++;
537 unit = VDUNIT(bp->b_dev);
538 st = &vdst[vddinfo[unit]->ui_type];
539 mdcb = &mdcbx[vddinfo[unit]->ui_ctlr];
540 index = FLSYS(bp->b_dev);
541 sizep = st->sizes;
542 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
543 dcb->intflg = INTDUN; /* interrupt on completion */
544 dcb->opcode = (bp->b_flags & B_READ) ? RD : WD;
545 dcb->operrsta = 0;
546 dcb->devselect = (char)(vddinfo[unit])->ui_slave;
547 dcb->trailcnt = (char)3;
548 ct = vddinfo[unit]->ui_ctlr;
549
550 switch (ct) {
551 case 0:
552 phadr = get_ioadr(bp, vdbuf[0], VD0map, (caddr_t)vd0utl);
553 break;
554 case 1:
555 phadr = get_ioadr(bp, vdbuf[1], VD1map, (caddr_t)vd1utl);
556 break;
557 case 2:
558 phadr = get_ioadr(bp, vdbuf[2], VD2map, (caddr_t)vd2utl);
559 break;
560 case 3:
561 phadr = get_ioadr(bp, vdbuf[3], VD3map, (caddr_t)vd3utl);
562 break;
563 }
564/*
565 phadr = get_ioadr(bp, vdbuf, IOmap, (caddr_t)ioutl);
566*/
567
568 if (vddinfo[unit]->ui_dk >= 0) {
569 int dku = vddinfo[unit]->ui_dk;
570 dk_busy |= 1<<dku;
571 dk_xfer[dku]++;
572 dk_wds[dku] += bp->b_bcount>>6;
573 }
574 dcb->trail.rwtrail.memadr = (char *)phadr;
575 dcb->trail.rwtrail.wcount = (bp->b_bcount + 1) / 2;
576 sblock = sizep[index].block0 + bp->b_blkno;
577 dcb->trail.rwtrail.disk.cylinder = (short)(sblock / st->nspc);
578 dcb->trail.rwtrail.disk.track = (char)((sblock % st->nspc) / st->nsect);
579 dcb->trail.rwtrail.disk.sector = (char)(sblock*2 % (st->nsect*2));
580
581#ifdef VDDCPERF
582 scope_out(1);
583#endif
584
585 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb)) /* do it */
586}
587
588
589/*
590 * Handle a disk interrupt.
591 */
592vdintr(vdnum)
593register vdnum;
594{
595 register struct buf *bp, *dp;
596 register struct vba_ctlr *um = vdminfo[vdnum];
597 register struct fmt_dcb *dcb = &dcbx[vdnum];
598 register struct fmt_mdcb *mdcb = &mdcbx[vdnum];
599 register struct vdst *st;
600 int unit;
601 struct vba_device *ui;
602
603#ifdef VDDCPERF
604 scope_out(2);
605#endif
606 if (intenable == 0 || vdintflg == 0) /* ignore all interrupts */
607 return;
608 if (um->um_tab.b_active == NULL) return;/* unexpected interrupt */
609 uncache((char *)&mdcb->intdcb);
610 uncache((char *)&dcb->operrsta);
611 if ( mdcb->intdcb != (struct fmt_dcb *)PHYS(dcb)) { /* dcb causing interrupt */
612 printf("vd%d: bad dcb=%x (phys=%x)\n",
613 vdnum, mdcb->intdcb, PHYS(dcb));
614 return;
615 }
616 if (! (dcb->operrsta & DCBCMP)) { /* unexpected interrupt */
617 printf("vd%d: unexpected interrupt, err=%b\n", vdnum,
618 dcb->operrsta, ERRBITS);
619 return;
620 }
621 dp = um->um_tab.b_actf; /* device queue head in ctlr queue */
622 bp = dp->b_actf; /* first buffer in device queue */
623 unit = VDUNIT(bp->b_dev);
624 ui = vddinfo[unit];
625 if (ui->ui_dk >= 0)
626 dk_busy &= ~(1 << ui->ui_dk);
627 if (dcb->operrsta & (HRDERR|SFTERR)) {
628 st = &vdst[ui->ui_type];
629 if (dcb->operrsta & HRDERR) {
630 harderr(bp, &st->name[7]);
631 printf("status=%b\n", dcb->operrsta, ERRBITS);
632 dskrst(bp);
633 bp->b_flags |= B_ERROR;
634 } else
635#define SECTOR(x) ((x)*2)
636 printf("%s%d: soft error sn%d status=%b\n", &st->name[7], unit,
637 SECTOR(bp->b_blkno + st->sizes[FLSYS(bp->b_dev)].block0),
638 dcb->operrsta, ERRBITS);
639 }
640 switch (vdnum) {
641 case 0:
642 end_transfer(bp, vdbuf[0], VD0map, (caddr_t)vd0utl);
643 break;
644 case 1:
645 end_transfer(bp, vdbuf[1], VD1map, (caddr_t)vd1utl);
646 break;
647 case 2:
648 end_transfer(bp, vdbuf[2], VD2map, (caddr_t)vd2utl);
649 break;
650 case 3:
651 end_transfer(bp, vdbuf[3], VD3map, (caddr_t)vd3utl);
652 break;
653 }
654
655 um->um_tab.b_active = 0;
656 um->um_tab.b_errcnt = 0;
657 if (dp->b_forw != NULL) { /* more than 1 unit on queue */
658 um->um_tab.b_actf = dp->b_forw; /* next device on ctlr queue */
659 dp->b_forw = um->um_tab.b_actl->b_forw; /* be last in queue */
660 um->um_tab.b_actl->b_forw = dp; /* last points now to dp */
661 um->um_tab.b_actl = dp; /* pointer in ctlr structure */
662 }
663 dp->b_errcnt = 0;
664 dp->b_actf = bp->av_forw; /* remove first from queue */
665 bp->b_resid = 0; /* All data read here */
666
667#ifdef VDDCPERF
668 scope_out(3);
669#endif
670
671 iodone(bp);
672 vdstart(um); /* start requests for next device on queue */
673}
674
675
676vdread(dev, uio)
677dev_t dev;
678struct uio *uio;
679{
680 register int unit = VDUNIT(dev);
681 register int error;
682 register int ct;
683 register int s;
684
685 if (unit >= NFSD)
686 error = ENXIO;
687 else {
688 ct = vddinfo[unit]->ui_ctlr;
689 s = spl8();
690 while (vdbufused[ct]) sleep (&vdbufused[ct],PRIBIO+1);
691 vdbufused[ct] = 1;
692 splx(s);
693 error = physio(vdstrategy, &rvdbuf[unit], dev, B_READ, minphys, uio);
694 vdbufused[ct] = 0;
695 wakeup (&vdbufused[ct]);
696 }
697 return error;
698}
699
700vdwrite(dev, uio)
701dev_t dev;
702struct uio *uio;
703{
704 register int unit = VDUNIT(dev);
705 register int error;
706 register int ct;
707 register int s;
708
709 if (unit >= NFSD)
710 error = ENXIO;
711 else {
712 ct = vddinfo[unit]->ui_ctlr;
713 s = spl8();
714 while (vdbufused[ct]) sleep (&vdbufused[ct],PRIBIO+1);
715 vdbufused[ct] = 1;
716 splx(s);
717 error = physio(vdstrategy, &rvdbuf[unit], dev, B_WRITE, minphys, uio);
718 vdbufused[ct] = 0;
719 wakeup (&vdbufused[ct]);
720 }
721 return error;
722}
723
724#define DUMPSIZE 32 /* Up to 32k at a time - controller limit */
725
726vddump(dev)
727dev_t dev;
728/*
729 * Dump the main memory to the given device.
730 */
731{
732 register struct vba_ctlr *um;
733 register struct fmt_dcb *dcb = &dcbx[0];
734 register struct fmt_mdcb *mdcb = &mdcbx[0];
735 register struct vdst *st;
736 register int unit;
737 register caddr_t cntrl_vaddr ;
738 register struct size *sizep; /* Pointer to one of the tables */
739 int index,sblock,blkcount,thiscount;
740 int memaddr;
741
742 unit = VDUNIT(dev);
743 um = (vddinfo[unit])->ui_mi;
744 st = &vdst[(vddinfo[unit])->ui_type];
745 dcb = &dcbx[um->um_ctlr];
746 cntrl_vaddr = um->um_addr;
747 memaddr = 0x0;
748 index = FLSYS(dev);
749 sizep = st->sizes;
750 blkcount = maxfree - 2; /* In 1k byte pages */
751 if (dumplo + blkcount > sizep[index].nblocks) return(EINVAL);
752 sblock = sizep[index].block0 + dumplo;
753 while (blkcount > 0) {
754 thiscount = MIN (blkcount, DUMPSIZE);
755 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
756 dcb->intflg = NOINT;
757 dcb->opcode = WD;
758 dcb->operrsta = 0;
759 dcb->devselect = (char)(vddinfo[unit])->ui_slave;
760 dcb->trailcnt = (char)3;
761 dcb->trail.rwtrail.memadr = (char *)memaddr;
762 dcb->trail.rwtrail.wcount = thiscount*512;
763 dcb->trail.rwtrail.disk.cylinder= (short)(sblock/st->nspc);
764 dcb->trail.rwtrail.disk.track = (char)((sblock % st->nspc)
765 / st->nsect);
766 dcb->trail.rwtrail.disk.sector = (char)(sblock*2 % (st->nsect*2));
767 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */
768 POLLTILLDONE(5,"WD");
769 if (dcb->operrsta & HRDERR) {
770 if (vddebug)
771 printf("vd%d: i/o error, err=%b\n", unit,
772 dcb->operrsta, ERRBITS);
773 return(EIO);
774 };
775 blkcount -= thiscount;
776 memaddr += thiscount*NBPG;
777 sblock += thiscount;
778 }
779 return(0);
780}
781
782vdopen(dev, flag)
783register dev_t dev;
784int flag;
785{
786 register struct vba_device *ui;
787 register unit = VDUNIT(dev);
788
789 ui = vddinfo[unit];
790 if (ui == 0 || ui->ui_alive == 0 || ui->ui_type >= NVDDRV)
791 return ENXIO;
792 return 0;
793}
794
795vdsize(dev)
796register dev_t dev;
797{
798 register struct vba_device *ui;
799 register unit = VDUNIT(dev);
800
801 ui = vddinfo[unit];
802 if (ui == 0 || ui->ui_alive == 0 || ui->ui_type >= NVDDRV)
803 return -1;
804 return vdst[ui->ui_type].sizes[FLSYS(dev)].nblocks;
805}
806
807/* reset a drive after a hard error */
808dskrst(bp)
809 register struct buf *bp;
810{
811 register struct vdst *st;
812 register struct fmt_dcb *dcb;
813 register struct fmt_mdcb *mdcb;
814 register struct vba_device *ui;
815 register caddr_t cntrl_vaddr ;
816 int unit;
817
818 unit = VDUNIT(bp->b_dev);
819 ui = vddinfo[unit];
820 mdcb = &mdcbx[ui->ui_ctlr];
821 dcb = &dcbx[ui->ui_ctlr];
822 cntrl_vaddr = (ui->ui_mi)->um_addr;
823 st = &vdst[vddinfo[unit]->ui_type];
824 dcb->opcode = RSTCFG; /* configure drive command */
825 dcb->intflg = NOINT;
826 dcb->operrsta = 0;
827 dcb->trail.resetrail.ncyl = st->ncyl;
828 dcb->trail.resetrail.nsurfaces = st->ntrak;
829 dcb->devselect = (char)ui->ui_slave;
830 dcb->trailcnt = (char)2;
831 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb);
832 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */
833 POLLTILLDONE(3,"reset")
834 if (dcb->operrsta & HRDERR) {
835 if (vddebug) {
836 harderr(bp, &st->name[7]);
837 printf("reset failed, err=%b\n", dcb->operrsta,ERRBITS);
838 }
839 }
840}
841#endif