Annotation of researchv8dc/sys/dev/om.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.