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