|
|
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.