|
|
1.1 ! root 1: /* ******************************************************************** */ ! 2: /* */ ! 3: /* METHEUS Corporation */ ! 4: /* */ ! 5: /* UNIX - DMA Interface Driver Source Code */ ! 6: /* */ ! 7: /* This program and the subroutines implemented thereby are */ ! 8: /* proprietary information of Metheus Corporation and may not */ ! 9: /* be reproduced, or disclosed or released to, or used by any */ ! 10: /* other person without the express written consent of Metheus */ ! 11: /* Corporation. */ ! 12: /* */ ! 13: /* (c) 1983 Metheus Corporation */ ! 14: /* All rights reserved */ ! 15: /* */ ! 16: /* UNIX DR-11W DMA Interface Software by Ed Mills */ ! 17: /* */ ! 18: /* Version: UNIX DMA Interface Driver low-level (OM) routines */ ! 19: /* Release: 1.0 */ ! 20: /* Date: May 15, 1983 */ ! 21: /* */ ! 22: /* */ ! 23: /* */ ! 24: /* FUNCTIONAL DESCRIPTION: */ ! 25: /* */ ! 26: /* OPEN: */ ! 27: /* omopen initializes the device and allows */ ! 28: /* IO to commence. Only one user may have the */ ! 29: /* device open at any given time. */ ! 30: /* omopen sets the read mode to no stall and */ ! 31: /* and the timeout period to 1 second. (see below) */ ! 32: /* omopen sets the write mode to no stall and */ ! 33: /* and the timeout period to 1 minute. (see below) */ ! 34: /* */ ! 35: /* CLOSE: */ ! 36: /* omclose disallows further IO and makes the */ ! 37: /* device available for another user to open. */ ! 38: /* */ ! 39: /* READ: */ ! 40: /* omread has two modes, stall and no stall. */ ! 41: /* In stall mode omread behaves as a standard */ ! 42: /* read. It stalls until the requested amount */ ! 43: /* of data has been read and then returns. */ ! 44: /* In no stall mode omread waits for the timeout */ ! 45: /* period (set via ioctl) to expire. If the */ ! 46: /* requested data is available before the end of */ ! 47: /* the timeout period, it is returned. If not, */ ! 48: /* then as much data as was available is returned. */ ! 49: /* In either case, the user level read returns the */ ! 50: /* actual number read. */ ! 51: /* Since the OMEGA 440 can only transmit words, */ ! 52: /* the count requested from omread must be even */ ! 53: /* or an IO error will be generated. */ ! 54: /* */ ! 55: /* WRITE: */ ! 56: /* omwrite transmits the requested number of bytes */ ! 57: /* to the device. Like READ, WRITE has two modes, */ ! 58: /* stall and no stall which behave similarly to */ ! 59: /* omread's. */ ! 60: /* Since the OMEGA 440 can only transmit words, */ ! 61: /* the count sent to omwrite must be even or an */ ! 62: /* IO error will be generated. */ ! 63: /* */ ! 64: /* IOCTL: */ ! 65: /* omioctl has 14 commands, OM_SETRSTALL, */ ! 66: /* OM_SETNORSTALL, OM_GETRSTALL,, OM_SETRTIMEOUT, */ ! 67: /* OM_GETRTIMEOUT, OM_SETWSTALL, OM_SETNOWSTALL, */ ! 68: /* OM_GETWSTALL, OM_SETWTIMEOUT, OM_GETWTIMEOUT, */ ! 69: /* OM_WRITEREADY, OM_READREADY, OM_BUSY, */ ! 70: /* and OM_RESET. */ ! 71: /* */ ! 72: /* OM_SETRSTALL: */ ! 73: /* Set omread to stall mode. */ ! 74: /* */ ! 75: /* OM_SETNORSTALL: */ ! 76: /* Set omread to no stall mode. */ ! 77: /* */ ! 78: /* OM_GETRSTALL: */ ! 79: /* Returns true if in read stall mode. */ ! 80: /* */ ! 81: /* OM_SETRTIMEOUT: */ ! 82: /* Sets the read stall mode timeout period in */ ! 83: /* tenths of a second. */ ! 84: /* */ ! 85: /* OM_GETRTIMEOUT: */ ! 86: /* Returns the read stall mode timeout period in */ ! 87: /* tenths of a second. */ ! 88: /* */ ! 89: /* OM_SETWSTALL: */ ! 90: /* Set omwrite to stall mode. */ ! 91: /* */ ! 92: /* OM_SETNOWSTALL: */ ! 93: /* Set omwrite to no stall mode. */ ! 94: /* */ ! 95: /* OM_GETWSTALL: */ ! 96: /* Returns true if in write stall mode. */ ! 97: /* */ ! 98: /* OM_SETWTIMEOUT: */ ! 99: /* Sets the write stall mode timeout period in */ ! 100: /* tenths of a second. */ ! 101: /* */ ! 102: /* OM_GETWTIMEOUT: */ ! 103: /* Returns the write stall mode timeout period in */ ! 104: /* tenths of a second. */ ! 105: /* */ ! 106: /* OM_WRITEREADY: */ ! 107: /* Returns a value of 1 if the device can accept */ ! 108: /* data, 0 otherwise. Internally this is the */ ! 109: /* DR11-W STAT A bit. */ ! 110: /* */ ! 111: /* OM_READREADY: */ ! 112: /* Returns a value of 1 if the device has data */ ! 113: /* to be read, 0 otherwise. Internally this is */ ! 114: /* the DR11-W STAT B bit. */ ! 115: /* */ ! 116: /* OM_BUSY: */ ! 117: /* Returns a value of 1 if the device is busy, */ ! 118: /* 0 otherwise. Internally this is the DR11-W */ ! 119: /* STAT C bit. */ ! 120: /* */ ! 121: /* OM_RESET: */ ! 122: /* Resets the OMEGA to its power on condition */ ! 123: /* by asserting the CSR MAINTENANCE bit. */ ! 124: /* */ ! 125: /* */ ! 126: /* CAVEATS: */ ! 127: /* */ ! 128: /* This driver is designed to allow multiple devices, */ ! 129: /* although it has only been tested with one. */ ! 130: /* This driver should also function with the DR11-B, */ ! 131: /* although this hasn't been tested either. */ ! 132: /* */ ! 133: /* USER NOTES: */ ! 134: /* */ ! 135: /* All IO is done with an even number of bytes. Hence, */ ! 136: /* when writing, a zero byte should be appended on the */ ! 137: /* end of odd length byte arrays. This must only be done */ ! 138: /* between commands, never within one. When reading, the */ ! 139: /* user must gaurentee that there is an even number number */ ! 140: /* of bytes to be read. i.e. send the read pixel command */ ! 141: /* twice. */ ! 142: /* */ ! 143: /* Data pending to be read can prevent write operations. */ ! 144: /* Hopefully, one always knows when there is data to be */ ! 145: /* read. If not, one can read 2 bytes at a time until the */ ! 146: /* READREADY ioctl clears. CLEARINPUT_OM() in om-dmacros.h */ ! 147: /* does this. */ ! 148: /* */ ! 149: /* If the OMEGA ever does hang, typing ^C's on the */ ! 150: /* terminal and THEN cycling the OMEGA's power seems */ ! 151: /* to fix things. */ ! 152: /* */ ! 153: /* */ ! 154: /* INSTALLATION: */ ! 155: /* */ ! 156: /* The standard DR11-W parameters are, */ ! 157: /* */ ! 158: /* Base address 0772410 */ ! 159: /* CSR address 0772414 */ ! 160: /* Interrupt vector 0124 */ ! 161: /* Interrupt priority 5 */ ! 162: /* */ ! 163: /* The following line should be in the system configuration file. */ ! 164: /* ! 165: device om0 at uba? csr 0172414 vector omintr ! 166: /* */ ! 167: /* The configure routine should reflect the new device. */ ! 168: /* (/usr/beaver/usr/sys/dev/conf.c on vlsi-vax.) */ ! 169: /* */ ! 170: /* For vlsi-vax the following was added, ! 171: ! 172: #include "om.h" ! 173: #if NOM > 0 ! 174: int omopen(),omclose(),omread(),omwrite(),omioctl(); ! 175: #else ! 176: #define omopen nodev ! 177: #define omclose nodev ! 178: #define omread nodev ! 179: #define omwrite nodev ! 180: #define omioctl nodev ! 181: #endif ! 182: ! 183: struct cdevsw cdevsw[] = ! 184: { ! 185: omopen, omclose, omread, omwrite, ! 186: omioctl, nulldev, nodev, 0, ! 187: 0, ! 188: }; ! 189: */ ! 190: /* ******************************************************************** */ ! 191: /* */ ! 192: /* Finally, om.h should be put in the configuration directory */ ! 193: /* to define NOM. */ ! 194: /* */ ! 195: /* ******************************************************************** */ ! 196: ! 197: #include "om.h" ! 198: #if NOM > 0 ! 199: ! 200: #include "../h/param.h" ! 201: #include "../h/dir.h" ! 202: #include "../h/user.h" ! 203: #include "../h/buf.h" ! 204: #include "../h/systm.h" ! 205: #include "../h/ubavar.h" ! 206: #include <sys/om-consts.h> ! 207: ! 208: #define OMPRI (PZERO) ! 209: ! 210: struct omdevice { ! 211: unsigned short WC; /* 2410 Word count. */ ! 212: unsigned short BAR; /* 2412 Bus address register. */ ! 213: unsigned short CSR_EIR; /* 2414 Control and status register - ! 214: Error and information register. */ ! 215: /* We never use the EIR. We should always ! 216: write CSR bit 15 as a zero. */ ! 217: unsigned short IDR_ODR; /* 2416 Input data register - ! 218: Output data register. */ ! 219: }; ! 220: ! 221: /* DR11-W CSR register bits. */ ! 222: #define OM_ERROR 0100000 ! 223: #define OM_NEXMEM 0040000 ! 224: #define OM_ATTN 0020000 ! 225: #define OM_MAINT 0010000 ! 226: #define OM_STATA 0004000 ! 227: #define OM_STATB 0002000 ! 228: #define OM_STATC 0001000 ! 229: #define OM_CYCLE 0000400 ! 230: #define OM_READY 0000200 ! 231: #define OM_IENABLE 0000100 ! 232: #define OM_XBA 0000060 ! 233: #define OM_FUNCTION3 0000010 ! 234: #define OM_FUNCTION2 0000004 ! 235: #define OM_FUNCTION1 0000002 ! 236: #define OM_GO 0000001 ! 237: ! 238: /* Amounts to shift by to get the status bits from the CSR. */ ! 239: #define OM_STATA_SHIFT 11 ! 240: #define OM_STATB_SHIFT 10 ! 241: #define OM_STATC_SHIFT 9 ! 242: ! 243: /* DR11-W EIR register bits. OM_ERROR, OM_NEXMEM, and OM_ATTN also apply. */ ! 244: #define OM_MCREQ 0010000 ! 245: #define OM_ACLO 0004000 ! 246: #define OM_PARERR 0002000 ! 247: #define OM_BURSTDL 0001000 ! 248: #define OM_NCBURST 0000400 ! 249: #define OM_EIRREG 0000001 ! 250: ! 251: /* The following are specific to the OMEGA 440 as interfaced to the DR11-W. */ ! 252: #define OM_READ OM_FUNCTION1 /* Read from OMEGA. */ ! 253: #define OM_WRITE 0 /* Write to OMEGA. */ ! 254: #define OM_WAKEUP OM_FUNCTION3 /* Have OMEGA assert ATTN line which ! 255: will cause an error, stop any pending ! 256: DMA, and cause an interrupt if ! 257: enabled. */ ! 258: #define OM_WRITE_SHIFT OM_STATA_SHIFT /* Ready to write bit. */ ! 259: #define OM_READ_SHIFT OM_STATB_SHIFT /* Ready to read bit. */ ! 260: #define OM_BUSY_SHIFT OM_STATC_SHIFT /* Busy bit. */ ! 261: ! 262: struct om_softc { ! 263: short sc_state; /* Current state of the device. */ ! 264: short sc_operation; /* Current operation (read or write). */ ! 265: unsigned int ! 266: sc_rtimoticks, /* Number of ticks before timing out ! 267: on a no stall read. */ ! 268: sc_wtimoticks, /* Number of ticks before timing out ! 269: on a no stall write. */ ! 270: sc_currenttimo; /* The number of the current timeout call ! 271: to omrwtimo. */ ! 272: int sc_ubinfo; /* UNIBUS information. */ ! 273: int sc_ubadd; /* physical unibus address for cursor */ ! 274: unsigned char sc_curbuf[512]; /* buffer for cursor dma commands */ ! 275: } om_softc[NOM]; ! 276: ! 277: ! 278: /* sc_state bits */ ! 279: #define OMSC_OPEN (1 << 0) /* The device is open. */ ! 280: #define OMSC_BUSY (1 << 1) /* The device is busy. */ ! 281: #define OMSC_NORSTALL (1 << 2) /* The device is set to use ! 282: no stall mode for reads. */ ! 283: #define OMSC_NOWSTALL (1 << 3) /* The device is set to use ! 284: no stall mode for writes. */ ! 285: #define OMSC_TIMEDOUT (1 << 4) /* The device timed out on a ! 286: stall mode read or write. */ ! 287: ! 288: struct uba_device *omdinfo[NOM]; ! 289: ! 290: #define OMUNIT(dev) (minor(dev)) ! 291: ! 292: struct buf rombuf[NOM]; ! 293: ! 294: int omprobe(), omattach(), omstrategy(), omrwtimo(); ! 295: unsigned minomph(); ! 296: ! 297: u_short omstd[] = { 0772410, 0772430, 0 }; ! 298: struct uba_driver omdriver = { ! 299: omprobe, /* Address of probe routine to cause an interrupt. */ ! 300: 0, /* ? */ ! 301: omattach, /* Address of attach routine to set IO address. */ ! 302: 0, /* ? */ ! 303: omstd, /* Address of the device (omdevice) on the UNIBUS. */ ! 304: "om", /* Name of the device. */ ! 305: omdinfo, /* UBA device information for the device. */ ! 306: 0, 0 ! 307: }; ! 308: ! 309: ! 310: /* OMPROBE */ ! 311: /* Omprobe generates an interrupt when called by asserting the OMEGA attention ! 312: line with interrupts enabled. */ ! 313: ! 314: omprobe(reg) ! 315: caddr_t reg; ! 316: { ! 317: register int br, cvec; /* value-result */ ! 318: register struct omdevice *omaddr = (struct omdevice *)(reg-04); ! 319: ! 320: #ifdef lint ! 321: br = 0; cvec = br; br = cvec; ! 322: #endif ! 323: /* Stop any DMA and force an interrupt. */ ! 324: omaddr->CSR_EIR = (OM_ATTN | OM_WAKEUP | OM_IENABLE); ! 325: DELAY(100); ! 326: omaddr->CSR_EIR = OM_IENABLE; ! 327: /* kludge */ ! 328: br = 0x15; ! 329: switch ((int)omaddr & 070) ! 330: { ! 331: case 010: ! 332: cvec = 0124; ! 333: break; ! 334: case 030: ! 335: cvec = 0134; ! 336: break; ! 337: } ! 338: return (sizeof (struct omdevice)); ! 339: } ! 340: ! 341: ! 342: /* OMATTACH */ ! 343: /* Attach to and initialize the device. */ ! 344: ! 345: omattach(ui) struct uba_device *ui; ! 346: { ! 347: register struct omdevice *omaddr; ! 348: register struct om_softc *omsp; ! 349: ! 350: /* Move the address back from the CSR to the begining of the device. */ ! 351: ui->ui_addr -= 04; ! 352: ui->ui_physaddr -= 04; ! 353: omaddr = (struct omdevice *)ui->ui_addr; ! 354: ! 355: /* Initialize the DR11-W by setting then clearing MAINT in the CSR ! 356: with CYCLE and GO clear. */ ! 357: omaddr->CSR_EIR = 0; ! 358: omaddr->CSR_EIR = OM_MAINT; ! 359: DELAY(100); ! 360: omaddr->CSR_EIR = 0; ! 361: ! 362: omaddr->CSR_EIR = OM_IENABLE; /* Enable interrupts. */ ! 363: ! 364: /* Set the current timeout to zero. */ ! 365: /* What I want here is for OMUNIT(ui->ui_unit) to give the minor ! 366: device number of each device as we attach to it. I think that's ! 367: what it does. When there is only one device, I know that's what ! 368: it does. I check range just to make sure things never get out ! 369: of hand. Since all we need from sc_currenttimo is that it be ! 370: distinct each time we increment it, we don't really care where ! 371: it starts. */ ! 372: omsp = &om_softc[OMUNIT(ui->ui_unit)]; ! 373: if ((OMUNIT(ui->ui_unit) >= 0) && (OMUNIT(ui->ui_unit) < NOM)) ! 374: omsp->sc_currenttimo = 0; ! 375: ! 376: /* allocate a physical unibus dma buffer for cursor tracking */ ! 377: if(omsp->sc_ubadd == 0) ! 378: { omsp->sc_ubadd = uballoc(0, /* which unibus adapter */ ! 379: (caddr_t)omsp->sc_curbuf, ! 380: sizeof(omsp->sc_curbuf), 0); ! 381: if(omsp->sc_ubadd == 0) ! 382: panic("UB AD 0 in omattach"); ! 383: } ! 384: } ! 385: ! 386: /* OMOPEN */ ! 387: /* Open the device. */ ! 388: ! 389: omopen(dev) ! 390: dev_t dev; ! 391: { ! 392: register struct om_softc *sc; ! 393: register struct uba_device *ui; ! 394: register struct omdevice *omaddr; ! 395: ! 396: if ((OMUNIT(dev) >= NOM) || /* No such device. */ ! 397: ((ui = omdinfo[OMUNIT(dev)]) == 0)) { /* Device not there. */ ! 398: u.u_error = ENXIO; ! 399: return; ! 400: } ! 401: ! 402: if ((ui->ui_alive) == 0) { /* Dead. */ ! 403: u.u_error = EIO; ! 404: return; ! 405: } ! 406: ! 407: if (((sc = &om_softc[OMUNIT(dev)])->sc_state)&OMSC_OPEN) { ! 408: u.u_error = EBUSY; /* Already open. */ ! 409: return; ! 410: } ! 411: ! 412: /* Set only the open bit in the state. */ ! 413: (sc->sc_state) = OMSC_OPEN; ! 414: ! 415: /* Set the read no stall timeout to 1 second. */ ! 416: (sc->sc_rtimoticks) = hz; ! 417: ! 418: /* Set the write no stall timeout to 1 minute. */ ! 419: (sc->sc_wtimoticks) = hz*60; ! 420: ! 421: /* Start the self-kicker. */ ! 422: omtimo(dev); ! 423: ! 424: /* Stop any DMA without causing an interrupt. (No OM_IENABLE bit.) */ ! 425: omaddr = (struct omdevice *)ui->ui_addr; ! 426: omaddr->CSR_EIR = (OM_WAKEUP | OM_ATTN); ! 427: DELAY(100); ! 428: ! 429: /* ************************************************************************ */ ! 430: /* ! 431: /* The following commented piece of code will cause the OMEGA to do a ! 432: /* hardware reset each time it is opened. This gaurentees the device to ! 433: /* be in a known state, but doesn't allow a program to manipulate an ! 434: /* image produced by a previous program since it clears the screen. ! 435: /* ! 436: /* ************************************************************************ */ ! 437: /* ! 438: /* /* Initialize the DR11-W by setting then clearing MAINT in the CSR ! 439: /* with CYCLE and GO clear. */ ! 440: /* omaddr->CSR_EIR = 0; ! 441: /* omaddr->CSR_EIR = OM_MAINT; ! 442: /* DELAY(100); ! 443: /* omaddr->CSR_EIR = 0; ! 444: /* ! 445: /* /* Wait for the omega to become ready. */ ! 446: /* while((omaddr->CSR_EIR)&OM_STATC) ! 447: /* sleep((caddr_t)sc, OMPRI); ! 448: /* ! 449: /* ************************************************************************ */ ! 450: ! 451: /* Enable interrupts. */ ! 452: omaddr->CSR_EIR = OM_IENABLE; ! 453: ! 454: ! 455: /* Make sure the device is really there and OK. */ ! 456: /* forget this! */ ! 457: /* if (((omaddr->CSR_EIR) >> OM_BUSY_SHIFT) & 1) { ! 458: /* u.u_error = EIO; ! 459: /* sc->sc_state = 0; ! 460: /* return; ! 461: /* } ! 462: */ ! 463: } ! 464: ! 465: ! 466: /* OMCLOSE */ ! 467: /* Close the device. */ ! 468: ! 469: omclose(dev) ! 470: dev_t dev; ! 471: { ! 472: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 473: ! 474: /* Set the state blank. */ ! 475: sc->sc_state = 0; ! 476: } ! 477: ! 478: ! 479: /* OMREAD */ ! 480: /* Reads characters from the device. If in stall mode, the read will be the ! 481: standard read which will not return until the requested number of characters ! 482: have been read. If in no stall mode, then the read will return after an ! 483: interval set in omioctl and report how many characters it read. ! 484: The count must be even since the DMA is by words. */ ! 485: ! 486: omread(dev) ! 487: dev_t dev; ! 488: { ! 489: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 490: register struct omdevice *omaddr = ! 491: (struct omdevice *)omdinfo[OMUNIT(dev)]->ui_addr; ! 492: register int spl; ! 493: ! 494: /* Make sure that the count is even. */ ! 495: if (u.u_count & 1) { ! 496: u.u_error = EINVAL; ! 497: return; ! 498: } ! 499: ! 500: /* Set the DR11-W to read. */ ! 501: sc->sc_operation = OM_READ; ! 502: ! 503: /* The following is to make up for something physio should really do ! 504: for us. If bp->b_resid has been left non-zero by the last call, ! 505: (ie an error), and the present call has a count of zero then the ! 506: old residual will be returned as the count. To correct this, we just ! 507: set the residual to zero before we start. */ ! 508: rombuf[OMUNIT(dev)].b_resid = 0; ! 509: ! 510: /* Are we in no stall or stall mode? */ ! 511: if ((sc->sc_state) & OMSC_NORSTALL) { ! 512: ! 513: /* We're in no stall mode. */ ! 514: ! 515: /* Start the timer running. */ ! 516: /* Don't let anything stop us once the timer's running. */ ! 517: spl = spl6(); ! 518: timeout(omrwtimo, (caddr_t) ! 519: ( ((sc->sc_currenttimo)<<8) | OMUNIT(dev) ), ! 520: (sc->sc_rtimoticks)); ! 521: ! 522: /* Perform the read. */ ! 523: physio(omstrategy, &rombuf[OMUNIT(dev)], dev, B_READ, minomph); ! 524: if (u.u_error) (void) splx(spl); ! 525: ! 526: /* Update the current timeout number. */ ! 527: (sc->sc_currenttimo)++; ! 528: ! 529: /* Did we timeout? */ ! 530: if ((sc->sc_state) & OMSC_TIMEDOUT) { ! 531: ! 532: /* Clear the timeout. */ ! 533: (sc->sc_state) &= (~OMSC_TIMEDOUT); ! 534: ! 535: /* Patch up the error. */ ! 536: ! 537: /* We made the error ourself, ignore it. */ ! 538: u.u_error = 0; ! 539: } ! 540: } ! 541: ! 542: else { ! 543: ! 544: /* We're in stall mode. */ ! 545: ! 546: /* Perform the read. */ ! 547: physio(omstrategy, &rombuf[OMUNIT(dev)], dev, B_READ, minomph); ! 548: } ! 549: } ! 550: ! 551: ! 552: /* OMWRITE */ ! 553: /* omwrite writes the passed data to the device using DMA. ! 554: The count must be even since the DMA is by words. */ ! 555: /* Timeouts are handled as in omread. */ ! 556: ! 557: omwrite(dev) ! 558: dev_t dev; ! 559: { ! 560: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 561: register int spl; ! 562: ! 563: /* Make sure that the count is even. */ ! 564: if (u.u_count & 1) { ! 565: u.u_error = EINVAL; ! 566: return; ! 567: } ! 568: ! 569: /* This call is to write around a system bug--on a B_WRITE call to ! 570: physio, the system checks to see if the user has read access to the ! 571: requested block. Then it locks necessary pages in virtual memory. ! 572: It checks for write access in the course of this, and, if the user ! 573: does not have it, panics ("vslock"). So, if the user sends, say, an ! 574: address in his code (0 is an example), the system crashes. So I ! 575: start by checking for write access. */ ! 576: if (useracc(u.u_base,u.u_count,B_WRITE) == NULL) { ! 577: u.u_error = EFAULT; ! 578: return; ! 579: } ! 580: ! 581: /* Set the DR11-W to write. */ ! 582: sc->sc_operation = OM_WRITE; ! 583: ! 584: /* The following is to make up for something physio should really do ! 585: for us. If bp->b_resid has been left non-zero by the last call, ! 586: (ie an error), and the present call has a count of zero then the ! 587: old residual will be returned as the count. To correct this, we just ! 588: set the residual to zero before we start. */ ! 589: rombuf[OMUNIT(dev)].b_resid = 0; ! 590: ! 591: /* Are we in no stall or stall mode? */ ! 592: if ((sc->sc_state) & OMSC_NOWSTALL) { ! 593: ! 594: /* We're in no stall mode. */ ! 595: ! 596: /* Start the timer running. */ ! 597: /* Don't let anything stop us once the timer's running. */ ! 598: spl = spl6(); ! 599: timeout(omrwtimo, (caddr_t) ! 600: ( ((sc->sc_currenttimo)<<8) | OMUNIT(dev) ), ! 601: (sc->sc_wtimoticks)); ! 602: ! 603: /* Perform the write. */ ! 604: physio(omstrategy, &rombuf[OMUNIT(dev)], dev, ! 605: B_WRITE, minomph); ! 606: if (u.u_error) (void) splx(spl); ! 607: ! 608: /* Update the current timeout number. */ ! 609: (sc->sc_currenttimo)++; ! 610: ! 611: /* Did we timeout? */ ! 612: if ((sc->sc_state) & OMSC_TIMEDOUT) { ! 613: ! 614: /* Clear the timeout. */ ! 615: (sc->sc_state) &= (~OMSC_TIMEDOUT); ! 616: ! 617: /* Patch up the error. */ ! 618: ! 619: /* We made the error ourself, ignore it. */ ! 620: u.u_error = 0; ! 621: } ! 622: } ! 623: ! 624: else { ! 625: ! 626: /* We're in stall mode. */ ! 627: ! 628: /* Perform the write. */ ! 629: physio(omstrategy, &rombuf[OMUNIT(dev)], dev, ! 630: B_WRITE, minomph); ! 631: } ! 632: } ! 633: ! 634: ! 635: /* OMIOCTL */ ! 636: /* IO control function. */ ! 637: ! 638: omioctl(dev, cmd, addr, flag) ! 639: dev_t dev; ! 640: int cmd; ! 641: register caddr_t addr; ! 642: int flag; ! 643: ! 644: { ! 645: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 646: register struct omdevice *omaddr = ! 647: (struct omdevice *)omdinfo[OMUNIT(dev)]->ui_addr; ! 648: int temp; ! 649: ! 650: switch(cmd) { ! 651: ! 652: case OM_SETRSTALL: ! 653: ! 654: /* Set read stall mode. */ ! 655: (sc->sc_state) &= (~OMSC_NORSTALL); ! 656: break; ! 657: ! 658: case OM_SETNORSTALL: ! 659: ! 660: /* Set read stall mode. */ ! 661: (sc->sc_state) |= OMSC_NORSTALL; ! 662: break; ! 663: ! 664: case OM_GETRSTALL: ! 665: ! 666: /* Returns true if in read stall mode. */ ! 667: temp = (!((sc->sc_state)&OMSC_NORSTALL)); ! 668: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 669: u.u_error = EFAULT; ! 670: } ! 671: break; ! 672: ! 673: case OM_SETRTIMEOUT: ! 674: ! 675: /* Set the number of ticks before a no stall read times out. ! 676: The argument is given in tenths of a second. */ ! 677: if (copyin(addr, (caddr_t)&temp, sizeof(temp))) { ! 678: u.u_error = EFAULT; ! 679: break; ! 680: } ! 681: if (temp < 1) { ! 682: u.u_error = EINVAL; ! 683: temp = 1; ! 684: } ! 685: (sc->sc_rtimoticks) = (temp * hz )/10; ! 686: break; ! 687: ! 688: case OM_GETRTIMEOUT: ! 689: ! 690: /* Returns the number of tenths of seconds before ! 691: a no stall read times out. */ ! 692: /* The argument is given in tenths of a second. */ ! 693: temp = ((sc->sc_rtimoticks)*10)/hz; ! 694: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 695: u.u_error = EFAULT; ! 696: } ! 697: break; ! 698: ! 699: case OM_SETWSTALL: ! 700: ! 701: /* Set write stall mode. */ ! 702: (sc->sc_state) &= (~OMSC_NOWSTALL); ! 703: break; ! 704: ! 705: case OM_SETNOWSTALL: ! 706: ! 707: /* Set write stall mode. */ ! 708: (sc->sc_state) |= OMSC_NOWSTALL; ! 709: break; ! 710: ! 711: case OM_GETWSTALL: ! 712: ! 713: /* Returns true if in write stall mode. */ ! 714: temp = (!((sc->sc_state)&OMSC_NOWSTALL)); ! 715: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 716: u.u_error = EFAULT; ! 717: } ! 718: break; ! 719: ! 720: case OM_SETWTIMEOUT: ! 721: ! 722: /* Set the number of ticks before a no stall write times out. ! 723: The argument is given in tenths of a second. */ ! 724: if (copyin(addr, (caddr_t)&temp, sizeof(temp))) { ! 725: u.u_error = EFAULT; ! 726: break; ! 727: } ! 728: if (temp < 1) { ! 729: u.u_error = EINVAL; ! 730: temp = 1; ! 731: } ! 732: (sc->sc_wtimoticks) = (temp * hz )/10; ! 733: break; ! 734: ! 735: case OM_GETWTIMEOUT: ! 736: ! 737: /* Returns the number of tenths of seconds before ! 738: a no stall write times out. */ ! 739: /* The argument is given in tenths of a second. */ ! 740: temp = ((sc->sc_wtimoticks)*10)/hz; ! 741: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 742: u.u_error = EFAULT; ! 743: } ! 744: break; ! 745: ! 746: case OM_WRITEREADY: ! 747: ! 748: /* Returns a value of 1 if the device can accept ! 749: data, 0 otherwise. Internally this is the ! 750: DR11-W STAT A bit. */ ! 751: temp = (((omaddr->CSR_EIR) >> OM_WRITE_SHIFT) & 1); ! 752: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 753: u.u_error = EFAULT; ! 754: } ! 755: break; ! 756: ! 757: case OM_READREADY: ! 758: ! 759: /* Returns a value of 1 if the device has data ! 760: to be read, 0 otherwise. Internally this is ! 761: the DR11-W STAT B bit. */ ! 762: temp = (((omaddr->CSR_EIR) >> OM_READ_SHIFT) & 1); ! 763: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 764: u.u_error = EFAULT; ! 765: } ! 766: break; ! 767: ! 768: case OM_BUSY: ! 769: ! 770: /* Returns a value of 1 if the device is busy, ! 771: 0 otherwise. Internally this is the DR11-W ! 772: STAT C bit. */ ! 773: temp = (((omaddr->CSR_EIR) >> OM_BUSY_SHIFT) & 1); ! 774: if (copyout((caddr_t)&temp, addr, sizeof(temp))) { ! 775: u.u_error = EFAULT; ! 776: } ! 777: break; ! 778: ! 779: case OM_RESET: ! 780: ! 781: /* Resets the OMEGA to its power on condition ! 782: by asserting the CSR MAINTENANCE bit. */ ! 783: ! 784: /* Initialize the DR11-W by setting then clearing MAINT ! 785: in the CSR with CYCLE and GO clear. */ ! 786: omaddr->CSR_EIR = 0; ! 787: omaddr->CSR_EIR = OM_MAINT; ! 788: DELAY(100); ! 789: omaddr->CSR_EIR = 0; ! 790: ! 791: /* Wait for the omega to become ready. */ ! 792: /* forget this! */ ! 793: /* while((omaddr->CSR_EIR)&OM_STATC) ! 794: /* tsleep((caddr_t)sc, OMPRI, 30); ! 795: */ ! 796: break; ! 797: ! 798: default: ! 799: ! 800: /* Flag the error. */ ! 801: u.u_error = EINVAL; ! 802: break; ! 803: ! 804: } ! 805: ! 806: return; ! 807: } ! 808: ! 809: ! 810: /* OMSTRATEGY */ ! 811: /* Routine to determine the DMA strategy for physio. */ ! 812: ! 813: omstrategy(bp) ! 814: register struct buf *bp; ! 815: { ! 816: register int e; ! 817: register int spl; ! 818: register struct om_softc *sc = &om_softc[OMUNIT(bp->b_dev)]; ! 819: register struct uba_device *ui = omdinfo[OMUNIT(bp->b_dev)]; ! 820: register struct omdevice *omaddr = (struct omdevice *)ui->ui_addr; ! 821: ! 822: spl = spl6(); ! 823: while (sc->sc_state & OMSC_BUSY) ! 824: tsleep((caddr_t)sc, OMPRI, 30); ! 825: sc->sc_state |= OMSC_BUSY; ! 826: sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); ! 827: omstart(bp->b_dev, bp->b_bcount); ! 828: e = omwait(bp->b_dev); ! 829: (bp->b_resid) = u.u_count - (bp->b_bcount) + ! 830: (((-(omaddr->WC))&0xFFFF)<<1); ! 831: (void) splx(spl); ! 832: ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); ! 833: sc->sc_state &= ~OMSC_BUSY; ! 834: iodone(bp); ! 835: if (e) ! 836: /* Cause physio to terminate and ! 837: geterror to give an EIO error. */ ! 838: (bp->b_flags) |= B_ERROR; ! 839: wakeup((caddr_t)sc); ! 840: } ! 841: ! 842: ! 843: /* MINOMPH */ ! 844: /* Set the maximum physical transfer size. */ ! 845: ! 846: unsigned ! 847: minomph(bp) ! 848: struct buf *bp; ! 849: { ! 850: ! 851: if (bp->b_bcount > OM_BLOCKSIZE) ! 852: bp->b_bcount = OM_BLOCKSIZE; ! 853: } ! 854: ! 855: ! 856: /* OMSTART */ ! 857: /* Start a DMA IO transfer. */ ! 858: ! 859: omstart(dev, count) ! 860: dev_t dev; ! 861: long count; ! 862: { ! 863: register int spl; ! 864: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 865: register struct omdevice *omaddr = ! 866: (struct omdevice *)omdinfo[OMUNIT(dev)]->ui_addr; ! 867: int i; ! 868: ! 869: spl = spl7(); /* don't interrupt me with a cursor */ ! 870: for (i = 100; (omaddr->CSR_EIR & OM_READY == 0) && i; --i) ! 871: ; /* wait in case cursor dma active */ ! 872: if (i == 0) ! 873: { ! 874: (void) splx(spl); ! 875: printf("omstart: device busy\n"); ! 876: u.u_error = EIO; ! 877: return; ! 878: } ! 879: ! 880: /* Set the DMA buffer address. */ ! 881: (omaddr->BAR) = (sc->sc_ubinfo); ! 882: ! 883: /* Set the word count to the 2's complement ! 884: of the count in words. */ ! 885: (omaddr->WC) = (-(count>>1)); ! 886: ! 887: /* Start the transfer with interrupts enabled. */ ! 888: (omaddr->CSR_EIR) = (OM_IENABLE | (sc->sc_operation) | ! 889: ((sc->sc_ubinfo >> 12) & OM_XBA)); ! 890: (omaddr->CSR_EIR) = (OM_IENABLE | (sc->sc_operation) | ! 891: ((sc->sc_ubinfo >> 12) & OM_XBA)| OM_GO); ! 892: ! 893: (void) splx(spl); ! 894: return; ! 895: } ! 896: ! 897: ! 898: /* OMRWTIMO */ ! 899: /* Routine to deal with no stall read/write timeouts. If the read/write ! 900: completed by itself, we just return. If not, we mark a timeout and ! 901: cause a DMA error and interrupt. */ ! 902: ! 903: omrwtimo(timeoutinfo) ! 904: register unsigned int timeoutinfo; ! 905: /* The low 8 bits of timeoutinfo are the minor device number. ! 906: The remaining higher bits are the current timeout number. */ ! 907: { ! 908: register int minordev = OMUNIT(timeoutinfo); ! 909: register struct om_softc *sc = &om_softc[minordev]; ! 910: register struct omdevice *omaddr = ! 911: (struct omdevice *)omdinfo[minordev]->ui_addr; ! 912: ! 913: /* If this is not the timeout that omread/omwrite is waiting for ! 914: then we should just go away. */ ! 915: if ((timeoutinfo&(~0377)) != ((sc->sc_currenttimo)<<8)) return; ! 916: ! 917: /* Mark that the device timed out. */ ! 918: (sc->sc_state) |= OMSC_TIMEDOUT; ! 919: ! 920: /* Send an OM_WAKEUP signal to halt any pending DMA and generate ! 921: an interrupt so that omwait will see the error and tell everyone ! 922: the transfer is done. */ ! 923: omaddr->CSR_EIR = (OM_ATTN | OM_WAKEUP | OM_IENABLE); ! 924: } ! 925: ! 926: ! 927: /* OMWAIT */ ! 928: /* Wait for the DR11-W to come ready. ! 929: Return a non-zero value if there is an error. */ ! 930: ! 931: omwait(dev) ! 932: dev_t dev; ! 933: { ! 934: register struct omdevice *omaddr = ! 935: (struct omdevice *)omdinfo[OMUNIT(dev)]->ui_addr; ! 936: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 937: register int e; ! 938: ! 939: while (!((e = (omaddr->CSR_EIR)) & OM_READY)) { ! 940: tsleep((caddr_t)sc, OMPRI, 30); ! 941: } ! 942: ! 943: /* Reset any error conditions. */ ! 944: (omaddr->CSR_EIR) = OM_IENABLE; ! 945: ! 946: return (e & OM_ERROR); ! 947: } ! 948: ! 949: ! 950: /* OMINTR */ ! 951: /* Wakup any process waiting for an interrupt. */ ! 952: ! 953: omintr(dev) ! 954: dev_t dev; ! 955: { ! 956: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 957: ! 958: wakeup((caddr_t)sc); ! 959: } ! 960: ! 961: ! 962: /* OMTIMO */ ! 963: /* Kick the driver every second. */ ! 964: ! 965: omtimo(dev) ! 966: dev_t dev; ! 967: { ! 968: register struct om_softc *sc = &om_softc[OMUNIT(dev)]; ! 969: ! 970: if (sc->sc_state&OMSC_OPEN) ! 971: timeout(omtimo, (caddr_t)dev, hz); ! 972: omintr(dev); ! 973: } ! 974: ! 975: omcur(dev, x, y) /* position cursor - called from bpd driver */ ! 976: dev_t dev; ! 977: { ! 978: register struct uba_device *ui = omdinfo[minor(dev)]; ! 979: register struct omdevice *omp = (struct omdevice *)(ui->ui_addr); ! 980: register struct om_softc *oms = &om_softc[minor(dev)]; ! 981: register i, j; ! 982: int spl; ! 983: ! 984: spl = spl6(); ! 985: if( (oms->sc_state & OMSC_OPEN == 0) || ! 986: (oms->sc_state & OMSC_BUSY) || ! 987: (omp->CSR_EIR & OM_READY == 0) ) ! 988: return; ! 989: x *= 1280; x /= 1024; /* scale x coordinate */ ! 990: y = 1024 - y; /* negate y coordinate */ ! 991: /* setup cursor command */ ! 992: oms->sc_curbuf[0] = 0x52; /* movp1 opcode */ ! 993: oms->sc_curbuf[1] = x & 0xFF; ! 994: oms->sc_curbuf[2] = (x >> 8) & 0x07; ! 995: oms->sc_curbuf[3] = y & 0xFF; ! 996: oms->sc_curbuf[4] = (y >> 8) & 0x07; ! 997: oms->sc_curbuf[5] = 0x71; /* display cursor opcode */ ! 998: ! 999: omp->BAR = oms->sc_ubadd; /* setup dma */ ! 1000: omp->WC = -3; ! 1001: omp->CSR_EIR = OM_WRITE|(OM_XBA & (oms->sc_ubadd >> 12)); ! 1002: omp->CSR_EIR = OM_WRITE|OM_GO|(OM_XBA & (oms->sc_ubadd >> 12)); ! 1003: splx(spl); ! 1004: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.