Annotation of researchv8dc/sys/dev/om.c, revision 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.