|
|
1.1 root 1: /* (-lgl
2: * COHERENT Driver Kit Version 1.1.0
3: * Copyright (c) 1982, 1990 by Mark Williams Company.
4: * All rights reserved. May not be copied without permission.
5: *
6: * $Log: ps.c,v $
7: * Revision 1.10 91/11/11 12:29:03 hal
8: * Use n_atdr.
9: *
10: * Revision 1.9 91/10/30 10:47:46 hal
11: * Get psparms from tboot.
12: *
13: * Revision 1.8 91/10/24 12:36:25 hal
14: * Bump PSSECS from 4 to 6.
15: * Poll HF_REG (3F6) rather than CSR_REG (1F6).
16: * COH 3.2.03.
17: *
18: * Revision 1.7 91/09/11 14:45:38 hal
19: * Trial patch for Seagate 157A problems.
20: *
21: * Revision 1.6 91/09/11 13:23:12 hal
22: * Explicit sys in include paths. AT_MAJOR.
23: *
24: * Revision 1.5 91/05/22 15:06:59 hal
25: * Don't force 8's bit of control byte.
26: *
27: * Revision 1.4 91/03/14 14:22:32 hal
28: *
29: -lgl) */
30: /*
31: * This is a driver for the
32: * hard disk on the PS.
33: *
34: * Reads drive characteristics from ROM (thru interrupt vector 0x41 and 0x46).
35: * Reads partition information from disk.
36: */
37: #include <sys/coherent.h>
38: #include <sys/fdisk.h>
39: #include <sys/hdioctl.h>
40: #include <sys/buf.h>
41: #include <sys/con.h>
42: #include <sys/devices.h>
43: #include <sys/stat.h>
44: #include <sys/uproc.h>
45: #include <sys/typed.h>
46: #include <sys/timeout.h> /* TIM */
47: #include <sys/sched.h>
48: #include <errno.h>
49:
50: extern saddr_t sds; /* System Data Selector */
51: extern short n_atdr; /* Number of "ps" drives */
52: int ATSREG = 0x3F6;
53:
54: /*
55: * Configurable parameters
56: */
57: #define HDIRQ 14 /* Level 14 */
58: #define NDRIVE 2 /* only two drives supported */
59: #define SOFTLIM 6 /* (7) num of retrys before diag */
60: #define HARDLIM 8 /* number of retrys before fail */
61: #define BADLIM 100 /* num to stop recov if flagged bad */
62:
63: #define BIT(n) (1 << (n))
64:
65: #define CMOSA 0x70 /* write cmos address to this port */
66: #define CMOSD 0x71 /* read cmos data through this port */
67:
68: /*
69: * Driver configuration.
70: */
71: void psload();
72: void psunload();
73: void psopen();
74: void psread();
75: void pswrite();
76: int psioctl();
77: void pstimer();
78: void psblock();
79: int nulldev();
80: int nonedev();
81:
82: CON pscon = {
83: DFBLK|DFCHR, /* Flags */
84: AT_MAJOR, /* Major index */
85: psopen, /* Open */
86: nulldev, /* Close */
87: psblock, /* Block */
88: psread, /* Read */
89: pswrite, /* Write */
90: psioctl, /* Ioctl */
91: nulldev, /* Powerfail */
92: nulldev, /* Timeout */
93: psload, /* Load */
94: psunload /* Unload */
95: };
96:
97: /*
98: * Forward Referenced Functions.
99: */
100: void psreset();
101: int psdequeue();
102: void psstart();
103: void psintr();
104: static void psstatus();
105: void psdone();
106: void disk_function();
107: void disk_functionb();
108:
109: /*
110: * Device States.
111: */
112: #define SIDLE 0 /* controller idle */
113: #define SRETRY 1 /* seeking */
114: #define SREAD 2 /* reading */
115: #define SWRITE 3 /* writing */
116: #define SRESET 4 /* reseting */
117:
118: char *smsg[] = { "SIDLE", "SRETRY", "SREAD", "SWRITE", "SRESET" };
119:
120: /*
121: * Drive Parameters - copied from ROM.
122: * If patched, use the given values instead of reading from the ROM.
123: * NOTE: Exactly duplicates hdparm_s struct.
124: */
125: struct dparm_s {
126: unsigned short d_ncyl; /* number of cylinders */
127: unsigned char d_nhead; /* number of heads */
128: unsigned short d_rwcc; /* reduced write current cyl */
129: unsigned short d_wpcc; /* write pre-compensation cyl */
130: unsigned char d_eccl; /* max ecc data length */
131: unsigned char d_ctrl; /* control byte */
132: unsigned char d_fill2[3];
133: unsigned short d_landc; /* landing zone cylinder */
134: unsigned char d_nspt; /* number of sectors per track */
135: unsigned char d_fill3;
136:
137: } psparm[ NDRIVE ] = {
138: 0 /* Initialized to allow patching */
139: };
140:
141: /*
142: * Partition Parameters - copied from disk.
143: *
144: * There are NDRIVE * NPARTN positions for the user partitions,
145: * plus NDRIVE additional partitions to span each drive.
146: *
147: * Aligning partitions on cylinder boundaries:
148: * Optimal partition size: 2 * 3 * 4 * 5 * 7 * 17 = 14280 blocks
149: * Acceptable partition size: 3 * 4 * 5 * 7 * 17 = 7140 blocks
150: */
151: static
152: struct fdisk_s pparm[NDRIVE*NPARTN + NDRIVE];
153:
154: /*
155: * Per disk controller data.
156: * Only one controller; no more, no less.
157: */
158: static
159: struct ps {
160: BUF *ps_actf; /* Link to first */
161: BUF *ps_actl; /* Link to last */
162: faddr_t ps_faddr; /* Source/Dest virtual address */
163: daddr_t ps_bno; /* Block # on disk */
164: unsigned ps_nsec; /* # of sectors on current transfer */
165: unsigned ps_drv;
166: unsigned ps_head;
167: unsigned ps_cyl;
168: unsigned ps_sec;
169: unsigned ps_partn;
170: unsigned char ps_dtype[ NDRIVE ]; /* drive type, 0 if unused */
171: unsigned char ps_tries;
172: unsigned char ps_state;
173: unsigned char ps_caching; /* caching in progress */
174: unsigned ps_bad_drv;
175: unsigned ps_bad_head;
176: unsigned ps_bad_cyl;
177: } ps;
178:
179: static BUF dbuf; /* For raw I/O */
180:
181:
182: #include <sys/abios.h>
183: #include <sys/mmu.h>
184: #include <sys/types.h>
185: #include <stdio.h>
186:
187: static request_block_hd rb;
188:
189: char killbuf[1024]; /* don't forget to fix bio.c */
190: char l_com_data[0x80];
191: paddr_t com_data_p, dev1p, fcn1p, dev2p, fcn2p;
192: a_sys_parm sp;
193: a_init_table it0, it1, it2, it15;
194:
195: char fcn0[0x10], fcn1[0x50], fcn2[0x40], fcn15[0x58];
196:
197: extern int com_data,i0, i1, i2, i15, fcn_trn0, fcn_trn1, fcn_trn2, fcn_trn15;
198:
199: #define cscolon(d) ((faddr_t)(0x600000L + (unsigned) (d)))
200: #define init_tab_cp(s,r) fkcopy(cscolon(ffword(cscolon(s))), r, 24)
201:
202: /*
203: * Patchable variables.
204: * PSBSYW is a loop count for busy-waiting after issuing commands.
205: * PSSECS is number of seconds to wait for an expected interrupt.
206: */
207: int PSBSYW = 50; /* patchable */
208: int PSSECS = 6; /* patchable */
209:
210: /**
211: *
212: * void
213: * psload() - load routine.
214: *
215: * Action: The controller is reset and the interrupt vector is grabbed.
216: * The drive characteristics are set up ps this time.
217: */
218: static void
219: psload()
220: {
221: unsigned int u;
222: register int s;
223: struct dparm_s * dp;
224:
225: init_abios();
226:
227: n_atdr = 1;
228:
229: if (n_atdr == 0)
230: return;
231:
232: ps.ps_actf = NULL; /* Start up with this Null to avoid phony calls */
233:
234: /*
235: * Obtain (hardwire) Drive Types.
236: */
237: ps.ps_dtype[0] = 1; /* This just means that it exists */
238: ps.ps_dtype[1] = 0; /* This just means that it doesn't exist */
239:
240: /*
241: * Obtain Drive Characteristics.
242: */
243:
244: for (u = 0, dp = &psparm[0]; u < n_atdr; ++dp, ++u)
245: {
246: rb.length = 0x80;
247: rb.logical_id = 5;
248: rb.unit = 0;
249: rb.function = 3;
250: rb.reserved = 0L;
251: rb.ret_code = 0xffff;
252: rb.vars.f3.reserved = 0L;
253: d2_func(&rb, START_P);
254: if (rb.ret_code)
255: printf("\nhard disk function 3 returned = %d\n",
256: rb.ret_code);
257: dp->d_ncyl = rb.vars.f3.cylinders;
258: dp->d_nhead = rb.vars.f3.heads;
259: dp->d_nspt = rb.vars.f3.sectors_track;
260: dp->d_wpcc = 0xffff;
261: dp->d_landc = rb.vars.f3.cylinders;
262: if (dp->d_nhead > 8)
263: dp->d_ctrl |= 8;
264:
265: #if 0
266:
267: printf(" drive %d parameters\n", u);
268: printf(
269: "ps%d: ncyl=%d nhead=%d wpcc=%d eccl=%d ctrl=%d landc=%d nspt=%d\n",
270: u,
271: dp->d_ncyl,
272: dp->d_nhead,
273: dp->d_wpcc,
274: dp->d_eccl,
275: dp->d_ctrl,
276: dp->d_landc,
277: dp->d_nspt);
278: printf("\nhard disk function 3 returned = %d\n", rb.ret_code);
279: printf("\nretries = %d", rb.vars.f3.retries);
280: printf("\nblock_addresses = %lu", rb.vars.f3.block_addresses);
281: printf("\nmax_blocks = %d\n", rb.vars.f3.max_blocks);
282:
283: #endif
284: }
285:
286: /*
287: * Initialize Drive Size.
288: */
289: for (u = 0, dp = &psparm[0]; u < n_atdr; ++dp, ++u) {
290:
291: if (ps.ps_dtype[u] == 0)
292: continue;
293:
294: pparm[NDRIVE*NPARTN + u].p_size =
295: (long) dp->d_ncyl * dp->d_nhead * dp->d_nspt;
296: }
297:
298:
299: s = sphi();
300: setivec(HDIRQ, psintr);
301: spl( s );
302:
303: ps.ps_bad_drv = -1;
304:
305: /*
306: * Initialize Drive Controller.
307: */
308: psreset();
309: }
310:
311: paddr_t prot;
312:
313: /* This is the protected mode part of the abios initialization */
314: init_abios()
315: {
316: unsigned int i, count, *tmp1;
317: paddr_t codeseg;
318: paddr_t *tmp, tmpp;
319: static short done = 0;
320:
321: if (done) /* Make sure we don't call this twice */
322: return;
323:
324: done++;
325:
326: printf("init_abios_a() = %x\n", iresult());
327:
328: /* First create the virtual pointer to the comm area */
329: com_data_p = ptov(vtop(l_com_data, sds), 0x80L);
330:
331: /* Now copy the common data table into local space */
332: fkcopy(cscolon((unsigned)(&com_data) & 0xfff0), l_com_data, 0x80);
333:
334: /* Now copy the initialization tables into local space */
335: init_tab_cp(&i0, &it0);
336: init_tab_cp(&i1, &it1);
337: init_tab_cp(&i15, &it15);
338: init_tab_cp(&i2, &it2);
339:
340: /* Now convert each real mode device block pointer into a protected
341: * mode device block pointer .
342: */
343:
344: tmp = tmp1 = l_com_data; /* Make thing easier on the compiler */
345:
346: codeseg = ptov(0x0600L, 0xffffL); /* Set up an r/w alias to the cs */
347:
348: /* Fix the segments in the CDA */
349: /* the offsets are still ok */
350: tmp1[9] = tmp1[13] = tmp1[17] = tmp1[21] = FP_SEL(codeseg);
351:
352: dev1p = tmp[6];
353: dev2p = tmp[10]; /* Set this up so calls are easier later */
354:
355: /* Now fix each function transfer table pointer in the cda so that
356: * it points to the proper spot in the ds
357: */
358:
359: /* Fix the segments in the CDA */
360: tmp1[11] = tmp1[15] = tmp1[19] = tmp1[23] = sds;
361:
362: tmp1[10] = (unsigned)fcn0; /* Now fix the offsets */
363: tmp1[14] = (unsigned)fcn1;
364: tmp1[18] = (unsigned)fcn15;
365: tmp1[22] = (unsigned)fcn2;
366:
367: fcn1p = tmp[7];
368: fcn2p = tmp[11]; /* Set this up so calls are easier later */
369:
370: /* Now convert the pointers in the ftts to protected mode pointers */
371:
372: /* This is the location of the Abios */
373: fkcopy(cscolon(&fcn_trn0), &tmpp, 4);
374: tmpp = (tmpp & 0xffff0000L) >> 12;
375: prot = ptovx(tmpp);
376:
377: /* First do the system level functions */
378: cnvt_ptrs(&fcn_trn0, fcn0, it0.ftt_length);
379: /* Now do the diskette functions */
380: cnvt_ptrs(&fcn_trn1, fcn1, it1.ftt_length);
381: /* Now do the DMA functions */
382: cnvt_ptrs(&fcn_trn15, fcn15, it15.ftt_length);
383: /* Finish up with the hard disk functions table */
384: cnvt_ptrs(&fcn_trn2, fcn2, it2.ftt_length);
385:
386: /* Finally, Convert the data pointers */
387:
388: i = *(int *)l_com_data; /* i is now a pointer to the first pointer */
389: count = *(int *)(l_com_data+i+6);/* count is the # of data pointers*/
390: while (count--) /* Any more data pointers? */
391: { /* Redo the pointer using the saved size */
392: tmp = l_com_data + i + 2;
393: *tmp = ptov(*tmp, (long)*(unsigned *)(tmp-2));
394: i -= 6; /* Now point to the next pointer */
395: }
396: }
397:
398:
399: cnvt_ptrs(cs_src, fcn_dest, length)
400: int cs_src, length;
401: char *fcn_dest;
402: {
403: paddr_t *tmp;
404: int count, i;
405:
406: /* First copy the tables into the data space */
407: fkcopy(cscolon(cs_src), fcn_dest, length);
408:
409: /* First do the system level functions */
410:
411: tmp = fcn_dest;
412:
413: FP_SEL(tmp[0]) = FP_SEL(prot); /* First the start routine */
414: FP_SEL(tmp[1]) = FP_SEL(prot); /* Next the interrupt routine */
415: FP_SEL(tmp[2]) = FP_SEL(prot); /* Next the time-out ruutine */
416:
417: /* Then do the individual functions */
418:
419: count = *((int *)(fcn_dest+0x0c)); /* how many functions */
420: for (i=0; i < count; i++) /* convert each function */
421: if (FP_OFF(tmp[i+4]))
422: FP_SEL(tmp[i+4]) = FP_SEL(prot);
423: }
424:
425:
426: /**
427: *
428: * void
429: * psunload() - unload routine.
430: */
431: static void
432: psunload()
433: {
434: clrivec(HDIRQ);
435: }
436:
437: /**
438: *
439: * void
440: * psreset() -- reset hard disk controller, define drive characteristics.
441: */
442: static void
443: psreset()
444: {
445: ps.ps_state = SRESET;
446: rb.length = 0x80;
447: rb.logical_id = 5;
448: rb.unit = 0;
449: rb.function = 5;
450: rb.reserved = 0L;
451: rb.ret_code = 0xffff;
452: rb.vars.f5.reserved = 0;
453: /* disk_function(START_P); */
454: d2_func(&rb, START_P);
455: while (rb.ret_code == 2) /* Wait for time */
456: {
457: unsigned long i;
458:
459: printf("PS: reset - %x\n", rb.ret_code);
460: for(i=0L; i < rb.vars.f8.wait_time; i+=4)
461: ;
462:
463: d2_func(&rb, INTERRUPT_P);
464: }
465: ps.ps_state = SIDLE;
466: if (rb.ret_code != 0)
467: printf("PS: reset failed - %x\n", rb.ret_code);
468: return;
469: }
470:
471: /**
472: *
473: * void
474: * psopen(dev, mode)
475: * dev_t dev;
476: * int mode;
477: *
478: * Input: dev = disk device to be opened.
479: * mode = access mode [IPR,IPW, IPR+IPW].
480: *
481: * Action: Validate the minor device.
482: * Update the paritition table if necessary.
483: */
484: static void
485: psopen(dev, mode)
486: register dev_t dev;
487: {
488: register int d; /* drive */
489: register int p; /* partition */
490:
491: p = minor(dev) % (NDRIVE*NPARTN);
492:
493: if (minor(dev) & SDEV) {
494: d = minor(dev) % NDRIVE;
495: p += NDRIVE * NPARTN;
496: }
497: else
498: d = minor(dev) / NPARTN;
499:
500: if ((d >= NDRIVE) || (ps.ps_dtype[d] == 0)) {
501: u.u_error = ENXIO;
502: return;
503: }
504:
505: if (minor(dev) & SDEV)
506: return;
507:
508: /*
509: * If partition not defined read partition characteristics.
510: */
511: if (pparm[p].p_size == 0)
512: fdisk(makedev(major(dev), SDEV + d), &pparm[ d * NPARTN ]);
513: /*
514: * Ensure partition lies within drive boundaries and is non-zero size.
515: */
516: if ((pparm[p].p_base+pparm[p].p_size) > pparm[d+NDRIVE*NPARTN].p_size)
517: u.u_error = EBADFMT;
518: else if (pparm[p].p_size == 0)
519: u.u_error = ENODEV;
520: }
521:
522: /**
523: *
524: * void
525: * psread(dev, iop) - read a block from the raw disk
526: * dev_t dev;
527: * IO * iop;
528: *
529: * Input: dev = disk device to be written to.
530: * iop = pointer to source I/O structure.
531: *
532: * Action: Invoke the common raw I/O processing code.
533: */
534: static void
535: psread(dev, iop)
536: dev_t dev;
537: IO *iop;
538: {
539: ioreq(&dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC);
540: }
541:
542: /**
543: *
544: * void
545: * pswrite(dev, iop) - write a block to the raw disk
546: * dev_t dev;
547: * IO * iop;
548: *
549: * Input: dev = disk device to be written to.
550: * iop = pointer to source I/O structure.
551: *
552: * Action: Invoke the common raw I/O processing code.
553: */
554: static void
555: pswrite(dev, iop)
556: dev_t dev;
557: IO *iop;
558: {
559: ioreq(&dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC);
560: }
561:
562: /**
563: *
564: * int
565: * psioctl(dev, cmd, arg)
566: * dev_t dev;
567: * int cmd;
568: * char * vec;
569: *
570: * Input: dev = disk device to be operated on.
571: * cmd = input/output request to be performed.
572: * vec = (pointer to) optional argument.
573: *
574: * Action: Validate the minor device.
575: * Update the paritition table if necessary.
576: */
577: static int
578: psioctl(dev, cmd, vec)
579: register dev_t dev;
580: int cmd;
581: char * vec;
582: {
583: int d;
584:
585: /*
586: * Identify drive number.
587: */
588: if (minor(dev) & SDEV)
589: d = minor(dev) % NDRIVE;
590: else
591: d = minor(dev) / NPARTN;
592:
593: /*
594: * Identify input/output request.
595: */
596: switch (cmd) {
597:
598: case HDGETA:
599: /*
600: * Get hard disk attributes.
601: */
602: kucopy(&psparm[d], vec, sizeof(psparm[0]));
603: return(0);
604:
605: case HDSETA:
606: return 0; /* For now, do not allow this */
607: /* Set hard disk pstributes. */
608:
609: ukcopy(vec, &psparm[d], sizeof(psparm[0]));
610: ps.ps_dtype[d] = 1; /* set drive type nonzero */
611: pparm[NDRIVE * NPARTN + d].p_size = (long) psparm[d].d_ncyl
612: * psparm[d].d_nhead * psparm[d].d_nspt;
613: psreset();
614: return 0;
615:
616: default:
617: u.u_error = EINVAL;
618: return(-1);
619: }
620: }
621:
622: /**
623: *
624: * void
625: * pstimer() - wait for timeout
626: *
627: * Action: If drvl[AT_MAJOR] is greater than zero, decrement it.
628: * If it decrements to zero, call the abios again
629: */
630: static void
631: pstimer()
632: {
633: register int s;
634:
635: s = sphi();
636: if (--drvl[AT_MAJOR].d_time > 0) {
637: spl(s);
638: return;
639: }
640: disk_function(INTERRUPT_P);
641: spl(s);
642: }
643:
644: /**
645: *
646: * void
647: * psblock(bp) - queue a block to the disk
648: *
649: * Input: bp = pointer to block to be queued.
650: *
651: * Action: Queue a block to the disk.
652: * Make sure that the transfer is within the disk partition.
653: */
654: static void
655: psblock(bp)
656: register BUF *bp;
657: {
658: register struct fdisk_s *pp;
659: int partn = minor(bp->b_dev) % (NDRIVE*NPARTN);
660:
661: if (minor(bp->b_dev) & SDEV)
662: partn += NDRIVE * NPARTN;
663:
664: pp = &pparm[ partn ];
665:
666: /*
667: * Check for read at end of partition.
668: */
669: if ((bp->b_req == BREAD) && (bp->b_bno == pp->p_size)) {
670: bdone(bp);
671: return;
672: }
673:
674: /*
675: * Range check disk region.
676: */
677: if (((bp->b_bno + (bp->b_count/BSIZE)) > pp->p_size)
678: || (bp->b_count % BSIZE) || bp->b_count == 0) {
679: bp->b_flag |= BFERR;
680: bdone(bp);
681: return;
682: }
683:
684: bp->b_actf = NULL;
685: if (ps.ps_actf == NULL)
686: ps.ps_actf = bp;
687: else
688: ps.ps_actl->b_actf = bp;
689: ps.ps_actl = bp;
690: if (ps.ps_state == SIDLE)
691: if (psdequeue())
692: psstart();
693: }
694:
695: /**
696: *
697: * int
698: * psdequeue() - obtain next disk read/write operation
699: *
700: * Action: Pull some work from the disk queue.
701: *
702: * Return: 0 = no work.
703: * * = work to do.
704: */
705: static int
706: psdequeue()
707: {
708: register BUF * bp = ps.ps_actf;
709: register struct fdisk_s * pp;
710: unsigned int nspt;
711:
712: ps.ps_caching = 0;
713: ps.ps_tries = 0;
714:
715: if (bp == NULL)
716: return (0);
717:
718: ps.ps_partn = minor(bp->b_dev) % (NDRIVE*NPARTN);
719:
720: if (minor(bp->b_dev) & SDEV) {
721: ps.ps_partn += (NDRIVE*NPARTN);
722: ps.ps_drv = minor(bp->b_dev) % NDRIVE;
723: }
724: else
725: ps.ps_drv = minor(bp->b_dev) / NPARTN;
726: nspt = psparm[ps.ps_drv].d_nspt;
727:
728: pp = &pparm[ ps.ps_partn ];
729: ps.ps_bno = pp->p_base + bp->b_bno;
730: ps.ps_nsec = bp->b_count / BSIZE;
731: ps.ps_faddr = bp->b_faddr;
732: return (1);
733: }
734:
735:
736: /**
737: *
738: * void
739: * psstart() - start or restart next disk read/write operation.
740: *
741: * Action: Initiate disk read/write operation.
742: */
743: static void
744: psstart()
745: {
746: register struct dparm_s *dp;
747:
748: dp = &psparm[ ps.ps_drv ];
749: #if 0
750: ps.ps_cyl = (ps.ps_bno / dp->d_nspt) / dp->d_nhead;
751: ps.ps_head = (ps.ps_bno / dp->d_nspt) % dp->d_nhead;
752: ps.ps_sec = (ps.ps_bno % dp->d_nspt) + 1;
753:
754: /*
755: * Check for repeated access to most recently identified bad track.
756: */
757: if ((ps.ps_drv == ps.ps_bad_drv)
758: && (ps.ps_cyl == ps.ps_bad_cyl)
759: && (ps.ps_head == ps.ps_bad_head)) {
760: BUF * bp = ps.ps_actf;
761: printf("ps%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>\n",
762: ps.ps_drv,
763: (bp->b_dev & SDEV) ? 'x' : ps.ps_partn % NPARTN + 'a',
764: bp->b_bno,
765: ps.ps_head,
766: ps.ps_cyl);
767: bp->b_flag |= BFERR;
768: psdone();
769: return;
770: }
771: #endif
772: rb.length = 0x80;
773: rb.logical_id = 5;
774: rb.unit = 0;
775: rb.reserved = 0L;
776: rb.ret_code = 0xffff;
777:
778: /* Note that the items below are set up the same way for a
779: * read or a write. */
780: rb.vars.f8.reserved = 0;
781: rb.vars.f8.reserved1 = 0;
782: rb.vars.f8.dptr = vtop(ps.ps_faddr);
783: rb.vars.f8.reserved2 = 0;
784: rb.vars.f8.rb_address = ps.ps_bno;
785: rb.vars.f8.reserved3 = 0;
786: rb.vars.f8.blocks_read = ps.ps_nsec;
787: rb.vars.f8.caching = 0;
788:
789: if (ps.ps_actf->b_req == BWRITE) {
790: rb.function = 9;
791: ps.ps_state = SWRITE;
792: }
793: else {
794: rb.function = 8;
795: ps.ps_state = SREAD;
796:
797: }
798: disk_function(START_P);
799: }
800:
801: /**
802: *
803: * void
804: * psintr() - Interrupt routine.
805: *
806: */
807: static void
808: psintr()
809: {
810: d2_func(&rb, INTERRUPT_P);
811: defer(disk_functionb, 0);
812: }
813:
814: /**
815: *
816: * static void
817: * psstatus()
818: *
819: * Print out appropiate error message
820: */
821: static void
822: psstatus()
823: {
824: register BUF * bp = ps.ps_actf;
825:
826: printf("ps%d%c: bno=%U head=%u cyl=%u <",
827: ps.ps_drv,
828: (bp->b_dev & SDEV) ? 'x' : ps.ps_partn % NPARTN + 'a',
829: (bp->b_count/BSIZE) + bp->b_bno + ps.ps_caching
830: - ps.ps_nsec, ps.ps_head, ps.ps_cyl);
831:
832: switch (rb.ret_code | 0x00ff) {
833: case 0x00aa:
834: printf("Drive Not Ready>");
835: break;
836: case 0x00cc:
837: printf("Write Fault>");
838: break;
839: case 0x0002:
840: printf("No Data Addr Mark>");
841: break;
842: case 0x0010:
843: printf("Bad Data Checksum>");
844: break;
845: case 0x00a:
846: case 0x00b:
847: printf("Block Flagged Bad>");
848: break;
849: default:
850: printf("Error 0x%x>", rb.ret_code);
851: }
852: printf("\n");
853:
854: }
855:
856: /**
857: *
858: * void
859: * psdone()
860: *
861: * Action: Release current i/o buffer to the O/S.
862: */
863: static void
864: psdone()
865: {
866: register BUF * bp = ps.ps_actf;
867:
868: drvl[AT_MAJOR].d_time = 0;
869: ps.ps_state = SIDLE;
870: bdone(bp);
871:
872: ps.ps_actf = bp->b_actf;
873:
874: if (psdequeue())
875: psstart();
876: }
877:
878:
879: void disk_function(type)
880: int type;
881: {
882: /* printf("disk function\n"); */
883: d2_func(&rb, type);
884: printf("%s", "");
885: disk_functionb();
886: }
887:
888: static TIM pstim;
889:
890: void disk_functionb()
891: {
892: /* printf("rb.ret_code = %x\r", rb.ret_code); */
893: while (rb.ret_code == 2) /* Wait for time */
894: {
895: long i;
896: for(i=0L; i < rb.vars.f8.wait_time; i+=128)
897: ;
898:
899: d2_func(&rb, INTERRUPT_P);
900: }
901:
902: if (rb.ret_code == 0) /* Finished */
903: {
904: ps.ps_actf->b_resid = 0;
905: psdone();
906: }
907: else if (rb.ret_code == 1) /* Wat for int */
908: {
909: /*ps.ps_state = SINT; */
910: }
911: else
912: {
913: register BUF *bp = ps.ps_actf;
914:
915: psstatus();
916: bp->b_flag |= BFERR;
917: psdone();
918: }
919: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.