|
|
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:
53: /*
54: * Configurable parameters
55: */
56: #define HDIRQ 14 /* Level 14 */
57: #define NDRIVE 2 /* only two drives supported */
58: #define SOFTLIM 6 /* (7) num of retrys before diag */
59: #define HARDLIM 4 /* number of retrys before fail */
60: #define BADLIM 100 /* num to stop recov if flagged bad */
61:
62: #define BIT(n) (1 << (n))
63:
64: #define CMOSA 0x70 /* write cmos address to this port */
65: #define CMOSD 0x71 /* read cmos data through this port */
66:
67: /*
68: * Driver configuration.
69: */
70: void psload();
71: void psunload();
72: void psopen();
73: void psread();
74: void pswrite();
75: int psioctl();
76: void pstimer();
77: void psblock();
78: int nulldev();
79: int nonedev();
80:
81: CON pscon = {
82: DFBLK|DFCHR, /* Flags */
83: AT_MAJOR, /* Major index */
84: psopen, /* Open */
85: nulldev, /* Close */
86: psblock, /* Block */
87: psread, /* Read */
88: pswrite, /* Write */
89: psioctl, /* Ioctl */
90: nulldev, /* Powerfail */
91: pstimer, /* Timeout */
92: psload, /* Load */
93: psunload /* Unload */
94: };
95:
96: /*
97: * Forward Referenced Functions.
98: */
99: void psreset();
100: int psdequeue();
101: void psstart();
102: void psintr();
103: int pserror();
104: void psrecov();
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, it7, it15;
194:
195:
196: char fcn0[0x10], fcn1[0x50], fcn2[0x40], fcn7[0x50], fcn15[0x58];
197:
198: extern int com_data,i0, i1, i2, i7, i15, end_table,
199: fcn_trn0, fcn_trn1, fcn_trn2, fcn_trn7, fcn_trn15;
200:
201: #define cscolon(d) ((faddr_t)(0x600000L + (unsigned) (d)))
202: #define ftop(d) ((paddr_t)(FP_SEL(d)<<4L) + FP_OFF(d))
203: #define init_tab_cp(s,r) fkcopy(cscolon(ffword(cscolon(s))), r, 24)
204:
205: /*
206: * Patchable variables.
207: * PSBSYW is a loop count for busy-waiting after issuing commands.
208: * PSSECS is number of seconds to wait for an expected interrupt.
209: */
210: int PSBSYW = 50; /* patchable */
211: int PSSECS = 6; /* patchable */
212:
213: /**
214: *
215: * void
216: * psload() - load routine.
217: *
218: * Action: The controller is reset and the interrupt vector is grabbed.
219: * The drive characteristics are set up ps this time.
220: */
221: static void
222: psload()
223: {
224: unsigned int u;
225: register int s;
226: struct dparm_s * dp;
227:
228: {int i; for (i=0;i<1000; i++);}
229: {int i; for (i=0;i<1000; i++);}
230: {int i; for (i=0;i<1000; i++);}
231: {int i; for (i=0;i<1000; i++);}
232: {int i; for (i=0;i<1000; i++);}
233: {int i; for (i=0;i<1000; i++);}
234: {int i; for (i=0;i<1000; i++);}
235: {int i; for (i=0;i<1000; i++);}
236: {int i; for (i=0;i<1000; i++);}
237: {int i; for (i=0;i<1000; i++);}
238: {int i; for (i=0;i<1000; i++);}
239: {int i; for (i=0;i<1000; i++);}
240: {int i; for (i=0;i<1000; i++);}
241: {int i; for (i=0;i<1000; i++);}
242: {int i; for (i=0;i<1000; i++);}
243: {int i; for (i=0;i<1000; i++);}
244: {int i; for (i=0;i<1000; i++);}
245:
246: printf("loading ps\n");
247: init_abios();
248:
249: n_atdr = 1;
250: /* printf("n_atdr = %d\n", n_atdr); */
251:
252: if (n_atdr == 0)
253: return;
254:
255: ps.ps_actf = NULL; /* Start up with this Null to avoid phony calls */
256:
257: /*
258: * Obtain (hardwire) Drive Types.
259: */
260: ps.ps_dtype[0] = 1; /* This just means that it exists */
261: ps.ps_dtype[1] = 0; /* This just means that it doesn't exist */
262:
263: /*
264: * Obtain Drive Characteristics.
265: */
266:
267: for (u = 0, dp = &psparm[0]; u < n_atdr; ++dp, ++u)
268: {
269: rb.length = 0x80;
270: rb.logical_id = 6;
271: rb.unit = 0;
272: rb.function = 3;
273: rb.reserved = 0L;
274: rb.ret_code = 0xffff;
275: rb.vars.f3.reserved = 0L;
276: d2_func(&rb, START_P);
277: if (rb.ret_code)
278: printf("\nhard disk function 3 returned = %d\n",
279: rb.ret_code);
280: dp->d_ncyl = rb.vars.f3.cylinders;
281: dp->d_nhead = rb.vars.f3.heads;
282: dp->d_nspt = rb.vars.f3.sectors_track;
283: dp->d_wpcc = 0xffff;
284: dp->d_landc = rb.vars.f3.cylinders;
285: if (dp->d_nhead > 8)
286: dp->d_ctrl |= 8;
287:
288: #if 0
289:
290: printf(" drive %d parameters\n", u);
291: printf(
292: "ps%d: ncyl=%d nhead=%d wpcc=%d eccl=%d ctrl=%d landc=%d nspt=%d\n",
293: u,
294: dp->d_ncyl,
295: dp->d_nhead,
296: dp->d_wpcc,
297: dp->d_eccl,
298: dp->d_ctrl,
299: dp->d_landc,
300: dp->d_nspt);
301: printf("\nhard disk function 3 returned = %d\n", rb.ret_code);
302: printf("\nretries = %d", rb.vars.f3.retries);
303: printf("\nblock_addresses = %lu", rb.vars.f3.block_addresses);
304: printf("\nmax_blocks = %d\n", rb.vars.f3.max_blocks);
305:
306: #endif
307: }
308:
309: /*
310: * Initialize Drive Size.
311: */
312: for (u = 0, dp = &psparm[0]; u < n_atdr; ++dp, ++u) {
313:
314: if (ps.ps_dtype[u] == 0)
315: continue;
316:
317: pparm[NDRIVE*NPARTN + u].p_size =
318: (long) dp->d_ncyl * dp->d_nhead * dp->d_nspt;
319: }
320:
321: /*
322: s = sphi();
323: spl( s );
324: */
325: setivec(HDIRQ, psintr);
326:
327: ps.ps_bad_drv = -1;
328:
329: /*
330: * Initialize Drive Controller.
331: */
332: psreset();
333: }
334:
335: paddr_t prot;
336:
337: /* This is the protected mode part of the abios initialization */
338: init_abios()
339: {
340: unsigned int i, count, *tmp1;
341: paddr_t codeseg;
342: paddr_t *tmp;
343: static short done = 0;
344:
345: if (done) /* Make sure we don't call this twice */
346: return;
347:
348: done++;
349:
350: printf("init_abios_a() = %x\n", iresult());
351:
352: /* First create the virtual pointer to the comm area */
353: com_data_p = ptov(vtop(l_com_data, sds), 0x80L);
354:
355: /* Now copy the common data table into local space */
356: fkcopy(cscolon((unsigned)(&com_data) & 0xfff0), l_com_data, 0x80);
357:
358: /* Now copy the initialization tables into local space */
359: init_tab_cp(&i0, &it0);
360: init_tab_cp(&i1, &it1);
361: init_tab_cp(&i7, &it7);
362: init_tab_cp(&i15, &it15);
363: init_tab_cp(&i2, &it2);
364: /*
365: fkcopy(cscolon(ffword(cscolon(&i0))), &it0, 24);
366: fkcopy(cscolon(ffword(cscolon(&i1))), &it1, 24);
367: fkcopy(cscolon(ffword(cscolon(&i1))), &it7, 24);
368: fkcopy(cscolon(ffword(cscolon(&i15))), &it15, 24);
369: fkcopy(cscolon(ffword(cscolon(&i2))), &it2, 24);
370: */
371: /* Now convert each real mode device block pointer into a protected
372: * mode device block pointer .
373: */
374:
375: tmp = tmp1 = l_com_data; /* Make thing easier on the compiler */
376:
377: codeseg = ptov(0x0600L,&end_table);/* Set up an r/w alias to the cs */
378:
379: /* Fix the segments in the CDA */
380: /* the offsets are still ok */
381: tmp1[9] = tmp1[13] = tmp1[17] = tmp1[21] = tmp1[25] = FP_SEL(codeseg);
382:
383: dev1p = tmp[6];
384: dev2p = tmp[12]; /* Set this up so calls are easier later */
385:
386: /* Now fix each function transfer table pointer in the cda so that
387: * it points to the proper spot in the ds
388: */
389:
390: /* Fix the segments in the CDA */
391: tmp1[11] = tmp1[15] = tmp1[19] = tmp1[23] = tmp1[27] = sds;
392:
393: tmp1[10] = (unsigned)fcn0; /* Now fix the offsets */
394: tmp1[14] = (unsigned)fcn1;
395: tmp1[18] = (unsigned)fcn7;
396: tmp1[22] = (unsigned)fcn15;
397: tmp1[26] = (unsigned)fcn2;
398:
399: fcn1p = tmp[7];
400: fcn2p = tmp[13]; /* Set this up so calls are easier later */
401:
402: /* Now convert the pointers in the ftts to protected mode pointers */
403: /* This is the location of the Abios */
404: prot = ptovx((paddr_t)(0xE0000L));
405: /* Take out this hardwired number later */
406:
407: /* First do the system level functions */
408: cnvt_ptrs(&fcn_trn0, fcn0, it0.ftt_length);
409: /* Now do the diskette functions */
410: cnvt_ptrs(&fcn_trn1, fcn1, it1.ftt_length);
411: /* Now do the timer functions */
412: cnvt_ptrs(&fcn_trn7, fcn7, it7.ftt_length);
413: /* Now do the DMA functions */
414: cnvt_ptrs(&fcn_trn15, fcn15, it15.ftt_length);
415: /* Finish up with the hard disk functions table */
416: cnvt_ptrs(&fcn_trn2, fcn2, it2.ftt_length);
417:
418: /* Finally, Convert the data pointers */
419:
420: i = *(int *)l_com_data; /* i is now a pointer to the first pointer */
421: count = *(int *)(l_com_data+i+6);/* count is the # of data pointers*/
422: while (count--) /* Any more data pointers? */
423: { /* Redo the pointer using the saved size */
424: tmp = l_com_data + i + 2;
425: *tmp = ptov(ftop(*tmp),(long)*(unsigned *)(tmp-2));
426: i -= 6; /* Now point to the next pointer */
427: }
428:
429: printf("abios inited\n");
430: }
431:
432:
433: cnvt_ptrs(cs_src, fcn_dest, length)
434: int cs_src, length;
435: char *fcn_dest;
436: {
437: paddr_t *tmp;
438: int count, i;
439:
440: /* First copy the tables into the data space */
441: fkcopy(cscolon(cs_src), fcn_dest, length);
442:
443: /* First do the system level functions */
444:
445: tmp = fcn_dest;
446:
447: FP_SEL(tmp[0]) = FP_SEL(prot); /* First the start routine */
448: FP_SEL(tmp[1]) = FP_SEL(prot); /* Next the interrupt routine */
449: FP_SEL(tmp[2]) = FP_SEL(prot); /* Next the time-out ruutine */
450:
451: /* Then do the individual functions */
452:
453: count = *((int *)(fcn_dest+0x0c)); /* how many functions */
454: for (i=0; i < count; i++) /* convert each function */
455: if (FP_OFF(tmp[i+4]))
456: FP_SEL(tmp[i+4]) = FP_SEL(prot);
457: }
458:
459:
460: /**
461: *
462: * void
463: * psunload() - unload routine.
464: */
465: static void
466: psunload()
467: {
468: clrivec(HDIRQ);
469: }
470:
471: static TIM psrstlck;
472:
473: /**
474: *
475: * void
476: * psreset() -- reset hard disk controller, define drive characteristics.
477: */
478: static void
479: psreset()
480: {
481: register int s;
482:
483: ps.ps_state = SRESET;
484: rb.length = 0x80;
485: rb.logical_id = 6;
486: rb.unit = 0;
487: rb.function = 5;
488: rb.reserved = 0L;
489: rb.ret_code = 0xffff;
490: rb.vars.f5.reserved = 0;
491:
492: d2_func(&rb, START_P);
493:
494: while (rb.ret_code == 2) /* Wait for time */
495: {
496: unsigned long i;
497:
498: for(i=0L; i < rb.vars.f8.wait_time; i+=8)
499: ;
500: d2_func(&rb, INTERRUPT_P);
501: }
502:
503: ps.ps_state = SIDLE;
504: if (rb.ret_code != 0)
505: printf("PS: reset failed - %x\n", rb.ret_code);
506: return;
507: #if 0
508: disk_function(START_P);
509:
510: s = sphi();
511: while ((rb.ret_code == 1) || (rb.ret_code == 2))
512: sleep(&psrstlck, CVWAIT, IVWAIT, SVWAIT);
513: spl( s );
514:
515: ps.ps_state = SIDLE;
516: if (rb.ret_code != 0)
517: printf("PS: reset failed - %u\n", rb.ret_code);
518: return;
519: #endif
520: }
521:
522: /**
523: *
524: * void
525: * psopen(dev, mode)
526: * dev_t dev;
527: * int mode;
528: *
529: * Input: dev = disk device to be opened.
530: * mode = access mode [IPR,IPW, IPR+IPW].
531: *
532: * Action: Validate the minor device.
533: * Update the paritition table if necessary.
534: */
535: static void
536: psopen(dev, mode)
537: register dev_t dev;
538: {
539: register int d; /* drive */
540: register int p; /* partition */
541:
542: p = minor(dev) % (NDRIVE*NPARTN);
543:
544: if (minor(dev) & SDEV) {
545: d = minor(dev) % NDRIVE;
546: p += NDRIVE * NPARTN;
547: }
548: else
549: d = minor(dev) / NPARTN;
550:
551: if ((d >= NDRIVE) || (ps.ps_dtype[d] == 0)) {
552: u.u_error = ENXIO;
553: return;
554: }
555:
556: if (minor(dev) & SDEV)
557: return;
558:
559: /*
560: * If partition not defined read partition characteristics.
561: */
562: if (pparm[p].p_size == 0)
563: fdisk(makedev(major(dev), SDEV + d), &pparm[ d * NPARTN ]);
564: /*
565: * Ensure partition lies within drive boundaries and is non-zero size.
566: */
567: if ((pparm[p].p_base+pparm[p].p_size) > pparm[d+NDRIVE*NPARTN].p_size)
568: u.u_error = EBADFMT;
569: else if (pparm[p].p_size == 0)
570: u.u_error = ENODEV;
571: }
572:
573: /**
574: *
575: * void
576: * psread(dev, iop) - read a block from the raw disk
577: * dev_t dev;
578: * IO * iop;
579: *
580: * Input: dev = disk device to be written to.
581: * iop = pointer to source I/O structure.
582: *
583: * Action: Invoke the common raw I/O processing code.
584: */
585: static void
586: psread(dev, iop)
587: dev_t dev;
588: IO *iop;
589: {
590: ioreq(&dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC);
591: }
592:
593: /**
594: *
595: * void
596: * pswrite(dev, iop) - write a block to the raw disk
597: * dev_t dev;
598: * IO * iop;
599: *
600: * Input: dev = disk device to be written to.
601: * iop = pointer to source I/O structure.
602: *
603: * Action: Invoke the common raw I/O processing code.
604: */
605: static void
606: pswrite(dev, iop)
607: dev_t dev;
608: IO *iop;
609: {
610: ioreq(&dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC);
611: }
612:
613: /**
614: *
615: * int
616: * psioctl(dev, cmd, arg)
617: * dev_t dev;
618: * int cmd;
619: * char * vec;
620: *
621: * Input: dev = disk device to be operated on.
622: * cmd = input/output request to be performed.
623: * vec = (pointer to) optional argument.
624: *
625: * Action: Validate the minor device.
626: * Update the paritition table if necessary.
627: */
628: static int
629: psioctl(dev, cmd, vec)
630: register dev_t dev;
631: int cmd;
632: char * vec;
633: {
634: int d;
635:
636: /*
637: * Identify drive number.
638: */
639: if (minor(dev) & SDEV)
640: d = minor(dev) % NDRIVE;
641: else
642: d = minor(dev) / NPARTN;
643:
644: /*
645: * Identify input/output request.
646: */
647: switch (cmd) {
648:
649: case HDGETA:
650: /*
651: * Get hard disk attributes.
652: */
653: kucopy(&psparm[d], vec, sizeof(psparm[0]));
654: return(0);
655:
656: case HDSETA:
657: return 0; /* For now, do not allow this */
658: /* Set hard disk pstributes. */
659: ukcopy(vec, &psparm[d], sizeof(psparm[0]));
660: ps.ps_dtype[d] = 1; /* set drive type nonzero */
661: pparm[NDRIVE * NPARTN + d].p_size = (long) psparm[d].d_ncyl
662: * psparm[d].d_nhead * psparm[d].d_nspt;
663: psreset();
664: return 0;
665:
666: default:
667: u.u_error = EINVAL;
668: return(-1);
669: }
670: }
671:
672: /**
673: *
674: * void
675: * pstimer() - wait for timeout
676: *
677: * Action: If drvl[AT_MAJOR] is greater than zero, decrement it.
678: * If it decrements to zero, call the abios again
679: */
680: static void
681: pstimer()
682: {
683: register int s;
684:
685: s = sphi();
686: if (--drvl[AT_MAJOR].d_time > 0) {
687: spl(s);
688: return;
689: }
690: disk_function(INTERRUPT_P);
691: spl(s);
692: }
693:
694: /**
695: *
696: * void
697: * psblock(bp) - queue a block to the disk
698: *
699: * Input: bp = pointer to block to be queued.
700: *
701: * Action: Queue a block to the disk.
702: * Make sure that the transfer is within the disk partition.
703: */
704: static void
705: psblock(bp)
706: register BUF *bp;
707: {
708: register struct fdisk_s *pp;
709: int partn = minor(bp->b_dev) % (NDRIVE*NPARTN);
710:
711: if (minor(bp->b_dev) & SDEV)
712: partn += NDRIVE * NPARTN;
713:
714: pp = &pparm[ partn ];
715:
716: /*
717: * Check for read at end of partition.
718: */
719: if ((bp->b_req == BREAD) && (bp->b_bno == pp->p_size)) {
720: bdone(bp);
721: return;
722: }
723:
724: /*
725: * Range check disk region.
726: */
727: if (((bp->b_bno + (bp->b_count/BSIZE)) > pp->p_size)
728: || (bp->b_count % BSIZE) || bp->b_count == 0) {
729: bp->b_flag |= BFERR;
730: bdone(bp);
731: return;
732: }
733:
734: bp->b_actf = NULL;
735: if (ps.ps_actf == NULL)
736: ps.ps_actf = bp;
737: else
738: ps.ps_actl->b_actf = bp;
739: ps.ps_actl = bp;
740: if (ps.ps_state == SIDLE)
741: if (psdequeue())
742: psstart();
743: }
744:
745: /**
746: *
747: * int
748: * psdequeue() - obtain next disk read/write operation
749: *
750: * Action: Pull some work from the disk queue.
751: *
752: * Return: 0 = no work.
753: * * = work to do.
754: */
755: static int
756: psdequeue()
757: {
758: register BUF * bp = ps.ps_actf;
759: register struct fdisk_s * pp;
760: unsigned int nspt;
761:
762: ps.ps_caching = 0;
763: ps.ps_tries = 0;
764:
765: if (bp == NULL)
766: return (0);
767:
768: ps.ps_partn = minor(bp->b_dev) % (NDRIVE*NPARTN);
769:
770: if (minor(bp->b_dev) & SDEV) {
771: ps.ps_partn += (NDRIVE*NPARTN);
772: ps.ps_drv = minor(bp->b_dev) % NDRIVE;
773: }
774: else
775: ps.ps_drv = minor(bp->b_dev) / NPARTN;
776: nspt = psparm[ps.ps_drv].d_nspt;
777:
778: pp = &pparm[ ps.ps_partn ];
779: ps.ps_bno = pp->p_base + bp->b_bno;
780: ps.ps_nsec = bp->b_count / BSIZE;
781: ps.ps_faddr = bp->b_faddr;
782: return (1);
783: }
784:
785:
786: /**
787: *
788: * void
789: * psstart() - start or restart next disk read/write operation.
790: *
791: * Action: Initiate disk read/write operation.
792: */
793: static void
794: psstart()
795: {
796: register struct dparm_s *dp;
797:
798: dp = &psparm[ ps.ps_drv ];
799: #if 0
800: ps.ps_cyl = (ps.ps_bno / dp->d_nspt) / dp->d_nhead;
801: ps.ps_head = (ps.ps_bno / dp->d_nspt) % dp->d_nhead;
802: ps.ps_sec = (ps.ps_bno % dp->d_nspt) + 1;
803:
804: /*
805: * Check for repeated access to most recently identified bad track.
806: */
807: if ((ps.ps_drv == ps.ps_bad_drv)
808: && (ps.ps_cyl == ps.ps_bad_cyl)
809: && (ps.ps_head == ps.ps_bad_head)) {
810: BUF * bp = ps.ps_actf;
811: printf("ps%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>\n",
812: ps.ps_drv,
813: (bp->b_dev & SDEV) ? 'x' : ps.ps_partn % NPARTN + 'a',
814: bp->b_bno,
815: ps.ps_head,
816: ps.ps_cyl);
817: bp->b_flag |= BFERR;
818: psdone();
819: return;
820: }
821: #endif
822: rb.length = 0x80;
823: rb.logical_id = 6;
824: rb.unit = 0;
825: rb.reserved = 0L;
826: rb.ret_code = 0xffff;
827:
828: /* Note that the items below are set up the same way for a
829: * read or a write. */
830: rb.vars.f8.reserved = 0;
831: rb.vars.f8.reserved1 = 0;
832: rb.vars.f8.dptr = vtop(ps.ps_faddr);
833: rb.vars.f8.reserved2 = 0;
834: rb.vars.f8.rb_address = ps.ps_bno;
835: rb.vars.f8.reserved3 = 0;
836: rb.vars.f8.blocks_read = ps.ps_nsec;
837: rb.vars.f8.caching = 0;
838: if (ps.ps_actf->b_req == BWRITE) {
839: rb.function = 9;
840: ps.ps_state = SWRITE;
841: }
842: else {
843: rb.function = 8;
844: ps.ps_state = SREAD;
845:
846: }
847: disk_function(START_P);
848: }
849:
850: /**
851: *
852: * void
853: * psintr() - Interrupt routine.
854: *
855: */
856: static void
857: psintr()
858: {
859: d2_func(&rb, INTERRUPT_P);
860: defer(disk_functionb, 0);
861: }
862:
863: /**
864: *
865: * int
866: * pserror()
867: *
868: * Action: Check for drive error.
869: * If found, increment error count and report it.
870: *
871: * Return: 0 = No error found.
872: * 1 = Error occurred.
873: */
874: static int
875: pserror()
876: {
877: register BUF * bp = ps.ps_actf;
878:
879: if (rb.ret_code <= 2)
880: return 0; /* For now, do nothing */
881: else
882: {
883: printf("ps%d%c: bno=%U head=%u cyl=%u error=%x",
884: ps.ps_drv,
885: (bp->b_dev & SDEV) ? 'x' : ps.ps_partn % NPARTN + 'a',
886: (bp->b_count/BSIZE) + bp->b_bno
887: + ps.ps_caching - ps.ps_nsec,
888: ps.ps_head, ps.ps_cyl, rb.ret_code);
889: return rb.ret_code;
890: }
891:
892: #if 0
893: if ((csr = inb(HF_REG)) & (ERR_ST|WFLT_ST)) {
894:
895: aux = inb(AUX_REG);
896:
897: if (aux & BAD_ERR) {
898: ps.ps_tries = BADLIM;
899: ps.ps_bad_drv = ps.ps_drv;
900: ps.ps_bad_head = ps.ps_head;
901: ps.ps_bad_cyl = ps.ps_cyl;
902: }
903: else if (++ps.ps_tries < SOFTLIM)
904: return 1;
905:
906: printf("ps%d%c: bno=%U head=%u cyl=%u",
907: ps.ps_drv,
908: (bp->b_dev & SDEV) ? 'x' : ps.ps_partn % NPARTN + 'a',
909: (bp->b_count/BSIZE) + bp->b_bno
910: + ps.ps_caching - ps.ps_nsec,
911: ps.ps_head, ps.ps_cyl);
912:
913: #if VERBOSE > 0
914: if ((csr & RDY_ST) == 0)
915: printf(" <Drive Not Ready>");
916: if (csr & WFLT_ST)
917: printf(" <Write Fault>");
918:
919: if (aux & DAM_ERR)
920: printf(" <No Data Addr Mark>");
921: if (aux & TR0_ERR)
922: printf(" <Track 0 Not Found>");
923: if (aux & ID_ERR)
924: printf(" <ID Not Found>");
925: if (aux & ECC_ERR)
926: printf(" <Bad Data Checksum>");
927: if (aux & ABT_ERR)
928: printf(" <Command Aborted>");
929: #else
930: if ((csr & (RDY_ST|WFLT_ST)) != RDY_ST)
931: printf(" csr=%x", csr);
932: if (aux & (DAM_ERR|TR0_ERR|ID_ERR|ECC_ERR|ABT_ERR))
933: printf(" aux=%x", aux);
934: #endif
935: if (aux & BAD_ERR)
936: printf(" <Block Flagged Bad>");
937:
938: if (ps.ps_tries < HARDLIM)
939: printf(" retrying...");
940: printf("\n");
941: return 1;
942: }
943: return 0;
944: #endif
945: }
946:
947: /**
948: *
949: * void
950: * psrecov()
951: *
952: * Action: Attempt recovery.
953: */
954: static void
955: psrecov()
956: {
957: register BUF *bp = ps.ps_actf;
958: if (ps.ps_tries < HARDLIM) {
959: ps.ps_tries++;
960: psdequeue();
961: psstart();
962: }
963:
964: /*
965: * Give up on block.
966: */
967: else {
968: bp->b_flag |= BFERR;
969: psdone();
970: }
971: }
972:
973: /**
974: *
975: * void
976: * psdone()
977: *
978: * Action: Release current i/o buffer to the O/S.
979: */
980: static void
981: psdone()
982: {
983: register BUF * bp = ps.ps_actf;
984:
985: drvl[AT_MAJOR].d_time = 0;
986: ps.ps_state = SIDLE;
987: bdone(bp);
988:
989: ps.ps_actf = bp->b_actf;
990:
991: if (psdequeue())
992: psstart();
993: }
994:
995:
996: void disk_function(type)
997: int type;
998: {
999: d2_func(&rb, type);
1000: disk_functionb();
1001: }
1002:
1003: static TIM pstim;
1004:
1005: void disk_functionb()
1006: {
1007: static int test=0;
1008: while (rb.ret_code == 2) /* Wait for time */
1009: {
1010: test++;
1011: if (test > 1) printf("%");
1012: /* timeout(&pstim, 1, wakeup, (int)&pstim);
1013: sleep((char *)&pstim, CVTTOUT, IVTTOUT, SVTTOUT);
1014: */
1015: {
1016: long i;
1017: for(i=0L; i < rb.vars.f8.wait_time; i+=64)
1018: ;
1019: }
1020: d2_func(&rb, INTERRUPT_P);
1021: }
1022: test=0;
1023: if (rb.ret_code == 0) /* Finished */
1024: {
1025: if (ps.ps_state != SRESET)
1026: {
1027: ps.ps_actf->b_resid = 0;
1028: psdone();
1029: }
1030: else
1031: wakeup(&psrstlck);
1032: }
1033: else if (rb.ret_code == 1) /* Wat for int */
1034: {
1035: /*ps.ps_state = SINT; */
1036: }
1037: else
1038: {
1039: printf("PS: error %x in %s.\n", rb.ret_code,
1040: smsg[ps.ps_state]);
1041: psrecov();
1042: }
1043:
1044: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.