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