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