vmedma.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 442 行 · 第 1/2 页

C
442
字号
      {             sc->sc_open = XXOPEN;             return(0);       }      /* Otherwise, return an error. */       else return(ENXIO);}/********* Close Routine **********************************//*                                                        *//* The xxclose routine is called from the ULTRIX          *//* spec_close routine.  The xxclose routine clears the    *//* XXOPEN flag to allow other processes to use the        */ /* device.                                                *//*                                                        *//**********************************************************/xxclose(dev, flag)dev_t  dev; /* Major/minor device number */ int flag;   /* Flags from /usr/sys/h/file.h */ {      /* Initialize unit to the minor device number */       register int unit = minor(dev);       /* Initialize pointer to uba_device structure */       register struct uba_device  *devptr = xxdinfo[unit];       /* Initialize pointer to xx_softc structure */       register struct xx_softc *sc = &xx_softc[unit];      /* Initialize pointer to xx_reg structure */       struct xx_reg *reg = (struct xx_reg *) devptr->ui_addr;             sc->sc_open = XXCLOSE; /* Turn off the open bit. */      reg->csr = 0; /* Turn off interrupts. */      wbflush(); /* Assure write to I/O space completes. */      return(0); /* Return success. */}/**********************************************************//*         READ AND WRITE                                 *//*                                                        *//**********************************************************//********* Read Routine ***********************************//*                                                        *//* The xxread routine is called from the ULTRIX           *//* spec_rwgp routine.  The xxread routine will call       *//* the ULTRIX physio routine to perform the buffer        *//* lock, buffer check, I/O package set up.                *//* The physio routine calls the xxstrategy routine        *//* to access the device.                                  *//*                                                        *//**********************************************************/xxread(dev, uio)dev_t  dev; /* Major/minor device number */ struct uio *uio; /* Pointer to uio structure */ {      /* Initialize unit to the minor device number */       register int unit = minor(dev);       /* Call physio to perform buffer lock, buffer check, and */      /* I/O package set up. */       return (physio(xxstrategy, &xxbuf[unit], dev, B_READ, minphys, uio));}/********* Write Routine **********************************//*                                                        *//* The xxwrite routine is called from the ULTRIX          *//* spec_rwgp routine.  The xxwrite routine will call      *//* the ULTRIX physio routine to perform the buffer        *//* lock, buffer check, I/O package set up.                *//* The physio routine calls the xxstrategy routine        *//* to access the device.                                  *//*                                                        *//**********************************************************/xxwrite(dev, uio)dev_t  dev; /* Major/minor device number */struct uio *uio; /* Pointer to uio structure */{      /* Initialize unit to the minor device number */      register int unit = minor(dev);       /* Call physio to perform buffer lock, buffer check, and */      /* I/O package set up. */       return (physio(xxstrategy, &xxbuf[unit], dev, B_WRITE, minphys, uio));}/**********************************************************//*         STRATEGY                                       *//*                                                        *//**********************************************************//*                                                        *//********* Strategy Routine *******************************//*                                                        *//* The xxstrategy routine is called from the ULTRIX       *//* physio routine.  The xxstrategy routine first makes    *//* sure that the user buffer is both readable and         *//* writeable.  It then determines if the buffer size      *//* is larger than XXMAXPHYS.                              *//**********************************************************/xxstrategy(bp)struct buf  *bp; /* Pointer to buf structure */ {      /**************************************************/      /* Declare and initialize: unit variable, pointer */      /* to uba_device structure, pointer to xx_softc   */      /* structure, pointer to xx_reg structure, and    */      /* csr variable.                                  */      /************************************************/      register int unit = minor(bp->b_dev);       register struct uba_device *devptr = xxdinfo[unit];        register struct xx_softc *sc = &xx_softc[unit];       register struct xx_reg *reg = (struct xx_reg *) devptr->ui_addr;       short csr;        /* Determine if the user buffer is writeable */       /* during write operations and readable      */       /* during read operations.                   */       if (useracc(bp->b_un.b_addr, (int) bp->b_bcount,         ((bp->b_flags & B_READ)==B_READ?B_READ:B_WRITE))            == NULL){                             bp->b_error = EACCFAULT; /* Access violation */              sc->sc_error = bp->b_error; /* A copy to sc_error */              bp->b_flags |= B_ERROR; /* Flag the error */                            /* to xxstrategy                         */               iodone(bp); /* Complete the I/O and return execution */	                  /* to xxstrategy                         */              return;        }      /* Determine if the buffer size is larger than */      /* XXMAXPHYS */       if (bp->b_bcount > XXMAXPHYS) {              bp->b_error = EBUFTOOBIG; /* Indicate error */              sc->sc_error = bp->b_error; /* A copy to the xx_softc struct */              bp->b_flags |= B_ERROR;               /* Complete the I/O and return execution */              /* to xxstrategy                         */               iodone(bp);               return;        }        /* Save bp for use in interrupt routine */         sc->bp = bp;        /* Set up the DMA mapping registers */         sc->vmeaddr = vbasetup (devptr->ui_vbahd, bp,                                VME_DMA | VMEA32D32 | VME_BS_NOSWAP,                                0);        /* If requested mapping could not be performed */         if (sc->vmeaddr == 0) {                bp->b_error = ENOMAPREG;                sc->sc_error = bp->b_error;                bp->b_flags |= B_ERROR;                iodone(bp);                return;        }         /* If requested mapping could be performed, */         /* set up the device for transfer.          */         reg->addr = sc->vmeaddr;        reg->count = bp->b_bcount;        if (bp->b_flags & B_READ)                csr = READ | IE;        else                csr = IE;        reg->csr = csr | DMA_GO;        wbflush();}/**********************************************************//*         INTERRUPT                                      *//*                                                        *//**********************************************************//*                                                        *//********* Interrupt Routine ******************************//*                                                        *//*                                                        *//* The xxintr routine is the interrupt service routine    *//* for the XX device.  It releases VMEbus mapping         *//* registers and flushes the cache if the operation was   *//* a DMA read.  It then calls iodone to finish the I/O.   */ /**********************************************************/xxintr(unit)int  unit; /* Logical unit number for device */  {      /**************************************************/      /* Declare and initialize: pointer to uba_device  */      /* structure, pointer to xx_softc structure,      */      /* and pointer to xx_reg structure.  Declare      */      /* pointer to buf structure.                      */      /**************************************************/        register struct uba_device *devptr = xxdinfo[unit];         register struct xx_softc *sc = &xx_softc[unit];         register struct xx_reg *reg = (struct xx_reg *) devptr->ui_addr;         struct buf *bp;         bp = sc->bp; /* Retrieve saved buf pointer */        /* To Be Supplied. Is reg->sc_csr correct ? */         if (reg->csr & ERROR) {                bp->b_error = EIO;                bp->b_flags |= B_ERROR;        }        /* Record the number of bytes remaining */         bp->b_resid = reg->count;               /* Release the mapping registers. */         vbarelse(devptr->ui_vbahd, sc->vmeaddr);        /* If the operation was a read, then it is necessary */        /* to flush the data cache to ensure that the next */        /* access will get the newly read data. */         if (bp->b_flags & B_READ) bufflush(bp);        iodone(bp); }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?