home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- ***** C h a m e l e o n I r i x P c i D r i v e r *****
- ***** *****
- ******************************************************************************
- */
- #include <sys/types.h>
- #include "sys/cmn_err.h"
- #include "sys/sema.h"
- #include <sys/param.h>
- #include <sys/errno.h>
- #include <sys/syslog.h>
- #include <sys/conf.h>
- #include <sys/pio.h>
- #include "sys/systm.h"
- #include <sys/time.h>
- #include <sys/ksynch.h>
- #include <sys/ktime.h>
- #include <sys/invent.h>
- #include <sys/kmem.h>
- #include <sys/kabi.h>
- #include <sys/mload.h>
- #include <sys/ddi.h>
- #include <sys/cred.h>
- #include <sys/immu.h>
- #include <sys/region.h>
- #include <sys/alenlist.h>
- #include <sys/ioerror.h>
- #include <sys/PCI/PCI_defs.h>
- #include <sys/PCI/pciio.h>
-
- #include "coco.h"
- #include "coco_user.h"
-
- /* ddi/dki and irix required */
- char *coco_mversion = M_VERSION; /* loadable driver requirement */
- int coco_devflag = D_MP; /* ddi/dki requirement */
-
- /* ======================================
- * Device Driver/PCI entry routines
- * ====================================== */
- int coco_unload(void);
- int coco_open(dev_t *, int, int, cred_t *);
- int coco_close(dev_t, int, int, cred_t *);
- int coco_read( dev_t, uio_t *, cred_t *);
- int coco_write( dev_t, uio_t *, cred_t *);
- int coco_ioctl(dev_t, int, void *, int, cred_t *, int *);
- int coco_map ( dev_t, vhandl_t *, off_t, size_t, uint_t );
- int coco_unmap ( dev_t, vhandl_t * );
- int coco_init();
- int coco_reg(void);
- int coco_reg(void);
-
- int coco_attach(vertex_hdl_t);
- int coco_detach(vertex_hdl_t);
-
- /*
- * Our error handler and interrupt handler
- * Note: We do not set any error handler
- */
- static error_handler_f coco_error;
- void coco_intr( intr_arg_t );
-
-
- /* =================================
- * Supporting internal routines
- * ================================= */
- static void cocoReset( card_t * );
- static void cocoProgFlags ( caddr_t, uint_t, ushort_t, ushort_t, ushort_t,
- ushort_t);
- static void cocoSetMode ( card_t *, int, int, int, int );
- static void cocoCommand ( card_t *, uint_t, uint_t );
- static void cocoBufOut ( card_t *, uint_t *, int );
- static void cocoBufIn ( card_t *, uint_t *, int );
- static void cocoReadDmaRegs ( card_t *, uint_t * );
- static void cocoWriteDmaRegs ( card_t *, uint_t * );
- static void cocoSetAddr ( card_t *, uint_t );
- static void cocoReadIntRam ( card_t *, uint_t *, int, int );
- static void cocoWriteIntRam ( card_t *, uint_t *, int, int );
- static void cocoReadExtRam ( card_t *, uint_t *, int );
- static void cocoWriteExtRam ( card_t *, uint_t *, int );
- static void cocoConvert ( card_t *, uint_t );
- static void cocoConvertTest ( card_t *, coco_convert_t *);
- static void cocoPrepAmcc ( card_t * );
- static void cocoResetAmcc ( card_t *);
- static void cocoStartProgDma ( card_t *, iopaddr_t, int, int );
- static void cocoStartSingleDma ( card_t *, alenaddr_t, size_t, int );
- static void cocoReport ( card_t *, char * );
- static void cocoShowChain( char *, coco_dmapage_t * );
- static void cocoTimeOut( card_t *);
- static void cocoTimeOut2( card_t *);
- static void cocoDumpAmcc ( card_t *);
- static void cocoReportTime ( caddr_t, card_t *, int );
- static void cocoShowAlenlist ( caddr_t, alenlist_t );
- static void cocoUnlockUser ( caddr_t, int, int );
- static void cocoTestLock ( card_t * );
- static void cocoTestNorm ( card_t * );
- static void cocoConvTime ( struct timespec *, coco_timeval_t * );
- static void cocoMakeHwGraph ( card_t *);
-
- static void cocoDiffTime ( struct timespec *, struct timespec *,
- struct timespec *);
-
- static int cocoStrategy ( buf_t * );
- static int cocoReadAmccFifo ( card_t * );
- static int cocoFifoTest ( card_t *, int );
- static int cocoPattern ( int, int );
- static int cocoReadMode ( card_t * );
- static int cocoReadAddr (card_t *);
- static int cocoDmaRegsTest ( card_t * );
- static int cocoIntRamTest ( card_t * );
- static int cocoExtRamTest ( card_t * );
- static int cocoDmaToLuts( card_t *, coco_buf_t *, int );
- static int cocoReadWrite( card_t *, coco_rw_t * );
- static int cocoStartRWDma ( card_t *, iopaddr_t, int, iopaddr_t, int );
- static int cocoMakeChainRW ( card_t *, coco_dmapage_t **, coco_dmapage_t **);
- static int cocoAlenlistSize ( alenlist_t );
- static int cocoLockUser ( caddr_t, int, int );
- static int coco_copyin_buf ( card_t *, void *, coco_buf_t * );
- static int coco_copyin_rw ( card_t *, caddr_t, coco_rw_t * );
-
- static coco_dmapage_t * cocoMakeChain ( card_t *, alenlist_t, int );
- static char *cocoIoctlStr(int);
-
-
-
- /*
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~~~~~~~~~~~ ~~~~~~~~~~~~~
- ~~~~~~~~~~~ D r i v e r ' s E n t r y R o u t i n e s ~~~~~~~~~~~~~~
- ~~~~~~~~~~~ ~~~~~~~~~~~~~
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
- /*************************************************************************
- *** c o c o _ i n i t ***
- *************************************************************************
- *
- * Name: coco_init
- *
- * Purpose: Called by kernel. For Irix6.4 only: We do not register
- * here but we will do it in coco_reg. For init, we simply
- * do nothing.
- *
- * Returns: None
- *
- *************************************************************************/
- int
- coco_init()
- {
- return(0);
- }
-
- /*************************************************************************
- *** c o c o _ r e g ***
- *************************************************************************
- *
- * Name: coco_reg
- *
- * Purpose: Called by kernel when the driver is loaded.
- * Here we register ourselves for the card, identified by
- * Vendor and Device ID.
- *
- * Note: This is for Irix6.4 only.
- *
- * Returns: None
- *
- *************************************************************************/
- int
- coco_reg()
- {
- register int ret;
-
- /* Register and identify the card */
- ret = pciio_driver_register(VENDOR_ID, DEVICE_ID, DRIVER_PREFIX, 0);
-
- if ( ret ) {
- cmn_err (CE_WARN, "coco_reg: registration returned %d", ret );
- }
-
- return(ret);
- }
-
- /*************************************************************************
- *** c o c o _ a t t a c h ***
- *************************************************************************
- *
- * Name: coco_attach
- *
- * Purpose: Called by the kernel. Our card is installed and hence
- * we are called. Prepare everything necessary to handle
- * the card. Note that when the card is found, the following
- * is set in the Command field of Config space:
- * - Bus master enabled/
- * - Memory and IO space access enabled.
- * - Cache line is set to 0x20 (32)
- * - Latency Timer is set to 0x30 (48)
- *
- * For Chameleon, beside Configuration address space, we need 4
- * Memory address spaces to be mapped:
- * Base_Reg 0 = AMCC Registers and Fifos
- * Base_Reg 3 = Normal DMA registers
- * Base_Reg 4 = Configuration Register.
- *
- * Returns: 0 for Success, or errno
- *
- *************************************************************************/
- int
- coco_attach(vertex_hdl_t conn)
- {
-
- card_t *cp;
- caddr_t cfg_adr, mem_ptr, amcc_adr, conf_adr, norm_adr;
- pciio_piomap_t cfg_map, amcc_map, conf_map, norm_map;
- register int ret, i;
- uint_t vendor_id, device_id, base_reg, cmd_reg, tmp_int;
- vertex_hdl_t coco_vhdl;
- device_desc_t dev_desc;
-
- /* dev_desc = device_desc_default_get(conn); */
- dev_desc = 0;
-
- /* =========================
- * Configuration Space
- * ========================= */
-
- cfg_map = (pciio_piomap_t)NULL;
- cfg_adr = (caddr_t)pciio_pio_addr (
- conn, /* connection vertex */
- dev_desc, /* default device descr. */
- PCIIO_SPACE_CFG, /* config space wanted */
- 0, /* from the start of space */
- COCO_CONFIG_HDR, /* for this many bytes */
- &cfg_map, /* in case we need piomap */
- 0); /* unused flag */
-
- if ( cfg_adr == (caddr_t)NULL ) {
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- cmn_err ( CE_WARN, "coco_attach: Cannot get to Config space");
- return(EIO);
- }
-
-
- /* ===============================
- * Configuration data printout
- * =============================== */
-
- /* vendor_id, device_id */
- tmp_int = Inp32(cfg_adr);
- vendor_id = tmp_int & 0x0000ffff;
- device_id = tmp_int >> 16;
-
- #ifdef DEBUG
- printf ("coco_attach: Config values\n");
- printf ("vendor_id = 0x%x, device_id = 0x%x\n", vendor_id, device_id );
-
- /* command and status */
- tmp_int = Inp32(cfg_adr + 0x04);
- printf ("Command = 0x%x, Status = 0x%x\n", (tmp_int & 0x0000ffff),
- (tmp_int >> 16) );
-
- /* interrupt line and pin */
- tmp_int = Inp32(cfg_adr + 0x3c);
- printf ("Int Line = %d, Int Pin = %d\n", (tmp_int & 0x000000ff),
- (tmp_int & 0x0000ff00) >> 8 );
-
- /* cache line size and latency timer */
- tmp_int = Inp32(cfg_adr + 0x0c);
- printf ("Cache line size = %d, latency timer = %d\n",
- (tmp_int & 0x000000ff), (tmp_int & 0x0000ff00) >> 8 );
-
- /* all 6 base registers */
- for ( i = 0; i < 6; i++ ) {
- printf ("Base_Reg_%d = 0x%x\n", i, Inp32(cfg_adr+0x10+(i*4)) );
- }
- #endif
-
- /* ==========================
- * AMCC Registers
- * ========================== */
-
- /* Get Amcc Register addresses */
- amcc_map = (pciio_piomap_t)NULL;
- amcc_adr = (caddr_t)pciio_pio_addr (
- conn, /* connection vertext */
- dev_desc, /* default device descr. */
- PCIIO_SPACE_WIN(0), /* Base register 0 space */
- 0, /* from the start of space */
- AMCC_RAM_SIZE, /* for this many bytes */
- &amcc_map, /* in case we need piomap */
- 0); /* unused flag */
-
- if ( amcc_adr == (caddr_t)NULL ) {
- cmn_err(CE_WARN, "coco_attach: Cannot get to AMCC address space");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- return (EIO);
- }
-
-
- /* ================================
- * DMA Configuration Registers
- * ================================ */
- conf_map = (pciio_piomap_t)NULL;
- conf_adr = (caddr_t)pciio_pio_addr (
- conn, /* connection vertext */
- dev_desc, /* default device descr. */
- PCIIO_SPACE_WIN(4), /* Base register 4 space */
- 0, /* from the start of space */
- CONFIG_RAM_SIZE, /* for this many bytes */
- &conf_map, /* in case we need piomap */
- 0); /* unused flag */
-
-
- if ( conf_adr == (caddr_t)NULL ) {
- cmn_err(CE_WARN, "coco_attach: Cannot get to Config Register");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- if ( conf_map ) pciio_piomap_done ( conf_map );
- return (EIO);
- }
-
-
- /* ================================
- * Normal DMA registers
- * ================================ */
- norm_map = (pciio_piomap_t)NULL;
- norm_adr = (caddr_t)pciio_pio_addr (
- conn, /* connection vertext */
- dev_desc, /* default device descr. */
- PCIIO_SPACE_WIN(3), /* Base register 3 space */
- 0, /* from the start of space */
- NORMAL_DMA_RAM_SIZE,/* for this many bytes */
- &norm_map, /* in case we need piomap */
- 0); /* unused flag */
-
-
- if ( norm_adr == (caddr_t)NULL ) {
- cmn_err(CE_WARN, "coco_attach: Cannot get to Normal DMA address");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- if ( conf_map ) pciio_piomap_done ( conf_map );
- if ( norm_map ) pciio_piomap_done ( norm_map );
- return (EIO);
- }
-
-
- /* allocate an internal structure for this card and save everything */
- cp = (card_t *)kmem_zalloc ( sizeof(card_t), KM_NOSLEEP );
- if ( cp == (card_t *)NULL ) {
- cmn_err(CE_WARN, "coco_attach: Cannot allocate memory");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- if ( conf_map ) pciio_piomap_done ( conf_map );
- if ( norm_map ) pciio_piomap_done ( norm_map );
- return(ENOMEM);
- }
-
- #ifdef DEBUG
- printf ("coco_attach: amcc_adr = 0x%x, conf_adr = 0x%x\n",
- amcc_adr, conf_adr );
- printf (" cfg_adr = 0x%x, norm_adr = 0x%x\n",
- cfg_adr, norm_adr );
-
- printf ("Maps allocated: %s %s %s %s\n",
- amcc_map ? "Amcc":"",
- norm_map ? "Norm":"",
- conf_map ? "Conf":"",
- cfg_map ? "Cfg":"" );
- #endif
-
- cp->conn = conn;
- cp->cfg_adr = cfg_adr;
- cp->amcc_adr = amcc_adr;
- cp->conf_adr = conf_adr;
- cp->norm_adr = norm_adr;
- cp->amcc_map = amcc_map;
- cp->norm_map = norm_map;
- cp->conf_map = conf_map;
- cp->cfg_map = cfg_map;
- cp->kernel_abi = get_current_abi(); /* ABI_IRIX5_64 for 64-bit kernel */
-
- /* initialize our mutex lock and sv_t for sleep/wake */
- COCO_LOCK_INIT(&cp->coco_mlock);
- SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
-
- /* create a vertex for our device off of the connection point */
- ret = hwgraph_char_device_add(conn, "coco", "coco_", &coco_vhdl );
- if ( ret != GRAPH_SUCCESS ) {
- cmn_err (CE_WARN, "coco_attach: could not addr vertex");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- if ( conf_map ) pciio_piomap_done ( conf_map );
- if ( norm_map ) pciio_piomap_done ( norm_map );
- kmem_free ( cp, sizeof(card_t) );
- return(EIO);
- }
-
- hwgraph_chmod( coco_vhdl, 0666 );
- cp->vhdl = coco_vhdl;
-
- /* once ioconfig and COCO_MKHWGRAPH works, remove this area */
- ret = hwgraph_edge_add ( hwgraph_root, coco_vhdl, "coco" );
- if ( ret != GRAPH_SUCCESS ) {
- cmn_err (CE_WARN, "coco_attach: Cannot create node /hw/coco");
- }
-
-
-
- /* =====================================
- * Interrupt Handler Registration
- * ===================================== */
- cp->dev_intr = pciio_intr_alloc ( conn, dev_desc,
- PCIIO_INTR_LINE_A,
- coco_vhdl );
-
- if (cp->dev_intr == (pciio_intr_t)NULL){
- cmn_err(CE_WARN, "coco_attach: Can't pciio_intr_alloc");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- if ( conf_map ) pciio_piomap_done ( conf_map );
- if ( norm_map ) pciio_piomap_done ( norm_map );
- kmem_free ( cp, sizeof(card_t) );
- hwgraph_edge_remove(conn, "coco", &coco_vhdl);
- device_info_set ( coco_vhdl, 0 );
- hwgraph_vertex_destroy ( coco_vhdl );
- return(EIO);
- }
-
- ret = pciio_intr_connect ( cp->dev_intr, (intr_func_t)coco_intr,
- (intr_arg_t)cp, 0 );
-
- if ( ret != 0 ) {
- cmn_err(CE_WARN, "coco_attach: Cannot register interrupt handler");
- if ( cfg_map ) pciio_piomap_done ( cfg_map );
- if ( amcc_map ) pciio_piomap_done ( amcc_map );
- if ( conf_map ) pciio_piomap_done ( conf_map );
- if ( norm_map ) pciio_piomap_done ( norm_map );
- kmem_free ( cp, sizeof(card_t) );
- hwgraph_edge_remove(conn, "coco", &coco_vhdl);
- device_info_set ( coco_vhdl, 0 );
- hwgraph_vertex_destroy ( coco_vhdl );
- return (EIO);
- }
-
- /* ========================================
- * Register an error handler for 6.4
- * ======================================== */
-
- #if 0
- pciio_error_register(conn, (error_handler_f *)coco_error, cp );
- #endif
-
- cp->status = CARD_ATTACHED;
-
- /* allocate memory for mapping */
- for ( i = MAP_PAGES; i > 0; i-- ) {
- cp->mappedkv = kmem_alloc (i * NBPP,
- KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
- if ( cp->mappedkv != (caddr_t)NULL )
- break;
- }
- if ( cp->mappedkv == (caddr_t)NULL ) {
- cmn_err (CE_NOTE, "coco_attach: Not enough memory for mapping");
- cmn_err (CE_WARN, "coco_attach: No mapping is allowed");
- }
- else {
- cp->mappedkvlen = i * NBPP;
- cmn_err (CE_NOTE, "coco_attach: %d bytes allocated, %d available for mapping",
- cp->mappedkvlen, cp->mappedkvlen - LESS_MAP );
- }
-
- /* save our structure */
- device_info_set ( coco_vhdl, (void *)cp );
-
- cmn_err ( CE_NOTE, "coco_attach: driver is ready");
- return(0);
- }
-
- /*************************************************************************
- *** c o c o _ d e t a c h ***
- *************************************************************************
- *
- * Name: coco_detach
- *
- * Purpose: Detaches a driver. Called by the pciio infrastructure
- * once for each vertext representing a crosstalk widget
- * when unregistering the driver.
- *
- * Returns: 0 Success or errno
- *
- *************************************************************************/
-
- int
- coco_detach(vertex_hdl_t conn)
- {
- register card_t *cp;
- vertex_hdl_t vhdl;
-
- if ( hwgraph_traverse(conn, "coco", &vhdl) != GRAPH_SUCCESS )
- return(-1);
-
- cmn_err(CE_NOTE,
- "coco_detach: Unregister Interrupt handler and free up mem");
-
- cp = (card_t *)device_info_get ( vhdl );
-
- /* our struct is there ? clean up our driver's stuff */
- if ( cp != (card_t *)NULL ) {
-
- /* free up memory for mapping */
- if ( cp->mappedkv )
- kmem_free ( cp->mappedkv, cp->mappedkvlen );
-
- /* Unregister the Interrupt Handler */
- pciio_intr_disconnect(cp->dev_intr);
- pciio_intr_free(cp->dev_intr);
- #if 0
- /* unregister error handler */
- pciio_error_register(conn, 0, 0);
- #endif
-
- /* free up all our maps */
- if ( cp->cfg_map ) pciio_piomap_done ( cp->cfg_map );
- if ( cp->amcc_map ) pciio_piomap_done ( cp->amcc_map );
- if ( cp->conf_map ) pciio_piomap_done ( cp->conf_map );
- if ( cp->norm_map ) pciio_piomap_done ( cp->norm_map );
-
- /* free up the struct itself */
- kmem_free ( cp, sizeof(card_t) );
-
- }
-
- /* free up our vertextes */
- hwgraph_edge_remove ( hwgraph_root, "coco", &vhdl);
- hwgraph_edge_remove(conn, "coco", &vhdl);
- device_info_set ( vhdl, 0 );
- hwgraph_vertex_destroy ( vhdl );
-
- return(0);
- }
-
- /*************************************************************************
- *** c o c o _ i n t r ***
- *************************************************************************
- *
- * Name: coco_intr
- *
- * Purpose: Our interrupt handler.
- *
- * Returns: None.
- *
- *************************************************************************/
-
- void
- coco_intr( intr_arg_t arg )
- {
- register card_t *cp;
- register buf_t *bp;
- register caddr_t adr_cfg, adr_amcc, adr_norm;
- register uint_t intcsr, xil_stat, mbox;
- register uint_t dmastat, dmatype, dmacfg, dmabits;
- register int rw, err;
- register int s;
- size_t p_size;
- alenaddr_t p_addr;
-
- /* get the lock */
- cp = (card_t *)arg;
- nanotime ( & cp->intr_time);
- s = COCO_LOCK(&cp->coco_mlock);
-
- /* a stray interrupt ? */
- adr_amcc = cp->amcc_adr;
- intcsr = Inp32(adr_amcc+AMCC_OP_REG_INTCSR);
- if ( (intcsr & 0x00800000) == 0 ) {
- COCO_UNLOCK(&cp->coco_mlock, s);
- return;
- }
-
- #ifdef DEBUGTIME
- cocoReportTime ( "cocoIntr", cp, 0 );
- #endif
-
- bp = cp->bp;
-
- adr_cfg = cp->conf_adr;
- adr_norm = cp->norm_adr;
- dmacfg = cp->dmacfg;
- dmabits = cp->dmabits;
- dmastat = cp->dmastat;
- dmatype = cp->dmatype;
-
- /* cancel any outstanding timer */
- if ( cp->tid > 0 ) {
- untimeout(cp->tid);
- cp->tid = 0;
- }
-
- /* ======================================
- * Reseting Interrupt and Status
- * ====================================== */
-
- /* disable any Dma and read in Xilinx status */
- Out32(adr_cfg, dmacfg | DMAREG_STAT );
- /* xil_stat = Inp32(adr_norm); */
- mbox = Inp32(adr_amcc+AMCC_OP_REG_IMB4);
-
- /* Reset Amcc Interrupts and enable interrupts again */
- Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_RST | AMCC_INTCSR_RCLR |
- AMCC_INTCSR_WCLR );
- Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_MASK);
-
-
-
- /* ===============================================
- * End of Dma Read or Write
- * =============================================== */
- if ( (mbox & AMCC_MB_EOFDMAR) || (mbox & AMCC_MB_EOFDMAW) ) {
- dmabits &= ~(DMAREG_REN | DMAREG_INTREN);
- dmabits &= ~(DMAREG_WEN | DMAREG_INTWEN );
-
- #ifdef DEBUG
- if ( mbox & AMCC_MB_EOFDMAR)
- printf ("cocoIntr: End of DMA Read\n");
- else printf ("cocoIntr: End of DMA Write\n");
- #endif
- }
-
- /* ===============================================
- * End of Chain Dma Read or Write
- * =============================================== */
- if ( (mbox & AMCC_MB_EOFPRDMAR) || (mbox & AMCC_MB_EOFPRDMAW) ) {
- dmabits &= ~(DMAREG_PREN | DMAREG_INTPREN);
- dmabits &= ~(DMAREG_PWEN | DMAREG_INTPWEN);
- dmabits &= ~(DMAREG_WEN | DMAREG_REN);
-
- #ifdef DEBUG
- if ( mbox & AMCC_MB_EOFPRDMAR )
- printf ("cocoIntr: End Prog DMA Read\n");
- else printf ("cocoIntr: End Prog DMA Write\n");
- #endif
- }
-
- cp->dmabits = dmabits;
- cp->iostat = IO_OK;
-
- switch ( cp->dmastat ) {
- /* ==============================
- * Dma to Lut
- * ============================== */
- case DMA_LUT_WAIT:
-
- #ifdef DEBUG
- printf ("cocoIntr: Waking up Dma_Lut_Wait\n");
- #endif
-
- cp->dmastat = DMA_IDLE;
- WAKE_EVENT(&cp->coco_sv);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
-
-
- /* ==================================
- * Read/Write Dma
- * ================================== */
- case DMA_READ_WAIT:
- case DMA_WRITE_WAIT:
-
- /* what we do depends on which type of Dma is done */
- switch ( cp->dmatype ) {
-
- /* chained Dma is done. Simply wake the process up */
- case DMA_PROG:
-
- #ifdef DEBUG
- printf ("cocoIntr: biodone() read/write\n");
- #endif
-
- kmem_free ( cp->chain_list,
- cp->page_no * sizeof(coco_dmapage_t) );
- alenlist_done(cp->addrList);
- cp->addrList = 0;
- cp->dmastat = DMA_IDLE;
- bp->b_resid -= cp->dmasize;
-
- biodone(cp->bp);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
-
- /* single page Dma done. Dma the next page if any */
- case DMA_SINGLE:
-
- bp->b_resid -= cp->dmasize;
- cp->page_no--;
-
- if ( cp->page_no <= 0 ) { /* no more pages */
-
- #ifdef DEBUG
- printf ("cocoIntr: No more pages to Dma\n");
- printf ("cocoIntr: biodone() read/write\n");
- #endif
-
- alenlist_done(cp->addrList);
- cp->addrList = 0;
- cp->dmastat = DMA_IDLE;
-
- biodone(cp->bp);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
- }
-
- /* get next page to DMA */
- #ifdef DEBUG
- printf ("cocoIntr: Dma next page ..left = %d\n",
- cp->page_no-1 );
- #endif
-
- if ( alenlist_get(cp->addrList, NULL, NBPP,
- &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN,
- "cocoIntr: Bad scatter-gather");
- cp->iostat = IO_ERROR;
- #ifdef DEBUG
- printf ("cocoIntr: biodone() read/write\n");
- #endif
-
- alenlist_done(cp->addrList);
- cp->addrList = 0;
- cp->dmastat = DMA_IDLE;
- bioerror (cp->bp, EIO);
- biodone(cp->bp);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
- }
- if ( cp->dmastat == DMA_READ_WAIT )
- rw = B_READ;
- else rw = B_WRITE;
- cocoStartSingleDma ( cp, p_addr, p_size, rw );
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
-
-
- } /*** switch ( cp->dmatype ) ***/
-
- /* ==========================
- * Simultaneus read/write
- * ========================== */
- case DMA_RW_WAIT:
-
- /* what we do depends on which type of Dma is done */
- switch ( cp->dmatype ) {
-
- /* chained Dma is done. Both read/write is done */
- case DMA_PROG:
- #ifdef DEBUG
- printf ("cocoIntr: Waking up Dma_RW_Wait\n");
- #endif
-
- cp->dmastat = DMA_IDLE;
- WAKE_EVENT(&cp->coco_sv);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
-
-
- /* single page Dma done. Dma the next page if any */
- case DMA_SINGLE:
-
- /* Keep transfering as long as there is data */
- if ( cp->w_page_no > 0 ||
- cp->r_page_no > 0 ||
- cp->wp_size > 0 ||
- cp->rp_size > 0 ) {
-
- #ifdef DEBUG
- printf ("cocoIntr: Dma next page, w_left = %d, r_left = %d\n", cp->w_page_no, cp->r_page_no);
- #endif
-
- err = cocoStartRWDma(cp, 0, 0, 0, 0);
- if ( err == 0 ) {
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
- }
-
- #ifdef DEBUG
- printf ("cocoIntr: error Dmaing next page\n");
- #endif
- cp->dmastat = DMA_IDLE;
- cp->iostat = IO_ERROR;
- WAKE_EVENT(&cp->coco_sv);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
- }
-
- #ifdef DEBUG
- printf ("cocoIntr: Waking up Dma_RW_Wait\n");
- #endif
-
- cp->dmastat = DMA_IDLE;
- WAKE_EVENT(&cp->coco_sv);
- COCO_UNLOCK(&cp->coco_mlock, s);
- goto get_out;
-
- } /*** switch ( cp->dmatype ) ***/
-
- } /*** switch ( cp->dmastat ) ***/
-
- get_out:
- #ifdef DEBUG
- cocoReport ( cp, "cocoIntr exit" );
- #endif
-
- return;
-
- }
-
-
- /*************************************************************************
- *** c o c o _ u n l o a d ***
- *************************************************************************
- *
- * Name: coco_unload
- *
- * Purpose: Unloads the driver.
- *
- * Returns: 0 Success or errno
- *
- *************************************************************************/
- int
- coco_unload(void)
- {
- cmn_err (CE_NOTE, "Unloading the Chameleon Driver");
- return(0);
- }
-
-
- /*************************************************************************
- *** c o c o _ u n r e g ***
- *************************************************************************
- *
- * Name: coco_unreg
- *
- * Purpose: Unregister the driver
- *
- * Returns: 0 Success or errno
- *
- *************************************************************************/
- int
- coco_unreg(void)
- {
- cmn_err (CE_NOTE, "Unregisterning Chameleon Driver");
- pciio_driver_unregister(DRIVER_PREFIX);
-
- return(0);
- }
-
-
- /*************************************************************************
- *** c o c o _ o p e n ***
- *************************************************************************
- *
- * Name: coco_open
- *
- * Purpose: Opens the card. This sample driver simply verifies that
- * the card's info structure can be retrieved and checks
- * the card's Base_Register.
- *
- * Returns: 0 = Success, or errno.
- *
- *************************************************************************/
- int
- coco_open(dev_t *devp, int flag, int otyp, cred_t *cred)
- {
- register card_t *cp;
- register vertex_hdl_t vhdl;
- __userabi_t uabi;
-
- /* Get the vertex handle and pointer to card's info */
- vhdl = dev_to_vhdl ( *devp );
- if (vhdl == NULL){
- cmn_err(CE_WARN, "coco_open: dev_to_vhdl returns NULL");
- return(EIO);
- }
-
- cp = (card_t *)device_info_get ( vhdl );
-
-
- /* some error checking first */
- if ( !(cp->status & CARD_ATTACHED) ) {
- cmn_err (CE_WARN, "coco_open: Driver is not attached");
- return (ENODEV);
- }
-
- if ( cp->status & CARD_OPEN) {
- cmn_err (CE_WARN, "coco_open: Device is busy");
- return (EBUSY);
- }
-
- cocoReset(cp); /* reset the board */
- cp->status |= CARD_OPEN;
-
- /* default values */
- cp->dmatype = DMA_SINGLE;
- cp->dmacmd = COCO_TRANSP;
-
- /* get user's ABI for correct struct usage in coco_ioctl() */
- userabi(&uabi);
- if ( uabi.uabi_szptr == 8 )
- cp->user_abi = ABI_IRIX5_64;
- else cp->user_abi = ABI_IRIX5_N32;
-
- /* initialize our mutex lock and sv_t for sleep/wake */
- COCO_LOCK_INIT(&cp->coco_mlock);
- SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
-
-
- /* zero out all time measurements */
- bzero ( &cp->start_time, sizeof(struct timespec) );
- bzero ( &cp->intr_time, sizeof(struct timespec) );
- bzero ( &cp->call_time, sizeof(struct timespec) );
- bzero ( &cp->ret_time, sizeof(struct timespec) );
-
- return(0);
- }
-
-
-
-
- /*************************************************************************
- *** c o c o _ c l o s e ***
- *************************************************************************
- *
- * Name: coco_close
- *
- * Purpose: Closes the card. This sample driver's close statement
- * prints out the addresses and Base_Register's value for
- * verification.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- int
- coco_close(dev_t dev, int flag, int otyp, cred_t *cred)
- {
- register card_t *cp;
- register vertex_hdl_t vhdl;
-
- /* get the vertex handle and pointer to card's info */
- vhdl = dev_to_vhdl ( dev );
-
- cp = (card_t *)device_info_get ( vhdl );
- cp->status &= ~CARD_OPEN;
-
- /* zero out all time measurements */
- bzero ( &cp->start_time, sizeof(struct timespec) );
- bzero ( &cp->intr_time, sizeof(struct timespec) );
- bzero ( &cp->call_time, sizeof(struct timespec) );
- bzero ( &cp->ret_time, sizeof(struct timespec) );
-
-
- return(0);
- }
-
-
- /*************************************************************************
- *** c o c o _ m a p ***
- *************************************************************************
- *
- * Name: coco_map
- *
- * Purpose: Allocate a piece of continious memory and map it to user's
- * address space.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- int
- coco_map ( dev_t dev, vhandl_t *vh, off_t offset, size_t len, uint_t prot )
- {
- register int ret;
- register int s;
- register caddr_t kv;
- register vertex_hdl_t vhdl;
- register card_t *cp;
-
- /* get the vertex handle and pointer to card's info */
- vhdl = dev_to_vhdl ( dev );
- cp = (card_t *)device_info_get ( vhdl );
-
- if ( cp->mappedkv == (caddr_t)NULL ) {
- cmn_err (CE_NOTE, "coco_map: Not memory for mapping");
- return (ENOMEM);
- }
-
- if ( len > (size_t)(cp->mappedkvlen - LESS_MAP) ) {
- cmn_err (CE_NOTE, "coco_map: Only %d bytes available for map, requested %d bytes", cp->mappedkvlen - LESS_MAP, len );
- return (ENOMEM);
- }
-
- ret = v_mapphys( vh, (void *)cp->mappedkv, len );
-
- if ( ret > 0 ) {
- cmn_err (CE_WARN, "coco_map: Could not map, ret = %d", ret );
- return (ret);
- }
-
- /* save for later */
- cp->vhandl = vh;
-
- cmn_err (CE_NOTE, "coco_map: mapped %d bytes", len );
- return (ret);
- }
-
- /*************************************************************************
- *** c o c o _ u n m a p ***
- *************************************************************************
- *
- * Name: coco_unmap
- *
- * Purpose: Unmap the kernel buffer we allocated before.
- *
- * Returns: Always 0. There is nothing to free up here.
- *
- *************************************************************************/
- int
- coco_unmap ( dev_t dev, vhandl_t *vh )
- {
- return (0);
- }
-
-
- /*************************************************************************
- *** c o c o _ i o c t l ***
- *************************************************************************
- *
- * Name: coco_ioctl
- *
- * Purpose: Handles user Ioctl command. These commands can be
- * found in coco_user.h.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- int
- coco_ioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *cred,
- int *rvalp )
- {
- register card_t *cp;
- register vertex_hdl_t vhdl;
- register uint_t *tmp_ibuf;
- register int tot_bytes, err, i, s;
- uint_t tmp_int;
- coco_buf_t coco_buf;
- coco_rw_t coco_rw;
- coco_mode_t coco_mode;
- coco_cmd_t coco_cmd;
- coco_convert_t coco_convert;
- uint_t dmaRegs[DMA_REGS];
- coco_time_t coco_time;
- struct timespec tv;
-
- #ifdef DEBUG
- printf ("\ncoco_ioctl: ---> command = %s [0x%x]\n",
- cocoIoctlStr(cmd), cmd );
- #endif
-
- /* get the vertex handle and pointer to card's info */
- vhdl = dev_to_vhdl ( dev );
-
- cp = (card_t *)device_info_get ( vhdl );
-
- if ( cp == (card_t *)NULL ) {
- cmn_err (CE_WARN, "coco_ioctl: Card_t is NULL");
- return (EIO);
- }
-
- /* is device opened ? */
- if (!( cp->status & CARD_OPEN) ) {
- cmn_err (CE_NOTE, "coco_ioctl: Device is not opened");
- return (EIO);
- }
-
- /* ===================
- * Ioctl commands
- * =================== */
-
- switch ( cmd ) {
-
- /* ===========================================
- * Make Hardware Graph nodes off of /hw
- * =========================================== */
- case COCO_MKHWGR:
- cocoMakeHwGraph ( cp );
- break;
-
- /* ==================================
- * Return Srart and Return time
- * ================================== */
- case COCO_GET_TIME:
- cocoDiffTime ( &cp->call_time, &cp->ret_time, &tv );
- cocoConvTime ( &cp->call_time, &coco_time.start_time );
- cocoConvTime ( &cp->ret_time, &coco_time.end_time );
- cocoConvTime ( &tv, &coco_time.diff_time );
- if ( copyout((caddr_t)&coco_time, (caddr_t)arg,
- sizeof(coco_time_t)) )
- return (EFAULT);
- break;
-
- /* ==================================
- * Report Map size available
- * ================================== */
- case COCO_MAP_SIZE:
- tmp_int = cp->mappedkvlen - LESS_MAP;
- if ( copyout((caddr_t)&tmp_int, (caddr_t)arg,
- sizeof(uint_t) ) )
- return (EFAULT);
-
- break;
-
- /* ==============================
- * Board Identification
- * ============================== */
- case COCO_ISPCI:
- *rvalp = 1;
- break;
-
- /* ==============================
- * Reset the board
- * ============================== */
- case COCO_RESET:
- cocoReset(cp);
- break;
-
- /* ==============================
- * Set DMA Command
- * ============================== */
- case COCO_SETCMD_TRANSP:
- cp->dmacmd = COCO_TRANSP;
- break;
-
- case COCO_SETCMD_CONVERT:
- cp->dmacmd = COCO_CONVERT;
- break;
-
- /* ===============================
- * Issue a Command
- * =============================== */
- case COCO_COMMAND:
- if ( copyin ( (char *)arg, &coco_cmd,
- sizeof(coco_cmd_t) ) )
- return (EFAULT);
-
- cocoCommand ( cp, coco_cmd.cmd, coco_cmd.datav );
- break;
-
- /* ===================================
- * Set DMA type (Prog or Single)
- * =================================== */
- case COCO_SET_SINGLE_DMA:
- cp->dmatype = DMA_SINGLE;
- break;
-
- case COCO_SET_PROG_DMA:
- cp->dmatype = DMA_PROG;
- break;
-
- /* ===============================
- * Set up Chameleon Mode
- * =============================== */
- case COCO_SET_MODE:
- if ( copyin ( (char *)arg, &coco_mode,
- sizeof(coco_mode_t) ) )
- return (EFAULT);
-
- cocoSetMode ( cp, coco_mode.mode, coco_mode.swap,
- coco_mode.slice, coco_mode.flag );
- break;
-
- /* =================================
- * Read Chameleon Mode
- * ================================= */
- case COCO_READ_MODE:
- tmp_int = cocoReadMode (cp);
- if ( copyout((char *)&tmp_int, arg, sizeof(uint_t) ) )
- return (EFAULT);
- break;
-
-
- /* ===============================
- * Raw write Buffer to Fifo *
- * =============================== */
- case COCO_RAW_WRITEB_FIFO:
-
- if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
- return(EFAULT);
-
- if ( coco_buf.buf_size == 0 )
- return (EINVAL);
-
- /*
- * the data is in coco_buf.buf in user address
- * space. Move it to kernel address space and dump it
- * to the board.
- */
- tot_bytes = coco_buf.buf_size * sizeof(uint_t);
- tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
- if ( tmp_ibuf == (uint_t *)NULL )
- return (ENOMEM);
-
- if ( copyin((caddr_t)coco_buf.buf, (caddr_t)tmp_ibuf,
- tot_bytes) ) {
- kmem_free (tmp_ibuf, tot_bytes);
- return(EFAULT);
- }
-
- cocoBufOut (cp, tmp_ibuf, coco_buf.buf_size);
- kmem_free (tmp_ibuf, tot_bytes );
- break;
-
- /* ===============================
- * Raw Read Buffer from Fifo *
- * =============================== */
- case COCO_RAW_READB_FIFO:
-
- if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
- return(EFAULT);
-
- if ( coco_buf.buf_size == 0 )
- return (EINVAL);
-
- /*
- * the buffer to be filled is coco_buf.buf and
- * it can contain coco_buf.buf_size 32-bit values.
- * Read that many into our own temp buffer and move them
- * to user-address space.
- */
- tot_bytes = coco_buf.buf_size * sizeof(uint_t);
- tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
- if ( tmp_ibuf == (uint_t *)NULL )
- return (ENOMEM);
-
- cocoBufIn(cp, tmp_ibuf, coco_buf.buf_size);
-
- if ( copyout ( (caddr_t)tmp_ibuf, (caddr_t)coco_buf.buf,
- tot_bytes)) {
- kmem_free ( tmp_ibuf, tot_bytes );
- return (EFAULT);
- }
-
- kmem_free ( tmp_ibuf, tot_bytes );
- break;
-
- /* =============================
- * Read 32-bit from Fifo
- * ============================= */
- case COCO_RAW_READ_FIFO:
-
- tmp_int = cocoReadAmccFifo(cp);
- if ( copyout((char *)&tmp_int, arg, sizeof(uint_t) ) )
- return(EFAULT);
- break;
-
- /* =============================
- * Write 32-bit value to Fifo
- * ============================= */
- case COCO_RAW_WRITE_FIFO:
-
- if ( copyin(arg, (char *)&tmp_int, sizeof(uint_t) ) )
- return(EFAULT);
-
- cocoCommand(cp, COCO_TRANSP, tmp_int );
- break;
-
- /* =============================
- * Test Fifo data path
- * ============================= */
- case COCO_FIFO_TEST:
- return (cocoFifoTest(cp, 1) );
-
- /* ===============================
- * Read DMA Registers
- * =============================== */
- case COCO_RAW_READ_DMA:
- cocoReadDmaRegs(cp, &dmaRegs[0]);
- for ( i = 0; i < DMA_REGS; i++)
- printf ("read[%d] = 0x%x\n", i, dmaRegs[i]);
-
- if ( copyout((char *)&dmaRegs[0], arg,
- sizeof(dmaRegs) ) )
- return (EFAULT);
- break;
-
- /* ===============================
- * Write DMA Registers
- * =============================== */
- case COCO_RAW_WRITE_DMA:
- if ( copyin(arg, (char *)&dmaRegs[0],
- sizeof(dmaRegs) ) )
- return (EFAULT);
- for ( i = 0; i < DMA_REGS; i++)
- printf ("write[%d] = 0x%x\n", i, dmaRegs[i]);
- cocoWriteDmaRegs(cp, &dmaRegs[0] );
- break;
-
- /* =============================
- * DMA Regsters Access Test
- * ============================= */
- case COCO_DMAREGS_TEST:
- return ( cocoDmaRegsTest(cp) );
-
- /* ===============================
- * Read Address Register
- * =============================== */
- case COCO_READ_ADDR:
- tmp_int = cocoReadAddr(cp);
- if ( copyout((char *)&tmp_int, arg, sizeof(uint_t) ) )
- return (EFAULT);
- break;
-
- /* ===============================
- * Write Address Register
- * =============================== */
- case COCO_SET_ADDR:
- if ( copyin(arg, (char *)&tmp_int, sizeof(uint_t) ) )
- return(EFAULT);
- cocoSetAddr(cp, tmp_int);
- break;
-
- /* ===============================
- * Internal RAM Test
- * =============================== */
- case COCO_INTRAM_TEST:
- return ( cocoIntRamTest(cp) );
-
- /* ===============================
- * External RAM Test
- * =============================== */
- case COCO_EXTRAM_TEST:
- return ( cocoExtRamTest(cp) );
-
- /* ==============================
- * Read Internal LUTs
- * ============================== */
- case COCO_READ_RAMIL:
- case COCO_READ_RAMIH:
- case COCO_READ_RAMO:
-
- if ( coco_copyin_buf(cp, arg, &coco_buf) )
- return(EFAULT);
-
- if ( coco_buf.buf_size == 0)
- return (EINVAL);
-
- if ( coco_buf.buf_size > INT_RAM_SIZE )
- return (EINVAL);
-
- /* allocate a buffer to hold Ram's contents */
- tot_bytes = coco_buf.buf_size * sizeof(uint_t);
- tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
-
- if ( tmp_ibuf == (uint_t *)NULL )
- return(EFAULT);
-
- /* read in Ram's contents into the buffer */
- cocoReadIntRam(cp, tmp_ibuf, cmd, coco_buf.buf_size );
-
- /* copy the kernel buffer to user's buffer */
- if ( copyout((void *)tmp_ibuf, (void *)coco_buf.buf,
- tot_bytes) ) {
- kmem_free ( (caddr_t)tmp_ibuf, tot_bytes );
- return (EFAULT);
- }
-
- kmem_free ( (void *)tmp_ibuf, tot_bytes );
- break;
-
-
-
- /* ================================
- * Write Internal LUTs
- * ================================ */
- case COCO_FILL_RAMIL:
- case COCO_FILL_RAMIH:
- case COCO_FILL_RAMO:
-
- if ( coco_copyin_buf(cp, arg, &coco_buf) )
- return(EFAULT);
-
- if ( coco_buf.buf_size == 0)
- return (EINVAL);
-
- if ( coco_buf.buf_size > 2 * INT_RAM_SIZE )
- return (EINVAL);
-
- /* allocate a buffer to hold user's data */
- tot_bytes = coco_buf.buf_size * sizeof(uint_t);
- tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
-
- if ( tmp_ibuf == (uint_t *)NULL )
- return(EFAULT);
-
- /* copy user's buffer to our own */
- if ( copyin((void *)coco_buf.buf, (void *)tmp_ibuf,
- tot_bytes ) ) {
- kmem_free ( tmp_ibuf, tot_bytes );
- return(EFAULT);
- }
-
- /* fill the Ram with data just moved over */
- cocoWriteIntRam ( cp, tmp_ibuf, cmd,
- coco_buf.buf_size );
-
- kmem_free ( tmp_ibuf, tot_bytes );
- break;
-
- /* ==============================
- * Read External LUT
- * ============================== */
- case COCO_READ_RAML:
-
- if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
- return(EFAULT);
-
- if ( coco_buf.buf_size == 0)
- return (EINVAL);
-
- if ( coco_buf.buf_size > EXT_RAM_SIZE )
- return (EINVAL);
-
- /* allocate a buffer to hold External Ram's contents */
- tot_bytes = coco_buf.buf_size * sizeof(uint_t);
- tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
-
- if ( tmp_ibuf == (uint_t *)NULL )
- return(EFAULT);
-
- /* fill the buffer with Ext. Ram's contents */
- cocoReadExtRam(cp, tmp_ibuf, coco_buf.buf_size);
-
- /* copy the data to user's buffer */
- if ( copyout((caddr_t)tmp_ibuf, (caddr_t)coco_buf.buf,
- tot_bytes) ) {
- kmem_free ( tmp_ibuf, tot_bytes );
- return (EFAULT);
- }
-
- kmem_free ( tmp_ibuf, tot_bytes );
- break;
-
-
- /* ==============================
- * Write External LUT
- * ============================== */
- case COCO_FILL_RAML:
-
- if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
- return(EFAULT);
-
- if ( coco_buf.buf_size == 0)
- return (EINVAL);
-
- if ( coco_buf.buf_size > 2 * EXT_RAM_SIZE )
- return (EINVAL);
-
- /* allocate a buffer to hold user's data */
- tot_bytes = coco_buf.buf_size * sizeof(uint_t);
- tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
-
- if ( tmp_ibuf == (uint_t *)NULL )
- return(EFAULT);
-
- /* copy user's buffer to our own */
- if ( copyin((caddr_t)coco_buf.buf, (caddr_t)tmp_ibuf,
- tot_bytes ) ) {
- kmem_free ( tmp_ibuf, tot_bytes );
- return(EFAULT);
- }
-
- /* fill the Ram with data just moved over */
- cocoWriteExtRam ( cp, tmp_ibuf, coco_buf.buf_size);
-
- kmem_free ( tmp_ibuf, tot_bytes );
- break;
-
- /* ==========================================
- * Chameleon Single pixel Conversion
- * ========================================== */
- case COCO_CONVERT_PIXLE:
-
- /* read in the coco_convert struct from user's space */
- if ( copyin(arg, (char *)&tmp_int, sizeof(uint_t) ) )
- return (EFAULT);
-
- cocoConvert ( cp, tmp_int );
- break;
-
- /* ============================================
- * Chameleon Single pixel Conversion Test
- * ============================================ */
- case COCO_CONVERT_TEST:
-
- /* read in the coco_convert struct from user's space */
- if ( copyin(arg, (char *)&coco_convert,
- sizeof(coco_convert_t) ) )
- return (EFAULT);
-
- cocoConvertTest ( cp, &coco_convert );
-
- /* copy the structure back */
- if ( copyout((char *)&coco_convert, arg,
- sizeof(coco_convert_t) ) )
- return(EFAULT);
- break;
-
- /* ================================================
- * DMA fill of LUTs (Internals and External)
- * ================================================ */
- case COCO_BLOCK_FILL_RAMIL:
- case COCO_BLOCK_FILL_RAMIH:
- case COCO_BLOCK_FILL_RAMO:
- case COCO_BLOCK_FILL_RAML:
-
- /* read in coco_buf_t struct..all we need is there */
- if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
- return(EFAULT);
-
- /* empty buffer ? */
- if ( coco_buf.buf_size == 0 )
- return (EINVAL);
-
- /* DMA the data and report back the result */
- nanotime ( &cp->call_time );
- err = cocoDmaToLuts(cp, &coco_buf, cmd );
- nanotime ( &cp->ret_time );
-
- #ifdef DEBUGTIME
- cocoReportTime ( "cocoDmaToLut", cp, 1 );
- #endif
-
- return (err);
-
- /* ================================================
- * Simultaneous Read/Write DMA
- * ================================================ */
- case COCO_RW_BUF:
-
- /* read in coco_rw_t struct..all we need is there */
- if ( coco_copyin_rw(cp, (caddr_t)arg, &coco_rw) )
- return(EFAULT);
-
-
- if ( coco_rw.buf_size <= 0 ) {
- cmn_err (CE_NOTE,
- "cocoIoctl: Bad Sim.read/write buff size of %d\n",
- coco_rw.buf_size );
- return(EINVAL);
- }
-
- nanotime ( &cp->call_time );
- err = cocoReadWrite(cp, &coco_rw );
- nanotime ( &cp->ret_time );
-
- #ifdef DEBUGTIME
- cocoReportTime ( "cocoReadWrite", cp, 1 );
- #endif
-
- if ( err != 0 )
- cmn_err (CE_NOTE,
- "cocoIoctl: cocoReadWrite reported error %d\n", err );
-
- return (err);
-
- default:
- cmn_err ( CE_WARN,
- "coco_ioctl: Unknown cmd 0x%x\n", cmd );
- return (EINVAL);
-
- } /*** end switch **/
-
- return(0);
- }
-
- /*************************************************************************
- *** c o c o _ r e a d ***
- *************************************************************************
- *
- * Name: coco_read
- *
- * Purpose: Read entry routine. DMAs data from the board to the
- * user's address space.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- int
- coco_read( dev_t dev, uio_t *uiop, cred_t *crp)
- {
- register card_t *cp;
- register vertex_hdl_t vhdl;
- register int ret;
-
- /* get to the board's info structure */
- vhdl = dev_to_vhdl ( dev );
-
- cp = (card_t *)device_info_get ( vhdl );
- cp->bp = (buf_t *)NULL;
- cp->addrList = 0;
- cp->dmastat = 0;
- cp->dmabits = 0;
- bzero ( &cp->start_time, sizeof(struct timespec) );
- bzero ( &cp->intr_time, sizeof(struct timespec) );
- bzero ( &cp->call_time, sizeof(struct timespec) );
- bzero ( &cp->ret_time, sizeof(struct timespec) );
-
- /* do the transfer */
- nanotime ( &cp->call_time );
- ret = uiophysio ( cocoStrategy, NULL, dev, B_READ, uiop );
- nanotime ( &cp->ret_time );
-
- if ( cp->addrList ) {
- alenlist_done(cp->addrList);
- cp->addrList = 0;
- }
-
- #ifdef DEBUGTIME
- cocoReportTime ( "cocoRead", cp, 1);
- #endif
-
- return ( ret );
- }
-
- /*************************************************************************
- *** c o c o _ w r i t e ***
- *************************************************************************
- *
- * Name: coco_write
- *
- * Purpose: Write entry routine. DMAs data from user's address space
- * to the board.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- int
- coco_write( dev_t dev, uio_t *uiop, cred_t *crp)
- {
- register card_t *cp;
- register vertex_hdl_t vhdl;
- register int ret;
-
- /* get to the board's info structure */
- vhdl = dev_to_vhdl ( dev );
- cp = (card_t *)device_info_get ( vhdl );
- cp->bp = (buf_t *)NULL;
- cp->dmastat = 0;
- cp->dmabits = 0;
- cp->addrList = 0;
- bzero ( &cp->start_time, sizeof(struct timespec) );
- bzero ( &cp->intr_time, sizeof(struct timespec) );
- bzero ( &cp->call_time, sizeof(struct timespec) );
- bzero ( &cp->ret_time, sizeof(struct timespec) );
-
- /* do the transfer */
- nanotime ( &cp->call_time );
- ret = uiophysio ( cocoStrategy, NULL, dev, B_WRITE, uiop );
- nanotime ( &cp->ret_time );
-
- if ( cp->addrList ) {
- alenlist_done(cp->addrList);
- cp->addrList = 0;
- }
-
- #ifdef DEBUGTIME
- cocoReportTime ( "cocoWrite", cp, 1);
- #endif
-
- return ( ret );
-
- }
-
-
- /*************************************************************************
- *** c o c o _ e r r o r ***
- *************************************************************************
- *
- * Name: coco_error
- *
- * Purpose: Traps PCI bus error.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
-
- static int
- coco_error(void *einfo,
- int error_code,
- ioerror_mode_t mode,
- ioerror_t *ioerror)
- {
- cmn_err (CE_NOTE, "coco_error: called");
- printf ("error_code = %d (0x%x)\n", error_code, error_code );
- printf ("io_errortype = %d\n", ioerror->ie_errortype );
- printf ("io_busspace = %d\n", ioerror->ie_busspace );
- printf ("io_busaddr = 0x%x\n", ioerror->ie_busaddr );
- printf ("io_memaddr = 0x%x\n", ioerror->ie_memaddr );
- printf ("error_mode = %d (0x%x)\n", mode, mode );
- return(IOERROR_UNHANDLED);
- }
-
-
-
- /*
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
- ~~~~~~~~~~~~~ S u p p o r t i n g R o u t i n e s ~~~~~~~~~~~~~~~~
- ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
- /*************************************************************************
- *** c o c o S t r a t e g y ***
- *************************************************************************
- *
- * Name: cocoStrategy
- *
- * Purpose: Strategy routine. It actually handles read/write
- * and starts the DMA. It is called by uiophysio() kernel
- * routine.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- static int
- cocoStrategy ( buf_t *bp )
- {
- register card_t *cp;
- register vertex_hdl_t vhdl, conn;
- register coco_dmapage_t *dmaPg;
- register int i, ret, rw, tot_bytes;
- register int s;
- register uint_t fill_bits;
- alenlist_t addrList2;
- size_t p_size;
- alenaddr_t p_addr;
- iopaddr_t p_dmaPg;
-
- if ( !BP_ISMAPPED(bp) ) {
- cmn_err (CE_NOTE, "cocoStrategy: Unmapped buf_t used\n");
- bioerror ( bp, EIO);
- biodone (bp);
- return(EIO);
- }
-
- /* get to the board's info structure */
- vhdl = dev_to_vhdl ( bp->b_edev );
- cp = (card_t *)device_info_get ( vhdl );
- conn = cp->conn;
-
- /* clear error and save bp */
- bioerror(bp, 0);
- bp->b_resid = bp->b_bcount;
- cp->bp = bp;
-
- if ( bp->b_flags & B_READ )
- rw = B_READ; /* board -> mem */
- else rw = B_WRITE; /* mem -> board */
-
- /* create scatter-gather list */
- addrList2 = buf_to_alenlist ((alenlist_t)NULL, bp, AL_NOCOMPACT);
- cp->addrList = pciio_dmatrans_list ( conn, 0, addrList2, 0);
- if ( cp->addrList == (alenaddr_t)NULL ) {
- cmn_err (CE_NOTE, "cocoStrategy: Cannot create alenlist");
- bioerror ( bp, EIO);
- biodone (bp);
- return(EIO);
- }
-
- #if 0
- cp->page_no = alenlist_size ( cp->addrList );
- #endif
- cp->page_no = cocoAlenlistSize ( cp->addrList );
-
- /* set the command to be executed during Dma */
- cp->dmabits = cp->dmacmd;
- cocoPrepAmcc ( cp );
-
- /* =======================
- * Chained DMA
- * ======================= */
- if ( cp->dmatype == DMA_PROG ) {
-
- dmaPg = cocoMakeChain ( cp, cp->addrList, cp->page_no );
- if ( dmaPg == (coco_dmapage_t *)NULL ) {
- cmn_err (CE_NOTE,
- "cocoStrategy: Error creating chain list");
- alenlist_done (cp->addrList);
- bioerror (bp, EIO);
- biodone (bp);
- return(EIO);
- }
-
- tot_bytes = cp->page_no * sizeof(coco_dmapage_t);
- p_dmaPg = pciio_dmatrans_addr ( conn, 0,
- kvtophys(dmaPg), tot_bytes, 0);
-
- /* write back cache for chain list */
- dki_dcache_wbinval ( dmaPg, tot_bytes );
-
- /* start the Chained Dma */
- s = COCO_LOCK(&cp->coco_mlock);
- cocoStartProgDma ( cp, p_dmaPg, bp->b_bcount, rw );
-
- if ( rw == B_READ )
- cp->dmastat = DMA_READ_WAIT;
- else cp->dmastat = DMA_WRITE_WAIT;
- cp->chain_list = (caddr_t)dmaPg;
-
- /* so we dont wait forever for an interrupt */
- cp->tid = itimeout(cocoTimeOut, cp, RW_TIMER,
- pltimeout, 0, 0, 0);
-
- COCO_UNLOCK(&cp->coco_mlock, s);
- return(0);
- }
-
-
- /* ===========================
- * Single page DMA
- * =========================== */
-
- /* get a page to DMA */
- if ( alenlist_get(cp->addrList, NULL, NBPP,
- &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN, "cocoDma: Not enough Memory");
- alenlist_done(cp->addrList);
- bioerror ( bp, EIO);
- biodone(bp);
- return(EIO);
- }
-
- /* single dma, memory -> board */
-
- s = COCO_LOCK(&cp->coco_mlock);
- cocoStartSingleDma ( cp, p_addr, p_size, rw );
-
- if ( rw == B_READ )
- cp->dmastat = DMA_READ_WAIT;
- else cp->dmastat = DMA_WRITE_WAIT;
- cp->chain_list = NULL;
-
- /* so we dont wait forever for an interrupt */
- cp->tid = itimeout(cocoTimeOut, cp, RW_TIMER,
- pltimeout, 0, 0, 0);
-
- COCO_UNLOCK(&cp->coco_mlock, s);
- return(0);
-
- }
-
- /*************************************************************************
- *** c o c o R e a d W r i t e ***
- *************************************************************************
- *
- * Name: cocoReadWrite
- *
- * Purpose: Starts simultaneous Read and Write DMA to user's space.
- *
- * Returns: 0 for success, or errno
- *
- *************************************************************************/
- static int
- cocoReadWrite ( card_t *cp, coco_rw_t *rw )
- {
- register caddr_t dum;
- register caddr_t w_kvaddr, r_kvaddr;
- register uint_t *cache_line, pci_flags;
- register int r_page_no, w_page_no, err, i, cache_bytes;
- register int s;
- register int tot_r_cache, tot_w_cache, tot_bytes;
- register int coco_adjust_chain, tot_wrong;
- coco_dmapage_t *w_dmaPg, *r_dmaPg;
- alenlist_t addrList2;
- iopaddr_t pr_dmaPg, pw_dmaPg;
-
- cocoResetAmcc(cp);
- cocoPrepAmcc(cp);
-
- pci_flags = PCIIO_WORD_VALUES | PCIIO_DMA_DATA;
-
- tot_bytes = rw->buf_size * sizeof(uint_t);
- coco_adjust_chain = rw->adjust_chain;
-
- #ifdef DEBUG
- printf ("w_buf = 0x%x, r_buf = 0x%x, tot_bytes = %d, NBPP = %d\n",
- rw->w_buf, rw->r_buf, tot_bytes, NBPP );
- #endif
-
- /* =========================================================
- * Scatter-Gather list for Write buffer (mem -> board)
- * ========================================================= */
-
-
- /* lock user's pages in memory for DMA */
- err = cocoLockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE);
- if ( err ) {
- cmn_err (CE_WARN, "cocoReadWrite: Cannot lock user's pages");
- return (err);
- }
-
- /*
- * write back and invalidate the data for mem->board
- * adjust the address for current data cache size
- */
- dki_dcache_wbinval ( rw->w_buf, tot_bytes );
-
- /* create scatter-gather list of user's buffer */
- addrList2 = uvaddr_to_alenlist( (alenlist_t)NULL, (caddr_t)rw->w_buf,
- (size_t)tot_bytes, 0 );
-
- /* did we make it ? */
- if ( addrList2 == (alenlist_t)NULL ) {
- cmn_err (CE_WARN, "cocoreadWrite: cannot create Wrt alenlist");
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
- return (EIO);
- }
-
- /* map it to PCI bus address space */
- cp->w_addrList = pciio_dmatrans_list ( cp->conn, 0, addrList2,
- pci_flags );
-
- if ( cp->w_addrList == (alenlist_t)NULL ) {
- cmn_err (CE_WARN, "cocoreadWrite: cannot map Write alenlist");
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
- return (EIO);
- }
-
- #if 0
- w_page_no = alenlist_size ( cp->w_addrList );
- #endif
-
- w_page_no = cocoAlenlistSize ( cp->w_addrList );
- cp->w_page_no = w_page_no;
-
- #ifdef DEBUG
- cocoShowAlenlist ( "Write Alenlist", cp->w_addrList );
- printf ("w_page_no = %d\n", w_page_no );
- #endif
-
- /* =========================================================
- * Scatter-Gather list for Read buffer ( board -> mem )
- * ========================================================= */
-
- /* lock user's pages in memory for DMA */
- err = cocoLockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
- if ( err ) {
- cmn_err (CE_WARN, "cocoReadWrite: Cannot lock user's pages");
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
- return (err);
- }
-
- /*
- * Invalidate the cache for board->mem
- * adjust the address for current data cache line size
- */
- dki_dcache_inval ( rw->r_buf, tot_bytes );
-
- /* create scatter-gather list */
- addrList2 = uvaddr_to_alenlist( (alenlist_t)NULL, (caddr_t)rw->r_buf,
- (size_t)tot_bytes, 0);
-
-
- /* did we make it ? */
- if ( addrList2 == (alenlist_t)NULL ) {
- cmn_err (CE_WARN, "cocoreadWrite: cannot create Rd alenlist");
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
- cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
- return (EIO);
- }
-
- cp->r_addrList = pciio_dmatrans_list ( cp->conn, 0, addrList2,
- pci_flags );
-
- if ( cp->r_addrList == (alenlist_t)NULL ) {
- cmn_err (CE_WARN, "cocoreadWrite: cannot map Read alenlist");
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
- cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
- return (EIO);
- }
-
- #if 0
- r_page_no = alenlist_size ( cp->r_addrList );
- #endif
- r_page_no = cocoAlenlistSize ( cp->r_addrList );
- cp->r_page_no = r_page_no;
-
- #ifdef DEBUG/
- cocoShowAlenlist ( "Read Alenlist", cp->r_addrList );
- printf ("r_page_no = %d\n", r_page_no );
- #endif
-
- /* assume Single Dma type */
- w_dmaPg = (coco_dmapage_t *)NULL;
- r_dmaPg = (coco_dmapage_t *)NULL;
-
- /* ======================================================
- * Chain DMA - Prepare chain list for read and write
- * ====================================================== */
- if ( cp->dmatype == DMA_PROG ) {
-
- /* need to adjust read/write byte counts */
- if ( (coco_adjust_chain == 1) &&
- (rw->r_buf != rw->w_buf) ) {
- err = cocoMakeChainRW ( cp, &w_dmaPg, &r_dmaPg );
- if ( err ) {
- cmn_err (CE_WARN,
- "cocoReadWrite: Could not make Chain List, err = %d",
- err );
- cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes,
- B_READ);
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes,
- B_WRITE);
- alenlist_done(cp->r_addrList);
- alenlist_done(cp->w_addrList);
- return (err);
- }
- }
-
- /* no need to adjust read/write byte counts */
- else {
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Prepare Chain List for Write
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- w_dmaPg = cocoMakeChain ( cp, cp->w_addrList, w_page_no );
- if ( w_dmaPg == (coco_dmapage_t *)NULL ) {
- cmn_err (CE_NOTE,
- "cocoReadWrite: Error creating chain list");
- cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes,
- B_READ);
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes,
- B_WRITE);
-
- alenlist_done(cp->r_addrList);
- alenlist_done(cp->w_addrList);
- return(EIO);
- }
-
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Prepare Chain List for Read
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- r_dmaPg = cocoMakeChain ( cp, cp->r_addrList, r_page_no );
- if ( r_dmaPg == (coco_dmapage_t *)NULL ) {
- cmn_err (CE_NOTE,
- "cocoReadWrite: Error creating chain list");
- cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes,
- B_READ);
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes,
- B_WRITE);
-
- alenlist_done(cp->r_addrList);
- alenlist_done(cp->w_addrList);
- kmem_free ( w_dmaPg,
- w_page_no * sizeof(coco_dmapage_t));
- return(EIO);
- }
- }
-
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Map to PCI and cache management
- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /* map Write chain list */
- if ( coco_adjust_chain == 1 )
- tot_w_cache = w_page_no * CHAIN_FACTOR *
- sizeof(coco_dmapage_t);
- else tot_w_cache = w_page_no * sizeof(coco_dmapage_t);
-
- pw_dmaPg = pciio_dmatrans_addr ( cp->conn, 0,
- kvtophys(w_dmaPg),
- tot_w_cache, 0);
-
- #ifdef DEBUG
- cocoShowChain( "Write Chain list", w_dmaPg );
- #endif
-
- /* write back the cache for this chain list */
- dki_dcache_wbinval ( w_dmaPg, tot_w_cache );
-
- /* map Read chain list */
- if ( coco_adjust_chain == 1 )
- tot_r_cache = r_page_no * CHAIN_FACTOR *
- sizeof(coco_dmapage_t);
- else tot_r_cache = r_page_no * sizeof(coco_dmapage_t);
-
- pr_dmaPg = pciio_dmatrans_addr ( cp->conn, 0,
- kvtophys(r_dmaPg),
- tot_r_cache, 0 );
- #ifdef DEBUG
- cocoShowChain( "Read Chain List", r_dmaPg );
- #endif
-
- /* write back the cache for this chain list */
- dki_dcache_wbinval ( r_dmaPg, tot_r_cache );
-
- }
-
- /* initialize our DMA event semaphore */
- SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
-
- cp->iostat = IO_OK;
- cp->dmabits = cp->dmacmd;
- cp->wp_addr = (alenaddr_t)0;
- cp->rp_addr = (alenaddr_t)0;
- cp->wp_size = 0;
- cp->rp_addr = 0;
-
- s = COCO_LOCK(&cp->coco_mlock);
- err = cocoStartRWDma( cp, pw_dmaPg, tot_bytes, pr_dmaPg, tot_bytes);
- if ( err == 0 ) {
- SLEEP_EVENT(&cp->coco_sv, &cp->coco_mlock, s);
-
- if ( cp->iostat == IO_OK ) {
- #ifdef DEBUG
- printf ("cocoReadWrite: woken up\n");
- #endif
- }
-
- if ( cp->iostat == IO_TIME ) {
- cmn_err (CE_NOTE, "cocoReadWrite: Timed out");
-
- #ifdef DEBUG
- cocoDumpAmcc(cp);
- #endif
-
- err = ETIME;
- }
- if ( cp->iostat == IO_ERROR ) {
- cmn_err (CE_NOTE, "cocoReadWrite: IO Error");
- err = EIO;
- }
-
- }
- else {
- COCO_UNLOCK(&cp->coco_mlock, s);
- cmn_err (CE_WARN,
- "cocoReadWrite: Could not start Sim read/write");
- }
-
- /* we are done */
- cp->dmastat = DMA_IDLE;
- cp->dmabits = 0;
-
- /*
- * Invalidate the cache for board->mem
- * adjust the address for current data cache line size
- */
- dki_dcache_inval ( rw->r_buf, tot_bytes );
-
- cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
- cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
- alenlist_done(cp->r_addrList);
- alenlist_done(cp->w_addrList);
- if ( r_dmaPg ) kmem_free ( r_dmaPg, tot_r_cache );
- if ( w_dmaPg ) kmem_free ( w_dmaPg, tot_w_cache);
-
- return(err);
- }
-
-
- /*************************************************************************
- *** c o c o S t a r t R W D m a ***
- *************************************************************************
- *
- * Name: cocoStartRWDma
- *
- * Purpose: Program the boards for Simultaneous Read/Write DMA.
- * The read and write channel's scatter-gather have been
- * prepared before and are in cp->r_addrList and cp->w_addrList
- * For Chained DMA, the chain list for read and write channels
- * are prepared before and passed to us as parameters.
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- static int
- cocoStartRWDma ( card_t *cp, iopaddr_t pw_dmaPg, int tot_write,
- iopaddr_t pr_dmaPg, int tot_read )
- {
-
- register caddr_t adr_cfg, adr_norm, adr_amcc;
- register int i, err, tot_words, tot_bytes;
- register uint_t dmabits, dmacfg, dmacmd;
- size_t rp_size, wp_size;
- alenaddr_t rp_addr, wp_addr;
-
-
- adr_cfg = cp->conf_adr;
- adr_norm = cp->norm_adr;
- adr_amcc = cp->amcc_adr;
- dmacfg = cp->dmacfg;
- dmabits = cp->dmabits;
- dmacmd = cp->dmacmd;
-
- Out32(adr_cfg, dmacfg ); /* clear eof markers */
-
- /* =======================
- * Chained DMA
- * ======================= */
- if ( cp->dmatype == DMA_PROG ) {
-
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Programming the board for Read/Write Chain Dma
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- /* prepare Amcc counters */
- Out32(adr_amcc+AMCC_OP_REG_MRTC, tot_write );
- Out32(adr_amcc+AMCC_OP_REG_MWTC, tot_read );
-
- /* Program the Write channel Address (board -> mem ) */
- dmabits |= DMAREG_PREN | DMAREG_PWEN;
- dmacfg |= dmabits;
- Out32(adr_cfg, dmacfg);
-
- /* Write channel address (b->m) */
- Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMPRWR );
- Out32(adr_norm, pr_dmaPg);
-
- /* Read channel address (m->b) */
- Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMPRRD );
- Out32(adr_norm, pw_dmaPg);
-
- /* Start Read/Write DMA - only Write(b->m) is enabled */
- dmabits |= DMAREG_INTPWEN | DMAREG_WEN | DMAREG_REN | dmacmd;
-
- cp->dmasize = tot_write;
- cp->dmabits = dmabits;
- cp->iostat = IO_OK;
- cp->dmastat = DMA_RW_WAIT;
-
- /* start the DMA */
- /* pciio_flush_buffers ( cp->vhdl ); */
- nanotime ( &cp->start_time );
- Out32(adr_cfg, dmacfg | dmabits );
-
- /* so we dont wait forever for an interrupt */
- cp->tid = itimeout(cocoTimeOut2, cp, SIMRW_TIMER,
- pltimeout, 0, 0, 0);
-
- return(0);
- }
-
-
-
-
- /* ===========================
- * Single page DMA
- * =========================== */
-
- /* get next page for Read channel if nothing left from past */
- if ( cp->wp_addr == (alenaddr_t)0 ) {
- if ( cp->w_page_no <= 0 ) {
-
- cmn_err (CE_WARN,
- "cocoStartRWDma: Premature end of Write, w_page = %d",
- cp->w_page_no );
- return(EIO);
- }
-
- if ( alenlist_get(cp->w_addrList, NULL, NBPP,
- &wp_addr, &wp_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN, "cocoStartRWDma: bad scater-gather");
- return(EIO);
- }
- cp->w_page_no--;
-
- }
- /* some bytes left from past */
- else {
- wp_addr = cp->wp_addr;
- wp_size = cp->wp_size;
- }
-
- /* get next page for Write channel if nothing left from past */
- if ( cp->rp_addr == (alenaddr_t)0 ) {
-
- if ( cp->r_page_no <= 0 ) {
- cmn_err (CE_WARN,
- "cocoStartRWDma: Premature end of Read, r_page = %d",
- cp->r_page_no);
- return(EIO);
- }
-
- if ( alenlist_get(cp->r_addrList, NULL, NBPP,
- &rp_addr, &rp_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN, "cocoReadWrite: bad scater-gather");
- return(EIO);
- }
- cp->r_page_no--;
-
- }
- /* some bytes left from past */
- else {
- rp_addr = cp->rp_addr;
- rp_size = cp->rp_size;
-
- }
-
- /* adjust - we shoud write as much as we can read */
- cp->wp_addr = (alenaddr_t)0;
- cp->rp_addr = (alenaddr_t)0;
- cp->wp_size = 0;
- cp->rp_size = 0;
-
- /* Write more than read ? */
- if ( wp_size == rp_size )
- tot_bytes = wp_size;
-
- if ( wp_size > rp_size ) {
- tot_bytes = rp_size;
- cp->wp_addr = (alenaddr_t)((int)wp_addr + tot_bytes);
- cp->wp_size = wp_size - tot_bytes;
- }
-
- /* read more than write ? */
- if ( rp_size > wp_size ) {
- tot_bytes = wp_size;
- cp->rp_addr = (alenaddr_t)((int)rp_addr + tot_bytes);
- cp->rp_size = rp_size - tot_bytes;
- }
-
- tot_words = (int)tot_bytes/sizeof(uint_t);
- tot_words--; /* counts down to 0xffff in hardware */
-
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Program the board for Read and Write
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- /* prepare Amcc counters */
- Out32(adr_amcc+AMCC_OP_REG_MRTC, tot_bytes);
- Out32(adr_amcc+AMCC_OP_REG_MWTC, tot_bytes );
-
- /* program for Write channel ( board -> mem ) */
- Out32(adr_cfg, dmacfg | DMAREG_WCNT);
- Out32(adr_norm, tot_words);
- Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMWADR); /* b->m */
- Out32(adr_norm, rp_addr);
-
- /* program for Read channel ( mem -> board ) */
- Out32(adr_cfg, dmacfg | DMAREG_RCNT);
- Out32(adr_norm, tot_words);
- Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMRADR); /* b->m */
- Out32(adr_norm, wp_addr);
-
- /* start read/write Dma - only write channel (b->m) is needed */
- dmabits |= DMAREG_INTWEN | DMAREG_REN | DMAREG_WEN | dmacmd;
- cp->dmasize = wp_size;
- cp->dmabits = dmabits;
- cp->dmastat = DMA_RW_WAIT;
- cp->iostat = IO_OK;
-
-
- /* start the DMA */
- nanotime ( &cp->start_time );
- Out32(adr_cfg, dmacfg | dmabits | dmacmd );
-
- /* so we dont wait forever for an interrupt */
- cp->tid = itimeout(cocoTimeOut2, cp, SIMRW_TIMER,
- pltimeout, 0, 0, 0);
-
- return(0);
-
- }
-
- /*************************************************************************
- *** c o c o R e s e t ***
- *************************************************************************
- *
- * Name: cocoReset
- *
- * Purpose: This routine initializes the board by resetting the add-on
- * logic, AMCC fifos, Chameleon chip and FIFOs.
- * After reset, FIFO flags are programmed, default DMA controller
- * config. register is written and Chameleon chip is enabled
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoReset( card_t *cp )
- {
-
- uint_t stat;
- register caddr_t adr_amcc;
- register caddr_t adr_cfg;
- register uint_t tmp;
-
- adr_amcc = cp->amcc_adr;
- adr_cfg = cp->conf_adr;
-
- /* disable interrupts */
- Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_RST | AMCC_INTCSR_RCLR |
- AMCC_INTCSR_WCLR );
-
- /* reset AMCC fifos and Xilinx */
- Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_ADDON );
- Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_FIFOS );
-
- /* reset Chameleon and FIFOs and bring FIFOs to programming flags */
- Out32(adr_cfg, DMAREG_CCRES | DMAREG_FRES | DMAREG_FSCLK );
- Out32(adr_cfg, DMAREG_FSCLK);
- Out32(adr_cfg, DMAREG_FSCLK);
-
- /* program FIFO flags */
- cocoProgFlags ( adr_cfg, DMAREG_FRES,100,450,100,450);
-
- /* bring FIFOs in functional mode and Chameleon out of reset */
- Out32(adr_cfg, DMAREG_FRES | DMAREG_FSCLK);
- Out32(adr_cfg, DMAREG_CCRES | DMAREG_FSCLK);
- Out32(adr_cfg, DMAREG_CCRES | DMAREG_FSCLK | DMAREG_PTEN);
-
- /* set default config. reg */
- cp->dmacfg = DMAREG_NVIFEN | DMAREG_PTEN | DMAREG_CCRES | DMAREG_FSCLK;
-
- /* initialize Chameleon */
- cocoSetMode(cp, 0,0,0,1);
-
- /* enable Amcc Interrupt */
- Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_MASK );
- }
-
-
- /*************************************************************************
- *** c o c o P r o g F l a g s ***
- *************************************************************************
- *
- * Name: cocoProgFlags
- *
- * Purpose: Program offsets of ASIC fifo flags by writing 18 bit
- * serial registers of FIFO containg 9 bit AF and 9 bit AE
- * flag offset
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoProgFlags ( caddr_t adr_cfg, uint_t d, ushort_t iae, ushort_t iaf,
- ushort_t oae, ushort_t oaf )
- {
- ushort_t andfl;
- ushort_t shft;
- ushort_t bit0;
- ushort_t bit1;
- uint_t bit;
-
- andfl=0x01;
- shft=0;
-
- do {
- bit0 = (iaf & andfl);
- bit1 = (oaf & andfl);
- bit = d | 0x00000010;
-
- if (bit0 == 0)
- bit |= 0x00000004;
-
- if (bit1 == 0)
- bit |= 0x00000008;
-
- Out32(adr_cfg, bit);
-
- bit &= 0xFFFFFFEF;
-
- Out32(adr_cfg, bit);
-
- andfl = andfl << 1;
- shft++;
- }
- while ( shft <= 8 );
-
- andfl = 0x01;
- shft = 0;
- do {
- bit0 = (iae & andfl);
- bit1 = (oae & andfl);
- bit = d | 0x00000010;
-
- if (bit0==0)
- bit |= 0x00000004;
-
- if (bit1==0)
- bit |= 0x00000008;
-
- Out32(adr_cfg, bit);
- bit = bit & 0xFFFFFFEF;
- Out32(adr_cfg, bit);
-
- andfl = andfl << 1;
- shft++;
- }
- while (shft<=8);
- }
-
-
- /*************************************************************************
- *** c o c o S e t M o d e ***
- *************************************************************************
- *
- * Name: cocoSetMode
- *
- * Purpose: Set Chameleon Mode Register
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoSetMode ( card_t *cp, int mode, int swap, int slice, int flag )
- {
-
- uint_t cmd;
- cmd = COCO_WRENA | COCO_DELAY;
-
- if (mode)
- cmd |= COCO_MODE;
-
-
- if (swap)
- cmd |= COCO_SWAP;
-
- if (slice)
- cmd |= COCO_SLICE;
-
- if (flag)
- cmd |= COCO_FLAG;
-
- cocoCommand (cp, COCO_SETMODE, cmd);
-
- }
-
-
- /*************************************************************************
- *** c o c o C o m m a n d ***
- *************************************************************************
- *
- * Name: cocoCommand
- *
- * Purpose: Sends a command to Chameleon. Writes the command to
- * the controller and writes the data to Fifo.
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoCommand ( card_t *cp, uint_t cmd, uint_t data )
- {
- register uint_t stat;
-
- /* set Chameleon connad in Config. Register */
- Out32(cp->conf_adr, cmd | cp->dmacfg );
-
- /* writes the data for the command to AMCC Fifo */
- Out32(cp->amcc_adr + AMCC_OP_REG_FIFO, data);
- }
-
-
- /*************************************************************************
- *** c o c o B u f O u t ***
- *************************************************************************
- *
- * Name: cocoBufOut
- *
- * Purpose: Dumps a buffer containig 32-bit values to Chameleon Fifo.
- * Data is given to Chameleon in Transparent mode.
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoBufOut ( card_t *cp, uint_t *buf, int size )
- {
- register int i, j;
- register uint_t cmd, stat;
-
- /* set to Transparent Mode */
- cmd = cp->dmacfg | COCO_TRANSP;
- Out32(cp->conf_adr, cmd );
-
- /* Dump the data */
- for ( i = 0; i < size; i++) {
- j = 0;
- stat = Inp32(cp->amcc_adr+AMCC_OP_REG_MCSR);
- if ( stat & 0x03 ) { /* fifo has room */
- Out32(cp->amcc_adr+AMCC_OP_REG_FIFO, buf[i] );
- continue;
- }
- printf ("cocoBufOut: Fifo is full, stat = 0x%x, discarding %d bytes\n", stat, size - i );
- break;
- }
-
- }
-
- /*************************************************************************
- *** c o c o B u f I n ***
- *************************************************************************
- *
- * Name: cocoBufIn
- *
- * Purpose: Reads Fifo entries into a buf.
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoBufIn ( card_t *cp, uint_t *buf, int size )
- {
- register int i;
-
- for ( i = 0; i < size; i++ ) {
- buf[i] = cocoReadAmccFifo(cp);
- }
-
- }
-
-
- /*************************************************************************
- *** c o c o R e a d A m c c F i f o ***
- *************************************************************************
- *
- * Name: cocoReadAmccFifo
- *
- * Purpose: Reads a 32-bit value word from AMCC Internal Fifo
- * Returns zero if Fifo is empty
- *
- * Returns: Fifo value or zero if fifo is empty
- *
- *************************************************************************/
- static int
- cocoReadAmccFifo ( card_t *cp )
- {
- register uint_t stat;
- register int i;
-
- for ( i = 0; i < 3; i++ )
- stat = Inp32(cp->amcc_adr+AMCC_OP_REG_MCSR);
-
- /* if ( stat != 0x000000e6 ) { */
- if ( stat != 0x26 ) {
- stat = Inp32(cp->amcc_adr + AMCC_OP_REG_FIFO );
- return(stat);
- }
-
- return(0);
- }
-
-
- /*************************************************************************
- *** c o c o F i f o T e s t ***
- *************************************************************************
- *
- * Name: cocoFifoTest
- *
- * Purpose: Fills Fifo with a pattern, read it back one by one
- * and compare. Reports back the results.
- *
- * Returns: 0 = Success, 1 = Failed.
- *
- *************************************************************************/
- static int
- cocoFifoTest ( card_t *cp, int pat )
- {
- register int i, j, err;
- uint_t res, expect;
-
- err = 0; /* assume success */
-
- /* test for 50 times .. */
- for( j = 0; j < 50; j++) {
-
- /* fill Fifo with pattern */
- for(i=0;i<750;i++)
- cocoCommand (cp, COCO_TRANSP, cocoPattern(pat,i) );
-
- /* read it back and compare */
- for( i = 0;i < 750; i++) {
-
- res = cocoReadAmccFifo( cp ); /* what we read */
- expect = cocoPattern( pat, i); /* what we expect */
-
- if (res != expect) {
- cmn_err (CE_NOTE,
- "cocoFifoTest: Fifo entry %d, expected 0x%x, read 0x%x (round %d)", i, expect, res, j);
- err = 1;
- }
- }
- }
-
- if ( err )
- cmn_err (CE_NOTE, "cocoFifoTest: Failed\n");
- else cmn_err (CE_NOTE, "cocoFifoTest: Succeeded\n");
-
- return(err);
- }
-
- /*************************************************************************
- *** c o c o P a t t e r n ***
- *************************************************************************
- *
- * Name: cocoPattern
- *
- * Purpose: Pattern generator for testing purpose.
- *
- * Returns: The generated pattern
- *
- *************************************************************************/
- static int
- cocoPattern ( int pat, int cnt )
- {
- register int res;
-
- /* for now, we always return pattern 1 */
- pat=1;
-
- switch (pat) {
- case 1:
- res = cnt;
- break;
-
- case 2:
- res = ~cnt;
- break;
-
- case 3:
- res = 0xFFFFFFFFL;
- break;
-
- case 4:
- res = 0x00000000L;
- break;
-
- case 5:
- if (cnt % 2 != 1)
- res = 0xaaaaaaaaL;
- else res = 0x55555555L;
- break;
-
- case 6:
- cnt = (cnt & 0x01FL);
- res = (1 << cnt);
- break;
-
- case 7:
- cnt = (cnt & 0x01FL);
- res = (1 << cnt);
- res = ~res;
- break;
-
- case 8:
- if ( cnt % 2 == 1)
- res = 0x0f0f0f0fL;
- else res = 0xf0f0f0f0L;
- break;
-
- case 9:
- cnt = (cnt & 0xFF);
- res = cnt + ( cnt << 8) + (cnt << 16) + (cnt << 24);
- break;
-
- case 10:
- cnt = (cnt & 0xFFFF);
- res = cnt + ( cnt << 16);
- break;
-
- }
-
- return(res);
- }
-
- /*************************************************************************
- *** c o c o R e a d M o d e ***
- *************************************************************************
- *
- * Name: cocoReadMode
- *
- * Purpose: Reads Chameleon Mode register
- *
- * Returns: The generated pattern
- *
- *************************************************************************/
- static int
- cocoReadMode ( card_t *cp )
- {
-
- register uint_t mode;
-
- /* set Chameleon command in Config. Register */
- cocoCommand ( cp, COCO_READMODE, 0x0 );
- mode = cocoReadAmccFifo(cp);
-
- return (mode);
- }
-
- /*************************************************************************
- *** c o c o R e a d D m a R e g s ***
- *************************************************************************
- *
- * Name: cocoReadDmaRegs
- *
- * Purpose: Reads Xilinx DMA Registers
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoReadDmaRegs ( card_t *cp, uint_t *dmaRegs )
- {
-
- register int i, k;
- register uint_t dmacfg;
-
- dmacfg = cp->dmacfg;
-
- /* read DMA registers into dmaRegs table */
- i = 0;
- for ( k = 13; k <= 16; k++) {
- Out32(cp->conf_adr, dmacfg | (k << 6) );
- dmaRegs[i++] = Inp32(cp->norm_adr);
- }
- }
-
- /*************************************************************************
- *** c o c o W r i t e D m a R e g s ***
- *************************************************************************
- *
- * Name: cocoWriteDmaRegs
- *
- * Purpose: Write values in dmaRegs[] to Xilinx DMA Registers
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoWriteDmaRegs ( card_t *cp, uint_t *dmaRegs )
- {
- register int i, k;
- register uint_t dmacfg;
-
- dmacfg = cp->dmacfg;
-
- /* read DMA registers into dmaRegs table */
- i = 0;
- for ( k = 13; k <= 16; k++) {
- Out32(cp->conf_adr, dmacfg | (k << 6) );
- Out32(cp->norm_adr, dmaRegs[i++] );
- }
- }
-
- /*************************************************************************
- *** c o c o R e a d A d d r ***
- *************************************************************************
- *
- * Name: cocoReadAddr
- *
- * Purpose: Reads Address Register
- *
- * Returns: Address Register value
- *
- *************************************************************************/
- static int
- cocoReadAddr (card_t *cp)
- {
- register uint_t addr_reg;
-
- cocoCommand ( cp, COCO_READADDR, 0x0 );
- addr_reg = cocoReadAmccFifo(cp);
-
- return(addr_reg);
- }
-
- /*************************************************************************
- *** c o c o S e t A d d r ***
- *************************************************************************
- *
- * Name: cocoSetAddr
- *
- * Purpose: Set Address Register to given value
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoSetAddr ( card_t *cp, uint_t val )
- {
- cocoCommand ( cp, COCO_SETADDR, val );
- }
-
- /*************************************************************************
- *** c o c o D m a R e g s T e s t ***
- *************************************************************************
- *
- * Name: cocoDmaRegsTest
- *
- * Purpose: Tests access to Xilinx DMA registers.
- * Write and read to DMA registers, compare values and
- * report back the results.
- *
- * Returns: Test result ( 0 = Success, 1 = Failed)
- *
- *************************************************************************/
- static int
- cocoDmaRegsTest ( card_t *cp )
- {
-
- register int i, j, k, err, res, expct, dmacfg, pat;
- register caddr_t adr_cfg, adr_norm;
-
- cmn_err (CE_NOTE, "testing Chameleon DMA registers access");
-
- adr_cfg = cp->conf_adr;
- adr_norm = cp->norm_adr;
- dmacfg = cp->dmacfg;
- err = 0;
- pat = 1;
-
- /* try for 500 times */
- for ( i = 0; i < 500; i++ ) {
-
- /* write to DMA Regsiers */
- for ( k = 13; k <= 16; k++ ) {
- Out32(adr_cfg, dmacfg | (k << 6) );
- Out32(adr_norm, cocoPattern(pat, i+k) );
- }
-
- /* read back registers and compare */
- for ( k = 13; k <= 16; k++ ) {
-
- Out32(adr_cfg, dmacfg | (k << 6) );
- res = Inp32(adr_norm);
- expct = cocoPattern(pat, i+k);
-
- /* not equal ..report it ! */
- if ( res != expct ) {
- cmn_err ( CE_NOTE,
- "Dma reg %d, expected 0x%x, read 0x%x, round %x",
- k, expct, res, i );
- err = 1;
- }
- }
-
- }
-
- cmn_err (CE_NOTE, "Chameleon DMA registers access test %s",
- (err == 0 ? "Succeeded": "Failed") );
-
- return(err);
- }
-
-
- /*************************************************************************
- *** c o c o I n t R a m T e s t ***
- *************************************************************************
- *
- * Name: cocoIntRamTest
- *
- * Purpose: Test CHameleon Internal LUTs.
- * Fills Internal LUT with a pattern and reads them back
- * for comparison and reports the results.
- *
- * Returns: Test result ( 0 = Success, 1 = Failed)
- *
- *************************************************************************/
- static int
- cocoIntRamTest ( card_t *cp )
- {
-
- register int i, err, pat, num;
- register uint_t res;
-
- cmn_err (CE_NOTE, "Testing Chameleon Internal Ram access\n");
-
- num = 1;
- err = 0;
-
- /* ====================
- * Fill LUTs
- * ==================== */
- for ( i = 0; i < INT_RAM_SIZE; i++ ) {
-
-
- pat = cocoPattern(num, i);
-
- /* set address of internal LUT location */
- cocoCommand (cp, COCO_SETADDR, i);
-
- /* fill Internal LUTs with pattern */
- cocoCommand (cp, COCO_FILLRAMIL, pat );
- cocoCommand (cp, COCO_FILLRAMIH, pat );
- cocoCommand (cp, COCO_FILLRAMO, pat );
- }
-
-
- /* =============================
- * Read LUTs and compare
- * ============================= */
- for ( i = 0; i < INT_RAM_SIZE; i++ ) {
-
-
- pat = cocoPattern(num, i) & 0x03ffff;
-
- /*
- * set address of internal RAMIL location
- * read value from that location and compare
- */
- cocoCommand (cp, COCO_SETADDR, i);
- cocoCommand ( cp, COCO_READRAMIL, 0x0 );
- res = cocoReadAmccFifo (cp);
-
- /* is what we read ok ? */
- if ( (res & 0x03ffff) != pat ) {
- cmn_err (CE_NOTE,
- "Chameleon RAMIL at 0x%x, expected 0x%x, read 0x%x\n",
- i, pat, res );
- err = 1;
- }
-
- /*
- * set address of internal RAMIH location
- * read value from that location and compare
- */
- cocoCommand (cp, COCO_SETADDR, i);
- cocoCommand ( cp, COCO_READRAMIH, 0x0 );
- res = cocoReadAmccFifo (cp);
-
- /* is what we read ok ? */
- if ( (res & 0x03ffff) != pat ) {
- cmn_err (CE_NOTE,
- "Chameleon RAMIH at 0x%x, expected 0x%x, read 0x%x\n",
- i, pat, res );
- err = 1;
- }
-
- /*
- * set address of internal RAMO location
- * read value from that location and compare
- */
- cocoCommand (cp, COCO_SETADDR, i);
- cocoCommand ( cp, COCO_READRAMO, 0x0 );
- res = cocoReadAmccFifo (cp);
-
- /* is what we read ok ? */
- if ( (res & 0x03ffff) != pat ) {
- cmn_err (CE_NOTE,
- "Chameleon RAMO at 0x%x, expected 0x%x, read 0x%x\n",
- i, pat, res );
- err = 1;
- }
-
- }
-
- cmn_err (CE_NOTE, "Chameleon Internal RAM test %s\n",
- ( err == 0 ? "Succeeded":"Failed") );
-
- return(err);
-
- }
-
- /*************************************************************************
- *** c o c o E x t R a m T e s t ***
- *************************************************************************
- *
- * Name: cocoExtRamTest
- *
- * Purpose: Test CHameleon External LUTs.
- * Fills External LUT with a pattern and reads them back
- * for comparison and reports the results.
- *
- * Returns: Test result ( 0 = Success, 1 = Failed)
- *
- *************************************************************************/
- static int
- cocoExtRamTest ( card_t *cp )
- {
-
- register int i, err, pat, num;
- register uint_t res;
-
- cmn_err (CE_NOTE, "Testing Chameleon External Ram access\n");
-
- num = 1;
- err = 0;
-
- /* ====================
- * Fill RAML
- * ==================== */
- for ( i = 0; i < EXT_RAM_SIZE; i++ ) {
-
- /* set address of internal LUT location */
- cocoCommand (cp, COCO_SETADDR, i);
-
- /* fill External LUTs with pattern */
- cocoCommand (cp, COCO_FILLRAML, cocoPattern(num, i) );
- }
-
-
- /* ===================================
- * Read External LUT and compare
- * =================================== */
- for ( i = 0; i < EXT_RAM_SIZE; i++ ) {
-
-
- pat = cocoPattern(num, i);
-
- /*
- * set address of internal RAMIL location
- * read value from that location and compare
- */
- cocoCommand (cp, COCO_SETADDR, i);
- cocoCommand ( cp, COCO_READRAML, 0x0 );
- res = cocoReadAmccFifo (cp);
-
- /* is what we read ok ? */
- if ( res != pat ) {
- cmn_err (CE_NOTE,
- "Chameleon RAML at 0x%x, expected 0x%x, read 0x%x\n",
- i, pat, res );
- err = 1;
- }
- }
-
-
- cmn_err (CE_NOTE, "Chameleon External RAM test %s\n",
- ( err == 0 ? "Succeeded":"Failed") );
-
- return(err);
-
- }
-
-
- /*************************************************************************
- *** c o c o R e a d I n t R a m ***
- *************************************************************************
- *
- * Name: cocoReadIntRam
- *
- * Purpose: Read Chameleon's Internal LUTs into given buffer.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoReadIntRam ( card_t *cp, uint_t *buf, int lut, int size )
- {
- register uint_t cmd;
- register int i;
-
- /* which LUT we should read ? */
- switch ( lut ) {
- case COCO_READ_RAMIL: cmd = COCO_READRAMIL; break;
- case COCO_READ_RAMIH: cmd = COCO_READRAMIH; break;
- case COCO_READ_RAMO: cmd = COCO_READRAMO; break;
- }
-
-
- /* fill buffer with contents of Internal Ram */
- for ( i = 0; i < size; i++ ) {
- cocoCommand (cp, COCO_SETADDR, i);
- cocoCommand (cp, cmd, 0x0 );
- buf[i] = cocoReadAmccFifo (cp);
- }
-
- }
-
- /*************************************************************************
- *** c o c o W r i t e I n t R a m ***
- *************************************************************************
- *
- * Name: cocoWriteIntRam
- *
- * Purpose: Write Chameleon's Internal LUTs into given buffer.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoWriteIntRam ( card_t *cp, uint_t *buf, int lut, int size )
- {
- register uint_t cmd;
- register int i;
-
- /* which LUT we should read ? */
- switch ( lut ) {
- case COCO_FILL_RAMIL: cmd = COCO_FILLRAMIL; break;
- case COCO_FILL_RAMIH: cmd = COCO_FILLRAMIH; break;
- case COCO_FILL_RAMO: cmd = COCO_FILLRAMO; break;
- }
-
-
- /* fill buffer with contents of Internal Ram */
- for ( i = 0; i < size; i+=2 ) {
- cocoCommand (cp, COCO_SETADDR, buf[i]);
- cocoCommand (cp, cmd, buf[i+1] );
- }
-
- }
-
- /*************************************************************************
- *** c o c o R e a d E x t R a m ***
- *************************************************************************
- *
- * Name: cocoReadExtRam
- *
- * Purpose: Read Chameleon's External LUT into given buffer.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoReadExtRam ( card_t *cp, uint_t *buf, int size )
- {
- register uint_t cmd;
- register int i;
-
-
- /* fill External Ram with contents of the buffer */
- for ( i = 0; i < size; i++ ) {
- cocoCommand (cp, COCO_SETADDR, i);
- cocoCommand (cp, COCO_READRAML, 0x0 );
- buf[i] = cocoReadAmccFifo (cp);
- }
-
- }
-
-
- /*************************************************************************
- *** c o c o W r i t e E x t R a m ***
- *************************************************************************
- *
- * Name: cocoWriteExtRam
- *
- * Purpose: Write Chameleon's External LUT into given buffer.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoWriteExtRam ( card_t *cp, uint_t *buf, int size )
- {
- register int i;
-
- /* fill buffer with contents of Internal Ram */
- for ( i = 0; i < size; i+=2 ) {
- cocoCommand (cp, COCO_SETADDR, buf[i]);
- cocoCommand (cp, COCO_FILLRAML, buf[i+1] );
- }
-
- }
-
-
- /*************************************************************************
- *** c o c o C o n v e r t ***
- *************************************************************************
- *
- * Name: cocoConvert
- *
- * Purpose: Converts a single value
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoConvert ( card_t *cp, uint_t val )
- {
- cocoCommand ( cp, COCO_CONVERT, val );
- }
-
-
- /*************************************************************************
- *** c o c o C o n v e r t T e s t ***
- *************************************************************************
- *
- * Name: cocoConvertTest
- *
- * Purpose: Converts a single value, read the converted value back
- * and compare to known value.
- *
- * Returns: None
- *
- *************************************************************************/
- static void
- cocoConvertTest ( card_t *cp, coco_convert_t *cv )
- {
- register uint_t res;
-
-
- /* convert the pixle value */
- cv->result = 0; /* assume success */
- cocoCommand ( cp, COCO_CONVERT, cv->in );
-
- /* read the converted value and compare */
- res = cocoReadAmccFifo (cp);
-
- if ( res != cv->out )
- cv->result = 1;
-
- }
-
- /*************************************************************************
- *** c o c o D m a T o L u t s ***
- *************************************************************************
- *
- * Name: cocoDmaToLuts
- *
- * Purpose: DMAs data in user's buffer to one of Internal LUTs or
- * the External LUTs (identified by cmd param). The DMA is
- * done either in SINGLE or PROG (chained) mode depending
- * on current set up (cp->dmatype).
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
- static int
- cocoDmaToLuts( card_t *cp, coco_buf_t *cb, int cmd )
- {
-
- register caddr_t kvaddr, amcc_adr;
- register coco_dmapage_t *dmaPg;
- register int len, page_no, i, dmatype, err, tot_bytes;
- register int s;
- register int cache_bytes;
- register uint_t dmabits, *ib, olddmacmd, dmacmd;
- register uint_t *cache_line;
- alenlist_t addrList2;
- alenlist_t addrList;
- size_t p_size;
- alenaddr_t p_addr;
- iopaddr_t p_dmaPg;
-
- amcc_adr = cp->amcc_adr;
- dmacmd = cp->dmacmd;
-
- /* ==========================================
- * Scatter-Gather list preparation
- * ========================================== */
-
- /* get the user's address and size */
- len = cb->buf_size * sizeof(uint_t);
-
- /* lock user pages into memory for DMA */
- err = cocoLockUser ( (caddr_t)cb->buf, len, B_WRITE);
- if ( err ) {
- cmn_err (CE_WARN, "cocoDmaToLuts: Cannot lock user pages");
- return (err);
- }
-
- /*
- * write back and invalidate the data for mem->board
- */
- dki_dcache_wbinval ( (caddr_t)cb->buf, len );
-
- /* create scatter-gather list of user's buffer */
- addrList2 = uvaddr_to_alenlist( (alenlist_t)NULL, (caddr_t)cb->buf,
- (size_t)len, 0);
-
- if ( addrList2 == (alenlist_t)NULL ) {
- cmn_err (CE_WARN, "cocoDmaToLuts: cannot create alenlist");
- cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE);
- return (EIO);
- }
-
- addrList = pciio_dmatrans_list ( cp->conn, 0,
- addrList2, 0 );
- #if 0
- page_no = alenlist_size ( addrList ); /* total pages to DMA */
- #endif
-
- page_no = cocoAlenlistSize ( addrList );
- cp->page_no = page_no;
-
- /* initialize our DMA event semaphore */
- cp->dmabits = 0;
- olddmacmd = dmacmd;
-
- dmatype = cp->dmatype;
-
- SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
-
- cocoResetAmcc ( cp );
- cocoPrepAmcc ( cp );
-
-
- /* ===============================
- * Set proper DMA flags
- * =============================== */
- dmacmd = DMAREG_FILL;
-
- /* set proper LUT fill bit */
- switch ( cmd ) {
-
- case COCO_BLOCK_FILL_RAMIL:
- dmacmd |= COCO_FILLRAMIL;
- break;
-
- case COCO_BLOCK_FILL_RAMIH:
- dmacmd |= COCO_FILLRAMIH;
- break;
-
- case COCO_BLOCK_FILL_RAMO:
- dmacmd |= COCO_FILLRAMO;
- break;
-
- case COCO_BLOCK_FILL_RAML:
- dmacmd |= COCO_FILLRAML;
- break;
- }
-
- cp->dmacmd = dmacmd;
-
- /* =======================
- * Chained DMA
- * ======================= */
- if ( dmatype == DMA_PROG ) {
-
- dmaPg = cocoMakeChain ( cp, addrList, page_no );
- if ( dmaPg == (coco_dmapage_t *)NULL ) {
- cmn_err (CE_NOTE,
- "cocoDmaLut: Error creating chain list");
- cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
- alenlist_done(addrList);
- return(EIO);
- }
-
-
- tot_bytes = page_no * sizeof(coco_dmapage_t);
- p_dmaPg = pciio_dmatrans_addr ( cp->conn, 0,
- kvtophys(dmaPg), tot_bytes, 0 );
-
- /* write back cache for the chain list */
- dki_dcache_wbinval(dmaPg, tot_bytes );
- err = 0;
-
- /* dma from memory -> board (selected lut buffer) */
- s = COCO_LOCK(&cp->coco_mlock);
- cocoStartProgDma ( cp, p_dmaPg, len, B_WRITE );
-
- cp->dmastat = DMA_LUT_WAIT;
-
- SLEEP_EVENT(&cp->coco_sv, &cp->coco_mlock, s);
-
- switch ( cp->iostat ) {
- case IO_OK: err = 0; break;
- case IO_TIME: err = ETIME; break;
- case IO_ERROR: err = EIO; break;
- }
-
- /* we are done */
- cp->dmastat = DMA_IDLE;
- cp->dmabits = 0;
- cp->dmacmd = olddmacmd;
- cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
- alenlist_done(addrList);
- kmem_free ( dmaPg, page_no * sizeof(coco_dmapage_t) );
-
- return(err);
- }
-
-
- /* ===========================
- * Single page DMA
- * =========================== */
-
- for ( i = 0; i < page_no; i++ ) {
-
- /* get a page to DMA */
- if ( alenlist_get(addrList, NULL, NBPP,
- &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN, "cocoDma: Bad scatter-gather");
- cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
- alenlist_done(addrList);
- return(ENOMEM);
- }
-
- err = 0;
-
- s = COCO_LOCK(&cp->coco_mlock);
- cp->dmastat = DMA_LUT_WAIT;
- cocoStartSingleDma ( cp, p_addr, p_size, B_WRITE );
-
- SLEEP_EVENT(&cp->coco_sv, &cp->coco_mlock, s);
-
- switch ( cp->iostat ) {
- case IO_OK: err = 0; break;
- case IO_TIME: err = ETIME; break;
- case IO_ERROR: err = EIO; break;
- }
-
- if ( err ) {
- cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
- alenlist_done(addrList);
- return(err);
- }
- }
-
- /* we are done */
- cp->dmastat = DMA_IDLE;
- cp->dmabits = 0;
- cp->dmacmd = olddmacmd;
- cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
- alenlist_done(addrList);
-
- return(err);
-
- }
-
-
- /*************************************************************************
- *** c o c o L o c k U s e r ***
- *************************************************************************
- *
- * Name: cocoLockUser
- *
- * Purpose: Given a user's address space pointer, it locks all user's
- * pages in memory in preparation for DMA.
- *
- * Returns: 0 = Success or errno
- *
- *************************************************************************/
- static int
- cocoLockUser ( caddr_t user_buf, int len, int direction )
- {
- register int ret;
-
- /* lock pages in memory */
- ret = userdma( (caddr_t)user_buf, len, direction, 0 );
- return (ret);
- }
-
- /*************************************************************************
- *** c o c o U n l o c k U s e r ***
- *************************************************************************
- *
- * Name: cocoUnlockUser
- *
- * Purpose: Given a user's address, unlock all pages for that address
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoUnlockUser ( caddr_t user_buf, int len, int direction )
- {
-
- undma ( user_buf, len, direction );
- }
-
- /*************************************************************************
- *** c o c o P r e p A m c c ***
- *************************************************************************
- *
- * Name: cocoPrepAmcc
- *
- * Purpose: Prepares AMCC chip for DMA.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoPrepAmcc ( card_t *cp )
- {
- register caddr_t adr_amcc;
- register uint_t mcsr, intcsr;
- register uint_t tmp;
-
- adr_amcc = cp->amcc_adr;
-
-
- /* ===========================
- * Prepare AMCC chip
- * =========================== */
-
- /*
- * Prepare AMCC as follow:
- * - Read Maibox registers to make sure they are empty
- * - Set Amcc DMA count to 0
- * - Enable Amcc Read/Write interrupts
- */
- tmp = Inp32(adr_amcc+AMCC_OP_REG_IMB4); /* Read In mbox */
- tmp = Inp32(adr_amcc+AMCC_OP_REG_OMB4); /* read Out mbox */
- Out32(adr_amcc+AMCC_OP_REG_MRTC, 0 );
- Out32(adr_amcc+AMCC_OP_REG_MWTC, 0 );
- Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_MASK );
-
- }
-
- /*************************************************************************
- *** c o c o R e s e t A m c c ***
- *************************************************************************
- *
- * Name: cocoResetAmcc
- *
- * Purpose: Resets Addon and Amcc Fifos
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoResetAmcc ( card_t *cp )
- {
- register caddr_t adr_amcc;
-
- adr_amcc = cp->amcc_adr;
-
- /* Reset Amcc Fifos and Addon interface */
- Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_ADDON );
- Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_FIFOS );
- }
-
-
- /*************************************************************************
- *** c o c o S t a r t P r o g D m a ***
- *************************************************************************
- *
- * Name: cocoStartProgDma
- *
- * Purpose: Programs the board for Chained DMA and starts the Dma
- *
- * Returns: None.
- *
- *************************************************************************/
-
- static void
- cocoStartProgDma ( card_t *cp, iopaddr_t p_dmaPg, int tot_bytes, int rw )
- {
- register caddr_t adr_cfg, adr_norm, adr_amcc;
- register uint_t adr_bits, enable_bits, dmacfg, dmacmd, dmabits;
-
- adr_cfg = cp->conf_adr;
- adr_norm = cp->norm_adr;
- adr_amcc = cp->amcc_adr;
- dmacfg = cp->dmacfg;
- dmacmd = cp->dmacmd;
- dmabits = cp->dmabits;
- cp->dmasize = tot_bytes;
-
- #ifdef DEBUG
- cocoReport ( cp, "before cocoStartProgDma");
- #endif
-
- /* clear eof marks */
- Out32(adr_cfg, dmacfg );
-
- /* ======================
- * board -> memory
- * ====================== */
- if ( rw == B_READ ) {
-
- /* set Amcc counters */
- Out32(adr_amcc+AMCC_OP_REG_MWTC, tot_bytes );
- Out32(adr_amcc+AMCC_OP_REG_MRTC, 0 );
-
- adr_bits = DMAREG_RAMPRWR;
- enable_bits = DMAREG_INTPWEN | DMAREG_WEN;
- dmabits |= DMAREG_PWEN;
-
- }
-
- /* ======================
- * memory -> board
- * ====================== */
- else {
-
- /* set Amcc counters */
- Out32(adr_amcc+AMCC_OP_REG_MRTC, tot_bytes );
- Out32(adr_amcc+AMCC_OP_REG_MWTC, 0 );
-
- adr_bits = DMAREG_RAMPRRD;
- enable_bits = DMAREG_INTPREN | DMAREG_REN;
- dmabits |= DMAREG_PREN;
- }
-
- /* enable chaining */
- dmacfg |= dmabits;
- Out32(adr_cfg, dmacfg );
-
- /* set address of chained list */
- Out32(adr_cfg, dmacfg | DMAREG_RAM | adr_bits );
- Out32(adr_norm, p_dmaPg);
-
- /* start the DMA */
- dmabits |= enable_bits | dmacmd;
- cp->dmabits = dmabits;
-
- #ifdef DEBUG
- cocoReport ( cp, "after cocoStartProgDma");
- #endif
-
- /* pciio_flush_buffers ( cp->vhdl ); */
- nanotime ( &cp->start_time );
- Out32(adr_cfg, dmacfg | dmabits );
-
- }
-
-
- /*************************************************************************
- *** c o c o S t a r t S i n g l e D m a ***
- *************************************************************************
- *
- * Name: cocoStartSingleDma
- *
- * Purpose: Programs the board for Single page DMA (read or write)
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoStartSingleDma ( card_t *cp, alenaddr_t p_addr, size_t p_size, int rw )
- {
-
- register caddr_t adr_cfg, adr_norm, adr_amcc;
- register uint_t adr_bits, enable_bits, dmacfg, dmacmd, dmabits, temp;
- register int tot_words;
-
- adr_cfg = cp->conf_adr;
- adr_norm = cp->norm_adr;
- adr_amcc = cp->amcc_adr;
- dmacfg = cp->dmacfg;
- dmacmd = cp->dmacmd;
- dmabits = cp->dmabits;
- enable_bits = 0;
- cp->dmasize = p_size;
-
- Out32(adr_cfg, dmacfg ); /* clear eof marks */
-
- /*
- * Select read/write count in DMA controller
- * and set the DMA size in 32-bit values
- */
- tot_words = (int)p_size/sizeof(uint_t);
- if ( rw == B_READ ) { /* board -> memory */
- Out32(adr_amcc+AMCC_OP_REG_MWTC, (uint_t)p_size );
- Out32(adr_amcc+AMCC_OP_REG_MRTC, 0xffffffff );
- /* Out32(adr_amcc+AMCC_OP_REG_MRTC, (uint_t)p_size ); */
- dmabits |= DMAREG_WEN;
- Out32(adr_cfg, dmacfg | DMAREG_WCNT);
- }
- else {
- Out32(adr_amcc+AMCC_OP_REG_MRTC, (uint_t)p_size );
- Out32(adr_amcc+AMCC_OP_REG_MWTC, 0xffffffff );
- /* Out32(adr_amcc+AMCC_OP_REG_MWTC, (uint_t)p_size ); */
- dmabits |= DMAREG_REN;
- Out32(adr_cfg, dmacfg | DMAREG_RCNT);
- }
-
- /* set transfer counts in words - -1 since counts down to 0xffff */
- tot_words--;
- Out32(adr_norm, (uint_t)tot_words);
-
- /* select Read/Write Address and set the DMA address */
- if ( rw == B_READ ) {
- Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMWADR); /* b->m */
- }
- else {
- Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMRADR); /* m->b */
- }
- Out32(adr_norm, (uint_t)p_addr );
-
- /* enable the right interrupt */
- if ( rw == B_READ )
- dmabits |= DMAREG_INTWEN; /* board -> memory */
- else dmabits |= DMAREG_INTREN; /* memory -> board */
-
- dmabits |= cp->dmacmd;
- cp->dmabits = dmabits;
-
- #ifdef DEBUG
- cocoReport ( cp, "cocoStartSingleDma exit");
- #endif
-
- /* pciio_flush_buffers ( cp->vhdl ); */
- nanotime ( &cp->start_time);
- Out32(adr_cfg, dmacfg | dmabits );
-
- }
-
-
-
- /*************************************************************************
- *** c o c o M a k e C h a i n ***
- *************************************************************************
- *
- * Name: cocoMakeCHain
- *
- * Purpose: given an alenlist, creates chained list for Prog DMA.
- *
- * Returns: NULL for error or address of chained list
- *
- *************************************************************************/
-
- static coco_dmapage_t *
- cocoMakeChain ( card_t *cp, alenlist_t addrList, int page_no )
- {
- register coco_dmapage_t * dmaPg;
- register int i, tot_words;
- size_t p_size;
- alenaddr_t p_addr;
- iopaddr_t pa;
-
- dmaPg = (coco_dmapage_t *)kmem_alloc (page_no * sizeof(coco_dmapage_t),
- KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
-
- if ( dmaPg == (coco_dmapage_t *)NULL ) {
- cmn_err (CE_NOTE,
- "cocoMakeChain: Not enough mem for chained list");
- return( (coco_dmapage_t *)NULL);
- }
-
- /* fill the chained list with address-size values */
- for ( i = 0; i < page_no; i++ ) {
- if ( alenlist_get(addrList, NULL, NBPP,
- &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN, "cocoMakeChain: Bad alenlist\n");
- return( (coco_dmapage_t *)NULL);
- }
-
-
- pa = pciio_dmatrans_addr ( cp->conn, 0,
- kvtophys(&dmaPg[i+1]),
- sizeof(coco_dmapage_t), 0 );
- dmaPg[i].nextaddr = pa;
- dmaPg[i].addr = p_addr;
- tot_words = (int)p_size/sizeof(uint_t);
- dmaPg[i].size = tot_words - 1;
- }
- dmaPg[i-1].size |= END_OF_CHAIN;
-
- return ( dmaPg );
- }
-
-
- /*************************************************************************
- *** c o c o M a k e C h a i n R W ***
- *************************************************************************
- *
- * Name: cocoMakeCHainRW
- *
- * Purpose: Creates chain list for simultaneous read and write
- * but makes sure we read and write the same amount of bytes
- * in each entry
- *
- * Returns: 0 = Success, or errno
- *
- *************************************************************************/
-
- static int
- cocoMakeChainRW ( card_t *cp,
- coco_dmapage_t **w_dmaPg,
- coco_dmapage_t **r_dmaPg )
-
- {
- register coco_dmapage_t *wp, *rp;
- register alenaddr_t wp_resadr, rp_resadr;
- register iopaddr_t pa;
- register size_t wp_left, rp_left;
- register int i, tot_rchain, tot_wchain, w_page, r_page;
- register int tot_bytes, tot_words;
- size_t wp_size, rp_size;
- alenaddr_t wp_addr, rp_addr;
-
- w_page = cp->w_page_no;
- r_page = cp->r_page_no;
- tot_rchain = r_page * CHAIN_FACTOR;
- tot_wchain = w_page * CHAIN_FACTOR;
-
- wp_resadr = 0;
- rp_resadr = 0;
- wp_left = 0;
- rp_left = 0;
-
- *w_dmaPg = (coco_dmapage_t *)NULL;
- *r_dmaPg = (coco_dmapage_t *)NULL;
-
- /* allocate chain list for Write */
- wp = (coco_dmapage_t *)kmem_alloc (tot_wchain * sizeof(coco_dmapage_t),
- KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
-
- if ( wp == (coco_dmapage_t *)NULL ) {
- cmn_err (CE_WARN, "cocoMakeChainRW: Not enough memory");
- return (ENOMEM);
- }
-
- /* allocate chain list for Read */
- rp = (coco_dmapage_t *)kmem_alloc (tot_rchain * sizeof(coco_dmapage_t),
- KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
-
- if ( rp == (coco_dmapage_t *)NULL ) {
- kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
- cmn_err (CE_WARN, "cocoMakeChainRW: Not enough memory");
- return (ENOMEM);
- }
-
- /* make sure we are at the top of the list */
- alenlist_cursor_init ( cp->r_addrList, NULL, NULL );
- alenlist_cursor_init ( cp->w_addrList, NULL, NULL );
-
- for ( i = 0;; i++ ) {
-
- /* ================================
- * Write address and count
- * ================================ */
-
- /* if no Write bytes left, get a new page */
- if ( wp_resadr == (alenaddr_t)NULL ) {
-
- /* we must have data for write */
- if ( w_page <= 0 ) {
- cmn_err (CE_WARN,
- "cocoMakeChainRW: Premature end of Write, w_page = %d, r_page = %d", w_page, r_page );
-
- kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
- kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
- return(EIO);
- }
-
- if ( alenlist_get(cp->w_addrList, NULL, NBPP,
- &wp_addr, &wp_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN,
- "cocoMakeChainRW: Bad Write alenlist\n");
- kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
- kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
- return(EIO);
- }
- w_page--;
- }
-
- /* some old Write bytes left - use those */
- else {
- wp_addr = wp_resadr;
- wp_size = wp_left;
- }
-
- /* ================================
- * Read address and count
- * ================================ */
-
- /* if no Read bytes left, get a new page */
- if ( rp_resadr == (alenaddr_t)NULL ) {
-
- /* we must have data for read */
- if ( r_page <= 0 ) {
- cmn_err (CE_WARN,
- "cocoMakeChainRW: Premature end of Read, r_page = %d, w_page = %d", r_page, w_page );
-
- kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
- kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
- return(EIO);
- }
-
- if ( alenlist_get(cp->r_addrList, NULL, NBPP,
- &rp_addr, &rp_size, 0) != ALENLIST_SUCCESS ) {
- cmn_err (CE_WARN,
- "cocoMakeChainRW: Bad Read alenlist\n");
- kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
- kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
- return(EIO);
- }
- r_page--;
- }
-
- /* some old Read bytes left - use those */
- else {
- rp_addr = rp_resadr;
- rp_size = rp_left;
- }
-
- /* ====================================
- * Adjust Read and Write counts
- * ==================================== */
-
- wp_resadr = 0;
- rp_resadr = 0;
- wp_left = 0;
- rp_left = 0;
-
- /* Writing and Reading the same amount ? no adjustment */
- if ( wp_size == rp_size ) {
- tot_bytes = wp_size;
- }
-
- /* Writing more than reading ? Adjust Write */
- if ( wp_size > rp_size ) {
- tot_bytes = rp_size;
- wp_resadr = (alenaddr_t)((int)wp_addr + tot_bytes);
- wp_left = wp_size - tot_bytes;
- }
-
- /* Reading more than write ? Adjust Read */
- if ( rp_size > wp_size ) {
- tot_bytes = wp_size;
- rp_resadr = (alenaddr_t)((int)rp_addr + tot_bytes);
- rp_left = rp_size - tot_bytes;
- }
-
-
- /* =======================================
- * Make Read and Write Chain Entries
- * ======================================= */
-
- tot_words = (int)tot_bytes/sizeof(uint_t);
- tot_words--;
-
- /* Make Write Chain entry */
- pa = pciio_dmatrans_addr ( cp->conn, 0,
- kvtophys(&wp[i+1]),
- sizeof(coco_dmapage_t), 0 );
-
- wp[i].nextaddr = pa;
- wp[i].addr = wp_addr;
- wp[i].size = tot_words;
-
- /* Make Write Chain entry */
- pa = pciio_dmatrans_addr ( cp->conn, 0,
- kvtophys(&rp[i+1]),
- sizeof(coco_dmapage_t), 0 );
-
- rp[i].nextaddr = pa;
- rp[i].addr = rp_addr;
- rp[i].size = tot_words;
-
- /* end of Write chain list ? */
- if ( (w_page <=0) && (wp_resadr == (alenaddr_t)NULL) )
- wp[i].size |= END_OF_CHAIN;
-
- /* end of Read chain list ? */
- if ( (r_page <=0) && (rp_resadr == (alenaddr_t)NULL) )
- rp[i].size |= END_OF_CHAIN;
-
- /* end of loop ? */
- if ( (rp[i].size & END_OF_CHAIN) &&
- (wp[i].size & END_OF_CHAIN) )
- break;
-
- /* ran out of memory ? */
- if ( (i >= tot_rchain) || (i >= tot_wchain) ) {
- cmn_err (CE_WARN,
- "cocoMakeChainRW: Ran out of Chain entries");
- kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
- kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
- return(EIO);
- }
-
-
- } /*** for ( i = 0;; i++ ) ***/
-
- *w_dmaPg = wp;
- *r_dmaPg = rp;
-
- return(0);
- }
-
-
- /*************************************************************************
- *** c o c o T i m e O u t ***
- *************************************************************************
- *
- * Name: cocoTimeOut
- *
- * Purpose: We timedout waiting for a read/write interrupt.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoTimeOut ( card_t *cp )
- {
- register uint_t intcsr;
- register int s;
-
- /* someone has the lock ? ignore the timeout */
- if ( ( s = COCO_TRYLOCK(&cp->coco_mlock)) == 0 )
- return;
-
- cmn_err (CE_NOTE, "cocoTimeOut: Read/Write Timed out");
-
- alenlist_done ( cp->addrList );
- cp->addrList = 0;
- cp->iostat = IO_TIME;
-
- bioerror ( cp->bp, ETIME);
- biodone (cp->bp);
- COCO_UNLOCK(&cp->coco_mlock, s);
- }
-
-
- /*************************************************************************
- *** c o c o T i m e O u t 2 ***
- *************************************************************************
- *
- * Name: cocoTimeOut2
- *
- * Purpose: We timedout waiting for a simultaneous read/write intr.
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoTimeOut2 ( card_t *cp )
- {
-
- register int s;
-
- /* someone has the lock ? ignore the timeout */
- if ( (s = COCO_TRYLOCK(&cp->coco_mlock)) == 0 )
- return;
-
- cmn_err (CE_NOTE, "cocoTimeOut2: Sim. Read/Write Timed out");
- cp->iostat = IO_TIME;
- WAKE_EVENT(&cp->coco_sv);
- COCO_UNLOCK(&cp->coco_mlock, s);
- }
-
-
-
- /*
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~~~~~~~~~~ ~~~~~~~~~~~~~
- ~~~~~~~~~~ D e b u g i n g R o u t i n e s ~~~~~~~~~~~~~~
- ~~~~~~~~~~ ~~~~~~~~~~~~~
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
- /*************************************************************************
- *** c o c o I o c t l S t r ***
- *************************************************************************
- *
- * Name: cocoIoctlStr
- *
- * Purpose: return string version of an Ioctl command
- *
- * Returns: pointer to string
- *
- *************************************************************************/
- static char *
- cocoIoctlStr ( int cmd )
- {
- switch ( cmd ) {
- case COCO_MKHWGR: return ("Coco_MkHwGr");
- case COCO_GET_TIME: return ("Coco_Get_Time");
- case COCO_MAP_SIZE: return ("Coco_Map_Size");
- case COCO_COMMAND: return ("Coco_Command");
- case COCO_RAW_READ_FIFO: return ("Raw_Read_Fifo");
- case COCO_RAW_WRITE_FIFO: return ("Raw_Write_Fifo");
- case COCO_RAW_READB_FIFO: return ("Raw_ReadB_Fifo");
- case COCO_RAW_WRITEB_FIFO: return ("Raw_WriteB_Fifo");
- case COCO_FIFO_TEST: return ("Fifo_Test");
- case COCO_SET_MODE: return ("Set_Mode");
- case COCO_READ_MODE: return ("Read_Mode");
- case COCO_RAW_READ_DMA: return ("Raw_Read_Dma");
- case COCO_RAW_WRITE_DMA: return ("Raw_Write_Dma");
- case COCO_READ_ADDR: return ("Read_Addr");
- case COCO_SET_ADDR: return ("Set_Addr");
- case COCO_DMAREGS_TEST: return ("DmaRegs_Test");
- case COCO_INTRAM_TEST: return ("IntRam_Test");
- case COCO_EXTRAM_TEST: return ("ExtRam_Test");
- case COCO_READ_RAMIL: return ("Read_RamIL");
- case COCO_READ_RAMIH: return ("Read_RamIH");
- case COCO_READ_RAMO: return ("Read_RamO");
- case COCO_READ_RAML: return ("Read_RamL");
- case COCO_FILL_RAMIL: return ("Fill_RamIL");
- case COCO_FILL_RAMIH: return ("Fill_RamIH");
- case COCO_FILL_RAMO: return ("Fill_RamO");
- case COCO_FILL_RAML: return ("Fill_RamL");
- case COCO_CONVERT_PIXLE: return ("Convert_Pixle");
- case COCO_CONVERT_TEST: return ("Convert_Test");
- case COCO_SET_SINGLE_DMA: return ("Set_Single_Dma");
- case COCO_SET_PROG_DMA: return ("Set_Prog_Dma");
- case COCO_BLOCK_FILL_RAMIL: return ("Block_Fill_RamIL");
- case COCO_BLOCK_FILL_RAMIH: return ("Block_Fill_RamIH");
- case COCO_BLOCK_FILL_RAML: return ("Block_Fill_RamL");
- case COCO_BLOCK_FILL_RAMO: return ("Block_Fill_RamO");
- case COCO_SETCMD_TRANSP: return ("SetCmd_Transp");
- case COCO_SETCMD_CONVERT: return ("SetCmd_Convert");
- case COCO_RESET: return ("Reset");
- case COCO_RW_BUF: return ("RW_Buff");
- case COCO_ISPCI: return ("Is_PCI");
- default: return ("Unknown");
- }
-
- }
-
-
- /*************************************************************************
- *** c o c o R e p o r t ***
- *************************************************************************
- *
- * Name: cocoReport
- *
- * Purpose: Prints out the bit setting in dmacfg and other status
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoReport ( card_t *cp, char *s )
- {
- register uint_t dmacfg, dmabits, dmacmd, ram;
- register int dmastat, dmatype;
-
- dmacmd = cp->dmacmd;
- dmabits = cp->dmabits;
- dmastat = cp->dmastat;
- dmatype = cp->dmatype;
-
- printf ("%s: ", s );
-
- printf ("dmabits: " );
- if ( dmabits & DMAREG_WEN ) printf ("|Wen");
- if ( dmabits & DMAREG_REN ) printf ("|Ren");
- if ( dmabits & DMAREG_PREN) printf ("|Pren");
- if ( dmabits & DMAREG_PWEN) printf ("|Pwen");
- if ( dmabits & DMAREG_FILL) printf ("|Reg_Fill");
- if ( dmabits & DMAREG_INTWEN) printf ("|IntWen");
- if ( dmabits & DMAREG_INTREN) printf ("|IntRen");
- if ( dmabits & DMAREG_INTPWEN ) printf ("|IntPWen");
- if ( dmabits & DMAREG_INTPREN ) printf ("|IntPRen");
- ram = dmabits & 0x0f000000;
- if ( ram == COCO_FILLRAML) printf ("|Fill_RamL");
- if ( ram == COCO_FILLRAMIL) printf ("|Fill_RamIL");
- if ( ram == COCO_FILLRAMIH) printf ("|Fill_RamIH");
- if ( ram == COCO_FILLRAMO) printf ("|Fill_RamO");
- if ( ram == COCO_TRANSP) printf ("|Transp");
- if ( ram == COCO_CONVERT) printf ("|Convrt");
-
- printf (" dmastat: ", dmastat);
- if ( dmastat == DMA_IDLE ) printf ("Idle");
- if ( dmastat == DMA_LUT_WAIT ) printf ("Dma_Lut_Wait");
- if ( dmastat == DMA_READ_WAIT ) printf ("Dma_Read_Wait");
- if ( dmastat == DMA_WRITE_WAIT ) printf ("Dma_Write_Wait");
- if ( dmastat == DMA_RW_WAIT ) printf ("Dma_RW_Wait");
- printf ("\n");
- }
-
-
- /*************************************************************************
- *** c o c o S h o w C h a i n ***
- *************************************************************************
- *
- * Name: cocoShowChain
- *
- * Purpose: Displays contents of a chain list
- *
- * Returns: None.
- *
- *************************************************************************/
-
- static void
- cocoShowChain( char *title, coco_dmapage_t *dmaPg )
- {
- register int i, tot_bytes, tot_words;
- register long all_bytes;
-
- printf ("--- %s ---\n", title );
- all_bytes = 0;
- for (i = 0;; i++ ) {
- tot_words = dmaPg[i].size;
- tot_bytes = ( (tot_words &~END_OF_CHAIN) +1) * sizeof(uint_t);
- all_bytes += tot_bytes;
- printf ("addr = 0x%x, size = %d next addr = 0x%x %s\n",
- dmaPg[i].addr, tot_bytes, dmaPg[i].nextaddr,
- tot_words & END_OF_CHAIN ? "[ End ]":" " );
-
- if ( tot_words & END_OF_CHAIN )
- break;
- }
- printf ("--- Total of %d entries, %d bytes ---\n\n", i, all_bytes );
-
- }
-
- /*************************************************************************
- *** c o c o D u m p A m c c ***
- *************************************************************************
- *
- * Name: cocoDumpAmcc
- *
- * Purpose: Dumps Amcc registers for debugging purpose.
- *
- * Returns: None.
- *
- *************************************************************************/
-
- static void
- cocoDumpAmcc ( card_t *cp )
- {
- register caddr_t amcc_adr, norm_adr, cfg_adr;
- register uint_t dmacfg, xil_stat, war, wcnt, rar, rcnt, mbef;
-
- amcc_adr = cp->amcc_adr;
- norm_adr = cp->norm_adr;
- cfg_adr = cp->conf_adr;
- dmacfg = cp->dmacfg;
-
- /* disable any Dma and read in Xilinx status */
- Out32(cfg_adr, dmacfg | DMAREG_STAT );
- /* xil_stat = Inp32(norm_adr); */
- war = Inp32(amcc_adr+AMCC_OP_REG_MWAR);
- wcnt = Inp32(amcc_adr+AMCC_OP_REG_MWTC);
- rar = Inp32(amcc_adr+AMCC_OP_REG_MRAR);
- rcnt = Inp32(amcc_adr+AMCC_OP_REG_MRTC);
- mbef = Inp32(amcc_adr+AMCC_OP_REG_MBEF);
-
- wcnt &= 0x01ffffff;
- rcnt &= 0x01ffffff;
- printf ("*** cocoDumpAmcc ***\n");
- printf ("WAR = 0x%x WTC = %d [ 0x%x ]\n", war, wcnt, wcnt );
- printf ("RAR = 0x%x RTC = %d [ 0x%x ]\n", rar, rcnt, rcnt );
- /* printf ("MBEF = 0x%x Xilinx = 0x%x\n", mbef, xil_stat ); */
- }
-
- /*************************************************************************
- *** c o c o S h o w A l e n l i s t ***
- *************************************************************************
- *
- * Name: cocoShowAlenlist
- *
- * Purpose: Displayes the contents of a given Alenlist
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoShowAlenlist ( caddr_t title, alenlist_t al )
- {
- size_t size;
- long tot_bytes;
- alenaddr_t addr;
- register int count, i;
-
- /* reset the cursor for the alenlist */
-
- alenlist_cursor_init ( al, NULL, NULL );
- printf ("cocoShowAlenlist: --- %s ---\n", title );
-
- tot_bytes = 0;
- count = 0;
- for ( ;; ) {
- if ( alenlist_get(al, NULL, NBPP, &addr, &size, 0) !=
- ALENLIST_SUCCESS ) {
- break;
- }
- printf ("addr = 0x%x, size = %d ...[%d]\n",addr, size, count );
- tot_bytes += size;
- count++;
- }
- printf ("--- Total of %d bytes [ %d entries ]---\n\n",
- tot_bytes, count );
-
- /* reset the cursor now */
- alenlist_cursor_init ( al, NULL, NULL );
- }
-
-
- /*************************************************************************
- *** c o c o A l e n l i s t S i z e ***
- *************************************************************************
- *
- * Name: cocoAlenlistSize
- *
- * Purpose: Returns number of pairs in a given alenlist.
- *
- * Returns: Number of address/size entries
- *
- *************************************************************************/
- static int
- cocoAlenlistSize ( alenlist_t al )
- {
- register int count;
- size_t size;
- alenaddr_t addr;
-
- alenlist_cursor_init ( al, NULL, NULL );
- count = 0;
- for ( ;; ) {
- if ( alenlist_get(al, NULL, NBPP, &addr, &size, 0) !=
- ALENLIST_SUCCESS ) {
- break;
- }
- count++;
- }
- alenlist_cursor_init ( al, NULL, NULL );
-
- return (count);
- }
-
- /*************************************************************************
- *** c o c o _ c o p y i n _ b u f ***
- *************************************************************************
- *
- * Name: coco_copyin_buf
- *
- * Purpose: Copyes the correct coco_buf_t structure to kernel space
- * from user's space.
- *
- * Returns: 0 or errno
- *
- *************************************************************************/
- static int
- coco_copyin_buf ( card_t *cp, void *arg, coco_buf_t *coco_buf )
- {
- coco_buf32_t coco_buf32;
-
- /* 32bit application */
- if ( cp->user_abi == ABI_IRIX5_N32 ) {
-
- if ( copyin( (void *)arg, (void *)&coco_buf32,
- sizeof(coco_buf32_t) ) )
- return (EFAULT);
-
- coco_buf->buf_size = coco_buf32.buf_size;
- coco_buf->buf = (uint_t *)coco_buf32.buf;
- return(0);
- }
-
- /* 64-bit application */
- if ( copyin( (void *)arg, (void *)coco_buf, sizeof(coco_buf_t) ) )
- return (EFAULT);
-
- return(0);
- }
-
-
- /*************************************************************************
- *** c o c o _ c o p y i n _ r w ***
- *************************************************************************
- *
- * Name: coco_copyin_rw
- *
- * Purpose: Copyes the correct coco_rw_t structure to kernel space
- * from user's space.
- *
- * Returns: 0 or errno
- *
- *************************************************************************/
- static int
- coco_copyin_rw ( card_t *cp, caddr_t arg, coco_rw_t *coco_rw )
- {
- coco_rw32_t coco_rw32;
-
- /* 32bit application */
- if ( cp->user_abi == ABI_IRIX5_N32 ) {
-
- if ( copyin( (char *)arg, &coco_rw32, sizeof(coco_rw32_t) ) )
- return (EFAULT);
-
- coco_rw->buf_size = coco_rw32.buf_size;
- coco_rw->adjust_chain = coco_rw32.buf_size;
- coco_rw->r_buf = (uint_t *)coco_rw32.r_buf;
- coco_rw->w_buf = (uint_t *)coco_rw32.w_buf;
- return(0);
- }
-
- /* 64-bit application */
- if ( copyin( (char *)arg, coco_rw, sizeof(coco_rw_t) ) )
- return (EFAULT);
-
- return(0);
- }
-
-
- #ifdef DEBUGTIME
- /*************************************************************************
- *** c o c o R e p o r t T i m e ***
- *************************************************************************
- *
- * Name: cocoReportTime
- *
- * Purpose: Displays start, intr and end time of Dma
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoReportTime ( caddr_t title, card_t *cp, int final )
- {
-
- register struct timespec *tv;
- struct timespec dtv;
- coco_timeval_t st;
- coco_timeval_t et;
- coco_timeval_t dt;
-
- /* report start and interrupt of DMA */
- if ( final == 0 ) {
- cocoDiffTime ( &cp->start_time, &cp->intr_time, &dtv );
- cocoConvTime ( &dtv, &dt );
- cocoConvTime ( &cp->start_time, &st );
- cocoConvTime ( &cp->intr_time, &et );
-
- printf ("\n%s: %s DMA, %d Bytes\n",
- title, cp->dmatype == DMA_PROG ? "Chain":"Single", cp->dmasize );
-
- printf ("Start:\t%8dm %8du %8dn\n",
- st.coco_msec, st.coco_usec, st.coco_nsec);
- printf ("Intrp:\t%8dm %8du %8dn\n",
- et.coco_msec, et.coco_usec, et.coco_nsec);
- printf ("Diff:\t%8dm %8du %8dn\n",
- dt.coco_msec, dt.coco_usec, dt.coco_nsec );
- return;
- }
-
-
- /* report the time difference of call came in and return time */
- cocoDiffTime ( &cp->call_time, &cp->ret_time, &dtv );
- cocoConvTime ( &dtv, &dt );
- cocoConvTime ( &cp->call_time, &st );
- cocoConvTime ( &cp->ret_time, &et );
-
- printf ("\n%s: final Call analysis\n", title );
- printf ("Call:\t%8dm %8du %8dn\n",
- st.coco_msec, st.coco_usec, st.coco_nsec );
- printf ("Ret:\t%8dm %8du %8dn\n",
- et.coco_msec, et.coco_usec, et.coco_nsec );
- printf ("Diff:\t%8dm %8du %8dn\n",
- dt.coco_msec, dt.coco_usec, dt.coco_nsec );
-
- }
- #endif
-
-
- /*************************************************************************
- *** c o c o D i f f T i m e ***
- *************************************************************************
- *
- * Name: cocoDiffTime
- *
- * Purpose: Given two timespec struct, it calculates the difference
- *
- * Returns: None.
- *
- *************************************************************************/
-
- static void
- cocoDiffTime ( struct timespec *st, struct timespec *et, struct timespec *dt )
- {
-
- register long s_sec, e_sec;
- register long s_totn, e_totn, diff_n;
-
- s_sec = st->tv_sec;
- s_totn = (s_sec * 1000000000L) + st->tv_nsec;
-
- e_sec = et->tv_sec;
- e_totn = (e_sec * 1000000000L) + et->tv_nsec;
-
- diff_n = e_totn - s_totn;
-
- dt->tv_sec = 0;
- dt->tv_nsec = diff_n;
-
- if ( diff_n > 1000000000L ) {
- dt->tv_sec = diff_n / 1000000000L;
- dt->tv_nsec = diff_n % 1000000000L;
- }
- }
-
-
- /*************************************************************************
- *** c o c o C o n v T i m e ***
- *************************************************************************
- *
- * Name: cocoConvTime
- *
- * Purpose: Converts a timespec_t to coco_timeval_t
- *
- * Returns: None.
- *
- *************************************************************************/
- static void
- cocoConvTime ( struct timespec *ts, coco_timeval_t *ct )
- {
- long totn, sec, msec, usec, nsec;
-
- totn = (ts->tv_sec * 1000000000L) + ts->tv_nsec;
- sec = msec = usec = nsec = 0;
-
- /* round up nano to micro */
- if ( totn > 1000L ) {
- usec = totn / 1000L;
- nsec = totn % 1000L;
- }
-
- /* round up micro to mili */
- if ( usec > 1000L ) {
- msec = usec / 1000L;
- usec = usec % 1000L;
- }
-
-
- /* round up mili to seconds */
- if ( msec > 1000L ) {
- sec = msec / 1000L;
- msec = msec % 1000L;
- }
-
- ct->coco_sec = sec;
- ct->coco_msec = msec;
- ct->coco_usec = usec;
- ct->coco_nsec = nsec;
-
- }
-
-
- /*************************************************************************
- *** c o c o M k H w G r a p h ***
- *************************************************************************
- *
- * Name: cocoMakeHwGraph
- *
- * Purpose: Make Nodes off of /hw for our card.
- *
- * Returns: None.
- *
- *************************************************************************/
-
- static void
- cocoMakeHwGraph ( card_t *cp )
- {
- register int ret, ctl;
- char cname[25];
-
- ctl = device_controller_num_get ( cp->vhdl );
- sprintf ( cname, "coco%d", ctl );
-
- ret = hwgraph_edge_add ( hwgraph_root, cp->vhdl, cname );
- if ( ret != GRAPH_SUCCESS ) {
- cmn_err (CE_WARN, "cocoMakeHwGraph: Cannot create node %s", cname );
- return;
- }
-
- cmn_err (CE_NOTE, "cocoMakeHwGraph: Created node /hw/%s", cname );
- }
-
-