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