📄 pdma3min.c
字号:
#ifndef lintstatic char *sccsid = "@(#)pdma3min.c 4.6 (ULTRIX) 4/4/91";#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_3min.c * * Pseudo DMA routines for the PMAZ-BA a.k.a. 3min. * * Modification history: * * 15 Aug 1990 Robert Scott * Created this file to implement PDMA code for 3min hardware. Based upon * 3max PDMA code. * ************************************************************************//* ---------------------------------------------------------------------- */#define ENTRYEXIT 0x00010000#define REGLOAD 0x00020000#define DETAILDAT 0x00040000#define INTTRACE 0x00080000#define PADTRACK 0x00100000 #define DUMPHEX 0x00200000#define PASS2 0x00400000#define FRAG 0x00800000#include "../data/scsi_data.c"#include "../io/tc/tc.h"#include "scsi_debug.h"#include "pdma3min.h"/* ---------------------------------------------------------------------- *//* External functions and variables. */extern int scsidebug;extern PDMA_ENTRY pdma_entry[]; /* the entry array *//* ---------------------------------------------------------------------- *//* Local Data area. *//* Entry structure for the pseudo DMA routines for the PMAZBA. The externaldeclarations are needed for the forward reference. */extern int pmaz_ba_init();extern int pmaz_ba_setup();extern int pmaz_ba_start();extern int pmaz_ba_cont();extern int pmaz_ba_end();extern int pmaz_ba_flush();extern int bcopy();extern int bzero();PDMA_ENTRY pdma_ds5000_100 ={ DS_5000_100, /* cpu type value */ ( 0 ), /* MISC control flags */ pmaz_ba_init, pmaz_ba_setup, pmaz_ba_start, pmaz_ba_cont, pmaz_ba_end, bcopy, /* kernel routines can be used */ bcopy, bzero, pmaz_ba_flush};int targmatch = 9;int targtmp;/* ---------------------------------------------------------------------- *//*unsigned *ioa_addrcvt( addr )Inputs: char *addr; K2SEG address for the data Function: Convert input virtual address to physical which, in turn, must be modified to meet IOASIC format requirements.Return: Physical memory address in IOASIC format.*/unsigned *ioa_addrcvt ( addr )char *addr; { unsigned long a = (unsigned long) addr; unsigned long p; if ( IS_KUSEG( a ) ) { printf( "ioa_addrcvt: KUSEG address passwd in!\n" ); p = a; return 0; } p = svtophy( a ); if ( p == 0 ) { printstate |= PANICPRINT; printf( "ioa_addrcvt: Invalid return from svtophy().\n" ); printf( "ioa_addrcvt: Address 0x%x maps to physical address 0.\n",a ); return 0; } a = ( p & 0x1ffffffc ) << 3; return (unsigned *) a; }/* ---------------------------------------------------------------------- *//*void *backcvt( addr )Inputs: void *addr; IOASIC format physical address Function: Convert an IOASIC format physical address into normal physical address format.Return: Physical memory address in standard format.*/void *backcvt( void *addr ) { unsigned long a = (unsigned long) addr; unsigned long p; p = a >> 3; return (void *)( PHYS_TO_K0( p )); }/* ---------------------------------------------------------------------- *//*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 3min, DAT table space and fragment buffer space must be allocated. The PDMA related fields will be cleared/initialized and one of the pipe buffers will be set to READY.Return: PDMA_SUCCESS all is ready and ok PDMA_FAIL a fatal(?) problem has occured */int pmaz_ba_init( sc )struct sz_softc *sc; { int targid; /* loop counter for targets */ PDMA *pd; /* pointer for the DMA control struct */ int *slotp; /* IOASIC SCSI DMA slot register pointer */ static char *fbp=0; /* Fragment buffer pool pointer *//* Setup the DMA engine address pointers in the softc. The base address for these and the SCSI chip should have already been set in the softc by the particular driver's probe code. *//* In contradiction with the previous comment, this line should be done somewhere in scsi_asc.c? */ sc->ioasicp = (char *) PHYS_TO_K1( BASE_IOASIC ); /* The IOASIC SCSI DMA slot register MUST be initialized before any communication with the '94 is attempted. */ slotp = (int *) ( (unsigned)sc->ioasicp + SCSI_DMASLOT_O); *slotp = SCSI_SLOT_DATA; /* magic cookie as found in v1.6 of spec */ /* FIX: This may change with PMAZ-BA's */ /* 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. */ /* Allocate a chunk of memory for the fragment buffers and DAT table for each target */ if ( !fbp ) KM_ALLOC( fbp, char *, (sizeof( FRAGBUF )+DATTBL_SIZ)*8, KM_DEVBUF, KM_NOW_CL_CO_CA|KM_NOCACHE ); 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 */ /* The DAT table and fragment buffer for a given target must be extracted from the large buffer kmalloc'ed above. One might think of the large buffer as being an array (of length 8) of structures containing a DAT table followed by a fragment buffer for each target. Then again, one might not. */ pd->dat_addr = (char *) ( fbp + targid * ( DATTBL_SIZ + sizeof( FRAGBUF ) ) ); pd->frag_bufp = (char *) ( fbp + targid * ( DATTBL_SIZ + sizeof( FRAGBUF ) ) + DATTBL_SIZ );#ifdef PDMADEBUG PRINTD( targid, DETAILDAT, ("init: pd->dat_addr = 0x%x\n", pd->dat_addr )); PRINTD( targid, DETAILDAT, ("init: pd->frag_bufp = 0x%x\n", pd->frag_bufp ));#endif pd->usercnt = 0; /* user space count */ pd->targcnt = 0; /* target count */ } return( PDMA_SUCCESS ); }/* ---------------------------------------------------------------------- *//*int pdma_setup( sc, targid, dir, count, addr )Inputs: sz_softc *sc; pointer to the softc structure int targid; current target ID int dir; direction for I/O xfer long count; number of bytes to xfer char *addr; address for the data Function:Return: PDMA_SUCCESS all is ready and ok PDMA_FAIL a fatal(?) problem has occured PDMA_RETRY(?) unable to setup, try again later */int pmaz_ba_setup( sc, targid, dir, count, addr )struct sz_softc *sc; /* pointer to the softc structure */int targid; /* current target 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 */ int i; /* loop counter */#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_setup: entry sc=0x%x targ=%d dir=%d cnt=%d addr=0x%x\n bcount=%d dmaxfer=%d\n", sc, targid, dir, count, addr, sc->sc_b_bcount[targid], sc->sc_dmaxfer[targid] ));#endif /* Setup the DMA control structure for this target. */ pd = &sc->pdma_ctrl[ targid ]; /* assign the pointer */ targtmp = targid; /* used for debugging purposes only */ /* If this pipe is not IDLE return PDMA_RETRY. */ if( pd->pstate != PDMA_IDLE ) { PRINTD( targid, ENTRYEXIT, ("pmaz_ba_setup: exit - PDMA_RETRY\n")); return( PDMA_RETRY ); } pd->pstate = PDMA_SETUP; /* setup is being done */ pd->iodir = dir; /* load direction */ /* must save difference between requested xfer count and real count */ /* in order to pad out the xfer with the '94 */ pd->count = sc->sc_b_bcount[targid] - sc->sc_dmaxfer[targid]; /* OK, so this doesn't have anything to do with the sii, we don't need another counter in the softc structure and I don't like using #defines to mask things. */ sc->sc_siidmacount[targid] = count - pd->count;#ifdef PDMADEBUG if ( scsidebug & PADTRACK && targmatch == targid ) { if ( sc->sc_siidmacount[targid] ) cprintf("setup: Padding %d -> %d : %d\n", count, pd->count, sc->sc_siidmacount[targid] ); }#endif pd->data_addr = addr; /* load data address */ pd->usercnt = 0; /* clear working count */ pd->targcnt = 0; /* clear working count */ /* Build the DAT table for this transfer. */ if ( blddattbl( targid, pd, pd->count, addr, dir ) == PDMA_FAIL ) { printf( "setup: dat table build failure\n" ); printf( " target=%d dat_addr=0x%x pd->count=%d addr=0x%x dir=%d\n", targid, pd->dat_addr, pd->count, addr, dir ); dumptbl( (DTENT *)pd->dat_addr ); return( PDMA_FAIL ); } /* The DAT indexing scheme always begins with 1 as entry 0 is reserved in case 'backing-up' is necessary. This could occur due to a disconnect which leaves a segment of less than a double word in length to be transferred. In such a case, the remainder of the segment interrupted would be broken into two portions: A transfer of less than a double word into a local buffer followed by a normal DMA transfer. */ pd->dat_index = 1;#ifdef PDMADEBUG if ( scsidebug & DETAILDAT && ( targid==targmatch ) ) dumptbl( (DTENT *)pd->dat_addr );#endif /* If the setup is for a write and there the table begins with a 'special case' transfer from a local buffer, fill that buffer right now. */ if ( ( dir == SZ_DMA_WRITE ) && is_local_xfer( pd ) ) frag_buf_load( pd );#ifdef PDMADEBUG PRINTD( targid, ENTRYEXIT, ("pmaz_ba_setup: exit\n"));#endif return( PDMA_SUCCESS ); /* ready */ }/* ---------------------------------------------------------------------- *//* int pdma_start( sc, targid, opcode )Inputs: sz_softc *sc; pointer to the softc structure int targid; current target ID int opcode; value to start the dma oper in the chip Function: This routine is fairly straight forward. It is responsible for loading what ever is necessary into the DMA engine and the SCSI chip. The dma control structure for the target should contain all the information.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -