|
|
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: -lgl) */ ! 6: /* ! 7: * This is a driver for the ! 8: * Archive SC-400 Series Tape Controller. ! 9: */ ! 10: #include <sys/coherent.h> ! 11: #include <sys/buf.h> ! 12: #include <sys/con.h> ! 13: #include <sys/const.h> ! 14: #include <sys/devices.h> ! 15: #include <sys/inode.h> ! 16: #include <sys/mtioctl.h> ! 17: #include <sys/sched.h> ! 18: #include <sys/seg.h> ! 19: #include <sys/stat.h> ! 20: #include <sys/uproc.h> ! 21: #include <errno.h> ! 22: ! 23: /* ! 24: * Fixed parameters. ! 25: */ ! 26: #define NCMDS 8 /* Max # chained commands */ ! 27: ! 28: /* ! 29: * Configurable parameters ! 30: */ ! 31: int STIRQ = 3; /* IRQ Level 3 */ ! 32: int STPORT = 0x200; /* I/O Port */ ! 33: int STDMA = 1; /* DMA Channel */ ! 34: ! 35: #define BIT(n) (1 << (n)) ! 36: ! 37: /* ! 38: * Forward referenced functions. ! 39: */ ! 40: void stcache(); ! 41: void stflush(); ! 42: void stinvoke(); ! 43: void ststart(); ! 44: void stintr(); ! 45: void strecov(); ! 46: void stnext(); ! 47: void stdiag(); ! 48: void stspin(); ! 49: ! 50: /* ! 51: * Driver configuration. ! 52: */ ! 53: int stload(); ! 54: int stuload(); ! 55: int stopen(); ! 56: int stclose(); ! 57: int stread(); ! 58: int stwrite(); ! 59: int stioctl(); ! 60: void stwatch(); ! 61: int nulldev(); ! 62: int nonedev(); ! 63: ! 64: CON stcon = { ! 65: DFCHR, /* Flags */ ! 66: ST_MAJOR, /* Major index */ ! 67: stopen, /* Open */ ! 68: stclose, /* Close */ ! 69: nonedev, /* Block */ ! 70: stread, /* Read */ ! 71: stwrite, /* Write */ ! 72: stioctl, /* Ioctl */ ! 73: nulldev, /* Powerfail */ ! 74: stwatch, /* Timeout */ ! 75: stload, /* Load */ ! 76: stuload /* Unload */ ! 77: }; ! 78: ! 79: /* ! 80: * I/O Port Addresses ! 81: */ ! 82: #define DATA_REG (STPORT+0) /* Data register */ ! 83: #define CTRL_REG (STPORT+1) /* Control/Status register */ ! 84: #define DMAGO_REG (STPORT+2) /* DMA Go register */ ! 85: #define DMARST_REG (STPORT+3) /* DMA reset register */ ! 86: ! 87: /* ! 88: * Control Register ! 89: */ ! 90: #define CR_RSTSAC BIT(7) /* 1 -> reset control micro */ ! 91: #define CR_REQ BIT(6) /* 1 -> request to LSI chip */ ! 92: #define CR_IEN BIT(5) /* 1 -> enables interrupts */ ! 93: #define CR_DNIEN BIT(4) /* 1 -> enable DONE interrupts */ ! 94: ! 95: /* ! 96: * Status Register ! 97: */ ! 98: #define SR_IRQF BIT(7) /* 1 -> Interrupt Request Flag */ ! 99: #define SR_NRDY BIT(6) /* 0 -> Ready */ ! 100: #define SR_NEXC BIT(5) /* 0 -> Exception */ ! 101: #define SR_DONE BIT(4) /* 1 -> DMA Done */ ! 102: #define SR_TO_PC BIT(3) /* 1 -> Direction is to PC */ ! 103: ! 104: /* ! 105: * Controller Commands. ! 106: */ ! 107: #define CC_SELECT 0x01 /* Select Drive 0 */ ! 108: #define CC_LOCK 0x11 /* Select Drive 0 and Lock */ ! 109: #define CC_BOT 0x21 /* Rewind to beginning of tape */ ! 110: #define CC_ERASE 0x22 /* Completely erase cartridge */ ! 111: #define CC_TENSION 0x24 /* Wind tape to BOT, EOT, BOT */ ! 112: #define CC_AUTO 0x25 /* Select auto-initialization */ ! 113: #define CC_QIC11 0x26 /* Select QIC-11 media format */ ! 114: #define CC_QIC24 0x27 /* Select QIC-24 media format */ ! 115: #define CC_WRITE 0x40 /* Write to tape */ ! 116: #define CC_WFM 0x60 /* Write file mark */ ! 117: #define CC_READ 0x80 /* Read from tape */ ! 118: #define CC_RFM 0xA0 /* Skip past next file mark */ ! 119: #define CC_SENSE 0xC0 /* Read controller status */ ! 120: ! 121: /* ! 122: * Sense Status Bytes 0 and 1. ! 123: */ ! 124: #define SS0_FIL BIT(0) /* File Mark Detected */ ! 125: #define SS0_BNL BIT(1) /* Bad Block Not located */ ! 126: #define SS0_UDA BIT(2) /* Unrecoverable data error */ ! 127: #define SS0_EOM BIT(3) /* End of media */ ! 128: #define SS0_WRP BIT(4) /* Write Protected Cartridge */ ! 129: #define SS0_USL BIT(5) /* Unselected Drive */ ! 130: #define SS0_CNI BIT(6) /* Cartridge Not In Place */ ! 131: #define SS0_ERR (SS0_BNL+SS0_UDA+SS0_USL+SS0_CNI) ! 132: ! 133: #define SS1_POR BIT(0) /* Power on Reset Occurred */ ! 134: #define SS1_BOM BIT(3) /* Beginning of media */ ! 135: #define SS1_MBD BIT(4) /* Marginal Block Detected */ ! 136: #define SS1_NDT BIT(5) /* No Data Detected */ ! 137: #define SS1_ILL BIT(6) /* Illegal Command */ ! 138: #define SS1_ERR (SS1_NDT+SS1_ILL) ! 139: ! 140: /* ! 141: * Device States. ! 142: */ ! 143: #define SDEAD 0 /* controller not found */ ! 144: #define SIDLE 1 /* controller idle */ ! 145: #define SCMD 2 /* initiating command */ ! 146: #define SRUN 3 /* performing command */ ! 147: #define SRDWR 4 /* starting read/write */ ! 148: #define SBLOCK 5 /* performing read/write */ ! 149: #define SBLEND 6 /* concluding block i/o */ ! 150: #define SSENSE 7 /* reading status bytes */ ! 151: #define SSDONE 8 /* concluding status sense */ ! 152: ! 153: /* ! 154: * Driver State Information. ! 155: */ ! 156: struct st_s { ! 157: int st_state; ! 158: int st_mode; /* IPR or IPW */ ! 159: int st_iocmd; /* CC_READ or CC_WRITE */ ! 160: int st_cmd; /* last command executed */ ! 161: int st_cmds[NCMDS]; /* list of chained commands */ ! 162: int st_ncmds; /* num of chained commands */ ! 163: int st_iswr; ! 164: int st_wasio; ! 165: int st_iseof; ! 166: int st_error; ! 167: paddr_t st_paddr; ! 168: fsize_t st_resid; ! 169: fsize_t st_size; ! 170: saddr_t st_sel; ! 171: SEG * st_seg; ! 172: char st_status[6]; ! 173: int st_nstat; ! 174: int st_rdys; /* number of ready watchdogs */ ! 175: int st_nlost; /* number of lost interrupts */ ! 176: } st; ! 177: ! 178: /** ! 179: * ! 180: * void ! 181: * stload() -- initialize tape device ! 182: * ! 183: * Action: Reset tape controller and drive. ! 184: * Seize tape interrupt vector. ! 185: * ! 186: * Note: If the tape controller is present and operational, ! 187: * a interrupt will occur and set st.st_state to SIDLE. ! 188: */ ! 189: static ! 190: stload() ! 191: { ! 192: /* ! 193: * Paranoia - Turn off DMA. ! 194: * Should already be turned off. ! 195: */ ! 196: dmaoff( STDMA ); ! 197: ! 198: /* ! 199: * Reset tape controller and drive ! 200: */ ! 201: outb( CTRL_REG, CR_RSTSAC ); ! 202: ! 203: /* ! 204: * Wait at least 25 microseconds ! 205: */ ! 206: stspin( 25 ); ! 207: ! 208: /* ! 209: * Terminate reset condition ! 210: */ ! 211: outb( CTRL_REG, CR_IEN ); ! 212: ! 213: /* ! 214: * Seize tape interrupt vector. ! 215: */ ! 216: setivec( STIRQ, &stintr ); ! 217: } ! 218: ! 219: /** ! 220: * ! 221: * stuload( dev ) -- Unload tape device. ! 222: * dev_t dev; ! 223: */ ! 224: stuload( dev ) ! 225: dev_t dev; ! 226: { ! 227: /* ! 228: * Turn off DMA. ! 229: */ ! 230: dmaoff( STDMA ); ! 231: ! 232: /* ! 233: * Release tape interrupt vector. ! 234: */ ! 235: clrivec( STIRQ ); ! 236: ! 237: /* ! 238: * Disable tape interrupts. ! 239: */ ! 240: outb( CTRL_REG, 0 ); ! 241: } ! 242: ! 243: /** ! 244: * ! 245: * stopen( dev, mode ) -- open tape device ! 246: * dev_t dev; ! 247: * int mode; ! 248: * ! 249: * Input: dev = tape device to be opened. ! 250: * mode = desired access mode. ! 251: * ! 252: * Action: Refuse access if tape drive does not exist or is in use. ! 253: * Refuse simultaneous read and write access. ! 254: * Refuse access if cartridge is not inserted in tape drive. ! 255: * Refuse write access to a write protected cartridge. ! 256: * Allocate tape cache. ! 257: * Initialize device state. ! 258: * Lock tape cartridge. ! 259: */ ! 260: static ! 261: stopen( dev, mode ) ! 262: register dev_t dev; ! 263: register int mode; ! 264: { ! 265: int s; ! 266: ! 267: /* ! 268: * Refuse access if no tape drive. ! 269: */ ! 270: if ( st.st_state == SDEAD ) { ! 271: u.u_error = ENXIO; ! 272: return; ! 273: } ! 274: ! 275: /* ! 276: * Refuse access if tape drive is already open. ! 277: */ ! 278: if ( st.st_mode != 0 ) { ! 279: u.u_error = EDBUSY; ! 280: return; ! 281: } ! 282: ! 283: /* ! 284: * Access must be read-only or write-only. ! 285: */ ! 286: if ( (mode != IPR) && (mode != IPW) ) { ! 287: u.u_error = EINVAL; ! 288: return; ! 289: } ! 290: ! 291: /* ! 292: * Wait for tape drive to become idle. ! 293: */ ! 294: if ( stwait() < 0 ) { ! 295: u.u_error = EINTR; ! 296: return; ! 297: } ! 298: ! 299: /* ! 300: * Initialize tape interface. ! 301: */ ! 302: s = sphi(); ! 303: outb( DMARST_REG, 0 ); ! 304: outb( CTRL_REG, CR_IEN ); ! 305: spl( s ); ! 306: ! 307: /* ! 308: * Obtain tape status. ! 309: */ ! 310: stinvoke( CC_SENSE ); ! 311: ! 312: /* ! 313: * Wait for tape status. ! 314: */ ! 315: if ( stwait() < 0 ) { ! 316: u.u_error = EINTR; ! 317: return; ! 318: } ! 319: ! 320: /* ! 321: * Refuse access if no cartridge. ! 322: */ ! 323: if ( st.st_status[0] & (SS0_CNI|SS0_USL) ) { ! 324: u.u_error = EDATTN; ! 325: return; ! 326: } ! 327: ! 328: /* ! 329: * Refuse write access to a write protected cartridge. ! 330: */ ! 331: if ( (mode == IPW) && (st.st_status[0] & SS0_WRP) ) { ! 332: u.u_error = EROFS; ! 333: return; ! 334: } ! 335: ! 336: /* ! 337: * Calculate desired cache size in Kbytes. ! 338: */ ! 339: st.st_size = minor(dev) & ~0x80; ! 340: if ( st.st_size == 0 ) ! 341: st.st_size = 256; ! 342: ! 343: /* ! 344: * Allocate cache ! 345: */ ! 346: for ( st.st_size *= 1024; st.st_size != 0; st.st_size -= 1024 ) ! 347: if ( st.st_seg = salloc( st.st_size, SFSYST|SFNSWP|SFNCLR ) ) ! 348: break; ! 349: ! 350: /* ! 351: * Refuse access if couldn't allocate cache. ! 352: */ ! 353: if ( st.st_seg == 0 ) { ! 354: u.u_error = ENOMEM; ! 355: return; ! 356: }; ! 357: ! 358: /* ! 359: * Initialize device state. ! 360: */ ! 361: st.st_sel = FP_SEL(st.st_seg->s_faddr); ! 362: st.st_iswr = (mode == IPW); ! 363: st.st_paddr = st.st_seg->s_paddr; ! 364: st.st_resid = (mode == IPW) ? st.st_size : 0 ; ! 365: st.st_iocmd = (mode == IPW) ? CC_WRITE : CC_READ ; ! 366: st.st_mode = mode; ! 367: st.st_iseof = 0; ! 368: st.st_wasio = 0; ! 369: st.st_error = 0; ! 370: st.st_rdys = 0; ! 371: st.st_nlost = 0; ! 372: ! 373: /* ! 374: * Lock cartridge if at beginning of media. ! 375: */ ! 376: if ( st.st_status[1] & SS1_BOM ) ! 377: stinvoke( CC_LOCK ); ! 378: } ! 379: ! 380: /** ! 381: * ! 382: * stclose( dev, mode ) -- close tape device ! 383: * dev_t dev; ! 384: * int mode; ! 385: * ! 386: * Input: dev = tape device to be closed. ! 387: * mode = access mode. ! 388: * ! 389: * Action: If access mode was for writing, flush the tape cache. ! 390: * If data was written to tape, write a file mark. ! 391: * If data was read from tape on the non rewinding device, ! 392: * read until end of file or an error is encountered. ! 393: * Rewind the tape if the rewinding device is open. ! 394: * Unlock the tape cartridge. ! 395: * Clear tape state and release tape cache memory. ! 396: */ ! 397: static ! 398: stclose( dev, mode ) ! 399: register dev_t dev; ! 400: { ! 401: /* ! 402: * Check if tape was opened for writing. ! 403: */ ! 404: if ( st.st_iswr ) { ! 405: ! 406: /* ! 407: * Flush the tape cache. ! 408: */ ! 409: stflush(); ! 410: ! 411: /* ! 412: * Write a file mark if data was written to tape. ! 413: */ ! 414: if ( st.st_wasio ) ! 415: stinvoke( CC_WFM ); ! 416: } ! 417: ! 418: /* ! 419: * Check if non-rewinding device was opened for reading. ! 420: */ ! 421: else if ( st.st_wasio && (dev & 0x80 ) ) { ! 422: ! 423: /* ! 424: * Read file mark if not just past one. ! 425: */ ! 426: if ( (st.st_status[0] & SS0_FIL) == 0 ) ! 427: stinvoke( CC_RFM ); ! 428: } ! 429: ! 430: /* ! 431: * Rewinding device. ! 432: */ ! 433: if ( (dev & 0x80) == 0 ) { ! 434: ! 435: /* ! 436: * Wait for controller to idle. ! 437: */ ! 438: while ( stwait() < 0 ) ! 439: ; ! 440: ! 441: /* ! 442: * Initiate rewind. ! 443: */ ! 444: stinvoke( CC_BOT ); ! 445: ! 446: /* ! 447: * Unlock the drive [turn off the light]. ! 448: */ ! 449: stinvoke( CC_SELECT ); ! 450: } ! 451: ! 452: /* ! 453: * Clear tape state, releasing tape cache. ! 454: */ ! 455: sfree( st.st_seg ); ! 456: st.st_seg = 0; ! 457: st.st_mode = 0; ! 458: } ! 459: ! 460: /** ! 461: * ! 462: * stread( dev, iop ) -- tape device read ! 463: * dev_t dev; ! 464: * IO * iop; ! 465: * ! 466: * Input: dev = tape device to be read from. ! 467: * iop = pointer to IO structure. ! 468: * ! 469: * Action: Transfer data from tape cache to user memory, ! 470: * filling the cache as required by initiating reads from tape. ! 471: */ ! 472: ! 473: static ! 474: stread( dev, iop ) ! 475: dev_t dev; ! 476: register IO * iop; ! 477: { ! 478: register int n; ! 479: register int ioc; ! 480: ! 481: ioc = iop->io_ioc; ! 482: ! 483: while ( iop->io_ioc > 0 ) { ! 484: ! 485: /* ! 486: * Check for empty cache. ! 487: */ ! 488: while ( st.st_resid == 0 ) { ! 489: ! 490: /* ! 491: * Special handling if end of file was encountered. ! 492: */ ! 493: if ( st.st_iseof ) { ! 494: ! 495: /* ! 496: * Clear EOF if no data was transferred yet. ! 497: */ ! 498: if ( ioc == iop->io_ioc ) ! 499: st.st_iseof = 0; ! 500: ! 501: return; ! 502: } ! 503: ! 504: /* ! 505: * Abort on I/O error. ! 506: */ ! 507: if ( u.u_error = st.st_error ) { ! 508: stdiag(); ! 509: return; ! 510: } ! 511: ! 512: /* ! 513: * Fill the cache from tape. ! 514: */ ! 515: stcache(); ! 516: } ! 517: ! 518: /* ! 519: * Determine max data transferable in one chunk. ! 520: */ ! 521: n = iop->io_ioc; ! 522: if ( n > st.st_resid ) ! 523: n = st.st_resid; ! 524: ! 525: /* ! 526: * Transfer some data from cache to user memory. ! 527: */ ! 528: if ( pucopy( st.st_paddr, iop->io_base, n ) != n ) ! 529: return; ! 530: ! 531: /* ! 532: * Update addresses and counts. ! 533: */ ! 534: iop->io_base += n; ! 535: iop->io_ioc -= n; ! 536: st.st_resid -= n; ! 537: st.st_paddr += n; ! 538: } ! 539: } ! 540: ! 541: /** ! 542: * ! 543: * stwrite( dev, iop ) -- write to tape device ! 544: * dev_t dev; ! 545: * IO * iop; ! 546: * ! 547: * Input: dev = tape device to be written to. ! 548: * iop = pointer to IO structure. ! 549: * ! 550: * Action: Transfer data from user memory to tape cache, ! 551: * flushing the cache as required by initiating writes to tape. ! 552: */ ! 553: ! 554: static ! 555: stwrite( dev, iop ) ! 556: dev_t dev; ! 557: register IO *iop; ! 558: { ! 559: register int n; ! 560: ! 561: while ( iop->io_ioc > 0 ) { ! 562: ! 563: /* ! 564: * Determine max data transferable in one chunk. ! 565: */ ! 566: n = iop->io_ioc; ! 567: if ( n > st.st_resid ) ! 568: n = st.st_resid; ! 569: ! 570: /* ! 571: * Transfer some data from user memory to cache. ! 572: */ ! 573: if ( upcopy( iop->io_base, st.st_paddr, n ) != n ) ! 574: break; ! 575: ! 576: /* ! 577: * Update addresses and counts. ! 578: */ ! 579: iop->io_base += n; ! 580: iop->io_ioc -= n; ! 581: st.st_paddr += n; ! 582: st.st_resid -= n; ! 583: ! 584: /* ! 585: * Flush the cache to tape if full. ! 586: */ ! 587: if ( st.st_resid == 0 ) ! 588: stflush(); ! 589: ! 590: /* ! 591: * Abort on I/O error. ! 592: */ ! 593: if ( u.u_error = st.st_error ) { ! 594: stdiag(); ! 595: return; ! 596: } ! 597: } ! 598: } ! 599: ! 600: /** ! 601: * ! 602: * stioctl( dev, cmd, arg ) -- service tape I/O control requests ! 603: * int dev; ! 604: * int cmd; ! 605: * int arg; ! 606: * ! 607: * Input: dev = tape device to be serviced ! 608: * cmd = ioctl command ! 609: * arg = argument to ioctl command ! 610: * ! 611: * Action: Service tape I/O control request. ! 612: */ ! 613: ! 614: static ! 615: stioctl( dev, cmd, arg ) ! 616: { ! 617: if ( st.st_iswr ) ! 618: stflush(); ! 619: ! 620: st.st_error = EINVAL; ! 621: ! 622: switch ( cmd ) { ! 623: ! 624: case MTERASE: ! 625: stinvoke( CC_ERASE ); ! 626: break; ! 627: ! 628: case MTTENSE: ! 629: stinvoke( CC_TENSION ); ! 630: break; ! 631: ! 632: case MTREWIND: ! 633: if ( st.st_iswr && st.st_wasio ) { ! 634: stinvoke( CC_WFM ); ! 635: st.st_wasio = 0; ! 636: } ! 637: stinvoke( CC_BOT ); ! 638: break; ! 639: ! 640: case MTWEOF: ! 641: if ( st.st_iswr ) { ! 642: stinvoke( CC_WFM ); ! 643: st.st_wasio = 0; ! 644: } ! 645: break; ! 646: ! 647: case MTFSKIP: ! 648: if ( ! st.st_iswr ) { ! 649: if ( ! st.st_iseof ) ! 650: stinvoke( CC_RFM ); ! 651: st.st_iseof = 0; ! 652: st.st_resid = 0; ! 653: } ! 654: break; ! 655: } ! 656: ! 657: /* ! 658: * Record tape error code. ! 659: */ ! 660: u.u_error = st.st_error; ! 661: } ! 662: ! 663: /** ! 664: * ! 665: * void ! 666: * stcache() -- read from tape into cache ! 667: * ! 668: * Action: Read as much data as possible into the tape cache. ! 669: * Set st.st_paddr to the cache address. ! 670: * Set st.st_resid to the number of data bytes in the cache. ! 671: */ ! 672: static void ! 673: stcache() ! 674: { ! 675: /* ! 676: * Try to fill cache from tape. ! 677: */ ! 678: st.st_paddr = st.st_seg->s_paddr; ! 679: st.st_resid = st.st_size; ! 680: ststart(); ! 681: ! 682: /* ! 683: * Update cache information. ! 684: */ ! 685: st.st_paddr = st.st_seg->s_paddr; ! 686: st.st_resid = st.st_size - st.st_resid; ! 687: ! 688: /* ! 689: * Clear the cache on I/O error. ! 690: */ ! 691: if ( st.st_error ) ! 692: st.st_resid = 0; ! 693: } ! 694: ! 695: /** ! 696: * ! 697: * void ! 698: * stflush() -- flush cache to tape ! 699: * ! 700: * Action: Ensure tape cache is block aligned. ! 701: * Write cache to the tape. ! 702: * Set st.st_paddr to the cache address. ! 703: * Set st.st_resid to the number of cache bytes available. ! 704: */ ! 705: static void ! 706: stflush() ! 707: { ! 708: static char zc; ! 709: ! 710: /* ! 711: * Check for empty cache. ! 712: */ ! 713: if ( st.st_resid == st.st_size ) ! 714: return; ! 715: ! 716: /* ! 717: * Block align the cache. ! 718: */ ! 719: while ( st.st_resid % BSIZE ) { ! 720: kpcopy( &zc, st.st_paddr, 1 ); ! 721: st.st_paddr++; ! 722: st.st_resid--; ! 723: } ! 724: ! 725: /* ! 726: * Flush the cache to tape. ! 727: */ ! 728: st.st_paddr = st.st_seg->s_paddr; ! 729: st.st_resid = st.st_size - st.st_resid; ! 730: ststart(); ! 731: ! 732: /* ! 733: * Update cache information. ! 734: */ ! 735: st.st_paddr = st.st_seg->s_paddr; ! 736: st.st_resid = st.st_size; ! 737: } ! 738: ! 739: /** ! 740: * ! 741: * void ! 742: * stinvoke() -- start tape control operation ! 743: * ! 744: * Action: Initiate tape control operation. ! 745: */ ! 746: static void ! 747: stinvoke( cmd ) ! 748: int cmd; ! 749: { ! 750: register int s; ! 751: ! 752: /* ! 753: * Disable interrupts. ! 754: */ ! 755: s = sphi(); ! 756: ! 757: /* ! 758: * Wait for controller to become idle. ! 759: */ ! 760: while ( st.st_state != SIDLE ) { ! 761: ! 762: /* ! 763: * Create chained command if possible. ! 764: */ ! 765: if ( st.st_ncmds < NCMDS ) { ! 766: st.st_cmds[ st.st_ncmds++ ] = cmd; ! 767: spl( s ); ! 768: return; ! 769: } ! 770: ! 771: sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT ); ! 772: } ! 773: ! 774: /* ! 775: * Setup for tape operation. ! 776: */ ! 777: drvl[ST_MAJOR].d_time = 1; ! 778: st.st_state = SCMD; ! 779: st.st_error = 0; ! 780: st.st_rdys = 0; ! 781: stspin( 100 ); ! 782: ! 783: /* ! 784: * Request tape operation. ! 785: * Do NOT wait for results. ! 786: */ ! 787: outb( DATA_REG, st.st_cmd = cmd ); ! 788: outb( CTRL_REG, CR_IEN+CR_REQ ); ! 789: ! 790: /* ! 791: * Enable interrupts. ! 792: */ ! 793: spl( s ); ! 794: } ! 795: ! 796: /** ! 797: * ! 798: * void ! 799: * ststart() -- start tape read/write operation ! 800: * ! 801: * Action: Initiate tape read/write operation. ! 802: * Wait for tape operation to complete. ! 803: */ ! 804: static void ! 805: ststart() ! 806: { ! 807: register int s; ! 808: ! 809: /* ! 810: * Disable interrupts. ! 811: */ ! 812: s = sphi(); ! 813: ! 814: /* ! 815: * Wait for controller to become idle. ! 816: */ ! 817: while ( st.st_state != SIDLE ) ! 818: sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT ); ! 819: ! 820: /* ! 821: * Setup for tape read/write. ! 822: */ ! 823: drvl[ST_MAJOR].d_time = 1; ! 824: st.st_state = SRDWR; ! 825: st.st_error = 0; ! 826: st.st_rdys = 0; ! 827: stspin( 100 ); ! 828: ! 829: /* ! 830: * Tape read/write was last command executed. ! 831: */ ! 832: if ( st.st_cmd == st.st_iocmd ) { ! 833: /* ! 834: * Resume tape i/o operation. ! 835: * Simulate RDY interrupt. ! 836: */ ! 837: stintr(); ! 838: } ! 839: else { ! 840: /* ! 841: * Request tape operation. ! 842: */ ! 843: outb( DATA_REG, st.st_cmd = st.st_iocmd ); ! 844: outb( CTRL_REG, CR_IEN+CR_REQ ); ! 845: } ! 846: ! 847: /* ! 848: * Wait for tape operation to complete. ! 849: */ ! 850: while ( st.st_state != SIDLE ) ! 851: sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT ); ! 852: ! 853: /* ! 854: * Enable interrupts. ! 855: */ ! 856: spl( s ); ! 857: } ! 858: ! 859: /** ! 860: * ! 861: * void ! 862: * stintr() -- tape interrupt handler ! 863: * ! 864: * Action: Service tape interrupts. ! 865: * Perform transitions to new tape states. ! 866: * Wake sleeping processes if appropriate. ! 867: */ ! 868: static void ! 869: stintr() ! 870: { ! 871: register int csr; ! 872: register int s; ! 873: ! 874: s = sphi(); ! 875: csr = inb( CTRL_REG ); ! 876: ! 877: /* ! 878: * Initiate exception recovery. ! 879: */ ! 880: if ( (csr & SR_NEXC) == 0 ) { ! 881: strecov(); ! 882: spl( s ); ! 883: return; ! 884: } ! 885: ! 886: /* ! 887: * Clear ready watchdog count. ! 888: */ ! 889: st.st_rdys = 0; ! 890: ! 891: /* ! 892: * Process normal operations. ! 893: */ ! 894: switch ( st.st_state ) { ! 895: ! 896: case SCMD: ! 897: /* ! 898: * Command has been acknowledged. ! 899: * Wait for command completion. ! 900: */ ! 901: outb( CTRL_REG, CR_IEN ); ! 902: st.st_state = (st.st_cmd == CC_SENSE) ? SSENSE : SRUN; ! 903: st.st_nstat = 0; ! 904: break; ! 905: ! 906: case SRUN: ! 907: /* ! 908: * Command has completed. ! 909: * Chain a sense status command if no other chained commands. ! 910: */ ! 911: if ( st.st_ncmds == 0 ) ! 912: st.st_cmds[ st.st_ncmds++ ] = CC_SENSE; ! 913: ! 914: /* ! 915: * Initiate next chained command. ! 916: */ ! 917: stnext(); ! 918: break; ! 919: ! 920: case SRDWR: ! 921: /* ! 922: * Read/Write command had been acknowledged. ! 923: * Clear tape request, enable done interrupt. ! 924: */ ! 925: outb( CTRL_REG, CR_IEN+CR_DNIEN ); ! 926: ! 927: /* ! 928: * Define direct memory access parameters. ! 929: */ ! 930: dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr ); ! 931: ! 932: /* ! 933: * If tape read command, wait for interface to switch direction ! 934: */ ! 935: if ( st.st_iocmd == CC_READ ) ! 936: while ( (inb(CTRL_REG) & SR_TO_PC) != SR_TO_PC ) ! 937: ; ! 938: ! 939: /* ! 940: * Enable DMA transfer on tape interface and at DMA controller chip. ! 941: */ ! 942: st.st_state = SBLOCK; ! 943: outb( DMAGO_REG, 0 ); ! 944: dmago( STDMA ); ! 945: break; ! 946: ! 947: case SBLOCK: ! 948: /* ! 949: * Perform Block I/O. ! 950: * Ignore RDY interrupt, wait for [DMA] DONE interrupt. ! 951: */ ! 952: if ( (csr & SR_DONE) == 0 ) ! 953: break; ! 954: ! 955: /* ! 956: * Turn off DMA. ! 957: */ ! 958: dmaoff( STDMA ); ! 959: ! 960: /* ! 961: * If more data remains to be transferred, reenable DMA. ! 962: * NOTE: do -= BEFORE if() to avoid potential compiler bug. ! 963: */ ! 964: st.st_resid -= BSIZE; ! 965: if ( st.st_resid > 0 ) { ! 966: st.st_paddr += BSIZE; ! 967: dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr ); ! 968: outb( DMAGO_REG, 0 ); ! 969: dmago( STDMA ); ! 970: break; ! 971: } ! 972: ! 973: /* ! 974: * Disable done interrupt. ! 975: * Wait for I/O completion. ! 976: */ ! 977: outb( CTRL_REG, CR_IEN ); ! 978: st.st_state = SBLEND; ! 979: break; ! 980: ! 981: case SBLEND: ! 982: /* ! 983: * Completion of Block I/O. ! 984: * Clear the file mark and beginning of media indicators. ! 985: * Record the fact that data has been transferred. ! 986: */ ! 987: st.st_status[0] &= ~SS0_FIL; ! 988: st.st_status[1] &= ~SS1_BOM; ! 989: st.st_wasio = 1; ! 990: stnext(); ! 991: break; ! 992: ! 993: case SSENSE: ! 994: /* ! 995: * Sense Status Byte. ! 996: * Wait for availability. ! 997: */ ! 998: do { ! 999: csr = inb(CTRL_REG) & (SR_NRDY|SR_TO_PC); ! 1000: } while ( csr != SR_TO_PC ); ! 1001: ! 1002: /* ! 1003: * Save status byte. ! 1004: */ ! 1005: st.st_status[st.st_nstat] = inb(DATA_REG); ! 1006: ! 1007: /* ! 1008: * Acknowledge reception. ! 1009: * CR_REQ must be present for at least 20 microseconds. ! 1010: */ ! 1011: outb( CTRL_REG, CR_IEN+CR_REQ ); ! 1012: stspin( 20 ); ! 1013: outb( CTRL_REG, CR_IEN ); ! 1014: ! 1015: /* ! 1016: * Change state to status completion if all bytes saved. ! 1017: */ ! 1018: if ( ++(st.st_nstat) == 6 ) ! 1019: st.st_state = SSDONE; ! 1020: break; ! 1021: ! 1022: case SSDONE: ! 1023: /* ! 1024: * Completion of Sense Status Command. ! 1025: * Check for file mark. ! 1026: */ ! 1027: if ( st.st_status[0] & SS0_FIL ) { ! 1028: outb( DMARST_REG, 0 ); ! 1029: st.st_iseof = 1; ! 1030: } ! 1031: ! 1032: /* ! 1033: * Check for I/O error. ! 1034: */ ! 1035: else if ( (st.st_status[0] & SS0_ERR) || ! 1036: (st.st_status[1] & SS1_ERR) ) { ! 1037: st.st_error = EIO; ! 1038: } ! 1039: ! 1040: /* ! 1041: * Check for write protected cartridge. ! 1042: */ ! 1043: else if ( (st.st_iocmd == CC_WRITE) && ! 1044: (st.st_status[0] & SS0_WRP) ) { ! 1045: st.st_error = EROFS; ! 1046: } ! 1047: ! 1048: stnext(); ! 1049: break; ! 1050: } ! 1051: ! 1052: spl( s ); ! 1053: } ! 1054: ! 1055: /** ! 1056: * ! 1057: * void ! 1058: * strecov() -- initiate recovery from exception conditions ! 1059: * ! 1060: * Action: Invoked when the tape controller asserts EXCEPTION. ! 1061: * A sense status command is initiated to clear the exception. ! 1062: */ ! 1063: static void ! 1064: strecov() ! 1065: { ! 1066: /* ! 1067: * Ensure tape interface is idle. ! 1068: */ ! 1069: outb( CTRL_REG, CR_IEN ); ! 1070: stspin( 100 ); ! 1071: ! 1072: /* ! 1073: * Turn off DMA on read/write exception. ! 1074: */ ! 1075: if ( st.st_cmd == st.st_iocmd ) ! 1076: dmaoff( STDMA ); ! 1077: ! 1078: /* ! 1079: * Initiate sense status command. ! 1080: */ ! 1081: outb( DATA_REG, st.st_cmd = CC_SENSE ); ! 1082: outb( CTRL_REG, CR_IEN+CR_REQ ); ! 1083: drvl[ST_MAJOR].d_time = 1; ! 1084: st.st_state = SCMD; ! 1085: st.st_error = 0; ! 1086: st.st_rdys = 0; ! 1087: } ! 1088: ! 1089: /** ! 1090: * ! 1091: * static void ! 1092: * stnext() -- initiate next chained command. ! 1093: */ ! 1094: static void ! 1095: stnext() ! 1096: { ! 1097: /* ! 1098: * Ensure tape interface is idle. ! 1099: */ ! 1100: outb( CTRL_REG, CR_IEN ); ! 1101: drvl[ST_MAJOR].d_time = 0; ! 1102: st.st_state = SIDLE; ! 1103: stspin( 100 ); ! 1104: ! 1105: /* ! 1106: * Initiate a chained command. ! 1107: */ ! 1108: if ( st.st_ncmds ) { ! 1109: outb( DATA_REG, st.st_cmd = st.st_cmds[ --st.st_ncmds ] ); ! 1110: outb( CTRL_REG, CR_IEN+CR_REQ ); ! 1111: drvl[ST_MAJOR].d_time = 1; ! 1112: st.st_state = SCMD; ! 1113: st.st_error = 0; ! 1114: st.st_rdys = 0; ! 1115: return; ! 1116: } ! 1117: ! 1118: /* ! 1119: * Wake waiting processes. ! 1120: */ ! 1121: wakeup( &st ); ! 1122: } ! 1123: ! 1124: /** ! 1125: * ! 1126: * void ! 1127: * stwatch() -- periodic [1 sec] watchdog ! 1128: * ! 1129: * Action: If an exception condition exists, initate recovery actions. ! 1130: * If ready condition exists for 1-2 seconds, simulate interrupt. ! 1131: * ! 1132: * Notes: If an exception condition occurs after a ready interrupt has ! 1133: * been serviced, but before the ready condition is cleared, ! 1134: * the exception interrupt will not occur, and is simulated here. ! 1135: */ ! 1136: static void ! 1137: stwatch() ! 1138: { ! 1139: register int csr; ! 1140: register int s; ! 1141: ! 1142: /* ! 1143: * Disable interrupts, preventing critical race with stintr(). ! 1144: */ ! 1145: s = sphi(); ! 1146: csr = inb(CTRL_REG); ! 1147: ! 1148: /* ! 1149: * Initiate recovery from exception conditions. ! 1150: */ ! 1151: if ( (csr & SR_NEXC) == 0 ) ! 1152: strecov(); ! 1153: ! 1154: /* ! 1155: * Reset ready watchdog if not ready. ! 1156: */ ! 1157: else if ( csr & SR_NRDY ) ! 1158: st.st_rdys = 0; ! 1159: ! 1160: /* ! 1161: * Simulate lost ready interrupts after 2 seconds. ! 1162: */ ! 1163: else if ( ++st.st_rdys >= 2 ) ! 1164: stintr(); ! 1165: ! 1166: /* ! 1167: * Enable interrupts. ! 1168: */ ! 1169: spl( s ); ! 1170: } ! 1171: ! 1172: /** ! 1173: * ! 1174: * void ! 1175: * stdiag() - Report tape status. ! 1176: * ! 1177: * Action: Identify and report the highest priority tape error. ! 1178: * There will normally only be one valid error present. ! 1179: * The USL error can invalidate most remaining flags. ! 1180: * The CNI error can invalidate cartridge related flags. ! 1181: * ! 1182: * Notes: Never called from interrupt level, but always from background. ! 1183: */ ! 1184: static void ! 1185: stdiag() ! 1186: { ! 1187: if ( st.st_status[0] & SS0_USL ) ! 1188: printf( "st: Unselected Drive\n" ); ! 1189: ! 1190: else if ( st.st_status[0] & SS0_CNI ) ! 1191: printf( "st: Cartridge missing\n" ); ! 1192: ! 1193: else if ( st.st_status[1] & SS1_NDT ) ! 1194: printf( "st: No data detected\n" ); ! 1195: ! 1196: else if ( st.st_status[0] & SS0_BNL ) ! 1197: printf( "st: Bad block not located\n" ); ! 1198: ! 1199: else if ( st.st_status[0] & SS0_UDA ) ! 1200: printf( "st: Unrecoverable data error\n" ); ! 1201: ! 1202: else if ( st.st_status[1] & SS1_ILL ) ! 1203: printf( "st: Illegal command\n" ); ! 1204: ! 1205: else ! 1206: printf( "st: %x\n", (st.st_status[1] << 8) + st.st_status[0] ); ! 1207: } ! 1208: ! 1209: /** ! 1210: * ! 1211: * int ! 1212: * stwait() -- wait for tape controller to idle. ! 1213: * ! 1214: * Return: 0 = tape controller idle. ! 1215: * -1 = signal received. ! 1216: */ ! 1217: static int ! 1218: stwait() ! 1219: { ! 1220: int s; ! 1221: ! 1222: s = sphi(); ! 1223: while ( st.st_state != SIDLE ) { ! 1224: ! 1225: sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT ); ! 1226: ! 1227: if ( SELF->p_ssig ) { ! 1228: spl( s ); ! 1229: return -1; ! 1230: } ! 1231: } ! 1232: spl( s ); ! 1233: ! 1234: return 0; ! 1235: } ! 1236: ! 1237: /** ! 1238: * ! 1239: * void ! 1240: * stspin( usec ) -- delay execution ! 1241: * int usec; ! 1242: * ! 1243: * Input: usec = number of micro-seconds to delay. ! 1244: * ! 1245: * Action: Wait at least 'usec' micro-seconds. ! 1246: * ! 1247: * Notes: Provides minimum delay required at times by tape controller. ! 1248: * Should function properly up to at least 16 Mhz system clock. ! 1249: */ ! 1250: ! 1251: static void ! 1252: stspin( usec ) ! 1253: register int usec; ! 1254: { ! 1255: while ( --usec >= 0 ) ! 1256: ; ! 1257: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.