📄 pdma_ds5000.c
字号:
#ifndef lintstatic char *sccsid = "@(#)pdma_ds5000.c 4.2 (ULTRIX) 11/13/90";#endif lint/************************************************************************ * * * Copyright (c) 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * pdma_ds5000.c 11/09/89 * * Pseudo DMA routines for the DS5000. * * Modification history: * * 09/07/90 Maria Vella * Submitted this file into release. * * 11/22/89 Mitch McConnell * Modified dma_cont to not use FIFO flags register. This routine is * only called with both TC set and same phase. For some reason ffr is * not being cleared by the chip and it is causing us to request more * data than the target has to give (it looks like - besides, the other * version of the asc driver does not use ffr in this case). For now, * I will leave it in dma_end - although I believe that the other driver * only uses it in this way when the previous phase was data out and * we get an unexpected phase change. * * 11/09/89 John A. Gallant * Created this file to support the PDMA work in the scsi drivers for the 3max. * ************************************************************************//************************************************************************ This file contains the Pseudo DMA routines needed for the DS5000. The DS5000 has an NCR 53c94 SCSI controller chip, and an 128K RAM buffer to use forthe DMA of data from the SCSI bus and Main memory. Data has to pass throughthis RAM buffer. The RAM buffer is dual ported, the 53c94 and CPU are ableto access it to deposite and remove data. The pseudo DMA code for the DS5000 uses the pipe/double buffer conceptto transfer data between memory and targets. The code sets up the RAMbuffer as 8 "pipes", one for each ID on the SCSI bus. Each pipe contains2 8k buffers for data xfer, each pipe has a total size of 16k. The 2 buffersare used interactivly, while the 53c94 is accessing one of the buffers theCPU accessing the other. For example in the case of a write the CPU hasprefilled both of the buffers with user data. The 53c94 is started on theinitial buffer to move the data to the target. Once the 53c94 is done withthat buffer the CPU switches the 53c94 to the other one. While the 53c94 isusing the new buffer the CPU then fills the previous buffer with more data. The RAM buffer in the DS5000 is accessed by the 53c94 in 16 bit words,the CPU can access the RAM buffer at byte addresses. On the CPU side theThere are no special routines used to read/write/zero the RAM buffer.The routines blkcopy and bzero are used. The usercnt and targcnt variables in the PDMA control structure are used differently. Targcnt is used to count the number of bytes that have actuallybeen transferd over the SCSI bus. Usercnt is used to keep track of how manybytes have been transfered via the active pipe. This is why with thebuffering on the data in the pipe these two numbers are used.*************************************************************************/#include "../data/scsi_data.c"#include "scsi_debug.h"#define sc_ascdmacount sc_siidmacount /* used to keep track of total number of bytes transferred *//* External functions and variables. */extern PDMA_ENTRY pdma_entry[]; /* the entry array *//* Local Data area. *//* Entry structure for the pseudo DMA routines for the DS5000. The externaldeclarations are needed for the forward reference. */extern int ds5000_init();extern int ds5000_setup();extern int ds5000_start();extern int ds5000_cont();extern int ds5000_end();extern int ds5000_flush();extern int bcopy();extern int bzero();PDMA_ENTRY pdma_ds5000 ={ DS_5000, /* cpu type value */ ( 0 ), /* MISC control flags */ ds5000_init, ds5000_setup, ds5000_start, ds5000_cont, ds5000_end, bcopy, /* kernel routines can be used */ bcopy, bzero, ds5000_flush};PDMA_ENTRY pdma_ds5500 ={ DS_5500, /* cpu type value */ ( 0 ), /* MISC control flags */ ds5000_init, ds5000_setup, ds5000_start, ds5000_cont, ds5000_end, bcopy, /* kernel routines can be used */ bcopy, bzero, ds5000_flush};/************************************************************************int pdma_init( sc )Inputs: sz_softc pointerFunction: Initialize all that is necessary for the DMA engine/code to run for the particular system. For the pipe code the pointers and offsets are set, one for each possible target. NOTE: for the pvax this may have to be more of a dynamic alloc for the buffer #'s perhaps done at setup(). The PDMA related fields will be cleared/initialized and one of the pipe buffers will be set to READY.Return: Success or Failure, on the ability to initialize for the DMA.**************************************************************************/intds5000_init( sc ) struct sz_softc *sc;{ int targid; /* loop counter for targets */ int offset; /* for cutting up the RAM buffer */ PDMA *pd; /* pointer for the DMA control struct */ int i; /* loop counter for pipe buffers */ PRINTD( 0xFF, 0x1, ("ds5000_init entry sc: %x\n", sc )); /* Setup the RAM buffer and DMA engine address pointers in the softc. The base address for these and the SCSI chip has already been set in the softc by the particular driver's probe code. */ sc->pdma_rambuff = DS5000_BUF_BASE(sc); /* ram buffer addr */ sc->pdma_addrreg = DS5000_AR_BASE(sc); /* engine address */ /* For each of the target slots on a SCSI bus, this is one of the valid magic #'s of 8. Setup and assign the pointers/offsets for each of the DMA control structures. */ offset = 0; /* start at the beginning of the buffer */ for( targid = 0; targid < NDPS; targid++ ) { pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */ /* Clear the per call elements. */ pd->pstate = PDMA_IDLE; /* clear out misc flags */ pd->iodir = 0; /* clear direction */ pd->count = 0; /* clear total count */ pd->data_addr = (char *)NULL; /* clear data address */ pd->usercnt = 0; /* user space count */ pd->targcnt = 0; /* target count */ /* Initialize the pipe/buffer related elements. */ pd->pb_addr = (char *)((int)sc->pdma_rambuff + offset); PRINTD( targid, 0x40, ("ds5000_init target %d offset %x\n", targid, offset )); for( i = 0; i < PIPE_BUF_NUM; i++ ) { /* Setup the offsets for the pipe buffer. */ pd->pb_offset[i] = offset; offset += MAX_XFER_SIZE; /* offset to next buffer */ /* Setup the counts and flags for the pipe buffer. */ pd->pb_count[i] = 0; pd->pb_flags[i] = PB_EMPTY; /* Flush, or zero out the pipe buffer. */ (*sc->dma_bzero) ( sc->pdma_rambuff + RAM_ADJUST(sc, pd->pb_offset[i]), MAX_XFER_SIZE ); wbflush(); }/* Question: check for offset overrun ?? set pstate to UNAVAILABLE ?? */ } PRINTD( 0xFF, 0x001, ("ds5000_init exit\n")); return( PDMA_SUCCESS );}/************************************************************************int pdma_setup( sc, targid, dir, count, addr )Inputs: sz_softc *sc; pointer to the softc structure int targid; current targit ID int dir; direction for I/O xfer long count; number of bytes to xfer char *addr; address for the data Function: Verify that a DMA operation can be done at this time, ie resources are available. NOTE: Pvax all pipes may be in "service". A wait return value would be sent back. The job would have to be tried again later. NOTE: Cmax all the DAT entries may be filled or there is not enough entries in a row for this transfer. (It could be broken up across DAT's, with the DMA engine being restarted.) All the DMA control structures will be setup. The pipe will be assigned, for a static case (Pmax, 3max) it may already be done. For a "write" operation both of the pipe buffers will be pre-filled and their status set to DATA_READY. NOTE: this will degenerate to a prefilled 16k buffer, if the CPU is unable to keep up with the SCSI chip. This is similiar to the current static allocation scheme in Pvax and Firefox. This routine WILL NOT !! startup the local DMA engine. This task will be left for the local driver or the call to the pdma_start() routine.Return: PDMA_SUCCESS all is ready and ok PDMA_FAIL a fatal(?) problem has occured PDMA_RETRY(?) unable to setup, try again later **************************************************************************/intds5000_setup( sc, targid, dir, count, addr ) struct sz_softc *sc; /* pointer to the softc structure */ int targid; /* current targit ID */ int dir; /* direction for I/O xfer */ long count; /* number of bytes to xfer */ char *addr; /* address for the data */{ PDMA *pd; /* pointer for the DMA control struct */ long lcount; /* local counter for xfers > MAX_XFER_SIZE */ int i; /* loop counter */ PRINTD( targid, 0x1, ("ds5000_setup entry sc:%x targ:%d dir:%d cnt:%d addr:%x\n", sc, targid, dir, count, addr )); /* Setup the DMA control structure for this target. */ pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */ /* If this pipe is not IDLE return PDMA_RETRY. */ if( pd->pstate != PDMA_IDLE ) { return( PDMA_RETRY ); } pd->pstate = PDMA_SETUP; /* setup is being done */ pd->iodir = dir; /* load direction */ pd->count = count; /* load total count */ pd->data_addr = addr; /* load data address */ pd->usercnt = 0; /* clear working count */ pd->targcnt = 0; /* clear working count */ /* Flush/NULL out the buffers, security reasons. [May remove ?] */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -