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 + -
显示快捷键?