home *** CD-ROM | disk | FTP | other *** search
/ More Insanity: Totally Insane 2 / totally_insane_ii.iso / src / PCIdriver / coco.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-29  |  138.6 KB  |  4,636 lines

  1. /******************************************************************************
  2.  *****        C h a m e l e o n   I r i x  P c i   D r i v e r          *****
  3.  *****                                      *****
  4.  ******************************************************************************
  5. */
  6. #include <sys/types.h>
  7. #include "sys/cmn_err.h"
  8. #include "sys/sema.h"    
  9. #include <sys/param.h>
  10. #include <sys/errno.h>
  11. #include <sys/syslog.h>
  12. #include <sys/conf.h>
  13. #include <sys/pio.h>
  14. #include "sys/systm.h"
  15. #include <sys/time.h>
  16. #include <sys/ksynch.h>
  17. #include <sys/ktime.h>
  18. #include <sys/invent.h>
  19. #include <sys/kmem.h> 
  20. #include <sys/kabi.h>
  21. #include <sys/mload.h>
  22. #include <sys/ddi.h>
  23. #include <sys/cred.h>
  24. #include <sys/immu.h>
  25. #include <sys/region.h>
  26. #include <sys/alenlist.h>
  27. #include <sys/ioerror.h>
  28. #include <sys/PCI/PCI_defs.h>
  29. #include <sys/PCI/pciio.h>
  30.  
  31. #include "coco.h"
  32. #include "coco_user.h"
  33.  
  34. /*  ddi/dki and irix required  */
  35. char   *coco_mversion = M_VERSION;   /*  loadable driver requirement */
  36. int    coco_devflag = D_MP;            /*  ddi/dki requirement         */
  37.  
  38. /* ======================================
  39.  *    Device Driver/PCI entry routines 
  40.  * ====================================== */
  41. int coco_unload(void);
  42. int coco_open(dev_t *, int, int, cred_t *);
  43. int coco_close(dev_t, int, int, cred_t *);
  44. int coco_read( dev_t, uio_t *, cred_t *);
  45. int coco_write( dev_t, uio_t *, cred_t *);
  46. int coco_ioctl(dev_t, int, void *, int, cred_t *, int *);
  47. int coco_map ( dev_t, vhandl_t *, off_t, size_t, uint_t );
  48. int coco_unmap ( dev_t, vhandl_t * );
  49. int coco_init();
  50. int coco_reg(void);
  51. int coco_reg(void);
  52.  
  53. int coco_attach(vertex_hdl_t);
  54. int coco_detach(vertex_hdl_t);
  55.  
  56. /*
  57.  *    Our error handler and interrupt handler
  58.  *      Note: We do not set any error handler
  59.  */
  60. static error_handler_f coco_error;
  61. void coco_intr( intr_arg_t ); 
  62.  
  63.  
  64. /* =================================
  65.  *   Supporting internal routines 
  66.  * ================================= */
  67. static void cocoReset( card_t  * );
  68. static void cocoProgFlags ( caddr_t, uint_t, ushort_t, ushort_t, ushort_t, 
  69.                 ushort_t);
  70. static void cocoSetMode ( card_t *, int, int, int, int );
  71. static void cocoCommand ( card_t *, uint_t, uint_t );
  72. static void cocoBufOut ( card_t *, uint_t *, int );
  73. static void cocoBufIn  ( card_t *, uint_t *, int );
  74. static void cocoReadDmaRegs ( card_t *, uint_t * );
  75. static void cocoWriteDmaRegs ( card_t *, uint_t * );
  76. static void cocoSetAddr ( card_t *, uint_t );
  77. static void cocoReadIntRam ( card_t *, uint_t *, int, int );
  78. static void cocoWriteIntRam ( card_t *, uint_t *, int, int );
  79. static void cocoReadExtRam ( card_t *, uint_t *, int );
  80. static void cocoWriteExtRam ( card_t *, uint_t *, int );
  81. static void cocoConvert ( card_t *, uint_t );
  82. static void cocoConvertTest ( card_t *, coco_convert_t *);
  83. static void cocoPrepAmcc ( card_t * );
  84. static void cocoResetAmcc ( card_t *);
  85. static void cocoStartProgDma ( card_t *, iopaddr_t, int, int );
  86. static void cocoStartSingleDma ( card_t *, alenaddr_t, size_t, int );
  87. static void cocoReport ( card_t *, char * );
  88. static void cocoShowChain( char *, coco_dmapage_t * );
  89. static void cocoTimeOut( card_t *); 
  90. static void cocoTimeOut2( card_t *); 
  91. static void cocoDumpAmcc ( card_t *);
  92. static void cocoReportTime ( caddr_t, card_t *, int );
  93. static void cocoShowAlenlist ( caddr_t, alenlist_t );
  94. static void cocoUnlockUser ( caddr_t, int, int );
  95. static void cocoTestLock ( card_t * );
  96. static void cocoTestNorm ( card_t * );
  97. static void cocoConvTime ( struct timespec *, coco_timeval_t * );
  98. static void cocoMakeHwGraph ( card_t *);
  99.  
  100. static void cocoDiffTime ( struct timespec *, struct timespec *, 
  101.                struct timespec *);
  102.  
  103. static int cocoStrategy ( buf_t * );
  104. static int  cocoReadAmccFifo ( card_t  * );
  105. static int  cocoFifoTest ( card_t *, int );
  106. static int  cocoPattern ( int, int );
  107. static int  cocoReadMode ( card_t * );
  108. static int  cocoReadAddr (card_t *);
  109. static int  cocoDmaRegsTest ( card_t * );
  110. static int  cocoIntRamTest ( card_t * );
  111. static int  cocoExtRamTest ( card_t * );
  112. static int  cocoDmaToLuts( card_t *, coco_buf_t *, int );
  113. static int  cocoReadWrite( card_t *, coco_rw_t * );
  114. static int  cocoStartRWDma ( card_t *, iopaddr_t, int, iopaddr_t, int );
  115. static int  cocoMakeChainRW ( card_t *, coco_dmapage_t **, coco_dmapage_t **);
  116. static int  cocoAlenlistSize ( alenlist_t );
  117. static int  cocoLockUser ( caddr_t, int, int );
  118. static int  coco_copyin_buf ( card_t *, void *, coco_buf_t * );
  119. static int  coco_copyin_rw  ( card_t *, caddr_t, coco_rw_t * );
  120.  
  121. static coco_dmapage_t * cocoMakeChain ( card_t *, alenlist_t, int );
  122. static char *cocoIoctlStr(int);
  123.  
  124.  
  125.  
  126. /*
  127. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  128. ~~~~~~~~~~~                             ~~~~~~~~~~~~~
  129. ~~~~~~~~~~~    D r i v e r ' s    E n t r y    R o u t i n e s   ~~~~~~~~~~~~~~
  130. ~~~~~~~~~~~                             ~~~~~~~~~~~~~
  131. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  132. */
  133.  
  134. /*************************************************************************
  135.  ***                   c o c o _  i n i t                              ***
  136.  *************************************************************************
  137.  *
  138.  *  Name:       coco_init
  139.  *
  140.  *  Purpose:    Called by kernel. For Irix6.4 only: We do not register
  141.  *        here but we will do it in coco_reg. For init, we simply
  142.  *        do nothing.
  143.  *
  144.  *  Returns:    None
  145.  *
  146.  *************************************************************************/
  147. int
  148. coco_init()
  149. {
  150.     return(0);
  151. }
  152.  
  153. /*************************************************************************
  154.  ***                   c o c o _  r e g                                ***
  155.  *************************************************************************
  156.  *
  157.  *  Name:       coco_reg 
  158.  *
  159.  *  Purpose:    Called by kernel when the driver is loaded.
  160.  *        Here we register ourselves for the card, identified by
  161.  *        Vendor and Device ID. 
  162.  *              
  163.  *  Note:       This is for Irix6.4 only.
  164.  *
  165.  *  Returns:    None
  166.  *
  167.  *************************************************************************/
  168. int
  169. coco_reg()
  170. {
  171.     register int  ret;
  172.  
  173.     /*    Register and identify the card   */
  174.     ret = pciio_driver_register(VENDOR_ID, DEVICE_ID, DRIVER_PREFIX, 0);
  175.  
  176.     if ( ret ) {
  177.     cmn_err (CE_WARN, "coco_reg: registration returned %d", ret );
  178.     }
  179.  
  180.     return(ret);
  181. }
  182.  
  183. /*************************************************************************
  184.  ***                   c o c o _ a t t a c h                           ***
  185.  *************************************************************************
  186.  *
  187.  *  Name:    coco_attach
  188.  *
  189.  *  Purpose:    Called by the kernel. Our card is installed and hence
  190.  *        we are called. Prepare everything necessary to handle 
  191.  *        the card. Note that when the card is found, the following
  192.  *        is set in the Command field of Config space:    
  193.  *            - Bus master enabled/
  194.  *            - Memory and IO space access enabled.
  195.  *            - Cache line is set to 0x20 (32) 
  196.  *            - Latency Timer is set to 0x30 (48)
  197.  *
  198.  *        For Chameleon, beside Configuration address space, we need 4 
  199.  *            Memory address spaces to be mapped:
  200.  *           Base_Reg 0 = AMCC Registers and Fifos
  201.  *           Base_Reg 3 = Normal DMA registers
  202.  *           Base_Reg 4 = Configuration Register.
  203.  *
  204.  *  Returns:    0 for Success, or errno 
  205.  *
  206.  *************************************************************************/
  207. int
  208. coco_attach(vertex_hdl_t conn)
  209. {
  210.  
  211.     card_t       *cp;
  212.     caddr_t           cfg_adr, mem_ptr, amcc_adr, conf_adr, norm_adr;
  213.     pciio_piomap_t   cfg_map, amcc_map, conf_map, norm_map;
  214.     register int     ret, i;
  215.     uint_t           vendor_id, device_id, base_reg, cmd_reg, tmp_int;
  216.     vertex_hdl_t     coco_vhdl;
  217.     device_desc_t    dev_desc;
  218.  
  219.     /* dev_desc = device_desc_default_get(conn); */
  220.     dev_desc    = 0;
  221.  
  222.     /* =========================
  223.      *    Configuration Space   
  224.      * ========================= */
  225.  
  226.     cfg_map = (pciio_piomap_t)NULL;
  227.     cfg_adr = (caddr_t)pciio_pio_addr ( 
  228.         conn,            /*  connection vertex      */
  229.         dev_desc,        /*  default device descr.  */ 
  230.         PCIIO_SPACE_CFG, /* config space wanted     */
  231.         0,         /* from the start of space */
  232.         COCO_CONFIG_HDR, /* for this many bytes     */
  233.         &cfg_map,     /* in case we need piomap  */
  234.         0);         /* unused flag             */
  235.  
  236.     if ( cfg_adr == (caddr_t)NULL ) {
  237.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  238.         cmn_err ( CE_WARN, "coco_attach: Cannot get to Config space");
  239.     return(EIO);
  240.     }
  241.  
  242.     
  243.     /* ===============================
  244.      *   Configuration data printout
  245.      * =============================== */
  246.  
  247.     /*  vendor_id, device_id  */
  248.     tmp_int   = Inp32(cfg_adr);
  249.     vendor_id = tmp_int & 0x0000ffff;
  250.     device_id = tmp_int >> 16;
  251.  
  252.     #ifdef DEBUG
  253.     printf ("coco_attach:  Config values\n");
  254.     printf ("vendor_id = 0x%x, device_id = 0x%x\n", vendor_id, device_id );
  255.  
  256.     /*  command and status  */
  257.     tmp_int   = Inp32(cfg_adr + 0x04);
  258.     printf ("Command   = 0x%x, Status    = 0x%x\n", (tmp_int & 0x0000ffff),
  259.         (tmp_int >> 16) );
  260.  
  261.     /*  interrupt line and pin   */
  262.     tmp_int   = Inp32(cfg_adr + 0x3c);
  263.     printf ("Int Line = %d, Int Pin = %d\n", (tmp_int & 0x000000ff),
  264.         (tmp_int & 0x0000ff00) >> 8 );
  265.  
  266.     /*  cache line size and latency timer  */
  267.     tmp_int = Inp32(cfg_adr + 0x0c);
  268.     printf ("Cache line size = %d,  latency timer = %d\n",
  269.             (tmp_int & 0x000000ff), (tmp_int & 0x0000ff00) >> 8 );
  270.  
  271.     /*  all 6 base registers  */
  272.     for ( i = 0; i < 6; i++ ) {
  273.       printf ("Base_Reg_%d = 0x%x\n", i, Inp32(cfg_adr+0x10+(i*4)) );
  274.     }
  275.     #endif
  276.  
  277.     /* ==========================
  278.      *    AMCC Registers     
  279.      * ========================== */
  280.  
  281.     /*  Get Amcc Register addresses */
  282.     amcc_map = (pciio_piomap_t)NULL;
  283.     amcc_adr = (caddr_t)pciio_pio_addr ( 
  284.                 conn,             /* connection vertext      */
  285.         dev_desc,           /* default device descr.   */ 
  286.                 PCIIO_SPACE_WIN(0), /* Base register 0 space   */
  287.                 0,                  /* from the start of space */
  288.                 AMCC_RAM_SIZE,      /* for this many bytes     */
  289.                 &amcc_map,          /* in case we need piomap  */
  290.                 0);                 /* unused flag             */
  291.  
  292.     if ( amcc_adr == (caddr_t)NULL ) {
  293.         cmn_err(CE_WARN, "coco_attach: Cannot get to AMCC address space");
  294.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  295.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  296.     return (EIO);
  297.     }
  298.  
  299.  
  300.     /* ================================
  301.      *       DMA Configuration Registers 
  302.      * ================================ */
  303.     conf_map = (pciio_piomap_t)NULL;
  304.     conf_adr = (caddr_t)pciio_pio_addr (   
  305.                 conn,             /* connection vertext      */
  306.         dev_desc,           /* default device descr.   */ 
  307.                 PCIIO_SPACE_WIN(4), /* Base register 4 space   */
  308.                 0,                  /* from the start of space */
  309.                 CONFIG_RAM_SIZE,    /* for this many bytes     */
  310.                 &conf_map,          /* in case we need piomap  */
  311.                 0);                 /* unused flag             */
  312.  
  313.  
  314.     if ( conf_adr == (caddr_t)NULL ) {
  315.     cmn_err(CE_WARN, "coco_attach: Cannot get to Config Register");
  316.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  317.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  318.         if ( conf_map ) pciio_piomap_done ( conf_map );
  319.         return (EIO);
  320.     }
  321.  
  322.  
  323.     /* ================================
  324.      *    Normal DMA registers 
  325.      * ================================ */
  326.     norm_map = (pciio_piomap_t)NULL;
  327.     norm_adr = (caddr_t)pciio_pio_addr (   
  328.                 conn,               /* connection vertext      */
  329.                 dev_desc,           /* default device descr.   */
  330.                 PCIIO_SPACE_WIN(3), /* Base register 3 space */
  331.                 0,                  /* from the start of space */
  332.                 NORMAL_DMA_RAM_SIZE,/* for this many bytes     */
  333.                 &norm_map,          /* in case we need piomap  */
  334.                 0);                 /* unused flag             */
  335.  
  336.  
  337.     if ( norm_adr == (caddr_t)NULL ) {
  338.         cmn_err(CE_WARN, "coco_attach: Cannot get to Normal DMA address");
  339.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  340.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  341.         if ( conf_map ) pciio_piomap_done ( conf_map );
  342.         if ( norm_map ) pciio_piomap_done ( norm_map );
  343.         return (EIO);
  344.     }
  345.  
  346.  
  347.     /*  allocate an internal structure for this card and save everything */
  348.     cp = (card_t *)kmem_zalloc ( sizeof(card_t), KM_NOSLEEP ); 
  349.     if ( cp == (card_t *)NULL ) {
  350.         cmn_err(CE_WARN, "coco_attach: Cannot allocate memory");
  351.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  352.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  353.         if ( conf_map ) pciio_piomap_done ( conf_map );
  354.         if ( norm_map ) pciio_piomap_done ( norm_map );
  355.     return(ENOMEM);
  356.     }
  357.  
  358.     #ifdef DEBUG
  359.     printf ("coco_attach: amcc_adr = 0x%x,     conf_adr = 0x%x\n",
  360.         amcc_adr, conf_adr );
  361.     printf ("             cfg_adr  = 0x%x,     norm_adr = 0x%x\n",
  362.         cfg_adr, norm_adr );
  363.  
  364.     printf ("Maps allocated: %s %s %s %s\n",
  365.         amcc_map ? "Amcc":"",
  366.         norm_map ? "Norm":"",
  367.         conf_map ? "Conf":"",
  368.         cfg_map  ? "Cfg":"" );
  369.     #endif
  370.  
  371.     cp->conn     = conn;
  372.     cp->cfg_adr  = cfg_adr;
  373.     cp->amcc_adr = amcc_adr;
  374.     cp->conf_adr = conf_adr;
  375.     cp->norm_adr = norm_adr;
  376.     cp->amcc_map = amcc_map;
  377.     cp->norm_map = norm_map;
  378.     cp->conf_map = conf_map;
  379.     cp->cfg_map  = cfg_map; 
  380.     cp->kernel_abi = get_current_abi();  /* ABI_IRIX5_64 for 64-bit kernel */ 
  381.  
  382.     /*  initialize our mutex lock and sv_t for sleep/wake  */
  383.     COCO_LOCK_INIT(&cp->coco_mlock);
  384.     SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );  
  385.  
  386.     /*    create a vertex for our device off of the connection point */
  387.     ret = hwgraph_char_device_add(conn, "coco", "coco_", &coco_vhdl );
  388.     if ( ret != GRAPH_SUCCESS ) {
  389.         cmn_err (CE_WARN, "coco_attach: could not addr vertex");
  390.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  391.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  392.         if ( conf_map ) pciio_piomap_done ( conf_map );
  393.         if ( norm_map ) pciio_piomap_done ( norm_map );
  394.     kmem_free ( cp, sizeof(card_t) );
  395.         return(EIO);
  396.     }
  397.  
  398.     hwgraph_chmod( coco_vhdl, 0666 );
  399.     cp->vhdl     = coco_vhdl;      
  400.  
  401.     /*  once ioconfig and COCO_MKHWGRAPH works, remove this area  */
  402.     ret =  hwgraph_edge_add ( hwgraph_root, coco_vhdl, "coco" ); 
  403.     if ( ret != GRAPH_SUCCESS ) {
  404.             cmn_err (CE_WARN, "coco_attach: Cannot create node /hw/coco");
  405.     }
  406.  
  407.  
  408.     
  409.     /* =====================================
  410.      *     Interrupt Handler Registration
  411.      * ===================================== */
  412.     cp->dev_intr = pciio_intr_alloc ( conn, dev_desc, 
  413.                       PCIIO_INTR_LINE_A,
  414.                       coco_vhdl );
  415.  
  416.     if (cp->dev_intr == (pciio_intr_t)NULL){
  417.     cmn_err(CE_WARN, "coco_attach: Can't pciio_intr_alloc");
  418.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  419.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  420.         if ( conf_map ) pciio_piomap_done ( conf_map );
  421.         if ( norm_map ) pciio_piomap_done ( norm_map );
  422.         kmem_free ( cp, sizeof(card_t) );
  423.         hwgraph_edge_remove(conn, "coco", &coco_vhdl);
  424.         device_info_set ( coco_vhdl, 0 );
  425.         hwgraph_vertex_destroy ( coco_vhdl );
  426.     return(EIO);
  427.     }
  428.  
  429.     ret = pciio_intr_connect ( cp->dev_intr, (intr_func_t)coco_intr,  
  430.                    (intr_arg_t)cp, 0 );
  431.  
  432.     if ( ret != 0 ) {
  433.         cmn_err(CE_WARN, "coco_attach: Cannot register interrupt handler");
  434.         if ( cfg_map )  pciio_piomap_done ( cfg_map );
  435.         if ( amcc_map ) pciio_piomap_done ( amcc_map );
  436.         if ( conf_map ) pciio_piomap_done ( conf_map );
  437.         if ( norm_map ) pciio_piomap_done ( norm_map );
  438.     kmem_free ( cp, sizeof(card_t) );
  439.         hwgraph_edge_remove(conn, "coco", &coco_vhdl);
  440.         device_info_set ( coco_vhdl, 0 );
  441.         hwgraph_vertex_destroy ( coco_vhdl );
  442.         return (EIO);
  443.     }
  444.  
  445.    /* ========================================
  446.     *    Register an error handler for 6.4
  447.     * ======================================== */
  448.  
  449. #if 0
  450.     pciio_error_register(conn, (error_handler_f *)coco_error, cp );
  451. #endif
  452.  
  453.     cp->status   = CARD_ATTACHED; 
  454.  
  455.     /*   allocate memory for mapping   */
  456.     for ( i = MAP_PAGES; i > 0; i-- ) {
  457.          cp->mappedkv = kmem_alloc (i * NBPP,
  458.                    KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
  459.         if ( cp->mappedkv != (caddr_t)NULL )
  460.         break;    
  461.     } 
  462.     if ( cp->mappedkv == (caddr_t)NULL ) {
  463.             cmn_err (CE_NOTE, "coco_attach: Not enough memory for mapping"); 
  464.         cmn_err (CE_WARN, "coco_attach: No mapping is allowed");
  465.     }
  466.     else {
  467.         cp->mappedkvlen = i * NBPP; 
  468.         cmn_err (CE_NOTE, "coco_attach: %d bytes allocated, %d available for mapping",
  469.          cp->mappedkvlen, cp->mappedkvlen - LESS_MAP );
  470.     }
  471.  
  472.     /*  save our structure  */
  473.     device_info_set ( coco_vhdl, (void *)cp );
  474.  
  475.     cmn_err ( CE_NOTE, "coco_attach: driver is ready");
  476.     return(0);
  477. }    
  478.  
  479. /*************************************************************************
  480.  ***                   c o c o _ d e t a c h                           ***
  481.  *************************************************************************
  482.  *
  483.  *  Name:       coco_detach
  484.  *
  485.  *  Purpose:    Detaches a driver. Called by the pciio infrastructure
  486.  *        once for each vertext representing a crosstalk widget
  487.  *        when unregistering the driver. 
  488.  *
  489.  *  Returns:    0 Success or errno
  490.  *
  491.  *************************************************************************/
  492.  
  493. int 
  494. coco_detach(vertex_hdl_t conn)
  495. {
  496.     register card_t       *cp;
  497.     vertex_hdl_t        vhdl;
  498.  
  499.     if ( hwgraph_traverse(conn, "coco", &vhdl) != GRAPH_SUCCESS ) 
  500.     return(-1);
  501.  
  502.     cmn_err(CE_NOTE, 
  503.        "coco_detach: Unregister Interrupt handler and free up mem");
  504.  
  505.     cp = (card_t *)device_info_get ( vhdl );
  506.  
  507.     /*  our struct is there ? clean up our driver's stuff */
  508.     if ( cp != (card_t *)NULL ) {
  509.  
  510.          /*  free up memory for mapping   */
  511.          if ( cp->mappedkv )
  512.               kmem_free ( cp->mappedkv, cp->mappedkvlen );
  513.  
  514.          /*  Unregister the Interrupt Handler  */
  515.          pciio_intr_disconnect(cp->dev_intr);
  516.          pciio_intr_free(cp->dev_intr);
  517. #if 0
  518.      /*  unregister error handler  */
  519.          pciio_error_register(conn, 0, 0);
  520. #endif
  521.  
  522.          /*  free up all our maps  */
  523.          if ( cp->cfg_map )  pciio_piomap_done ( cp->cfg_map );
  524.          if ( cp->amcc_map ) pciio_piomap_done ( cp->amcc_map );
  525.          if ( cp->conf_map ) pciio_piomap_done ( cp->conf_map );
  526.          if ( cp->norm_map ) pciio_piomap_done ( cp->norm_map );
  527.  
  528.      /*  free up the struct itself  */
  529.          kmem_free ( cp, sizeof(card_t) );
  530.  
  531.     }
  532.  
  533.     /*  free up our vertextes   */ 
  534.     hwgraph_edge_remove ( hwgraph_root, "coco", &vhdl);
  535.     hwgraph_edge_remove(conn, "coco", &vhdl);
  536.     device_info_set ( vhdl, 0 );
  537.     hwgraph_vertex_destroy ( vhdl );
  538.  
  539.     return(0);
  540. }
  541.  
  542. /*************************************************************************
  543.  ***                   c o c o _ i n t r                               ***
  544.  *************************************************************************
  545.  *
  546.  *  Name:       coco_intr  
  547.  *
  548.  *  Purpose:    Our interrupt handler. 
  549.  *
  550.  *  Returns:    None. 
  551.  *
  552.  *************************************************************************/
  553.  
  554. void
  555. coco_intr( intr_arg_t arg ) 
  556. {
  557.     register card_t  *cp;
  558.     register buf_t   *bp;
  559.     register caddr_t adr_cfg, adr_amcc, adr_norm;
  560.     register uint_t  intcsr, xil_stat, mbox;
  561.     register uint_t  dmastat, dmatype, dmacfg, dmabits;
  562.     register int     rw, err;
  563.     register int    s;
  564.         size_t           p_size;
  565.         alenaddr_t       p_addr;
  566.  
  567.     /*  get the lock  */ 
  568.     cp = (card_t *)arg;
  569.     nanotime ( & cp->intr_time);
  570.     s = COCO_LOCK(&cp->coco_mlock);
  571.  
  572.     /*  a stray interrupt ?  */
  573.     adr_amcc = cp->amcc_adr;
  574.     intcsr = Inp32(adr_amcc+AMCC_OP_REG_INTCSR);
  575.     if ( (intcsr & 0x00800000) == 0 ) {
  576.             COCO_UNLOCK(&cp->coco_mlock, s);
  577.         return;
  578.     }
  579.  
  580.     #ifdef DEBUGTIME
  581.     cocoReportTime ( "cocoIntr", cp, 0 );
  582.     #endif
  583.  
  584.     bp = cp->bp;
  585.  
  586.     adr_cfg  = cp->conf_adr;
  587.     adr_norm = cp->norm_adr;
  588.     dmacfg   = cp->dmacfg;
  589.     dmabits  = cp->dmabits;
  590.     dmastat  = cp->dmastat;
  591.     dmatype  = cp->dmatype;
  592.     
  593.     /*  cancel any outstanding timer  */
  594.     if ( cp->tid > 0 ) {
  595.         untimeout(cp->tid);
  596.         cp->tid = 0;
  597.     }
  598.  
  599.     /* ======================================
  600.      *    Reseting Interrupt and Status
  601.      * ====================================== */
  602.  
  603.         /*  disable any Dma and read in Xilinx status */
  604.         Out32(adr_cfg, dmacfg | DMAREG_STAT );
  605.         /* xil_stat = Inp32(adr_norm); */
  606.         mbox     = Inp32(adr_amcc+AMCC_OP_REG_IMB4);
  607.  
  608.     /*  Reset Amcc Interrupts and enable interrupts again   */ 
  609.     Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_RST | AMCC_INTCSR_RCLR |
  610.           AMCC_INTCSR_WCLR );
  611.         Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_MASK);
  612.  
  613.  
  614.  
  615.     /* ===============================================
  616.      *    End of Dma Read or Write 
  617.      * =============================================== */
  618.     if ( (mbox & AMCC_MB_EOFDMAR) || (mbox & AMCC_MB_EOFDMAW) ) {
  619.         dmabits &= ~(DMAREG_REN | DMAREG_INTREN);
  620.                 dmabits &= ~(DMAREG_WEN | DMAREG_INTWEN );
  621.  
  622.         #ifdef DEBUG
  623.         if ( mbox & AMCC_MB_EOFDMAR)
  624.             printf ("cocoIntr: End of DMA Read\n");
  625.         else    printf ("cocoIntr: End of DMA Write\n");
  626.         #endif
  627.     }
  628.  
  629.         /* ===============================================
  630.          *      End of Chain Dma Read or Write 
  631.          * =============================================== */
  632.     if ( (mbox & AMCC_MB_EOFPRDMAR) || (mbox & AMCC_MB_EOFPRDMAW) ) {
  633.         dmabits &= ~(DMAREG_PREN | DMAREG_INTPREN);
  634.         dmabits &= ~(DMAREG_PWEN | DMAREG_INTPWEN);
  635.         dmabits &= ~(DMAREG_WEN | DMAREG_REN);
  636.  
  637.         #ifdef DEBUG
  638.         if ( mbox & AMCC_MB_EOFPRDMAR )
  639.             printf ("cocoIntr: End Prog DMA Read\n");
  640.         else    printf ("cocoIntr: End Prog DMA Write\n");
  641.         #endif
  642.     }
  643.  
  644.     cp->dmabits = dmabits;
  645.     cp->iostat  = IO_OK;
  646.  
  647.     switch ( cp->dmastat ) {
  648.         /* ==============================
  649.          *     Dma to Lut
  650.          * ============================== */
  651.        case DMA_LUT_WAIT:
  652.  
  653.                 #ifdef DEBUG
  654.                 printf ("cocoIntr: Waking up Dma_Lut_Wait\n");
  655.                 #endif
  656.  
  657.                 cp->dmastat = DMA_IDLE;
  658.                 WAKE_EVENT(&cp->coco_sv);
  659.         COCO_UNLOCK(&cp->coco_mlock, s);
  660.         goto get_out; 
  661.  
  662.  
  663.         /* ==================================
  664.          *  Read/Write Dma
  665.          * ================================== */
  666.         case DMA_READ_WAIT:
  667.         case DMA_WRITE_WAIT:
  668.  
  669.         /*  what we do depends on which type of Dma is done */
  670.         switch ( cp->dmatype ) {
  671.  
  672.              /*  chained Dma is done. Simply wake the process up */
  673.              case DMA_PROG:
  674.  
  675.             #ifdef DEBUG
  676.             printf ("cocoIntr: biodone() read/write\n");
  677.             #endif
  678.  
  679.                     kmem_free ( cp->chain_list,  
  680.                                     cp->page_no * sizeof(coco_dmapage_t) );
  681.                     alenlist_done(cp->addrList);
  682.             cp->addrList = 0;
  683.             cp->dmastat = DMA_IDLE;
  684.             bp->b_resid -= cp->dmasize;
  685.  
  686.             biodone(cp->bp);
  687.             COCO_UNLOCK(&cp->coco_mlock, s);
  688.             goto get_out;
  689.  
  690.              /*  single page Dma done. Dma the next page if any  */ 
  691.              case DMA_SINGLE:
  692.  
  693.                bp->b_resid -= cp->dmasize;
  694.                cp->page_no--;
  695.  
  696.                if ( cp->page_no <= 0 ) {  /* no more pages */
  697.  
  698.                 #ifdef DEBUG
  699.                 printf ("cocoIntr: No more pages to Dma\n");
  700.                                 printf ("cocoIntr: biodone() read/write\n");
  701.                 #endif
  702.  
  703.                             alenlist_done(cp->addrList);
  704.                 cp->addrList = 0;
  705.                 cp->dmastat = DMA_IDLE;
  706.  
  707.                                 biodone(cp->bp);
  708.                 COCO_UNLOCK(&cp->coco_mlock, s);
  709.                     goto get_out;
  710.                } 
  711.  
  712.                    /*  get next page to DMA  */
  713.               #ifdef DEBUG
  714.               printf ("cocoIntr: Dma next page ..left = %d\n",
  715.                   cp->page_no-1 );
  716.               #endif
  717.  
  718.                    if ( alenlist_get(cp->addrList, NULL, NBPP,
  719.                             &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
  720.                         cmn_err (CE_WARN, 
  721.                         "cocoIntr: Bad scatter-gather"); 
  722.                 cp->iostat = IO_ERROR;
  723.                                 #ifdef DEBUG
  724.                                 printf ("cocoIntr: biodone() read/write\n");
  725.                                 #endif
  726.  
  727.                             alenlist_done(cp->addrList);
  728.                 cp->addrList = 0;
  729.                             cp->dmastat = DMA_IDLE;
  730.                 bioerror (cp->bp, EIO);
  731.                                 biodone(cp->bp);
  732.                                 COCO_UNLOCK(&cp->coco_mlock, s);
  733.                     goto get_out;
  734.               }
  735.               if ( cp->dmastat == DMA_READ_WAIT )
  736.                 rw = B_READ;
  737.               else  rw = B_WRITE; 
  738.                   cocoStartSingleDma ( cp, p_addr, p_size, rw );
  739.                           COCO_UNLOCK(&cp->coco_mlock, s);
  740.               goto get_out;
  741.  
  742.  
  743.         }  /*** switch ( cp->dmatype ) ***/
  744.  
  745.             /* ==========================
  746.              *   Simultaneus read/write 
  747.              * ========================== */
  748.             case DMA_RW_WAIT:
  749.  
  750.                 /*  what we do depends on which type of Dma is done */
  751.                 switch ( cp->dmatype ) {
  752.  
  753.                      /*  chained Dma is done. Both read/write is done */ 
  754.                      case DMA_PROG:
  755.                     #ifdef DEBUG
  756.                     printf ("cocoIntr: Waking up Dma_RW_Wait\n");
  757.                     #endif
  758.  
  759.                     cp->dmastat = DMA_IDLE;
  760.                     WAKE_EVENT(&cp->coco_sv);
  761.                         COCO_UNLOCK(&cp->coco_mlock, s);
  762.                     goto get_out;
  763.  
  764.  
  765.                      /*  single page Dma done. Dma the next page if any  */
  766.                      case DMA_SINGLE:
  767.  
  768.                /*  Keep transfering as long as there is data */ 
  769.                if ( cp->w_page_no > 0 ||
  770.                 cp->r_page_no > 0 ||
  771.                 cp->wp_size > 0   ||
  772.                 cp->rp_size > 0 ) {
  773.  
  774.                 #ifdef DEBUG
  775.                 printf ("cocoIntr: Dma next page, w_left = %d, r_left = %d\n", cp->w_page_no, cp->r_page_no);
  776.                 #endif
  777.  
  778.                 err = cocoStartRWDma(cp, 0, 0, 0, 0);
  779.                 if ( err == 0 )    {
  780.                     COCO_UNLOCK(&cp->coco_mlock, s);
  781.                     goto get_out;
  782.                     }
  783.  
  784.                 #ifdef DEBUG
  785.                 printf ("cocoIntr: error Dmaing next page\n");
  786.                 #endif
  787.                 cp->dmastat = DMA_IDLE;
  788.                 cp->iostat  = IO_ERROR;
  789.                 WAKE_EVENT(&cp->coco_sv);
  790.                             COCO_UNLOCK(&cp->coco_mlock, s);
  791.                 goto get_out;
  792.               }
  793.  
  794.               #ifdef DEBUG
  795.               printf ("cocoIntr: Waking up Dma_RW_Wait\n"); 
  796.               #endif
  797.  
  798.                           cp->dmastat = DMA_IDLE;
  799.                           WAKE_EVENT(&cp->coco_sv);
  800.                           COCO_UNLOCK(&cp->coco_mlock, s);
  801.                           goto get_out;
  802.  
  803.             }  /***  switch ( cp->dmatype ) ***/
  804.  
  805.          } /*** switch ( cp->dmastat ) ***/
  806.  
  807. get_out:
  808.         #ifdef DEBUG
  809.         cocoReport ( cp, "cocoIntr exit" );
  810.         #endif
  811.  
  812.     return;
  813.  
  814. }
  815.  
  816.  
  817. /*************************************************************************
  818.  ***                   c o c o _ u n l o a d                           ***
  819.  *************************************************************************
  820.  *
  821.  *  Name:    coco_unload
  822.  *
  823.  *  Purpose:    Unloads the driver. 
  824.  *
  825.  *  Returns:    0 Success or errno
  826.  *
  827.  *************************************************************************/
  828. int
  829. coco_unload(void)
  830. {
  831.     cmn_err (CE_NOTE, "Unloading the Chameleon Driver");
  832.     return(0);
  833. }
  834.  
  835.  
  836. /*************************************************************************
  837.  ***                   c o c o _ u n r e g                             ***
  838.  *************************************************************************
  839.  *
  840.  *  Name:       coco_unreg 
  841.  *
  842.  *  Purpose:    Unregister the driver
  843.  *
  844.  *  Returns:    0 Success or errno
  845.  *
  846.  *************************************************************************/
  847. int
  848. coco_unreg(void)
  849. {
  850.     cmn_err (CE_NOTE, "Unregisterning Chameleon Driver");
  851.         pciio_driver_unregister(DRIVER_PREFIX);
  852.  
  853.         return(0);
  854. }
  855.  
  856.  
  857. /*************************************************************************
  858.  ***                   c o c o _ o p e n                               ***
  859.  *************************************************************************
  860.  *
  861.  *  Name:    coco_open
  862.  *
  863.  *  Purpose:    Opens the card. This sample driver simply verifies that 
  864.  *        the card's info structure can be retrieved and checks
  865.  *        the card's Base_Register.
  866.  *
  867.  *  Returns:    0 = Success, or errno.
  868.  *
  869.  *************************************************************************/
  870. int
  871. coco_open(dev_t *devp, int flag, int otyp, cred_t *cred)
  872. {
  873.     register card_t       *cp;
  874.     register vertex_hdl_t vhdl;
  875.     __userabi_t           uabi;
  876.  
  877.        /*   Get the vertex handle and pointer to card's info  */
  878.     vhdl = dev_to_vhdl ( *devp );
  879.     if (vhdl == NULL){
  880.         cmn_err(CE_WARN, "coco_open: dev_to_vhdl returns NULL");
  881.         return(EIO);
  882.     }
  883.  
  884.     cp = (card_t *)device_info_get ( vhdl );
  885.  
  886.  
  887.     /*  some error checking first   */
  888.     if ( !(cp->status & CARD_ATTACHED) ) {
  889.         cmn_err (CE_WARN, "coco_open: Driver is not attached");
  890.         return (ENODEV);
  891.     }
  892.  
  893.     if ( cp->status & CARD_OPEN) {
  894.         cmn_err (CE_WARN, "coco_open: Device is busy");
  895.         return (EBUSY);
  896.     }
  897.     
  898.     cocoReset(cp);  /*  reset the board  */ 
  899.     cp->status |= CARD_OPEN;
  900.  
  901.     /*  default values */ 
  902.     cp->dmatype = DMA_SINGLE;
  903.     cp->dmacmd  = COCO_TRANSP;
  904.  
  905.     /*  get user's ABI for correct struct usage in coco_ioctl() */
  906.     userabi(&uabi);
  907.     if ( uabi.uabi_szptr == 8 )
  908.         cp->user_abi = ABI_IRIX5_64;
  909.     else    cp->user_abi = ABI_IRIX5_N32;
  910.  
  911.         /*  initialize our mutex lock and sv_t for sleep/wake  */
  912.         COCO_LOCK_INIT(&cp->coco_mlock);
  913.         SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
  914.  
  915.  
  916.     /*  zero out all time measurements   */
  917.     bzero ( &cp->start_time, sizeof(struct timespec) );
  918.     bzero ( &cp->intr_time, sizeof(struct timespec) );
  919.     bzero ( &cp->call_time, sizeof(struct timespec) );
  920.     bzero ( &cp->ret_time, sizeof(struct timespec) );
  921.  
  922.     return(0);
  923. }
  924.  
  925.  
  926.  
  927.  
  928. /*************************************************************************
  929.  ***                   c o c o _ c l o s e                             ***
  930.  *************************************************************************
  931.  *
  932.  *  Name:    coco_close
  933.  *
  934.  *  Purpose:    Closes the card. This sample driver's close statement
  935.  *        prints out the addresses and Base_Register's value for
  936.  *        verification.
  937.  *
  938.  *  Returns:    0 = Success, or errno
  939.  *
  940.  *************************************************************************/
  941. int
  942. coco_close(dev_t dev, int flag, int otyp, cred_t *cred)
  943. {
  944.         register card_t       *cp;
  945.         register vertex_hdl_t vhdl;
  946.  
  947.     /*  get the vertex handle and pointer to card's info  */
  948.         vhdl = dev_to_vhdl ( dev );
  949.  
  950.         cp = (card_t  *)device_info_get ( vhdl );
  951.     cp->status &= ~CARD_OPEN;
  952.  
  953.         /*  zero out all time measurements   */
  954.         bzero ( &cp->start_time, sizeof(struct timespec) );
  955.         bzero ( &cp->intr_time, sizeof(struct timespec) );
  956.         bzero ( &cp->call_time, sizeof(struct timespec) );
  957.         bzero ( &cp->ret_time, sizeof(struct timespec) );
  958.  
  959.  
  960.     return(0);
  961. }
  962.  
  963.  
  964. /*************************************************************************
  965.  ***                   c o c o _ m a p                                 ***
  966.  *************************************************************************
  967.  *
  968.  *  Name:       coco_map  
  969.  *
  970.  *  Purpose:    Allocate a piece of continious memory and map it to user's
  971.  *              address space.
  972.  *
  973.  *  Returns:    0 = Success, or errno
  974.  *
  975.  *************************************************************************/
  976. int
  977. coco_map ( dev_t dev, vhandl_t *vh, off_t offset, size_t len, uint_t prot )
  978. {
  979.     register int          ret;
  980.     register int         s;
  981.     register caddr_t      kv;
  982.         register vertex_hdl_t vhdl;
  983.     register card_t       *cp;
  984.  
  985.         /*  get the vertex handle and pointer to card's info  */
  986.         vhdl = dev_to_vhdl ( dev );
  987.         cp = (card_t  *)device_info_get ( vhdl );
  988.  
  989.     if ( cp->mappedkv == (caddr_t)NULL ) {
  990.         cmn_err (CE_NOTE, "coco_map: Not memory for mapping");
  991.         return (ENOMEM);
  992.     }
  993.  
  994.     if ( len > (size_t)(cp->mappedkvlen - LESS_MAP) ) {
  995.         cmn_err (CE_NOTE, "coco_map: Only %d bytes available for map, requested %d bytes", cp->mappedkvlen - LESS_MAP, len );
  996.         return (ENOMEM);
  997.     }
  998.  
  999.     ret = v_mapphys( vh, (void *)cp->mappedkv, len ); 
  1000.  
  1001.     if ( ret > 0  ) {
  1002.         cmn_err (CE_WARN, "coco_map: Could not map, ret = %d", ret );
  1003.         return (ret);    
  1004.     }
  1005.  
  1006.     /*  save for later */
  1007.     cp->vhandl = vh;
  1008.  
  1009.     cmn_err (CE_NOTE, "coco_map: mapped %d bytes", len );    
  1010.     return (ret);
  1011. }
  1012.  
  1013. /*************************************************************************
  1014.  ***                   c o c o _ u n m a p                             ***
  1015.  *************************************************************************
  1016.  *
  1017.  *  Name:       coco_unmap
  1018.  *
  1019.  *  Purpose:    Unmap the kernel buffer we allocated before.
  1020.  *
  1021.  *  Returns:    Always 0. There is nothing to free up here. 
  1022.  *
  1023.  *************************************************************************/
  1024. int
  1025. coco_unmap ( dev_t dev, vhandl_t *vh )
  1026. {
  1027.     return (0);
  1028. }
  1029.     
  1030.  
  1031. /*************************************************************************
  1032.  ***                   c o c o _ i o c t l                             ***
  1033.  *************************************************************************
  1034.  *
  1035.  *  Name:    coco_ioctl
  1036.  *
  1037.  *  Purpose:    Handles user Ioctl command. These commands can be 
  1038.  *        found in coco_user.h.
  1039.  *
  1040.  *  Returns:    0 = Success, or errno
  1041.  *
  1042.  *************************************************************************/
  1043. int
  1044. coco_ioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *cred, 
  1045.            int *rvalp )
  1046. {
  1047.         register card_t       *cp;
  1048.         register vertex_hdl_t vhdl;
  1049.     register uint_t      *tmp_ibuf;
  1050.     register int          tot_bytes, err, i, s;
  1051.     uint_t           tmp_int;
  1052.     coco_buf_t     coco_buf; 
  1053.     coco_rw_t      coco_rw;  
  1054.     coco_mode_t    coco_mode;
  1055.     coco_cmd_t     coco_cmd;
  1056.     coco_convert_t coco_convert;
  1057.     uint_t           dmaRegs[DMA_REGS];
  1058.     coco_time_t    coco_time;
  1059.     struct timespec tv;
  1060.  
  1061.     #ifdef DEBUG
  1062.         printf ("\ncoco_ioctl: ---> command = %s [0x%x]\n", 
  1063.          cocoIoctlStr(cmd), cmd );
  1064.     #endif
  1065.  
  1066.         /*  get the vertex handle and pointer to card's info  */
  1067.         vhdl = dev_to_vhdl ( dev );
  1068.  
  1069.         cp = (card_t  *)device_info_get ( vhdl );
  1070.  
  1071.         if ( cp == (card_t *)NULL ) {
  1072.         cmn_err (CE_WARN, "coco_ioctl: Card_t is NULL");
  1073.         return (EIO);
  1074.     }
  1075.  
  1076.     /*  is device opened ? */
  1077.         if (!( cp->status & CARD_OPEN) ) {
  1078.                 cmn_err (CE_NOTE, "coco_ioctl: Device is not opened"); 
  1079.                 return (EIO);
  1080.         }
  1081.  
  1082.     /* ===================
  1083.      *    Ioctl commands
  1084.      * =================== */
  1085.  
  1086.     switch ( cmd ) {
  1087.  
  1088.         /* ===========================================
  1089.          *    Make Hardware Graph nodes off of /hw
  1090.          * ===========================================  */
  1091.         case COCO_MKHWGR:
  1092.             cocoMakeHwGraph ( cp );
  1093.             break;
  1094.  
  1095.                 /* ==================================
  1096.                  *      Return Srart and Return time 
  1097.                  * ================================== */
  1098.         case COCO_GET_TIME:
  1099.             cocoDiffTime ( &cp->call_time, &cp->ret_time, &tv );
  1100.             cocoConvTime ( &cp->call_time, &coco_time.start_time );
  1101.                         cocoConvTime ( &cp->ret_time, &coco_time.end_time );
  1102.             cocoConvTime ( &tv, &coco_time.diff_time );
  1103.                         if ( copyout((caddr_t)&coco_time, (caddr_t)arg,
  1104.                              sizeof(coco_time_t)) )
  1105.                              return (EFAULT);
  1106.             break;
  1107.  
  1108.          /* ==================================
  1109.          *    Report Map size available
  1110.              * ================================== */
  1111.         case COCO_MAP_SIZE:
  1112.              tmp_int = cp->mappedkvlen - LESS_MAP;
  1113.                      if ( copyout((caddr_t)&tmp_int, (caddr_t)arg, 
  1114.               sizeof(uint_t) ) )
  1115.                         return (EFAULT);
  1116.  
  1117.                      break;
  1118.  
  1119.                 /* ==============================
  1120.                  *      Board Identification
  1121.                  * ============================== */
  1122.         case COCO_ISPCI:
  1123.             *rvalp = 1;
  1124.             break;
  1125.  
  1126.                 /* ==============================
  1127.                  *      Reset the board 
  1128.                  * ============================== */
  1129.         case COCO_RESET:
  1130.             cocoReset(cp); 
  1131.             break;
  1132.  
  1133.         /* ==============================
  1134.          *    Set DMA Command
  1135.          * ============================== */
  1136.         case COCO_SETCMD_TRANSP:
  1137.             cp->dmacmd = COCO_TRANSP;
  1138.             break;
  1139.  
  1140.         case COCO_SETCMD_CONVERT:
  1141.             cp->dmacmd = COCO_CONVERT;
  1142.             break;
  1143.  
  1144.                 /* ===============================
  1145.                  *     Issue a Command 
  1146.                  * =============================== */
  1147.                 case COCO_COMMAND:
  1148.                     if ( copyin ( (char *)arg, &coco_cmd, 
  1149.              sizeof(coco_cmd_t) ) )
  1150.              return (EFAULT);
  1151.  
  1152.             cocoCommand ( cp, coco_cmd.cmd, coco_cmd.datav );
  1153.                     break;
  1154.  
  1155.                 /* ===================================
  1156.                  *      Set DMA type (Prog or Single)
  1157.                  * =================================== */
  1158.         case COCO_SET_SINGLE_DMA:
  1159.             cp->dmatype = DMA_SINGLE;
  1160.             break;
  1161.  
  1162.         case COCO_SET_PROG_DMA:
  1163.             cp->dmatype = DMA_PROG;
  1164.             break;
  1165.  
  1166.         /* ===============================
  1167.          *    Set up Chameleon Mode
  1168.          * =============================== */
  1169.         case COCO_SET_MODE:   
  1170.             if ( copyin ( (char *)arg, &coco_mode, 
  1171.              sizeof(coco_mode_t) ) )
  1172.              return (EFAULT);
  1173.  
  1174.             cocoSetMode ( cp, coco_mode.mode, coco_mode.swap, 
  1175.                     coco_mode.slice, coco_mode.flag ); 
  1176.             break;
  1177.  
  1178.         /* =================================
  1179.          *    Read Chameleon Mode
  1180.          * ================================= */
  1181.         case COCO_READ_MODE:
  1182.              tmp_int = cocoReadMode (cp);
  1183.                      if ( copyout((char *)&tmp_int, arg, sizeof(uint_t) ) )
  1184.             return (EFAULT);
  1185.              break;
  1186.  
  1187.                 
  1188.         /* ===============================
  1189.          *   Raw write Buffer to Fifo    *
  1190.          * =============================== */
  1191.         case COCO_RAW_WRITEB_FIFO:
  1192.  
  1193.              if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
  1194.             return(EFAULT);
  1195.  
  1196.              if ( coco_buf.buf_size == 0 ) 
  1197.             return (EINVAL);
  1198.              
  1199.              /*
  1200.               *   the data is in coco_buf.buf in user address
  1201.               *   space. Move it to kernel address space and dump it
  1202.               *   to the board.
  1203.               */
  1204.              tot_bytes = coco_buf.buf_size * sizeof(uint_t);
  1205.              tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
  1206.              if ( tmp_ibuf == (uint_t *)NULL )
  1207.             return (ENOMEM);
  1208.  
  1209.              if ( copyin((caddr_t)coco_buf.buf, (caddr_t)tmp_ibuf, 
  1210.               tot_bytes) ) {
  1211.               kmem_free (tmp_ibuf, tot_bytes);
  1212.               return(EFAULT);
  1213.              }
  1214.  
  1215.              cocoBufOut (cp, tmp_ibuf, coco_buf.buf_size);
  1216.              kmem_free (tmp_ibuf, tot_bytes ); 
  1217.              break;    
  1218.  
  1219.         /* ===============================
  1220.          *  Raw Read Buffer from Fifo    *
  1221.          * =============================== */
  1222.         case COCO_RAW_READB_FIFO:
  1223.  
  1224.                      if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
  1225.                         return(EFAULT);
  1226.  
  1227.                      if ( coco_buf.buf_size == 0 ) 
  1228.                         return (EINVAL);
  1229.  
  1230.              /*
  1231.               *  the buffer to be filled is coco_buf.buf and 
  1232.               *  it can contain coco_buf.buf_size 32-bit values.
  1233.               *  Read that many into our own temp buffer and move them
  1234.               *  to user-address space.
  1235.               */
  1236.              tot_bytes = coco_buf.buf_size * sizeof(uint_t);
  1237.                      tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
  1238.                      if ( tmp_ibuf == (uint_t *)NULL )
  1239.                         return (ENOMEM);
  1240.  
  1241.              cocoBufIn(cp, tmp_ibuf, coco_buf.buf_size);
  1242.  
  1243.              if ( copyout ( (caddr_t)tmp_ibuf, (caddr_t)coco_buf.buf, 
  1244.                          tot_bytes)) {
  1245.               kmem_free ( tmp_ibuf, tot_bytes ); 
  1246.               return (EFAULT);
  1247.              }
  1248.  
  1249.                      kmem_free ( tmp_ibuf, tot_bytes );
  1250.              break;
  1251.  
  1252.         /* =============================
  1253.           *   Read 32-bit from Fifo     
  1254.          * ============================= */
  1255.         case COCO_RAW_READ_FIFO:
  1256.  
  1257.              tmp_int = cocoReadAmccFifo(cp);
  1258.              if ( copyout((char *)&tmp_int, arg, sizeof(uint_t) ) )
  1259.             return(EFAULT);
  1260.              break;    
  1261.  
  1262.                 /* =============================
  1263.                  *   Write 32-bit value to Fifo
  1264.                  * ============================= */
  1265.                 case COCO_RAW_WRITE_FIFO:
  1266.  
  1267.              if ( copyin(arg, (char *)&tmp_int, sizeof(uint_t) ) )
  1268.             return(EFAULT);
  1269.  
  1270.              cocoCommand(cp, COCO_TRANSP, tmp_int );
  1271.              break;
  1272.  
  1273.                 /* =============================
  1274.                  *   Test Fifo data path 
  1275.                  * ============================= */
  1276.         case COCO_FIFO_TEST:
  1277.              return (cocoFifoTest(cp, 1) );
  1278.  
  1279.         /* ===============================
  1280.          *     Read DMA Registers
  1281.          * =============================== */
  1282.         case COCO_RAW_READ_DMA:
  1283.             cocoReadDmaRegs(cp, &dmaRegs[0]);
  1284.                         for ( i = 0; i < DMA_REGS; i++)  
  1285.                                 printf ("read[%d] = 0x%x\n", i, dmaRegs[i]);
  1286.  
  1287.             if ( copyout((char *)&dmaRegs[0], arg, 
  1288.                  sizeof(dmaRegs) ) )
  1289.                 return (EFAULT);
  1290.             break;
  1291.  
  1292.                 /* ===============================
  1293.                  *     Write DMA Registers
  1294.                  * =============================== */
  1295.         case COCO_RAW_WRITE_DMA:
  1296.             if ( copyin(arg, (char *)&dmaRegs[0], 
  1297.                  sizeof(dmaRegs) ) )
  1298.                 return (EFAULT);
  1299.             for ( i = 0; i < DMA_REGS; i++)  
  1300.                 printf ("write[%d] = 0x%x\n", i, dmaRegs[i]);
  1301.             cocoWriteDmaRegs(cp, &dmaRegs[0] );
  1302.             break;
  1303.  
  1304.                 /* =============================
  1305.                  *    DMA Regsters Access Test 
  1306.                  * ============================= */
  1307.                 case COCO_DMAREGS_TEST:
  1308.              return ( cocoDmaRegsTest(cp) );
  1309.  
  1310.         /* ===============================
  1311.          *    Read Address Register
  1312.          * =============================== */
  1313.         case COCO_READ_ADDR:
  1314.             tmp_int = cocoReadAddr(cp);
  1315.                         if ( copyout((char *)&tmp_int, arg, sizeof(uint_t) ) )
  1316.                                 return (EFAULT);
  1317.             break;
  1318.  
  1319.                 /* ===============================
  1320.                  *      Write Address Register 
  1321.                  * =============================== */
  1322.         case COCO_SET_ADDR:
  1323.             if ( copyin(arg, (char *)&tmp_int, sizeof(uint_t) ) )
  1324.                 return(EFAULT);
  1325.             cocoSetAddr(cp, tmp_int);
  1326.             break;
  1327.  
  1328.                 /* ===============================
  1329.                  *      Internal RAM Test       
  1330.                  * =============================== */
  1331.                 case COCO_INTRAM_TEST:
  1332.             return ( cocoIntRamTest(cp) );
  1333.  
  1334.                 /* ===============================
  1335.                  *      External RAM Test
  1336.                  * =============================== */
  1337.                 case COCO_EXTRAM_TEST:
  1338.             return ( cocoExtRamTest(cp) );
  1339.         
  1340.         /* ==============================
  1341.          *      Read Internal LUTs
  1342.          * ============================== */
  1343.         case COCO_READ_RAMIL:
  1344.         case COCO_READ_RAMIH:
  1345.         case COCO_READ_RAMO:
  1346.  
  1347.                      if ( coco_copyin_buf(cp, arg, &coco_buf) )
  1348.                         return(EFAULT);
  1349.  
  1350.                      if ( coco_buf.buf_size == 0)
  1351.                         return (EINVAL);
  1352.  
  1353.                      if ( coco_buf.buf_size > INT_RAM_SIZE )
  1354.                         return (EINVAL);
  1355.  
  1356.              /*  allocate a buffer to hold Ram's contents  */
  1357.              tot_bytes = coco_buf.buf_size * sizeof(uint_t);
  1358.              tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
  1359.  
  1360.              if ( tmp_ibuf == (uint_t *)NULL )
  1361.             return(EFAULT);
  1362.  
  1363.              /*  read in Ram's contents into the buffer  */
  1364.              cocoReadIntRam(cp, tmp_ibuf, cmd, coco_buf.buf_size );
  1365.  
  1366.              /*  copy the kernel buffer to user's buffer  */
  1367.                      if ( copyout((void *)tmp_ibuf, (void *)coco_buf.buf, 
  1368.                        tot_bytes) ) {
  1369.                      kmem_free ( (caddr_t)tmp_ibuf, tot_bytes );
  1370.                                 return (EFAULT);
  1371.              }
  1372.  
  1373.              kmem_free ( (void *)tmp_ibuf, tot_bytes );
  1374.                      break;
  1375.  
  1376.  
  1377.  
  1378.         /* ================================
  1379.          *     Write Internal LUTs
  1380.          * ================================ */
  1381.                 case COCO_FILL_RAMIL:
  1382.                 case COCO_FILL_RAMIH:
  1383.                 case COCO_FILL_RAMO:
  1384.  
  1385.                      if ( coco_copyin_buf(cp, arg, &coco_buf) )
  1386.                         return(EFAULT);
  1387.  
  1388.                      if ( coco_buf.buf_size == 0)
  1389.                         return (EINVAL);
  1390.  
  1391.                      if ( coco_buf.buf_size > 2 * INT_RAM_SIZE )
  1392.                         return (EINVAL);
  1393.  
  1394.              /*  allocate a buffer to hold user's data  */
  1395.                      tot_bytes = coco_buf.buf_size * sizeof(uint_t);
  1396.                      tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
  1397.  
  1398.                      if ( tmp_ibuf == (uint_t *)NULL )
  1399.                         return(EFAULT);
  1400.  
  1401.              /*  copy user's buffer to our own  */
  1402.                      if ( copyin((void *)coco_buf.buf,  (void *)tmp_ibuf, 
  1403.               tot_bytes ) ) {
  1404.                 kmem_free ( tmp_ibuf, tot_bytes );
  1405.                                 return(EFAULT);
  1406.              }
  1407.  
  1408.              /*  fill the Ram with data just moved over  */
  1409.              cocoWriteIntRam ( cp, tmp_ibuf, cmd,
  1410.                        coco_buf.buf_size );
  1411.  
  1412.              kmem_free ( tmp_ibuf, tot_bytes );
  1413.              break;
  1414.  
  1415.         /* ==============================
  1416.          *     Read External LUT
  1417.          * ============================== */
  1418.         case COCO_READ_RAML:
  1419.  
  1420.                      if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
  1421.                         return(EFAULT);
  1422.  
  1423.                      if ( coco_buf.buf_size == 0)
  1424.                         return (EINVAL);
  1425.  
  1426.                      if ( coco_buf.buf_size > EXT_RAM_SIZE )
  1427.                         return (EINVAL);
  1428.  
  1429.              /*  allocate a buffer to hold External Ram's contents */
  1430.                      tot_bytes = coco_buf.buf_size * sizeof(uint_t);
  1431.                      tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
  1432.  
  1433.                      if ( tmp_ibuf == (uint_t *)NULL )
  1434.                         return(EFAULT);
  1435.  
  1436.              /*  fill the buffer with Ext. Ram's contents  */
  1437.                      cocoReadExtRam(cp, tmp_ibuf, coco_buf.buf_size);
  1438.  
  1439.              /*  copy the data to user's buffer  */
  1440.                      if ( copyout((caddr_t)tmp_ibuf, (caddr_t)coco_buf.buf, 
  1441.                    tot_bytes) ) {
  1442.                 kmem_free ( tmp_ibuf, tot_bytes );
  1443.                                 return (EFAULT);
  1444.              }
  1445.  
  1446.              kmem_free ( tmp_ibuf, tot_bytes );
  1447.                      break;
  1448.  
  1449.  
  1450.                 /* ==============================
  1451.                  *      Write External LUT
  1452.                  * ============================== */
  1453.         case COCO_FILL_RAML:
  1454.  
  1455.                      if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
  1456.                         return(EFAULT);
  1457.  
  1458.                      if ( coco_buf.buf_size == 0)
  1459.                         return (EINVAL);
  1460.  
  1461.                      if ( coco_buf.buf_size > 2 * EXT_RAM_SIZE )
  1462.                         return (EINVAL);
  1463.  
  1464.                      /*  allocate a buffer to hold user's data  */
  1465.                      tot_bytes = coco_buf.buf_size * sizeof(uint_t);
  1466.                      tmp_ibuf = (uint_t *)kmem_alloc (tot_bytes, KM_NOSLEEP);
  1467.  
  1468.                      if ( tmp_ibuf == (uint_t *)NULL )
  1469.                         return(EFAULT);
  1470.  
  1471.                      /*  copy user's buffer to our own  */
  1472.                      if ( copyin((caddr_t)coco_buf.buf, (caddr_t)tmp_ibuf, 
  1473.                   tot_bytes ) ) {
  1474.                                 kmem_free ( tmp_ibuf, tot_bytes );
  1475.                                 return(EFAULT);
  1476.                      }
  1477.  
  1478.                      /*  fill the Ram with data just moved over  */
  1479.                      cocoWriteExtRam ( cp, tmp_ibuf, coco_buf.buf_size);
  1480.  
  1481.                      kmem_free ( tmp_ibuf, tot_bytes );
  1482.                      break;
  1483.  
  1484.                 /* ==========================================
  1485.                  *      Chameleon Single pixel Conversion 
  1486.                  * ========================================== */
  1487.                 case COCO_CONVERT_PIXLE:
  1488.             
  1489.               /*  read in the coco_convert struct from user's space */ 
  1490.                       if ( copyin(arg, (char *)&tmp_int, sizeof(uint_t) ) )
  1491.                return (EFAULT);
  1492.  
  1493.               cocoConvert ( cp, tmp_int );
  1494.               break;
  1495.  
  1496.                 /* ============================================
  1497.                  *      Chameleon Single pixel Conversion Test
  1498.                  * ============================================ */
  1499.         case COCO_CONVERT_TEST:
  1500.  
  1501.                       /*  read in the coco_convert struct from user's space */
  1502.                       if ( copyin(arg, (char *)&coco_convert,
  1503.                            sizeof(coco_convert_t) ) )
  1504.                            return (EFAULT);
  1505.  
  1506.                       cocoConvertTest ( cp, &coco_convert );
  1507.  
  1508.                       /*  copy the structure back   */
  1509.                       if ( copyout((char *)&coco_convert, arg,
  1510.                            sizeof(coco_convert_t) ) )
  1511.                            return(EFAULT);
  1512.                       break;
  1513.  
  1514.                 /* ================================================
  1515.                  *      DMA fill of LUTs (Internals and External)
  1516.                  * ================================================ */
  1517.         case COCO_BLOCK_FILL_RAMIL:
  1518.         case COCO_BLOCK_FILL_RAMIH:
  1519.         case COCO_BLOCK_FILL_RAMO:
  1520.         case COCO_BLOCK_FILL_RAML:
  1521.  
  1522.              /*  read in coco_buf_t struct..all we need is there */
  1523.                      if ( coco_copyin_buf(cp, (caddr_t)arg, &coco_buf) )
  1524.                         return(EFAULT);
  1525.  
  1526.              /*  empty buffer ?  */
  1527.                      if ( coco_buf.buf_size == 0 )
  1528.                         return (EINVAL);
  1529.  
  1530.              /*  DMA the data and report back the result */
  1531.              nanotime ( &cp->call_time );
  1532.              err = cocoDmaToLuts(cp, &coco_buf, cmd );
  1533.              nanotime ( &cp->ret_time );
  1534.  
  1535.              #ifdef DEBUGTIME
  1536.              cocoReportTime ( "cocoDmaToLut", cp, 1 );
  1537.              #endif
  1538.  
  1539.              return (err);
  1540.  
  1541.                 /* ================================================
  1542.                  *      Simultaneous Read/Write DMA 
  1543.                  * ================================================ */
  1544.         case COCO_RW_BUF:
  1545.  
  1546.                      /*  read in coco_rw_t  struct..all we need is there */
  1547.                      if ( coco_copyin_rw(cp, (caddr_t)arg, &coco_rw) )
  1548.                         return(EFAULT);
  1549.  
  1550.  
  1551.              if ( coco_rw.buf_size <= 0 ) {
  1552.             cmn_err (CE_NOTE, 
  1553.             "cocoIoctl: Bad Sim.read/write buff size of %d\n",
  1554.             coco_rw.buf_size );
  1555.             return(EINVAL);
  1556.              }
  1557.  
  1558.              nanotime ( &cp->call_time );
  1559.              err = cocoReadWrite(cp, &coco_rw );
  1560.              nanotime ( &cp->ret_time );
  1561.  
  1562.                      #ifdef DEBUGTIME
  1563.                      cocoReportTime ( "cocoReadWrite", cp, 1 );
  1564.                      #endif
  1565.  
  1566.              if ( err != 0 ) 
  1567.             cmn_err (CE_NOTE, 
  1568.             "cocoIoctl: cocoReadWrite reported error %d\n", err );
  1569.  
  1570.              return (err);
  1571.  
  1572.         default:
  1573.             cmn_err ( CE_WARN, 
  1574.                   "coco_ioctl: Unknown cmd 0x%x\n", cmd );
  1575.             return (EINVAL);
  1576.  
  1577.     }  /***  end switch   **/
  1578.  
  1579.         return(0);
  1580. }
  1581.  
  1582. /*************************************************************************
  1583.  ***                   c o c o _ r e a d                               ***
  1584.  *************************************************************************
  1585.  *
  1586.  *  Name:       coco_read 
  1587.  *
  1588.  *  Purpose:    Read entry routine. DMAs data from the board to the 
  1589.  *        user's address space. 
  1590.  *
  1591.  *  Returns:    0 = Success, or errno
  1592.  *
  1593.  *************************************************************************/
  1594. int 
  1595. coco_read( dev_t dev, uio_t *uiop, cred_t *crp)
  1596. {
  1597.     register card_t  *cp;
  1598.     register vertex_hdl_t vhdl;
  1599.     register int          ret;
  1600.  
  1601.     /*   get to the board's info structure  */
  1602.         vhdl = dev_to_vhdl ( dev );
  1603.  
  1604.         cp = (card_t  *)device_info_get ( vhdl );
  1605.     cp->bp = (buf_t *)NULL;
  1606.     cp->addrList = 0;
  1607.     cp->dmastat = 0;
  1608.     cp->dmabits = 0;
  1609.         bzero ( &cp->start_time, sizeof(struct timespec) );
  1610.         bzero ( &cp->intr_time, sizeof(struct timespec) );
  1611.         bzero ( &cp->call_time, sizeof(struct timespec) );
  1612.         bzero ( &cp->ret_time, sizeof(struct timespec) );
  1613.  
  1614.     /*  do the transfer    */
  1615.     nanotime ( &cp->call_time );
  1616.     ret = uiophysio ( cocoStrategy, NULL, dev, B_READ, uiop );
  1617.     nanotime ( &cp->ret_time );
  1618.  
  1619.     if ( cp->addrList ) {
  1620.         alenlist_done(cp->addrList);
  1621.         cp->addrList = 0;
  1622.     }
  1623.  
  1624.     #ifdef DEBUGTIME
  1625.     cocoReportTime ( "cocoRead", cp, 1);
  1626.     #endif
  1627.  
  1628.     return ( ret );
  1629. }
  1630.  
  1631. /*************************************************************************
  1632.  ***                   c o c o _ w r i t e                             ***
  1633.  *************************************************************************
  1634.  *
  1635.  *  Name:       coco_write 
  1636.  *
  1637.  *  Purpose:    Write entry routine. DMAs data from user's address space
  1638.  *        to the board. 
  1639.  *
  1640.  *  Returns:    0 = Success, or errno
  1641.  *
  1642.  *************************************************************************/
  1643. int 
  1644. coco_write( dev_t dev, uio_t *uiop, cred_t *crp)
  1645. {
  1646.     register card_t       *cp;
  1647.         register vertex_hdl_t vhdl;
  1648.         register int          ret;
  1649.  
  1650.         /*   get to the board's info structure  */
  1651.         vhdl = dev_to_vhdl ( dev );
  1652.         cp = (card_t  *)device_info_get ( vhdl );
  1653.         cp->bp       = (buf_t *)NULL;
  1654.         cp->dmastat  = 0;
  1655.         cp->dmabits  = 0;
  1656.     cp->addrList = 0;
  1657.         bzero ( &cp->start_time, sizeof(struct timespec) );
  1658.         bzero ( &cp->intr_time, sizeof(struct timespec) );
  1659.         bzero ( &cp->call_time, sizeof(struct timespec) );
  1660.         bzero ( &cp->ret_time, sizeof(struct timespec) );
  1661.  
  1662.         /*  do the transfer    */
  1663.         nanotime ( &cp->call_time );
  1664.         ret = uiophysio ( cocoStrategy, NULL, dev, B_WRITE, uiop );
  1665.         nanotime ( &cp->ret_time );
  1666.  
  1667.         if ( cp->addrList ) {
  1668.                 alenlist_done(cp->addrList);
  1669.                 cp->addrList = 0;
  1670.         }
  1671.  
  1672.         #ifdef DEBUGTIME
  1673.         cocoReportTime ( "cocoWrite",  cp, 1);
  1674.         #endif
  1675.  
  1676.         return ( ret );
  1677.  
  1678. }
  1679.  
  1680.  
  1681. /*************************************************************************
  1682.  ***                   c o c o _ e r r o r                             ***
  1683.  *************************************************************************
  1684.  *
  1685.  *  Name:       coco_error
  1686.  *
  1687.  *  Purpose:    Traps PCI bus error. 
  1688.  *
  1689.  *  Returns:    0 = Success, or errno
  1690.  *
  1691.  *************************************************************************/
  1692.  
  1693. static int 
  1694. coco_error(void *einfo,
  1695.            int error_code,
  1696.            ioerror_mode_t mode,
  1697.            ioerror_t *ioerror)
  1698. {
  1699.     cmn_err (CE_NOTE, "coco_error: called");
  1700.     printf ("error_code = %d (0x%x)\n", error_code, error_code );
  1701.     printf ("io_errortype = %d\n", ioerror->ie_errortype );
  1702.     printf ("io_busspace  = %d\n", ioerror->ie_busspace );
  1703.     printf ("io_busaddr   = 0x%x\n", ioerror->ie_busaddr );
  1704.     printf ("io_memaddr   = 0x%x\n", ioerror->ie_memaddr );
  1705.     printf ("error_mode   = %d (0x%x)\n", mode, mode );
  1706.     return(IOERROR_UNHANDLED);
  1707. }
  1708.  
  1709.  
  1710.  
  1711. /*
  1712. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1713. ~~~~~~~~~~~~~                              ~~~~~~~~~~~~~~~~
  1714. ~~~~~~~~~~~~~    S u p p o r t i n g    R o u t i n e s       ~~~~~~~~~~~~~~~~
  1715. ~~~~~~~~~~~~~                              ~~~~~~~~~~~~~~~~
  1716. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1717. */
  1718.  
  1719. /*************************************************************************
  1720.  ***                   c o c o S t r a t e g y                         ***
  1721.  *************************************************************************
  1722.  *
  1723.  *  Name:       cocoStrategy
  1724.  *
  1725.  *  Purpose:    Strategy routine. It actually handles read/write
  1726.  *        and starts the DMA. It is called by uiophysio() kernel
  1727.  *        routine. 
  1728.  *
  1729.  *  Returns:    0 = Success, or errno
  1730.  *
  1731.  *************************************************************************/
  1732. static int 
  1733. cocoStrategy ( buf_t  *bp )
  1734. {
  1735.     register card_t    *cp;
  1736.         register vertex_hdl_t vhdl, conn;
  1737.         register coco_dmapage_t  *dmaPg;
  1738.         register int       i, ret, rw, tot_bytes;
  1739.     register int      s;
  1740.         register uint_t   fill_bits;
  1741.         alenlist_t        addrList2;
  1742.         size_t            p_size;
  1743.         alenaddr_t        p_addr;
  1744.     iopaddr_t         p_dmaPg; 
  1745.  
  1746.     if ( !BP_ISMAPPED(bp) ) {
  1747.         cmn_err (CE_NOTE, "cocoStrategy: Unmapped buf_t used\n");
  1748.         bioerror ( bp, EIO);
  1749.         biodone (bp);
  1750.         return(EIO);
  1751.     }
  1752.  
  1753.         /*   get to the board's info structure  */
  1754.         vhdl = dev_to_vhdl ( bp->b_edev );
  1755.         cp = (card_t  *)device_info_get ( vhdl );
  1756.     conn = cp->conn;
  1757.  
  1758.     /*  clear error and save bp  */
  1759.     bioerror(bp, 0);
  1760.     bp->b_resid = bp->b_bcount;
  1761.     cp->bp = bp;
  1762.  
  1763.     if ( bp->b_flags & B_READ ) 
  1764.         rw = B_READ;   /*  board -> mem   */
  1765.     else    rw = B_WRITE;  /*  mem   -> board */
  1766.  
  1767.     /*  create scatter-gather list   */
  1768.     addrList2  = buf_to_alenlist ((alenlist_t)NULL, bp, AL_NOCOMPACT);
  1769.         cp->addrList = pciio_dmatrans_list ( conn, 0, addrList2, 0);
  1770.     if ( cp->addrList == (alenaddr_t)NULL ) {
  1771.         cmn_err (CE_NOTE, "cocoStrategy: Cannot create alenlist");
  1772.                         bioerror ( bp, EIO);
  1773.                 biodone (bp);
  1774.                 return(EIO);
  1775.         }
  1776.  
  1777. #if 0
  1778.     cp->page_no  = alenlist_size ( cp->addrList );
  1779. #endif
  1780.     cp->page_no  = cocoAlenlistSize ( cp->addrList );
  1781.  
  1782.     /*  set the command to be executed during Dma  */
  1783.     cp->dmabits = cp->dmacmd;
  1784.     cocoPrepAmcc ( cp );
  1785.  
  1786.     /* =======================
  1787.      *    Chained DMA
  1788.      * ======================= */
  1789.     if ( cp->dmatype == DMA_PROG ) {
  1790.  
  1791.         dmaPg = cocoMakeChain ( cp, cp->addrList, cp->page_no );
  1792.         if ( dmaPg == (coco_dmapage_t *)NULL ) {
  1793.             cmn_err (CE_NOTE, 
  1794.                      "cocoStrategy: Error creating chain list");
  1795.             alenlist_done (cp->addrList);
  1796.             bioerror (bp, EIO);
  1797.             biodone (bp);
  1798.             return(EIO);
  1799.         }
  1800.  
  1801.         tot_bytes = cp->page_no * sizeof(coco_dmapage_t);
  1802.         p_dmaPg = pciio_dmatrans_addr ( conn, 0,  
  1803.                          kvtophys(dmaPg), tot_bytes, 0);
  1804.  
  1805.         /*  write back cache for chain list  */
  1806.         dki_dcache_wbinval ( dmaPg, tot_bytes );
  1807.  
  1808.         /*  start the Chained Dma  */ 
  1809.                 s = COCO_LOCK(&cp->coco_mlock);
  1810.         cocoStartProgDma ( cp, p_dmaPg, bp->b_bcount, rw ); 
  1811.  
  1812.         if ( rw == B_READ )
  1813.              cp->dmastat = DMA_READ_WAIT;
  1814.         else cp->dmastat = DMA_WRITE_WAIT;
  1815.         cp->chain_list = (caddr_t)dmaPg;
  1816.  
  1817.                 /*  so we dont wait forever for an interrupt  */
  1818.                 cp->tid = itimeout(cocoTimeOut, cp, RW_TIMER,
  1819.                                    pltimeout,  0, 0, 0);
  1820.  
  1821.         COCO_UNLOCK(&cp->coco_mlock, s);
  1822.         return(0);
  1823.     }
  1824.  
  1825.  
  1826.     /* ===========================
  1827.      *    Single page DMA
  1828.      * =========================== */
  1829.  
  1830.      /*  get a page to DMA  */
  1831.          if ( alenlist_get(cp->addrList, NULL, NBPP,
  1832.              &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
  1833.                 cmn_err (CE_WARN, "cocoDma: Not enough Memory");
  1834.                 alenlist_done(cp->addrList);
  1835.         bioerror ( bp, EIO);
  1836.         biodone(bp);
  1837.                 return(EIO);
  1838.          }
  1839.  
  1840.     /*  single dma, memory -> board  */
  1841.     
  1842.         s = COCO_LOCK(&cp->coco_mlock);
  1843.     cocoStartSingleDma ( cp, p_addr, p_size, rw );
  1844.  
  1845.         if ( rw == B_READ )
  1846.              cp->dmastat = DMA_READ_WAIT;
  1847.         else cp->dmastat = DMA_WRITE_WAIT;
  1848.     cp->chain_list   = NULL;
  1849.  
  1850.         /*  so we dont wait forever for an interrupt  */
  1851.         cp->tid = itimeout(cocoTimeOut, cp, RW_TIMER,
  1852.                            pltimeout,  0, 0, 0);
  1853.  
  1854.         COCO_UNLOCK(&cp->coco_mlock, s);
  1855.         return(0);
  1856.  
  1857. }
  1858.  
  1859. /*************************************************************************
  1860.  ***                   c o c o R e a d W r i t e                       ***
  1861.  *************************************************************************
  1862.  *
  1863.  *  Name:       cocoReadWrite
  1864.  *
  1865.  *  Purpose:    Starts simultaneous Read and Write DMA to user's space. 
  1866.  *
  1867.  * Returns:     0 for success, or errno 
  1868.  *
  1869.  *************************************************************************/
  1870. static int
  1871. cocoReadWrite ( card_t *cp, coco_rw_t *rw )
  1872. {
  1873.         register caddr_t  dum;
  1874.     register caddr_t  w_kvaddr, r_kvaddr;
  1875.     register uint_t  *cache_line, pci_flags;
  1876.     register int      r_page_no, w_page_no, err, i, cache_bytes;
  1877.     register int     s;
  1878.     register int      tot_r_cache, tot_w_cache, tot_bytes;
  1879.         register int      coco_adjust_chain, tot_wrong;
  1880.     coco_dmapage_t    *w_dmaPg, *r_dmaPg;
  1881.     alenlist_t        addrList2;
  1882.     iopaddr_t         pr_dmaPg, pw_dmaPg;
  1883.  
  1884.     cocoResetAmcc(cp);  
  1885.     cocoPrepAmcc(cp);
  1886.  
  1887.     pci_flags = PCIIO_WORD_VALUES | PCIIO_DMA_DATA;
  1888.  
  1889.     tot_bytes = rw->buf_size * sizeof(uint_t); 
  1890.     coco_adjust_chain = rw->adjust_chain; 
  1891.  
  1892.     #ifdef DEBUG
  1893.     printf ("w_buf = 0x%x, r_buf = 0x%x, tot_bytes = %d, NBPP = %d\n",
  1894.         rw->w_buf, rw->r_buf, tot_bytes, NBPP );
  1895.     #endif
  1896.  
  1897.     /* =========================================================
  1898.      *    Scatter-Gather list for Write buffer (mem -> board)
  1899.      * ========================================================= */
  1900.  
  1901.  
  1902.     /*  lock user's pages in memory for DMA  */
  1903.     err = cocoLockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE);
  1904.     if ( err ) { 
  1905.         cmn_err (CE_WARN, "cocoReadWrite: Cannot lock user's pages");
  1906.         return (err);
  1907.     }
  1908.  
  1909.     /*
  1910.      *   write back and invalidate the data for mem->board
  1911.      *   adjust the address for current data cache size 
  1912.          */
  1913.         dki_dcache_wbinval ( rw->w_buf, tot_bytes );
  1914.  
  1915.     /*   create scatter-gather list of user's buffer  */
  1916.     addrList2 = uvaddr_to_alenlist( (alenlist_t)NULL, (caddr_t)rw->w_buf, 
  1917.                     (size_t)tot_bytes, 0 ); 
  1918.  
  1919.     /*  did we make it ? */
  1920.     if ( addrList2 == (alenlist_t)NULL ) {
  1921.         cmn_err (CE_WARN, "cocoreadWrite: cannot create Wrt alenlist");
  1922.             cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
  1923.         return (EIO);
  1924.     }
  1925.  
  1926.     /*  map it to PCI bus address space  */
  1927.     cp->w_addrList = pciio_dmatrans_list ( cp->conn, 0, addrList2,
  1928.                            pci_flags ); 
  1929.  
  1930.     if ( cp->w_addrList == (alenlist_t)NULL ) {
  1931.                 cmn_err (CE_WARN, "cocoreadWrite: cannot map Write alenlist");
  1932.                 cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
  1933.                 return (EIO);
  1934.         }
  1935.  
  1936. #if 0
  1937.     w_page_no = alenlist_size ( cp->w_addrList );
  1938. #endif
  1939.  
  1940.     w_page_no = cocoAlenlistSize ( cp->w_addrList );
  1941.     cp->w_page_no = w_page_no; 
  1942.  
  1943.     #ifdef DEBUG
  1944.     cocoShowAlenlist ( "Write Alenlist", cp->w_addrList );
  1945.     printf ("w_page_no = %d\n", w_page_no ); 
  1946.     #endif
  1947.  
  1948.         /* =========================================================
  1949.          *      Scatter-Gather list for Read buffer ( board -> mem )
  1950.          * ========================================================= */
  1951.  
  1952.         /*  lock user's pages in memory for DMA  */
  1953.     err = cocoLockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
  1954.         if ( err ) { 
  1955.                 cmn_err (CE_WARN, "cocoReadWrite: Cannot lock user's pages");
  1956.         cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
  1957.                 return (err);
  1958.         }
  1959.  
  1960.     /*
  1961.          *   Invalidate the cache for board->mem
  1962.      *   adjust the address for current data cache line size
  1963.      */ 
  1964.         dki_dcache_inval ( rw->r_buf, tot_bytes ); 
  1965.  
  1966.         /*   create scatter-gather list  */ 
  1967.         addrList2 = uvaddr_to_alenlist( (alenlist_t)NULL, (caddr_t)rw->r_buf, 
  1968.                     (size_t)tot_bytes, 0);
  1969.  
  1970.  
  1971.     /*  did we make it ? */
  1972.         if ( addrList2 == (alenlist_t)NULL ) {
  1973.                 cmn_err (CE_WARN, "cocoreadWrite: cannot create Rd alenlist");
  1974.                 cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
  1975.                 cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
  1976.                 return (EIO);
  1977.         }
  1978.  
  1979.         cp->r_addrList = pciio_dmatrans_list ( cp->conn, 0,  addrList2,
  1980.                            pci_flags ); 
  1981.  
  1982.     if ( cp->r_addrList == (alenlist_t)NULL ) {
  1983.                 cmn_err (CE_WARN, "cocoreadWrite: cannot map Read alenlist");
  1984.                 cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
  1985.                 cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
  1986.                 return (EIO);
  1987.         }
  1988.  
  1989. #if 0
  1990.     r_page_no = alenlist_size ( cp->r_addrList );
  1991. #endif
  1992.     r_page_no = cocoAlenlistSize ( cp->r_addrList );
  1993.         cp->r_page_no = r_page_no; 
  1994.  
  1995.         #ifdef DEBUG/
  1996.         cocoShowAlenlist ( "Read Alenlist", cp->r_addrList );
  1997.         printf ("r_page_no = %d\n", r_page_no ); 
  1998.     #endif
  1999.  
  2000.     /*  assume Single Dma type   */
  2001.     w_dmaPg = (coco_dmapage_t *)NULL;
  2002.     r_dmaPg = (coco_dmapage_t *)NULL;
  2003.  
  2004.     /* ======================================================
  2005.      *    Chain DMA - Prepare chain list for read and write
  2006.      * ====================================================== */
  2007.     if ( cp->dmatype == DMA_PROG ) {
  2008.  
  2009.         /*  need to adjust read/write byte counts  */
  2010.         if ( (coco_adjust_chain == 1) &&
  2011.              (rw->r_buf != rw->w_buf) ) {    
  2012.             err = cocoMakeChainRW ( cp, &w_dmaPg, &r_dmaPg );
  2013.             if ( err ) {
  2014.                cmn_err (CE_WARN, 
  2015.                "cocoReadWrite: Could not make Chain List, err = %d",
  2016.                err );
  2017.                   cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes,
  2018.                         B_READ);
  2019.                   cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, 
  2020.                         B_WRITE);
  2021.                            alenlist_done(cp->r_addrList);
  2022.                            alenlist_done(cp->w_addrList);
  2023.                return (err);
  2024.             }
  2025.         }
  2026.  
  2027.         /*  no need to adjust read/write byte counts  */
  2028.         else {
  2029.                    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2030.                     *    Prepare Chain List for Write
  2031.                     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  2032.                    w_dmaPg = cocoMakeChain ( cp, cp->w_addrList, w_page_no );
  2033.                    if ( w_dmaPg == (coco_dmapage_t *)NULL ) {
  2034.             cmn_err (CE_NOTE,
  2035.                              "cocoReadWrite: Error creating chain list");
  2036.                         cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes,
  2037.                                           B_READ);
  2038.                         cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, 
  2039.                                           B_WRITE);
  2040.  
  2041.                         alenlist_done(cp->r_addrList);
  2042.                         alenlist_done(cp->w_addrList);
  2043.                         return(EIO);
  2044.                    }
  2045.  
  2046.                    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2047.                     *    Prepare Chain List for Read
  2048.                     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  2049.                     r_dmaPg = cocoMakeChain ( cp, cp->r_addrList, r_page_no );
  2050.                     if ( r_dmaPg == (coco_dmapage_t *)NULL ) {
  2051.                         cmn_err (CE_NOTE,
  2052.                                  "cocoReadWrite: Error creating chain list");
  2053.                         cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes,
  2054.                                           B_READ);
  2055.                         cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, 
  2056.                                           B_WRITE);
  2057.  
  2058.                         alenlist_done(cp->r_addrList);
  2059.                         alenlist_done(cp->w_addrList);
  2060.                         kmem_free ( w_dmaPg,
  2061.                                     w_page_no * sizeof(coco_dmapage_t));
  2062.                         return(EIO);
  2063.                     }
  2064.         }
  2065.  
  2066.  
  2067.         /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2068.          *    Map to PCI and cache management
  2069.          *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  2070.         /*  map Write chain list   */
  2071.         if ( coco_adjust_chain == 1 )
  2072.              tot_w_cache = w_page_no * CHAIN_FACTOR * 
  2073.                    sizeof(coco_dmapage_t);
  2074.         else tot_w_cache = w_page_no * sizeof(coco_dmapage_t);
  2075.  
  2076.                 pw_dmaPg = pciio_dmatrans_addr ( cp->conn, 0,  
  2077.                                           kvtophys(w_dmaPg),
  2078.                                           tot_w_cache, 0);
  2079.  
  2080.                 #ifdef DEBUG
  2081.                 cocoShowChain( "Write Chain list", w_dmaPg );
  2082.                 #endif
  2083.  
  2084.         /*  write back the cache for this chain list */
  2085.         dki_dcache_wbinval ( w_dmaPg, tot_w_cache );
  2086.  
  2087.                 /*  map Read chain list  */ 
  2088.                 if ( coco_adjust_chain == 1 )
  2089.                      tot_r_cache = r_page_no * CHAIN_FACTOR * 
  2090.                                    sizeof(coco_dmapage_t);
  2091.                 else tot_r_cache = r_page_no * sizeof(coco_dmapage_t);
  2092.  
  2093.                 pr_dmaPg = pciio_dmatrans_addr ( cp->conn, 0,  
  2094.                                           kvtophys(r_dmaPg),
  2095.                                           tot_r_cache, 0 ); 
  2096.                 #ifdef DEBUG
  2097.                 cocoShowChain( "Read Chain List", r_dmaPg );
  2098.                 #endif
  2099.  
  2100.                 /*  write back the cache for this chain list */
  2101.                 dki_dcache_wbinval ( r_dmaPg, tot_r_cache );
  2102.  
  2103.     }
  2104.  
  2105.     /*  initialize our DMA event semaphore  */
  2106.         SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
  2107.  
  2108.     cp->iostat = IO_OK;
  2109.     cp->dmabits = cp->dmacmd;
  2110.         cp->wp_addr = (alenaddr_t)0;
  2111.         cp->rp_addr = (alenaddr_t)0;
  2112.         cp->wp_size = 0;
  2113.         cp->rp_addr = 0;
  2114.  
  2115.     s = COCO_LOCK(&cp->coco_mlock);
  2116.     err = cocoStartRWDma( cp, pw_dmaPg, tot_bytes, pr_dmaPg, tot_bytes);
  2117.     if ( err == 0 ) {
  2118.         SLEEP_EVENT(&cp->coco_sv, &cp->coco_mlock, s);
  2119.  
  2120.                if ( cp->iostat == IO_OK ) {
  2121.            #ifdef DEBUG
  2122.                    printf ("cocoReadWrite: woken up\n");
  2123.            #endif
  2124.               } 
  2125.         
  2126.            if ( cp->iostat == IO_TIME ) {
  2127.             cmn_err (CE_NOTE, "cocoReadWrite: Timed out");    
  2128.  
  2129.             #ifdef DEBUG
  2130.             cocoDumpAmcc(cp);
  2131.             #endif
  2132.  
  2133.             err = ETIME;
  2134.         }
  2135.         if ( cp->iostat == IO_ERROR ) {
  2136.                         cmn_err (CE_NOTE, "cocoReadWrite: IO Error");
  2137.                         err = EIO;  
  2138.                 }
  2139.  
  2140.     }
  2141.     else {
  2142.         COCO_UNLOCK(&cp->coco_mlock, s);
  2143.         cmn_err (CE_WARN, 
  2144.             "cocoReadWrite: Could not start Sim read/write");
  2145.     }
  2146.  
  2147.         /*  we are done   */
  2148.         cp->dmastat = DMA_IDLE;
  2149.         cp->dmabits = 0;
  2150.  
  2151.         /*
  2152.          *   Invalidate the cache for board->mem
  2153.          *   adjust the address for current data cache line size
  2154.          */
  2155.         dki_dcache_inval ( rw->r_buf, tot_bytes );
  2156.  
  2157.         cocoUnlockUser ( (caddr_t)rw->w_buf, tot_bytes, B_WRITE );
  2158.         cocoUnlockUser ( (caddr_t)rw->r_buf, tot_bytes, B_READ);
  2159.         alenlist_done(cp->r_addrList);
  2160.         alenlist_done(cp->w_addrList);
  2161.     if ( r_dmaPg ) kmem_free ( r_dmaPg, tot_r_cache );
  2162.     if ( w_dmaPg ) kmem_free ( w_dmaPg, tot_w_cache); 
  2163.  
  2164.         return(err);
  2165. }
  2166.  
  2167.  
  2168. /*************************************************************************
  2169.  ***                   c o c o S t a r t R W D m a                     ***
  2170.  *************************************************************************
  2171.  *
  2172.  *  Name:       cocoStartRWDma
  2173.  *
  2174.  *  Purpose:    Program the boards for Simultaneous Read/Write DMA. 
  2175.  *              The read and write channel's scatter-gather have been
  2176.  *              prepared before and are in cp->r_addrList and cp->w_addrList
  2177.  *              For Chained DMA, the chain list for read and write channels
  2178.  *        are prepared before and passed to us as parameters.
  2179.  *
  2180.  * Returns:     0 = Success, or errno 
  2181.  *
  2182.  *************************************************************************/
  2183. static int
  2184. cocoStartRWDma ( card_t *cp, iopaddr_t pw_dmaPg, int tot_write, 
  2185.          iopaddr_t pr_dmaPg, int tot_read ) 
  2186. {
  2187.  
  2188.     register caddr_t   adr_cfg, adr_norm, adr_amcc;
  2189.     register int       i, err, tot_words, tot_bytes;
  2190.     register uint_t       dmabits, dmacfg, dmacmd;
  2191.         size_t            rp_size, wp_size;
  2192.         alenaddr_t        rp_addr, wp_addr;
  2193.  
  2194.  
  2195.     adr_cfg  = cp->conf_adr;
  2196.     adr_norm = cp->norm_adr;
  2197.     adr_amcc = cp->amcc_adr;
  2198.     dmacfg   = cp->dmacfg;
  2199.     dmabits  = cp->dmabits;
  2200.     dmacmd   = cp->dmacmd;
  2201.  
  2202.     Out32(adr_cfg, dmacfg );   /*  clear eof markers */ 
  2203.  
  2204.     /* =======================
  2205.      *    Chained DMA
  2206.      * ======================= */
  2207.     if ( cp->dmatype == DMA_PROG ) {
  2208.  
  2209.         /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2210.          *     Programming the board for Read/Write Chain Dma 
  2211.          * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  2212.  
  2213.         /*  prepare Amcc counters   */
  2214.             Out32(adr_amcc+AMCC_OP_REG_MRTC, tot_write );
  2215.             Out32(adr_amcc+AMCC_OP_REG_MWTC, tot_read ); 
  2216.  
  2217.         /*  Program the Write channel Address (board -> mem ) */ 
  2218.         dmabits |= DMAREG_PREN | DMAREG_PWEN;
  2219.         dmacfg |= dmabits;
  2220.         Out32(adr_cfg, dmacfg);
  2221.  
  2222.         /*   Write channel address  (b->m) */
  2223.         Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMPRWR );
  2224.         Out32(adr_norm, pr_dmaPg);
  2225.  
  2226.         /*  Read channel address (m->b)    */ 
  2227.                 Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMPRRD );
  2228.                 Out32(adr_norm, pw_dmaPg);
  2229.  
  2230.         /*   Start Read/Write DMA - only Write(b->m) is enabled   */ 
  2231.         dmabits |= DMAREG_INTPWEN | DMAREG_WEN | DMAREG_REN | dmacmd;
  2232.  
  2233.         cp->dmasize = tot_write;
  2234.         cp->dmabits = dmabits;
  2235.         cp->iostat  = IO_OK;
  2236.         cp->dmastat = DMA_RW_WAIT; 
  2237.  
  2238.         /*  start the DMA  */
  2239.             /* pciio_flush_buffers ( cp->vhdl ); */
  2240.         nanotime ( &cp->start_time );
  2241.         Out32(adr_cfg, dmacfg | dmabits );
  2242.  
  2243.                 /*  so we dont wait forever for an interrupt  */
  2244.                 cp->tid = itimeout(cocoTimeOut2, cp, SIMRW_TIMER,
  2245.                                    pltimeout,  0, 0, 0);
  2246.  
  2247.         return(0);
  2248.     }
  2249.  
  2250.  
  2251.  
  2252.  
  2253.     /* ===========================
  2254.      *    Single page DMA
  2255.      * =========================== */
  2256.  
  2257.          /*     get next page for Read channel if nothing left from past */
  2258.      if ( cp->wp_addr == (alenaddr_t)0 ) { 
  2259.          if ( cp->w_page_no <= 0 ) {
  2260.  
  2261.         cmn_err (CE_WARN, 
  2262.         "cocoStartRWDma: Premature end of Write, w_page = %d", 
  2263.          cp->w_page_no );
  2264.         return(EIO);
  2265.          }
  2266.  
  2267.              if ( alenlist_get(cp->w_addrList, NULL, NBPP,
  2268.                   &wp_addr, &wp_size, 0) != ALENLIST_SUCCESS ) {
  2269.                   cmn_err (CE_WARN, "cocoStartRWDma: bad scater-gather");
  2270.                   return(EIO);
  2271.          }
  2272.          cp->w_page_no--;
  2273.  
  2274.          }
  2275.      /*  some bytes left from past  */
  2276.      else {
  2277.         wp_addr = cp->wp_addr;
  2278.         wp_size = cp->wp_size;
  2279.      }
  2280.  
  2281.          /*     get next page for Write channel if nothing left from past */ 
  2282.      if ( cp->rp_addr == (alenaddr_t)0 ) {
  2283.  
  2284.              if ( cp->r_page_no <= 0 ) {
  2285.                 cmn_err (CE_WARN, 
  2286.         "cocoStartRWDma: Premature end of Read, r_page = %d",
  2287.         cp->r_page_no);
  2288.                 return(EIO);
  2289.              }
  2290.  
  2291.              if ( alenlist_get(cp->r_addrList, NULL, NBPP,
  2292.                   &rp_addr, &rp_size, 0) != ALENLIST_SUCCESS ) {
  2293.                   cmn_err (CE_WARN, "cocoReadWrite: bad scater-gather");
  2294.                   return(EIO);
  2295.          }
  2296.          cp->r_page_no--;
  2297.  
  2298.          }
  2299.      /*  some bytes left from past  */
  2300.      else {
  2301.                 rp_addr = cp->rp_addr;
  2302.                 rp_size = cp->rp_size;
  2303.  
  2304.          }
  2305.  
  2306.     /*  adjust - we shoud write as much as we can read   */
  2307.     cp->wp_addr = (alenaddr_t)0;
  2308.     cp->rp_addr = (alenaddr_t)0;
  2309.     cp->wp_size = 0;
  2310.     cp->rp_size = 0;
  2311.  
  2312.     /*  Write more than read ?   */
  2313.     if ( wp_size == rp_size )
  2314.         tot_bytes = wp_size;
  2315.  
  2316.     if ( wp_size > rp_size ) {
  2317.         tot_bytes   = rp_size;
  2318.         cp->wp_addr = (alenaddr_t)((int)wp_addr + tot_bytes);
  2319.         cp->wp_size = wp_size - tot_bytes;
  2320.     }
  2321.  
  2322.     /*  read more than write ?  */
  2323.     if ( rp_size > wp_size ) {
  2324.         tot_bytes = wp_size;
  2325.         cp->rp_addr = (alenaddr_t)((int)rp_addr + tot_bytes); 
  2326.         cp->rp_size = rp_size - tot_bytes;
  2327.     }
  2328.  
  2329.     tot_words = (int)tot_bytes/sizeof(uint_t);
  2330.     tot_words--;    /* counts down to 0xffff in hardware */
  2331.  
  2332.     /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2333.      *   Program the board for Read and Write
  2334.      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  2335.  
  2336.     /*  prepare Amcc counters   */
  2337.         Out32(adr_amcc+AMCC_OP_REG_MRTC, tot_bytes);  
  2338.         Out32(adr_amcc+AMCC_OP_REG_MWTC, tot_bytes ); 
  2339.  
  2340.     /*   program for Write channel ( board -> mem )  */
  2341.     Out32(adr_cfg, dmacfg | DMAREG_WCNT);
  2342.     Out32(adr_norm, tot_words);
  2343.         Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMWADR); /* b->m */
  2344.     Out32(adr_norm, rp_addr); 
  2345.  
  2346.     /*   program for Read channel ( mem -> board ) */
  2347.         Out32(adr_cfg, dmacfg | DMAREG_RCNT);
  2348.         Out32(adr_norm, tot_words); 
  2349.         Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMRADR); /* b->m */
  2350.         Out32(adr_norm, wp_addr);
  2351.  
  2352.     /*  start read/write Dma - only write channel (b->m) is needed   */
  2353.     dmabits |= DMAREG_INTWEN | DMAREG_REN | DMAREG_WEN | dmacmd;
  2354.     cp->dmasize = wp_size;
  2355.     cp->dmabits = dmabits;
  2356.     cp->dmastat = DMA_RW_WAIT;
  2357.     cp->iostat  = IO_OK;
  2358.  
  2359.  
  2360.     /*  start the DMA   */
  2361.     nanotime ( &cp->start_time );
  2362.     Out32(adr_cfg, dmacfg | dmabits | dmacmd );
  2363.  
  2364.         /*  so we dont wait forever for an interrupt  */
  2365.         cp->tid = itimeout(cocoTimeOut2, cp, SIMRW_TIMER,
  2366.                            pltimeout,  0, 0, 0);
  2367.  
  2368.         return(0);
  2369.  
  2370. }
  2371.  
  2372. /*************************************************************************
  2373.  ***                   c o c o R e s e t                               ***
  2374.  *************************************************************************
  2375.  *
  2376.  *  Name:       cocoReset
  2377.  *
  2378.  *  Purpose:    This routine initializes the board by resetting the add-on     
  2379.  *              logic, AMCC fifos, Chameleon chip and FIFOs. 
  2380.  *         After reset, FIFO flags are programmed, default DMA controller
  2381.  *              config. register is written and Chameleon chip is enabled     
  2382.  *
  2383.  * Returns:     None
  2384.  *
  2385.  *************************************************************************/
  2386. static void
  2387. cocoReset( card_t  *cp )
  2388. {
  2389.  
  2390.     uint_t   stat;
  2391.     register caddr_t  adr_amcc; 
  2392.     register caddr_t  adr_cfg;
  2393.     register uint_t   tmp; 
  2394.  
  2395.     adr_amcc = cp->amcc_adr;
  2396.     adr_cfg  = cp->conf_adr;
  2397.  
  2398.     /*  disable interrupts   */
  2399.         Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_RST | AMCC_INTCSR_RCLR |
  2400.                                      AMCC_INTCSR_WCLR );
  2401.  
  2402.       /* reset AMCC fifos and Xilinx  */
  2403.         Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_ADDON );
  2404.         Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_FIFOS ); 
  2405.  
  2406.       /* reset Chameleon and FIFOs and bring FIFOs to programming flags */
  2407.       Out32(adr_cfg, DMAREG_CCRES | DMAREG_FRES | DMAREG_FSCLK );
  2408.       Out32(adr_cfg, DMAREG_FSCLK);
  2409.       Out32(adr_cfg, DMAREG_FSCLK);
  2410.  
  2411.       /* program FIFO flags */
  2412.       cocoProgFlags ( adr_cfg, DMAREG_FRES,100,450,100,450);
  2413.  
  2414.       /* bring FIFOs in functional mode and Chameleon out of reset */
  2415.       Out32(adr_cfg, DMAREG_FRES | DMAREG_FSCLK);
  2416.       Out32(adr_cfg, DMAREG_CCRES | DMAREG_FSCLK);
  2417.       Out32(adr_cfg, DMAREG_CCRES | DMAREG_FSCLK | DMAREG_PTEN);
  2418.  
  2419.       /* set default config. reg */
  2420.       cp->dmacfg = DMAREG_NVIFEN | DMAREG_PTEN | DMAREG_CCRES | DMAREG_FSCLK;
  2421.  
  2422.       /* initialize Chameleon */
  2423.       cocoSetMode(cp, 0,0,0,1);
  2424.  
  2425.     /*  enable Amcc Interrupt   */
  2426.         Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_MASK );
  2427. }
  2428.  
  2429.  
  2430. /*************************************************************************
  2431.  ***                   c o c o P r o g F l a g s                       ***
  2432.  *************************************************************************
  2433.  *
  2434.  *  Name:       cocoProgFlags  
  2435.  *
  2436.  *  Purpose:    Program offsets of ASIC fifo flags by writing 18 bit 
  2437.  *              serial registers of FIFO containg 9 bit AF and 9 bit AE 
  2438.  *              flag offset
  2439.  *
  2440.  * Returns:     None
  2441.  *
  2442.  *************************************************************************/
  2443. static void
  2444. cocoProgFlags ( caddr_t adr_cfg, uint_t d, ushort_t iae, ushort_t iaf, 
  2445.             ushort_t oae, ushort_t oaf )
  2446. {
  2447.     ushort_t andfl;
  2448.      ushort_t shft;
  2449.      ushort_t bit0;
  2450.      ushort_t bit1;
  2451.      uint_t   bit;
  2452.  
  2453.      andfl=0x01;
  2454.      shft=0;
  2455.  
  2456.      do {
  2457.            bit0 = (iaf & andfl);
  2458.            bit1 = (oaf & andfl);
  2459.            bit = d | 0x00000010;
  2460.  
  2461.            if (bit0 == 0) 
  2462.             bit |= 0x00000004;
  2463.  
  2464.            if (bit1 == 0) 
  2465.             bit |= 0x00000008;
  2466.  
  2467.            Out32(adr_cfg, bit);
  2468.  
  2469.            bit &= 0xFFFFFFEF;
  2470.  
  2471.            Out32(adr_cfg, bit);
  2472.  
  2473.            andfl = andfl << 1;
  2474.            shft++;
  2475.        }
  2476.        while ( shft <= 8 );
  2477.  
  2478.      andfl = 0x01;
  2479.      shft = 0;
  2480.      do {
  2481.            bit0 = (iae & andfl);
  2482.            bit1 = (oae & andfl);
  2483.            bit = d | 0x00000010;
  2484.  
  2485.            if (bit0==0) 
  2486.             bit |= 0x00000004;
  2487.  
  2488.            if (bit1==0) 
  2489.             bit |= 0x00000008;
  2490.  
  2491.            Out32(adr_cfg, bit);
  2492.            bit = bit & 0xFFFFFFEF;
  2493.            Out32(adr_cfg, bit);
  2494.  
  2495.            andfl = andfl << 1;
  2496.            shft++;
  2497.       }
  2498.      while (shft<=8);
  2499. }
  2500.  
  2501.  
  2502. /*************************************************************************
  2503.  ***                   c o c o S e t  M o d e                          ***
  2504.  *************************************************************************
  2505.  *
  2506.  *  Name:       cocoSetMode
  2507.  *
  2508.  *  Purpose:    Set Chameleon Mode Register 
  2509.  *
  2510.  * Returns:     None
  2511.  *
  2512.  *************************************************************************/
  2513. static void
  2514. cocoSetMode ( card_t *cp, int mode, int swap, int slice, int flag )
  2515.  
  2516.     uint_t    cmd;
  2517.       cmd = COCO_WRENA | COCO_DELAY;
  2518.  
  2519.       if (mode) 
  2520.         cmd |=  COCO_MODE;
  2521.  
  2522.     
  2523.       if (swap) 
  2524.         cmd |= COCO_SWAP;
  2525.  
  2526.       if (slice) 
  2527.         cmd |= COCO_SLICE;
  2528.  
  2529.       if (flag) 
  2530.         cmd |= COCO_FLAG;
  2531.     
  2532.       cocoCommand (cp, COCO_SETMODE, cmd);
  2533.     
  2534. }
  2535.  
  2536.  
  2537. /*************************************************************************
  2538.  ***                   c o c o C o m m a n d                           ***
  2539.  *************************************************************************
  2540.  *
  2541.  *  Name:       cocoCommand  
  2542.  *
  2543.  *  Purpose:    Sends a command to Chameleon. Writes the command to 
  2544.  *        the controller and writes the data to Fifo.
  2545.  *
  2546.  * Returns:     None
  2547.  *
  2548.  *************************************************************************/
  2549. static void
  2550. cocoCommand ( card_t *cp, uint_t cmd, uint_t data )
  2551. {
  2552.     register uint_t   stat;
  2553.  
  2554.     /*  set Chameleon connad in Config. Register  */
  2555.     Out32(cp->conf_adr,  cmd | cp->dmacfg );
  2556.  
  2557.     /*  writes the data for the command to AMCC Fifo  */
  2558.     Out32(cp->amcc_adr + AMCC_OP_REG_FIFO, data);
  2559. }
  2560.  
  2561.  
  2562. /*************************************************************************
  2563.  ***                   c o c o B u f O u t                             ***
  2564.  *************************************************************************
  2565.  *
  2566.  *  Name:       cocoBufOut 
  2567.  *
  2568.  *  Purpose:    Dumps a buffer containig 32-bit values to Chameleon Fifo.
  2569.  *        Data is given to Chameleon in Transparent mode.
  2570.  *
  2571.  * Returns:     None
  2572.  *
  2573.  *************************************************************************/
  2574. static void
  2575. cocoBufOut ( card_t *cp, uint_t *buf, int size )
  2576. {
  2577.     register int    i, j;
  2578.     register uint_t cmd, stat;
  2579.  
  2580.     /*  set to Transparent Mode  */
  2581.     cmd = cp->dmacfg | COCO_TRANSP;
  2582.     Out32(cp->conf_adr, cmd );
  2583.  
  2584.     /*   Dump the data   */
  2585.     for ( i = 0; i < size; i++) {
  2586.         j = 0;
  2587.                 stat = Inp32(cp->amcc_adr+AMCC_OP_REG_MCSR);
  2588.         if ( stat & 0x03 ) {  /*  fifo has room  */
  2589.             Out32(cp->amcc_adr+AMCC_OP_REG_FIFO, buf[i] );
  2590.             continue;
  2591.         }
  2592.         printf ("cocoBufOut: Fifo is full, stat = 0x%x, discarding %d bytes\n", stat, size - i );        
  2593.         break; 
  2594.     }    
  2595.  
  2596. }
  2597.  
  2598. /*************************************************************************
  2599.  ***                   c o c o B u f I n                               ***
  2600.  *************************************************************************
  2601.  *
  2602.  *  Name:       cocoBufIn 
  2603.  *
  2604.  *  Purpose:    Reads Fifo entries into a buf.  
  2605.  *
  2606.  * Returns:     None
  2607.  *
  2608.  *************************************************************************/
  2609. static void
  2610. cocoBufIn ( card_t *cp, uint_t *buf, int size )
  2611. {
  2612.     register int    i;
  2613.  
  2614.     for ( i = 0; i < size; i++ ) {
  2615.         buf[i] = cocoReadAmccFifo(cp);
  2616.     }
  2617.  
  2618. }
  2619.  
  2620.  
  2621. /*************************************************************************
  2622.  ***                   c o c o R e a d A m c c F i f o                 ***
  2623.  *************************************************************************
  2624.  *
  2625.  *  Name:       cocoReadAmccFifo
  2626.  *
  2627.  *  Purpose:    Reads a 32-bit value word from AMCC Internal Fifo
  2628.  *        Returns zero if Fifo is empty
  2629.  *
  2630.  * Returns:     Fifo value or zero if fifo is empty
  2631.  *
  2632.  *************************************************************************/
  2633. static int 
  2634. cocoReadAmccFifo ( card_t  *cp )
  2635. {
  2636.     register uint_t  stat;
  2637.     register int     i;
  2638.  
  2639.     for ( i = 0; i < 3; i++ )
  2640.         stat = Inp32(cp->amcc_adr+AMCC_OP_REG_MCSR);
  2641.  
  2642.     /* if ( stat != 0x000000e6 )  {  */
  2643.     if ( stat != 0x26 )  {
  2644.         stat = Inp32(cp->amcc_adr + AMCC_OP_REG_FIFO );
  2645.         return(stat);
  2646.     }
  2647.  
  2648.     return(0);
  2649. }
  2650.  
  2651.  
  2652. /*************************************************************************
  2653.  ***                   c o c o F i f o T e s t                         ***
  2654.  *************************************************************************
  2655.  *
  2656.  *  Name:       cocoFifoTest
  2657.  *
  2658.  *  Purpose:    Fills Fifo with a pattern, read it back one by one
  2659.  *        and compare. Reports back the results.
  2660.  *
  2661.  * Returns:     0 = Success, 1 = Failed.
  2662.  *
  2663.  *************************************************************************/
  2664. static int
  2665. cocoFifoTest ( card_t *cp, int pat )
  2666. {
  2667.     register int  i, j, err;
  2668.     uint_t     res, expect;
  2669.  
  2670.     err = 0;   /* assume success */
  2671.  
  2672.     /*  test for 50 times ..  */
  2673.      for( j = 0; j < 50; j++) {
  2674.  
  2675.         /*  fill Fifo with pattern   */
  2676.         for(i=0;i<750;i++) 
  2677.                   cocoCommand (cp, COCO_TRANSP, cocoPattern(pat,i) );
  2678.  
  2679.         /* read it back and compare   */
  2680.          for( i = 0;i < 750; i++) {
  2681.  
  2682.                   res = cocoReadAmccFifo( cp );   /* what we read   */
  2683.                   expect = cocoPattern( pat, i);  /* what we expect */
  2684.  
  2685.                   if (res != expect) {
  2686.              cmn_err (CE_NOTE, 
  2687.                   "cocoFifoTest: Fifo entry %d, expected 0x%x, read 0x%x (round %d)", i, expect, res, j);
  2688.                  err = 1;
  2689.                  }
  2690.             }
  2691.      }
  2692.  
  2693.     if ( err ) 
  2694.         cmn_err (CE_NOTE, "cocoFifoTest: Failed\n");
  2695.     else    cmn_err (CE_NOTE, "cocoFifoTest: Succeeded\n");
  2696.  
  2697.     return(err);
  2698. }
  2699.  
  2700. /*************************************************************************
  2701.  ***                   c o c o P a t t e r n                           ***
  2702.  *************************************************************************
  2703.  *
  2704.  *  Name:       cocoPattern      
  2705.  *
  2706.  *  Purpose:    Pattern generator for testing purpose.
  2707.  *
  2708.  * Returns:     The generated pattern 
  2709.  *
  2710.  *************************************************************************/
  2711. static int
  2712. cocoPattern ( int pat, int cnt )
  2713. {
  2714.     register int res;
  2715.  
  2716.     /*  for now, we always return pattern 1  */
  2717.     pat=1;
  2718.     
  2719.     switch (pat) {
  2720.       case 1:   
  2721.         res = cnt;   
  2722.         break;
  2723.  
  2724.       case 2:   
  2725.         res = ~cnt;  
  2726.         break;
  2727.  
  2728.       case 3:
  2729.         res = 0xFFFFFFFFL;
  2730.              break;
  2731.  
  2732.       case 4:
  2733.         res = 0x00000000L;
  2734.              break;
  2735.  
  2736.       case 5:
  2737.         if (cnt % 2 != 1) 
  2738.              res = 0xaaaaaaaaL; 
  2739.         else res = 0x55555555L;
  2740.              break;
  2741.  
  2742.       case 6:
  2743.         cnt = (cnt & 0x01FL);
  2744.              res = (1 << cnt);
  2745.              break;
  2746.  
  2747.       case 7:
  2748.         cnt = (cnt & 0x01FL);
  2749.              res = (1 << cnt);
  2750.              res = ~res;
  2751.              break;
  2752.  
  2753.       case 8:
  2754.         if ( cnt % 2 == 1) 
  2755.              res = 0x0f0f0f0fL; 
  2756.         else res = 0xf0f0f0f0L;
  2757.              break;
  2758.  
  2759.       case 9:
  2760.         cnt = (cnt & 0xFF);
  2761.              res = cnt + ( cnt << 8) + (cnt << 16) + (cnt << 24);
  2762.              break;
  2763.  
  2764.       case 10:
  2765.         cnt = (cnt & 0xFFFF);
  2766.               res = cnt + ( cnt << 16);
  2767.               break;
  2768.  
  2769.       }
  2770.  
  2771.       return(res);
  2772. }
  2773.  
  2774. /*************************************************************************
  2775.  ***                   c o c o R e a d M o d e                         ***
  2776.  *************************************************************************
  2777.  *
  2778.  *  Name:       cocoReadMode
  2779.  *
  2780.  *  Purpose:    Reads Chameleon Mode register
  2781.  *
  2782.  * Returns:     The generated pattern
  2783.  *
  2784.  *************************************************************************/
  2785. static int
  2786. cocoReadMode ( card_t *cp )
  2787. {
  2788.  
  2789.     register uint_t   mode;
  2790.  
  2791.         /*  set Chameleon command in Config. Register  */
  2792.     cocoCommand ( cp, COCO_READMODE, 0x0 );
  2793.     mode = cocoReadAmccFifo(cp);
  2794.  
  2795.     return (mode);
  2796. }
  2797.  
  2798. /*************************************************************************
  2799.  ***                   c o c o R e a d D m a R e g s                   ***
  2800.  *************************************************************************
  2801.  *
  2802.  *  Name:       cocoReadDmaRegs
  2803.  *
  2804.  *  Purpose:    Reads Xilinx DMA Registers 
  2805.  *
  2806.  * Returns:     None. 
  2807.  *
  2808.  *************************************************************************/
  2809. static void
  2810. cocoReadDmaRegs ( card_t *cp, uint_t *dmaRegs )
  2811. {
  2812.  
  2813.     register int    i, k; 
  2814.     register uint_t  dmacfg;
  2815.  
  2816.     dmacfg = cp->dmacfg;
  2817.  
  2818.     /*  read DMA registers into dmaRegs table  */
  2819.     i = 0;
  2820.     for ( k = 13; k <= 16; k++) {
  2821.         Out32(cp->conf_adr, dmacfg | (k << 6) );
  2822.         dmaRegs[i++] = Inp32(cp->norm_adr);
  2823.     }
  2824. }
  2825.  
  2826. /*************************************************************************
  2827.  ***                   c o c o W r i t e D m a R e g s                 ***
  2828.  *************************************************************************
  2829.  *
  2830.  *  Name:       cocoWriteDmaRegs
  2831.  *
  2832.  *  Purpose:    Write values in dmaRegs[] to Xilinx DMA Registers
  2833.  *
  2834.  * Returns:     None.
  2835.  *
  2836.  *************************************************************************/
  2837. static void
  2838. cocoWriteDmaRegs ( card_t *cp, uint_t *dmaRegs )
  2839. {
  2840.         register int   i, k;
  2841.         register uint_t  dmacfg;
  2842.  
  2843.         dmacfg = cp->dmacfg;
  2844.  
  2845.         /*  read DMA registers into dmaRegs table  */
  2846.         i = 0;
  2847.         for ( k = 13; k <= 16; k++) {
  2848.                 Out32(cp->conf_adr, dmacfg | (k << 6) );
  2849.         Out32(cp->norm_adr, dmaRegs[i++] );
  2850.         }
  2851. }
  2852.  
  2853. /*************************************************************************
  2854.  ***                   c o c o R e a d A d d r                         ***
  2855.  *************************************************************************
  2856.  *
  2857.  *  Name:       cocoReadAddr     
  2858.  *
  2859.  *  Purpose:    Reads Address Register
  2860.  *
  2861.  * Returns:     Address Register value
  2862.  *
  2863.  *************************************************************************/
  2864. static int
  2865. cocoReadAddr (card_t *cp)
  2866. {
  2867.     register uint_t  addr_reg;
  2868.  
  2869.     cocoCommand ( cp, COCO_READADDR, 0x0 );
  2870.     addr_reg = cocoReadAmccFifo(cp);
  2871.     
  2872.     return(addr_reg);
  2873. }
  2874.  
  2875. /*************************************************************************
  2876.  ***                   c o c o S e t A d d r                           ***
  2877.  *************************************************************************
  2878.  *
  2879.  *  Name:       cocoSetAddr 
  2880.  *
  2881.  *  Purpose:    Set Address Register to given value 
  2882.  *
  2883.  * Returns:     None 
  2884.  *
  2885.  *************************************************************************/
  2886. static void
  2887. cocoSetAddr ( card_t *cp, uint_t val )
  2888. {
  2889.     cocoCommand ( cp, COCO_SETADDR, val );
  2890. }
  2891.  
  2892. /*************************************************************************
  2893.  ***                   c o c o D m a R e g s T e s t                   ***
  2894.  *************************************************************************
  2895.  *
  2896.  *  Name:       cocoDmaRegsTest
  2897.  *
  2898.  *  Purpose:    Tests access to Xilinx DMA registers.
  2899.  *        Write and read to DMA registers, compare values and 
  2900.  *        report back the results.
  2901.  *
  2902.  * Returns:     Test result ( 0 = Success, 1 = Failed) 
  2903.  *
  2904.  *************************************************************************/
  2905. static int
  2906. cocoDmaRegsTest ( card_t *cp )
  2907. {
  2908.  
  2909.     register int i, j, k, err, res, expct, dmacfg, pat;
  2910.     register caddr_t   adr_cfg, adr_norm;
  2911.  
  2912.     cmn_err (CE_NOTE, "testing Chameleon DMA registers access");
  2913.  
  2914.     adr_cfg  = cp->conf_adr;
  2915.     adr_norm = cp->norm_adr;
  2916.     dmacfg    = cp->dmacfg;
  2917.     err      = 0;
  2918.     pat      = 1;
  2919.  
  2920.     /*   try for 500 times   */
  2921.     for ( i = 0; i < 500; i++ ) {
  2922.         
  2923.         /*  write to DMA Regsiers  */
  2924.         for ( k = 13; k <= 16; k++ ) {
  2925.             Out32(adr_cfg, dmacfg | (k << 6) );
  2926.             Out32(adr_norm, cocoPattern(pat, i+k) );
  2927.         }
  2928.         
  2929.         /*  read back registers and compare   */
  2930.         for ( k = 13; k <= 16; k++ ) {
  2931.  
  2932.             Out32(adr_cfg, dmacfg | (k << 6) );
  2933.             res   = Inp32(adr_norm);
  2934.             expct = cocoPattern(pat, i+k);
  2935.  
  2936.             /*  not equal ..report it !  */
  2937.             if ( res != expct ) {
  2938.                cmn_err ( CE_NOTE, 
  2939.                "Dma reg %d, expected 0x%x, read 0x%x, round %x", 
  2940.                 k, expct, res, i ); 
  2941.                 err = 1;
  2942.             }
  2943.         }
  2944.  
  2945.     }
  2946.  
  2947.     cmn_err (CE_NOTE, "Chameleon DMA registers access test %s",
  2948.         (err == 0 ? "Succeeded": "Failed") ); 
  2949.  
  2950.     return(err);
  2951. }
  2952.  
  2953.  
  2954. /*************************************************************************
  2955.  ***                   c o c o I n t R a m T e s t                     ***
  2956.  *************************************************************************
  2957.  *
  2958.  *  Name:       cocoIntRamTest
  2959.  *
  2960.  *  Purpose:    Test CHameleon Internal LUTs. 
  2961.  *              Fills Internal LUT with a pattern and reads them back
  2962.  *        for comparison and reports the results. 
  2963.  *
  2964.  * Returns:     Test result ( 0 = Success, 1 = Failed)
  2965.  *
  2966.  *************************************************************************/
  2967. static int
  2968. cocoIntRamTest ( card_t *cp )
  2969. {
  2970.  
  2971.     register int  i, err, pat, num;
  2972.     register uint_t  res;
  2973.  
  2974.     cmn_err (CE_NOTE, "Testing Chameleon Internal Ram access\n");
  2975.  
  2976.     num = 1;
  2977.     err = 0;
  2978.     
  2979.     /* ====================
  2980.      *   Fill LUTs 
  2981.      * ==================== */
  2982.     for ( i = 0; i < INT_RAM_SIZE; i++ ) {
  2983.  
  2984.  
  2985.         pat = cocoPattern(num, i);
  2986.  
  2987.         /*  set address of internal LUT location  */
  2988.         cocoCommand (cp, COCO_SETADDR, i); 
  2989.  
  2990.         /*  fill Internal LUTs with pattern   */
  2991.         cocoCommand (cp, COCO_FILLRAMIL, pat ); 
  2992.         cocoCommand (cp, COCO_FILLRAMIH, pat ); 
  2993.         cocoCommand (cp, COCO_FILLRAMO,  pat ); 
  2994.     }
  2995.  
  2996.  
  2997.     /* =============================
  2998.      *     Read LUTs and compare
  2999.      * ============================= */
  3000.     for ( i = 0; i < INT_RAM_SIZE; i++ ) {
  3001.  
  3002.         
  3003.         pat = cocoPattern(num, i) & 0x03ffff;
  3004.  
  3005.         /* 
  3006.                  *  set address of internal RAMIL location 
  3007.          *  read value from that location and compare 
  3008.          */
  3009.                 cocoCommand (cp, COCO_SETADDR, i); 
  3010.         cocoCommand ( cp, COCO_READRAMIL, 0x0 );
  3011.         res = cocoReadAmccFifo (cp);
  3012.     
  3013.         /*  is what we read ok ?   */
  3014.         if ( (res & 0x03ffff) != pat ) {
  3015.             cmn_err (CE_NOTE, 
  3016.             "Chameleon RAMIL at 0x%x, expected 0x%x, read 0x%x\n",
  3017.              i, pat, res );
  3018.             err = 1;
  3019.         }
  3020.  
  3021.                 /*  
  3022.                  *  set address of internal RAMIH location    
  3023.                  *  read value from that location and compare
  3024.                  */
  3025.                 cocoCommand (cp, COCO_SETADDR, i);
  3026.                 cocoCommand ( cp, COCO_READRAMIH, 0x0 );
  3027.                 res = cocoReadAmccFifo (cp);
  3028.  
  3029.                 /*  is what we read ok ?   */   
  3030.                 if ( (res & 0x03ffff) != pat ) {                
  3031.                         cmn_err (CE_NOTE,               
  3032.                         "Chameleon RAMIH at 0x%x, expected 0x%x, read 0x%x\n",
  3033.                          i, pat, res );
  3034.                         err = 1;
  3035.                 }
  3036.  
  3037.                 /*  
  3038.                  *  set address of internal RAMO location    
  3039.                  *  read value from that location and compare
  3040.                  */
  3041.                 cocoCommand (cp, COCO_SETADDR, i);
  3042.                 cocoCommand ( cp, COCO_READRAMO, 0x0 );
  3043.                 res = cocoReadAmccFifo (cp);
  3044.  
  3045.                 /*  is what we read ok ?   */   
  3046.                 if ( (res & 0x03ffff) != pat ) {                
  3047.                         cmn_err (CE_NOTE,               
  3048.                         "Chameleon RAMO at 0x%x, expected 0x%x, read 0x%x\n",
  3049.                          i, pat, res );
  3050.                         err = 1;
  3051.                 }
  3052.  
  3053.     }
  3054.  
  3055.     cmn_err (CE_NOTE, "Chameleon Internal RAM test %s\n",
  3056.          ( err == 0 ? "Succeeded":"Failed") );
  3057.  
  3058.     return(err);
  3059.  
  3060. }
  3061.  
  3062. /*************************************************************************
  3063.  ***                   c o c o E x t R a m T e s t                     ***
  3064.  *************************************************************************
  3065.  *
  3066.  *  Name:       cocoExtRamTest
  3067.  *
  3068.  *  Purpose:    Test CHameleon External LUTs. 
  3069.  *              Fills External LUT with a pattern and reads them back
  3070.  *        for comparison and reports the results. 
  3071.  *
  3072.  * Returns:     Test result ( 0 = Success, 1 = Failed)
  3073.  *
  3074.  *************************************************************************/
  3075. static int
  3076. cocoExtRamTest ( card_t *cp )
  3077. {
  3078.  
  3079.     register int  i, err, pat, num;
  3080.     register uint_t  res;
  3081.  
  3082.     cmn_err (CE_NOTE, "Testing Chameleon External Ram access\n");
  3083.  
  3084.     num = 1;
  3085.     err = 0;
  3086.     
  3087.     /* ====================
  3088.      *   Fill RAML 
  3089.      * ==================== */
  3090.     for ( i = 0; i < EXT_RAM_SIZE; i++ ) {
  3091.  
  3092.         /*  set address of internal LUT location  */
  3093.         cocoCommand (cp, COCO_SETADDR, i); 
  3094.  
  3095.         /*  fill External LUTs with pattern   */
  3096.         cocoCommand (cp, COCO_FILLRAML, cocoPattern(num, i) );
  3097.     }
  3098.  
  3099.  
  3100.     /* ===================================
  3101.      *     Read External LUT and compare
  3102.      * =================================== */
  3103.     for ( i = 0; i < EXT_RAM_SIZE; i++ ) {
  3104.  
  3105.         
  3106.         pat = cocoPattern(num, i); 
  3107.  
  3108.         /* 
  3109.                  *  set address of internal RAMIL location 
  3110.          *  read value from that location and compare 
  3111.          */
  3112.                 cocoCommand (cp, COCO_SETADDR, i); 
  3113.         cocoCommand ( cp, COCO_READRAML, 0x0 );
  3114.         res = cocoReadAmccFifo (cp);
  3115.     
  3116.         /*  is what we read ok ?   */
  3117.         if ( res != pat ) {
  3118.             cmn_err (CE_NOTE, 
  3119.             "Chameleon RAML at 0x%x, expected 0x%x, read 0x%x\n",
  3120.              i, pat, res );
  3121.             err = 1;
  3122.         }
  3123.     }
  3124.  
  3125.  
  3126.         cmn_err (CE_NOTE, "Chameleon External RAM test %s\n",
  3127.                  ( err == 0 ? "Succeeded":"Failed") );
  3128.  
  3129.         return(err);
  3130.  
  3131. }
  3132.  
  3133.  
  3134. /*************************************************************************
  3135.  ***                   c o c o R e a d I n t R a m                *** 
  3136.  *************************************************************************
  3137.  *
  3138.  *  Name:       cocoReadIntRam
  3139.  *
  3140.  *  Purpose:    Read Chameleon's Internal LUTs into given buffer.
  3141.  *
  3142.  * Returns:     None. 
  3143.  *
  3144.  *************************************************************************/
  3145. static void
  3146. cocoReadIntRam ( card_t *cp, uint_t *buf, int lut, int size )
  3147. {
  3148.     register uint_t  cmd;
  3149.     register int     i;
  3150.  
  3151.     /*  which LUT we should read ?  */
  3152.     switch ( lut ) {
  3153.         case COCO_READ_RAMIL:  cmd = COCO_READRAMIL;  break;
  3154.         case COCO_READ_RAMIH:  cmd = COCO_READRAMIH;  break;
  3155.         case COCO_READ_RAMO:   cmd = COCO_READRAMO;   break;
  3156.     }
  3157.  
  3158.  
  3159.     /*   fill buffer with contents of Internal Ram  */
  3160.     for ( i = 0; i < size; i++ ) {
  3161.               cocoCommand (cp, COCO_SETADDR, i);
  3162.                 cocoCommand (cp, cmd, 0x0 );
  3163.                 buf[i] = cocoReadAmccFifo (cp);
  3164.     }
  3165.  
  3166. }
  3167.  
  3168. /*************************************************************************
  3169.  ***                   c o c o W r i t e I n t R a m                   ***
  3170.  *************************************************************************
  3171.  *
  3172.  *  Name:       cocoWriteIntRam
  3173.  *
  3174.  *  Purpose:    Write Chameleon's Internal LUTs into given buffer.
  3175.  *
  3176.  * Returns:     None.
  3177.  *
  3178.  *************************************************************************/
  3179. static void
  3180. cocoWriteIntRam ( card_t *cp, uint_t *buf, int lut, int size )
  3181. {
  3182.         register uint_t  cmd;
  3183.         register int     i;
  3184.  
  3185.         /*  which LUT we should read ?  */
  3186.         switch ( lut ) {
  3187.                 case COCO_FILL_RAMIL:  cmd = COCO_FILLRAMIL;  break;
  3188.                 case COCO_FILL_RAMIH:  cmd = COCO_FILLRAMIH;  break;
  3189.                 case COCO_FILL_RAMO:   cmd = COCO_FILLRAMO;   break;
  3190.         }
  3191.  
  3192.  
  3193.         /*   fill buffer with contents of Internal Ram  */
  3194.         for ( i = 0; i < size; i+=2 ) {
  3195.                 cocoCommand (cp, COCO_SETADDR, buf[i]);
  3196.                 cocoCommand (cp, cmd, buf[i+1] );
  3197.         }
  3198.  
  3199. }
  3200.  
  3201. /*************************************************************************
  3202.  ***                   c o c o R e a d E x t R a m                     ***
  3203.  *************************************************************************
  3204.  *
  3205.  *  Name:       cocoReadExtRam
  3206.  *
  3207.  *  Purpose:    Read Chameleon's External LUT into given buffer.
  3208.  *
  3209.  * Returns:     None.
  3210.  *
  3211.  *************************************************************************/
  3212. static void
  3213. cocoReadExtRam ( card_t *cp, uint_t *buf, int size )
  3214. {
  3215.         register uint_t  cmd;
  3216.         register int     i;
  3217.  
  3218.  
  3219.     /*   fill External Ram with contents of the buffer  */
  3220.         for ( i = 0; i < size; i++ ) {
  3221.                 cocoCommand (cp, COCO_SETADDR, i);
  3222.                 cocoCommand (cp, COCO_READRAML, 0x0 );
  3223.                 buf[i] = cocoReadAmccFifo (cp);
  3224.     }
  3225.  
  3226. }
  3227.  
  3228.  
  3229. /*************************************************************************
  3230.  ***                   c o c o W r i t e E x t R a m                   ***
  3231.  *************************************************************************
  3232.  *
  3233.  *  Name:       cocoWriteExtRam
  3234.  *
  3235.  *  Purpose:    Write Chameleon's External LUT into given buffer.
  3236.  *
  3237.  * Returns:     None.
  3238.  *
  3239.  *************************************************************************/
  3240. static void
  3241. cocoWriteExtRam ( card_t *cp, uint_t *buf, int size )
  3242. {
  3243.         register int     i;
  3244.  
  3245.         /*   fill buffer with contents of Internal Ram  */
  3246.         for ( i = 0; i < size; i+=2 ) {
  3247.                 cocoCommand (cp, COCO_SETADDR, buf[i]);
  3248.                 cocoCommand (cp, COCO_FILLRAML, buf[i+1] );
  3249.         }
  3250.  
  3251. }
  3252.  
  3253.  
  3254. /*************************************************************************
  3255.  ***                   c o c o C o n v e r t                           ***
  3256.  *************************************************************************
  3257.  *
  3258.  *  Name:       cocoConvert     
  3259.  *
  3260.  *  Purpose:    Converts a single value 
  3261.  *
  3262.  * Returns:     None
  3263.  *
  3264.  *************************************************************************/
  3265. static void
  3266. cocoConvert ( card_t *cp, uint_t val )
  3267. {
  3268.     cocoCommand ( cp, COCO_CONVERT, val );
  3269. }
  3270.  
  3271.  
  3272. /*************************************************************************
  3273.  ***                   c o c o C o n v e r t T e s t                   ***
  3274.  *************************************************************************
  3275.  *
  3276.  *  Name:       cocoConvertTest
  3277.  *
  3278.  *  Purpose:    Converts a single value, read the converted value back
  3279.  *        and compare to known value.
  3280.  *
  3281.  * Returns:     None 
  3282.  *
  3283.  *************************************************************************/
  3284. static void
  3285. cocoConvertTest ( card_t *cp, coco_convert_t *cv )
  3286. {
  3287.     register uint_t  res;
  3288.  
  3289.     
  3290.     /*  convert the pixle value   */
  3291.     cv->result = 0;         /*  assume success */
  3292.     cocoCommand ( cp, COCO_CONVERT, cv->in );
  3293.  
  3294.     /*  read the converted value and compare  */
  3295.     res = cocoReadAmccFifo (cp);
  3296.  
  3297.     if ( res != cv->out )
  3298.         cv->result = 1;
  3299.  
  3300. }
  3301.  
  3302. /*************************************************************************
  3303.  ***                   c o c o D m a T o L u t s                       ***
  3304.  *************************************************************************
  3305.  *
  3306.  *  Name:       cocoDmaToLuts  
  3307.  *
  3308.  *  Purpose:    DMAs data in user's buffer to one of Internal LUTs or 
  3309.  *              the External LUTs (identified by cmd param). The DMA is
  3310.  *        done either in SINGLE or PROG (chained) mode depending
  3311.  *        on current set up (cp->dmatype).
  3312.  *
  3313.  * Returns:     0 = Success, or errno
  3314.  *
  3315.  *************************************************************************/
  3316. static int
  3317. cocoDmaToLuts( card_t *cp, coco_buf_t *cb, int cmd )
  3318. {
  3319.  
  3320.     register caddr_t  kvaddr, amcc_adr;
  3321.     register coco_dmapage_t  *dmaPg;
  3322.     register int      len, page_no, i, dmatype, err, tot_bytes;
  3323.     register int     s;
  3324.     register int      cache_bytes;
  3325.     register uint_t   dmabits, *ib, olddmacmd, dmacmd;
  3326.     register uint_t   *cache_line;
  3327.     alenlist_t        addrList2;
  3328.     alenlist_t        addrList;
  3329.     size_t           p_size;
  3330.     alenaddr_t       p_addr;
  3331.     iopaddr_t         p_dmaPg;
  3332.  
  3333.     amcc_adr = cp->amcc_adr;
  3334.     dmacmd   = cp->dmacmd;
  3335.  
  3336.     /* ========================================== 
  3337.      *    Scatter-Gather list preparation
  3338.      * ========================================== */
  3339.  
  3340.     /*  get the user's address and size   */
  3341.     len = cb->buf_size * sizeof(uint_t);
  3342.    
  3343.     /*  lock user pages into memory for DMA  */
  3344.     err = cocoLockUser ( (caddr_t)cb->buf, len, B_WRITE);
  3345.     if ( err ) { 
  3346.         cmn_err (CE_WARN, "cocoDmaToLuts: Cannot lock user pages");
  3347.         return (err);
  3348.     }
  3349.  
  3350.         /*
  3351.          *   write back and invalidate the data for mem->board
  3352.          */
  3353.         dki_dcache_wbinval ( (caddr_t)cb->buf, len ); 
  3354.  
  3355.     /*   create scatter-gather list of user's buffer  */
  3356.     addrList2 = uvaddr_to_alenlist( (alenlist_t)NULL, (caddr_t)cb->buf, 
  3357.                     (size_t)len, 0);
  3358.  
  3359.         if ( addrList2 == (alenlist_t)NULL ) {
  3360.                 cmn_err (CE_WARN, "cocoDmaToLuts: cannot create alenlist");
  3361.                 cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE);
  3362.                 return (EIO);
  3363.         }
  3364.  
  3365.     addrList = pciio_dmatrans_list ( cp->conn, 0, 
  3366.                           addrList2, 0 ); 
  3367. #if 0
  3368.         page_no = alenlist_size ( addrList );   /*  total pages to DMA */
  3369. #endif
  3370.  
  3371.     page_no = cocoAlenlistSize ( addrList );
  3372.     cp->page_no = page_no;
  3373.  
  3374.     /*  initialize our DMA event semaphore  */
  3375.     cp->dmabits = 0;
  3376.     olddmacmd = dmacmd; 
  3377.  
  3378.     dmatype = cp->dmatype;
  3379.  
  3380.         SV_INIT(&cp->coco_sv, SV_DEFAULT, "cocosv" );
  3381.  
  3382.     cocoResetAmcc ( cp );
  3383.     cocoPrepAmcc ( cp );
  3384.  
  3385.  
  3386.     /* ===============================
  3387.      *    Set proper DMA flags
  3388.      * =============================== */
  3389.     dmacmd = DMAREG_FILL;
  3390.  
  3391.     /*  set proper LUT fill bit  */
  3392.     switch ( cmd ) {
  3393.  
  3394.                   case COCO_BLOCK_FILL_RAMIL: 
  3395.             dmacmd |= COCO_FILLRAMIL; 
  3396.              break;
  3397.  
  3398.                   case COCO_BLOCK_FILL_RAMIH:
  3399.                          dmacmd |= COCO_FILLRAMIH; 
  3400.                          break;
  3401.  
  3402.                   case COCO_BLOCK_FILL_RAMO:
  3403.                          dmacmd |= COCO_FILLRAMO; 
  3404.                          break;
  3405.  
  3406.                   case COCO_BLOCK_FILL_RAML:
  3407.                          dmacmd |= COCO_FILLRAML; 
  3408.                          break;
  3409.     }
  3410.  
  3411.     cp->dmacmd = dmacmd; 
  3412.  
  3413.     /* =======================
  3414.      *    Chained DMA
  3415.      * ======================= */
  3416.     if ( dmatype == DMA_PROG ) {
  3417.  
  3418.                 dmaPg = cocoMakeChain ( cp, addrList, page_no );
  3419.                 if ( dmaPg == (coco_dmapage_t *)NULL ) {
  3420.                         cmn_err (CE_NOTE,
  3421.                                  "cocoDmaLut: Error creating chain list");
  3422.             cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
  3423.                     alenlist_done(addrList);
  3424.                         return(EIO);
  3425.                 }
  3426.  
  3427.  
  3428.         tot_bytes = page_no * sizeof(coco_dmapage_t);
  3429.                 p_dmaPg = pciio_dmatrans_addr ( cp->conn, 0, 
  3430.                                           kvtophys(dmaPg), tot_bytes, 0 );
  3431.  
  3432.         /*   write back cache for the chain list */
  3433.         dki_dcache_wbinval(dmaPg, tot_bytes );
  3434.         err = 0;
  3435.  
  3436.         /*  dma from memory -> board (selected lut buffer) */
  3437.         s = COCO_LOCK(&cp->coco_mlock);
  3438.         cocoStartProgDma ( cp, p_dmaPg, len, B_WRITE );
  3439.  
  3440.         cp->dmastat = DMA_LUT_WAIT;
  3441.  
  3442.         SLEEP_EVENT(&cp->coco_sv, &cp->coco_mlock, s);
  3443.  
  3444.         switch ( cp->iostat ) {
  3445.             case IO_OK:     err = 0;      break;
  3446.             case IO_TIME:   err = ETIME;  break;
  3447.             case IO_ERROR:  err = EIO;    break;
  3448.         }
  3449.  
  3450.         /*  we are done   */
  3451.         cp->dmastat = DMA_IDLE;
  3452.         cp->dmabits = 0;
  3453.         cp->dmacmd  = olddmacmd;
  3454.                 cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
  3455.                 alenlist_done(addrList);
  3456.         kmem_free ( dmaPg, page_no * sizeof(coco_dmapage_t) );
  3457.  
  3458.         return(err);
  3459.     }
  3460.  
  3461.  
  3462.     /* ===========================
  3463.      *    Single page DMA
  3464.      * =========================== */
  3465.  
  3466.          for ( i = 0; i < page_no; i++ ) {
  3467.  
  3468.                /*  get a page to DMA  */
  3469.                    if ( alenlist_get(addrList, NULL, NBPP,
  3470.                     &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
  3471.                        cmn_err (CE_WARN, "cocoDma: Bad scatter-gather");
  3472.                        cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
  3473.                        alenlist_done(addrList);
  3474.                        return(ENOMEM);
  3475.                    }
  3476.  
  3477.         err = 0;
  3478.  
  3479.         s = COCO_LOCK(&cp->coco_mlock);
  3480.         cp->dmastat = DMA_LUT_WAIT;
  3481.         cocoStartSingleDma ( cp, p_addr, p_size, B_WRITE );
  3482.  
  3483.                 SLEEP_EVENT(&cp->coco_sv, &cp->coco_mlock, s);
  3484.  
  3485.                 switch ( cp->iostat ) {
  3486.                         case IO_OK:     err = 0;      break;
  3487.                         case IO_TIME:   err = ETIME;  break;
  3488.                         case IO_ERROR:  err = EIO;    break;
  3489.                 }
  3490.  
  3491.         if ( err ) { 
  3492.                         cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
  3493.                         alenlist_done(addrList);
  3494.                         return(err);
  3495.         }
  3496.     }
  3497.  
  3498.         /*  we are done   */
  3499.     cp->dmastat = DMA_IDLE;
  3500.     cp->dmabits = 0;
  3501.     cp->dmacmd  = olddmacmd;
  3502.         cocoUnlockUser ( (caddr_t)cb->buf, len, B_WRITE );
  3503.         alenlist_done(addrList);
  3504.  
  3505.         return(err);
  3506.             
  3507. }
  3508.  
  3509.  
  3510. /*************************************************************************
  3511.  ***                   c o c o L o c k U s e r                         ***
  3512.  *************************************************************************
  3513.  *
  3514.  *  Name:       cocoLockUser
  3515.  *
  3516.  *  Purpose:    Given a user's address space pointer, it locks all user's
  3517.  *              pages in memory in preparation for DMA.    
  3518.  *
  3519.  * Returns:     0 = Success or errno 
  3520.  *
  3521.  *************************************************************************/
  3522. static int 
  3523. cocoLockUser ( caddr_t user_buf, int len,  int direction )
  3524. {
  3525.     register int  ret;
  3526.  
  3527.         /*  lock pages in memory   */
  3528.     ret = userdma( (caddr_t)user_buf, len, direction, 0 );
  3529.         return (ret);
  3530. }
  3531.  
  3532. /*************************************************************************
  3533.  ***                   c o c o U n l o c k U s e r                     ***
  3534.  *************************************************************************
  3535.  *
  3536.  *  Name:       cocoUnlockUser
  3537.  *
  3538.  *  Purpose:    Given a user's address, unlock all pages for that address 
  3539.  *
  3540.  * Returns:     None.
  3541.  *
  3542.  *************************************************************************/
  3543. static void
  3544. cocoUnlockUser ( caddr_t user_buf, int len, int direction )
  3545. {
  3546.  
  3547.         undma ( user_buf, len, direction );
  3548. }
  3549.  
  3550. /*************************************************************************
  3551.  ***                   c o c o P r e p A m c c                         ***
  3552.  *************************************************************************
  3553.  *
  3554.  *  Name:       cocoPrepAmcc 
  3555.  *
  3556.  *  Purpose:    Prepares AMCC chip for DMA. 
  3557.  *
  3558.  * Returns:     None.
  3559.  *
  3560.  *************************************************************************/
  3561. static void
  3562. cocoPrepAmcc ( card_t *cp )
  3563. {
  3564.     register caddr_t  adr_amcc;
  3565.     register uint_t   mcsr, intcsr; 
  3566.     register uint_t   tmp;
  3567.  
  3568.     adr_amcc = cp->amcc_adr;
  3569.  
  3570.  
  3571.         /* ===========================
  3572.          *      Prepare AMCC chip
  3573.          * =========================== */
  3574.  
  3575.         /*
  3576.          *  Prepare AMCC as follow:
  3577.          *      - Read Maibox registers to make sure they are empty
  3578.          *      - Set Amcc DMA count to 0 
  3579.       *      - Enable Amcc Read/Write interrupts
  3580.          */
  3581.         tmp = Inp32(adr_amcc+AMCC_OP_REG_IMB4);           /* Read In mbox  */
  3582.         tmp = Inp32(adr_amcc+AMCC_OP_REG_OMB4);           /* read Out mbox */
  3583.         Out32(adr_amcc+AMCC_OP_REG_MRTC, 0 );
  3584.         Out32(adr_amcc+AMCC_OP_REG_MWTC, 0 );
  3585.         Out32(adr_amcc+AMCC_OP_REG_INTCSR, AMCC_INTCSR_MASK );
  3586.  
  3587. }
  3588.  
  3589. /*************************************************************************
  3590.  ***                   c o c o R e s e t A m c c                       ***
  3591.  *************************************************************************
  3592.  *
  3593.  *  Name:       cocoResetAmcc
  3594.  *
  3595.  *  Purpose:    Resets Addon and Amcc Fifos
  3596.  *
  3597.  * Returns:     None.
  3598.  *
  3599.  *************************************************************************/
  3600. static void
  3601. cocoResetAmcc ( card_t *cp )
  3602. {
  3603.     register caddr_t  adr_amcc;
  3604.  
  3605.     adr_amcc = cp->amcc_adr;
  3606.  
  3607.         /*  Reset Amcc Fifos and Addon interface     */ 
  3608.         Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_ADDON );
  3609.         Out32(adr_amcc+AMCC_OP_REG_MCSR, AMCC_RST_FIFOS ); 
  3610. }
  3611.  
  3612.  
  3613. /*************************************************************************
  3614.  ***                   c o c o S t a r t P r o g D m a                 ***
  3615.  *************************************************************************
  3616.  *
  3617.  *  Name:       cocoStartProgDma 
  3618.  *
  3619.  *  Purpose:    Programs the board for Chained DMA and starts the Dma 
  3620.  *
  3621.  * Returns:     None.
  3622.  *
  3623.  *************************************************************************/
  3624.  
  3625. static void
  3626. cocoStartProgDma ( card_t *cp, iopaddr_t p_dmaPg, int tot_bytes, int rw )
  3627. {
  3628.     register caddr_t  adr_cfg, adr_norm, adr_amcc;
  3629.     register uint_t   adr_bits, enable_bits, dmacfg, dmacmd, dmabits;
  3630.  
  3631.     adr_cfg  = cp->conf_adr;
  3632.     adr_norm = cp->norm_adr;
  3633.     adr_amcc = cp->amcc_adr;
  3634.     dmacfg   = cp->dmacfg;
  3635.     dmacmd   = cp->dmacmd;
  3636.     dmabits  = cp->dmabits; 
  3637.     cp->dmasize = tot_bytes;
  3638.  
  3639.     #ifdef DEBUG
  3640.     cocoReport ( cp, "before cocoStartProgDma");
  3641.     #endif
  3642.  
  3643.     /*  clear eof marks  */
  3644.     Out32(adr_cfg, dmacfg ); 
  3645.  
  3646.     /* ======================
  3647.      *  board -> memory 
  3648.      * ====================== */ 
  3649.     if ( rw == B_READ ) {
  3650.  
  3651.         /*  set Amcc counters  */
  3652.             Out32(adr_amcc+AMCC_OP_REG_MWTC, tot_bytes ); 
  3653.                 Out32(adr_amcc+AMCC_OP_REG_MRTC, 0 ); 
  3654.  
  3655.         adr_bits    = DMAREG_RAMPRWR;
  3656.         enable_bits = DMAREG_INTPWEN | DMAREG_WEN;
  3657.         dmabits |= DMAREG_PWEN;
  3658.  
  3659.     }
  3660.  
  3661.         /* ======================
  3662.          *  memory -> board  
  3663.          * ====================== */
  3664.     else {
  3665.  
  3666.         /*  set Amcc counters  */
  3667.         Out32(adr_amcc+AMCC_OP_REG_MRTC, tot_bytes ); 
  3668.                 Out32(adr_amcc+AMCC_OP_REG_MWTC, 0 ); 
  3669.  
  3670.                 adr_bits    = DMAREG_RAMPRRD;
  3671.                 enable_bits = DMAREG_INTPREN | DMAREG_REN;
  3672.         dmabits |= DMAREG_PREN;
  3673.     }
  3674.  
  3675.     /*  enable chaining  */
  3676.     dmacfg |= dmabits;
  3677.     Out32(adr_cfg, dmacfg );  
  3678.  
  3679.     /*  set address of chained list  */
  3680.     Out32(adr_cfg, dmacfg | DMAREG_RAM | adr_bits );
  3681.     Out32(adr_norm, p_dmaPg);
  3682.     
  3683.         /*  start the DMA   */
  3684.     dmabits |= enable_bits | dmacmd;
  3685.     cp->dmabits = dmabits; 
  3686.  
  3687.         #ifdef DEBUG
  3688.         cocoReport ( cp, "after cocoStartProgDma");
  3689.         #endif
  3690.  
  3691.         /* pciio_flush_buffers ( cp->vhdl ); */
  3692.     nanotime ( &cp->start_time );
  3693.       Out32(adr_cfg, dmacfg | dmabits ); 
  3694.  
  3695. }
  3696.  
  3697.  
  3698. /*************************************************************************
  3699.  ***                   c o c o S t a r t S i n g l e D m a             ***
  3700.  *************************************************************************
  3701.  *
  3702.  *  Name:       cocoStartSingleDma
  3703.  *
  3704.  *  Purpose:    Programs the board for Single page DMA (read or write) 
  3705.  *
  3706.  * Returns:     None.
  3707.  *
  3708.  *************************************************************************/
  3709. static void
  3710. cocoStartSingleDma ( card_t *cp, alenaddr_t p_addr, size_t p_size, int rw )
  3711. {
  3712.  
  3713.         register caddr_t  adr_cfg, adr_norm, adr_amcc;
  3714.         register uint_t   adr_bits, enable_bits, dmacfg, dmacmd, dmabits, temp;
  3715.     register int      tot_words;
  3716.  
  3717.         adr_cfg  = cp->conf_adr;
  3718.         adr_norm = cp->norm_adr;
  3719.     adr_amcc = cp->amcc_adr;
  3720.         dmacfg   = cp->dmacfg;
  3721.     dmacmd   = cp->dmacmd;
  3722.     dmabits  = cp->dmabits; 
  3723.     enable_bits = 0;
  3724.     cp->dmasize = p_size;
  3725.  
  3726.     Out32(adr_cfg, dmacfg );  /*  clear eof marks */
  3727.  
  3728.         /*
  3729.          *  Select read/write count in DMA controller
  3730.          *  and set the DMA size in 32-bit values
  3731.          */
  3732.     tot_words = (int)p_size/sizeof(uint_t);
  3733.     if ( rw == B_READ ) {   /*  board -> memory  */
  3734.          Out32(adr_amcc+AMCC_OP_REG_MWTC, (uint_t)p_size );
  3735.          Out32(adr_amcc+AMCC_OP_REG_MRTC, 0xffffffff ); 
  3736.          /* Out32(adr_amcc+AMCC_OP_REG_MRTC, (uint_t)p_size );  */
  3737.          dmabits |= DMAREG_WEN;
  3738.              Out32(adr_cfg, dmacfg | DMAREG_WCNT);
  3739.     }
  3740.     else {
  3741.          Out32(adr_amcc+AMCC_OP_REG_MRTC, (uint_t)p_size ); 
  3742.          Out32(adr_amcc+AMCC_OP_REG_MWTC, 0xffffffff ); 
  3743.          /* Out32(adr_amcc+AMCC_OP_REG_MWTC, (uint_t)p_size ); */
  3744.              dmabits |= DMAREG_REN;
  3745.          Out32(adr_cfg, dmacfg | DMAREG_RCNT);
  3746.     }
  3747.  
  3748.     /*  set transfer counts in words - -1 since counts down to 0xffff */
  3749.     tot_words--; 
  3750.         Out32(adr_norm, (uint_t)tot_words); 
  3751.  
  3752.         /* select Read/Write Address and set the DMA address  */
  3753.     if ( rw == B_READ ) { 
  3754.               Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMWADR); /* b->m */
  3755.     }
  3756.     else {
  3757.           Out32(adr_cfg, dmacfg | DMAREG_RAM | DMAREG_RAMRADR); /* m->b */
  3758.     }
  3759.         Out32(adr_norm, (uint_t)p_addr );
  3760.  
  3761.     /*   enable the right interrupt  */
  3762.     if ( rw == B_READ ) 
  3763.         dmabits |= DMAREG_INTWEN;   /*  board  -> memory  */
  3764.     else    dmabits |= DMAREG_INTREN;   /*  memory -> board   */
  3765.  
  3766.     dmabits |= cp->dmacmd;
  3767.     cp->dmabits = dmabits;
  3768.  
  3769.         #ifdef DEBUG
  3770.         cocoReport ( cp, "cocoStartSingleDma exit");
  3771.         #endif
  3772.  
  3773.         /* pciio_flush_buffers ( cp->vhdl ); */
  3774.     nanotime ( &cp->start_time);
  3775.     Out32(adr_cfg, dmacfg | dmabits ); 
  3776.  
  3777. }
  3778.  
  3779.  
  3780.  
  3781. /*************************************************************************
  3782.  ***                   c o c o M a k e C h a i n                       ***
  3783.  *************************************************************************
  3784.  *
  3785.  *  Name:       cocoMakeCHain
  3786.  *
  3787.  *  Purpose:    given an alenlist, creates chained list for Prog DMA. 
  3788.  *
  3789.  *  Returns:    NULL for error or address of chained list 
  3790.  *
  3791.  *************************************************************************/
  3792.  
  3793. static coco_dmapage_t * 
  3794. cocoMakeChain ( card_t *cp, alenlist_t addrList, int page_no )
  3795. {
  3796.     register coco_dmapage_t * dmaPg;
  3797.     register int              i, tot_words;
  3798.         size_t            p_size;
  3799.         alenaddr_t        p_addr;
  3800.     iopaddr_t         pa;    
  3801.                 
  3802.         dmaPg = (coco_dmapage_t *)kmem_alloc (page_no * sizeof(coco_dmapage_t), 
  3803.                   KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
  3804.  
  3805.         if ( dmaPg == (coco_dmapage_t *)NULL ) {
  3806.             cmn_err (CE_NOTE, 
  3807.                              "cocoMakeChain: Not enough mem for chained list");
  3808.                     return( (coco_dmapage_t *)NULL);
  3809.         }
  3810.  
  3811.         /*  fill the chained list with address-size values */
  3812.         for ( i = 0; i < page_no; i++ ) {
  3813.                 if ( alenlist_get(addrList, NULL, NBPP,
  3814.                      &p_addr, &p_size, 0) != ALENLIST_SUCCESS ) {
  3815.                      cmn_err (CE_WARN, "cocoMakeChain: Bad alenlist\n"); 
  3816.                      return( (coco_dmapage_t *)NULL);
  3817.                 }
  3818.  
  3819.  
  3820.                 pa  = pciio_dmatrans_addr ( cp->conn, 0,  
  3821.                                           kvtophys(&dmaPg[i+1]),
  3822.                                           sizeof(coco_dmapage_t), 0 );
  3823.                 dmaPg[i].nextaddr = pa; 
  3824.                 dmaPg[i].addr     = p_addr;
  3825.         tot_words         = (int)p_size/sizeof(uint_t);
  3826.                 dmaPg[i].size     = tot_words - 1; 
  3827.         }
  3828.         dmaPg[i-1].size |= END_OF_CHAIN;
  3829.  
  3830.     return ( dmaPg ); 
  3831. }
  3832.  
  3833.  
  3834. /*************************************************************************
  3835.  ***                   c o c o M a k e C h a i n R W                   ***
  3836.  *************************************************************************
  3837.  *
  3838.  *  Name:       cocoMakeCHainRW
  3839.  *
  3840.  *  Purpose:    Creates chain list for simultaneous read and write
  3841.  *        but makes sure we read and write the same amount of bytes
  3842.  *        in each entry 
  3843.  *
  3844.  *  Returns:    0 = Success, or errno 
  3845.  *
  3846.  *************************************************************************/
  3847.  
  3848. static int
  3849. cocoMakeChainRW ( card_t *cp, 
  3850.           coco_dmapage_t **w_dmaPg, 
  3851.           coco_dmapage_t **r_dmaPg )
  3852.  
  3853. {
  3854.         register coco_dmapage_t *wp, *rp; 
  3855.     register alenaddr_t wp_resadr, rp_resadr;
  3856.         register iopaddr_t  pa;
  3857.     register size_t     wp_left, rp_left;   
  3858.     register int        i, tot_rchain, tot_wchain, w_page, r_page;
  3859.     register int        tot_bytes, tot_words;
  3860.         size_t              wp_size, rp_size;
  3861.         alenaddr_t          wp_addr, rp_addr;
  3862.  
  3863.     w_page = cp->w_page_no;
  3864.     r_page = cp->r_page_no;
  3865.     tot_rchain = r_page * CHAIN_FACTOR;
  3866.     tot_wchain = w_page * CHAIN_FACTOR;
  3867.  
  3868.     wp_resadr = 0;
  3869.     rp_resadr = 0;
  3870.     wp_left   = 0;
  3871.     rp_left   = 0;
  3872.  
  3873.     *w_dmaPg = (coco_dmapage_t *)NULL; 
  3874.     *r_dmaPg = (coco_dmapage_t *)NULL;
  3875.  
  3876.     /*  allocate chain list for Write    */
  3877.         wp = (coco_dmapage_t *)kmem_alloc (tot_wchain * sizeof(coco_dmapage_t),
  3878.                                KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
  3879.  
  3880.         if ( wp  == (coco_dmapage_t *)NULL ) {
  3881.             cmn_err (CE_WARN, "cocoMakeChainRW: Not enough memory");
  3882.             return (ENOMEM);
  3883.         }
  3884.  
  3885.         /*  allocate chain list for Read   */
  3886.         rp = (coco_dmapage_t *)kmem_alloc (tot_rchain * sizeof(coco_dmapage_t),
  3887.                                KM_NOSLEEP | KM_PHYSCONTIG | KM_CACHEALIGN);
  3888.  
  3889.         if ( rp  == (coco_dmapage_t *)NULL ) {
  3890.                     kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
  3891.                     cmn_err (CE_WARN, "cocoMakeChainRW: Not enough memory");
  3892.                     return (ENOMEM);
  3893.         }
  3894.  
  3895.     /*  make sure we are at the top of the list  */
  3896.         alenlist_cursor_init ( cp->r_addrList, NULL, NULL );
  3897.         alenlist_cursor_init ( cp->w_addrList, NULL, NULL );
  3898.     
  3899.     for ( i = 0;; i++ ) {    
  3900.  
  3901.         /* ================================
  3902.          *    Write address and count
  3903.          * ================================ */
  3904.  
  3905.         /* if no Write bytes left, get a new page  */
  3906.         if ( wp_resadr == (alenaddr_t)NULL ) {
  3907.  
  3908.             /*  we must have data for write */
  3909.             if ( w_page <= 0 ) {
  3910.             cmn_err (CE_WARN,
  3911.             "cocoMakeChainRW: Premature end of Write, w_page = %d, r_page = %d", w_page, r_page );
  3912.              
  3913.                          kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
  3914.                          kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
  3915.                          return(EIO);
  3916.             }
  3917.  
  3918.                     if ( alenlist_get(cp->w_addrList, NULL, NBPP,
  3919.                          &wp_addr, &wp_size, 0) != ALENLIST_SUCCESS ) {
  3920.                          cmn_err (CE_WARN, 
  3921.              "cocoMakeChainRW: Bad Write alenlist\n");
  3922.                          kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) ); 
  3923.                          kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) ); 
  3924.              return(EIO);
  3925.                     }
  3926.             w_page--;
  3927.         }
  3928.  
  3929.         /*  some old Write bytes left - use those   */
  3930.         else {
  3931.             wp_addr = wp_resadr;
  3932.             wp_size = wp_left;
  3933.         }
  3934.  
  3935.                 /* ================================
  3936.                  *      Read address and count
  3937.                  * ================================ */
  3938.  
  3939.                 /* if no Read bytes left, get a new page  */
  3940.                 if ( rp_resadr == (alenaddr_t)NULL ) {
  3941.  
  3942.                     /*  we must have data for read */
  3943.                     if ( r_page <= 0 ) {
  3944.                         cmn_err (CE_WARN,  
  3945.                         "cocoMakeChainRW: Premature end of Read, r_page = %d, w_page = %d", r_page, w_page );
  3946.  
  3947.                          kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
  3948.                          kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
  3949.                          return(EIO);
  3950.                     }
  3951.  
  3952.                     if ( alenlist_get(cp->r_addrList, NULL, NBPP,
  3953.                          &rp_addr, &rp_size, 0) != ALENLIST_SUCCESS ) {
  3954.                          cmn_err (CE_WARN, 
  3955.                          "cocoMakeChainRW: Bad Read alenlist\n");
  3956.                          kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
  3957.                          kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
  3958.                          return(EIO);
  3959.                     }
  3960.             r_page--;
  3961.                 }
  3962.  
  3963.                 /*  some old Read bytes left - use those   */
  3964.                 else {
  3965.                         rp_addr = rp_resadr;
  3966.                         rp_size = rp_left;
  3967.                 }
  3968.  
  3969.                 /* ====================================
  3970.                  *      Adjust Read and Write counts
  3971.                  * ==================================== */
  3972.  
  3973.             wp_resadr = 0;
  3974.             rp_resadr = 0;
  3975.             wp_left   = 0;
  3976.             rp_left   = 0;
  3977.  
  3978.         /*  Writing and Reading the same amount ? no adjustment */ 
  3979.         if ( wp_size == rp_size ) {
  3980.             tot_bytes = wp_size;
  3981.         }
  3982.  
  3983.         /*  Writing more than reading ? Adjust Write  */
  3984.         if ( wp_size > rp_size ) {
  3985.             tot_bytes = rp_size;
  3986.             wp_resadr = (alenaddr_t)((int)wp_addr + tot_bytes);
  3987.             wp_left   = wp_size - tot_bytes;
  3988.         }
  3989.     
  3990.                 /*  Reading more than write ? Adjust Read   */
  3991.                 if ( rp_size > wp_size ) {
  3992.                         tot_bytes = wp_size;
  3993.                         rp_resadr = (alenaddr_t)((int)rp_addr + tot_bytes);
  3994.                         rp_left   = rp_size - tot_bytes;        
  3995.                 }       
  3996.  
  3997.  
  3998.                 /* =======================================
  3999.                  *      Make Read and Write Chain Entries 
  4000.                  * ======================================= */
  4001.  
  4002.         tot_words = (int)tot_bytes/sizeof(uint_t);
  4003.         tot_words--;
  4004.  
  4005.         /*  Make Write Chain entry   */
  4006.                 pa  = pciio_dmatrans_addr ( cp->conn, 0,  
  4007.                                           kvtophys(&wp[i+1]),
  4008.                                           sizeof(coco_dmapage_t), 0 );
  4009.  
  4010.                 wp[i].nextaddr = pa;
  4011.                 wp[i].addr     = wp_addr;
  4012.                 wp[i].size     = tot_words;
  4013.  
  4014.                 /*  Make Write Chain entry   */
  4015.                 pa  = pciio_dmatrans_addr ( cp->conn, 0,  
  4016.                                           kvtophys(&rp[i+1]),
  4017.                                           sizeof(coco_dmapage_t), 0 );
  4018.  
  4019.                 rp[i].nextaddr = pa;
  4020.                 rp[i].addr     = rp_addr;
  4021.                 rp[i].size     = tot_words;
  4022.  
  4023.                 /*  end of Write chain list ?   */
  4024.                 if ( (w_page <=0) && (wp_resadr == (alenaddr_t)NULL) )
  4025.                         wp[i].size |= END_OF_CHAIN;
  4026.  
  4027.         /*  end of Read chain list ?   */
  4028.         if ( (r_page <=0) && (rp_resadr == (alenaddr_t)NULL) )
  4029.             rp[i].size |= END_OF_CHAIN;
  4030.  
  4031.         /*  end of loop ?  */
  4032.         if ( (rp[i].size & END_OF_CHAIN) && 
  4033.              (wp[i].size & END_OF_CHAIN) )
  4034.             break;
  4035.  
  4036.         /*  ran out of memory ?   */
  4037.         if ( (i >= tot_rchain) || (i >= tot_wchain) ) {
  4038.             cmn_err (CE_WARN,
  4039.             "cocoMakeChainRW: Ran out of Chain entries");
  4040.                          kmem_free (wp, tot_wchain * sizeof(coco_dmapage_t) );
  4041.                          kmem_free (rp, tot_rchain * sizeof(coco_dmapage_t) );
  4042.                          return(EIO);
  4043.                  }
  4044.  
  4045.  
  4046.     }  /***  for ( i = 0;; i++ )  ***/
  4047.  
  4048.     *w_dmaPg = wp;
  4049.     *r_dmaPg = rp;
  4050.  
  4051.     return(0);
  4052. }
  4053.  
  4054.     
  4055. /*************************************************************************
  4056.  ***                   c o c o T i m e O u t                           ***
  4057.  *************************************************************************
  4058.  *
  4059.  *  Name:       cocoTimeOut   
  4060.  *
  4061.  *  Purpose:    We timedout waiting for a read/write interrupt. 
  4062.  *
  4063.  *  Returns:    None.
  4064.  *
  4065.  *************************************************************************/
  4066. static void
  4067. cocoTimeOut ( card_t *cp )
  4068. {
  4069.     register uint_t  intcsr;
  4070.     register int     s;
  4071.  
  4072.     /*  someone has the lock ? ignore the timeout  */
  4073.     if ( ( s = COCO_TRYLOCK(&cp->coco_mlock)) == 0 )
  4074.         return;
  4075.  
  4076.     cmn_err (CE_NOTE, "cocoTimeOut: Read/Write Timed out");
  4077.  
  4078.     alenlist_done ( cp->addrList );
  4079.     cp->addrList = 0;
  4080.     cp->iostat   = IO_TIME;
  4081.  
  4082.     bioerror ( cp->bp, ETIME);
  4083.     biodone (cp->bp);
  4084.     COCO_UNLOCK(&cp->coco_mlock, s);
  4085. }
  4086.  
  4087.  
  4088. /*************************************************************************
  4089.  ***                   c o c o T i m e O u t 2                         ***
  4090.  *************************************************************************
  4091.  *
  4092.  *  Name:       cocoTimeOut2
  4093.  *
  4094.  *  Purpose:    We timedout waiting for a simultaneous read/write intr.
  4095.  *
  4096.  *  Returns:    None.
  4097.  *
  4098.  *************************************************************************/
  4099. static void
  4100. cocoTimeOut2 ( card_t *cp )
  4101. {
  4102.  
  4103.     register int    s;
  4104.  
  4105.         /*  someone has the lock ? ignore the timeout  */
  4106.         if ( (s = COCO_TRYLOCK(&cp->coco_mlock)) == 0 )
  4107.                 return;
  4108.  
  4109.     cmn_err (CE_NOTE, "cocoTimeOut2: Sim. Read/Write Timed out");
  4110.     cp->iostat = IO_TIME;
  4111.     WAKE_EVENT(&cp->coco_sv);
  4112.     COCO_UNLOCK(&cp->coco_mlock, s);
  4113. }
  4114.  
  4115.  
  4116.  
  4117. /*
  4118. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4119. ~~~~~~~~~~                                                      ~~~~~~~~~~~~~
  4120. ~~~~~~~~~~         D e b u g i n g   R o u t i n e s            ~~~~~~~~~~~~~~
  4121. ~~~~~~~~~~                                                      ~~~~~~~~~~~~~
  4122. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4123. */
  4124.  
  4125. /*************************************************************************
  4126.  ***                   c o c o I o c t l S t r                         ***
  4127.  *************************************************************************
  4128.  *
  4129.  *  Name:       cocoIoctlStr 
  4130.  *
  4131.  *  Purpose:    return string version of an Ioctl command 
  4132.  *
  4133.  *  Returns:    pointer to string  
  4134.  *
  4135.  *************************************************************************/
  4136. static char *
  4137. cocoIoctlStr ( int cmd )
  4138. {
  4139.     switch ( cmd ) {
  4140.     case COCO_MKHWGR:          return ("Coco_MkHwGr");
  4141.     case COCO_GET_TIME:        return ("Coco_Get_Time");
  4142.     case COCO_MAP_SIZE:        return ("Coco_Map_Size");
  4143.     case COCO_COMMAND:         return ("Coco_Command");
  4144.     case COCO_RAW_READ_FIFO:   return ("Raw_Read_Fifo");
  4145.     case COCO_RAW_WRITE_FIFO:  return ("Raw_Write_Fifo");
  4146.     case COCO_RAW_READB_FIFO:  return ("Raw_ReadB_Fifo");
  4147.     case COCO_RAW_WRITEB_FIFO: return ("Raw_WriteB_Fifo");
  4148.     case COCO_FIFO_TEST:       return ("Fifo_Test");
  4149.     case COCO_SET_MODE:           return ("Set_Mode");
  4150.     case COCO_READ_MODE:       return ("Read_Mode");
  4151.     case COCO_RAW_READ_DMA:    return ("Raw_Read_Dma");
  4152.     case COCO_RAW_WRITE_DMA:   return ("Raw_Write_Dma");
  4153.     case COCO_READ_ADDR:       return ("Read_Addr");
  4154.     case COCO_SET_ADDR:        return ("Set_Addr");
  4155.     case COCO_DMAREGS_TEST:       return ("DmaRegs_Test");
  4156.     case COCO_INTRAM_TEST:       return ("IntRam_Test");
  4157.     case COCO_EXTRAM_TEST:     return ("ExtRam_Test");
  4158.     case COCO_READ_RAMIL:        return ("Read_RamIL");
  4159.     case COCO_READ_RAMIH:       return ("Read_RamIH");
  4160.     case COCO_READ_RAMO:       return ("Read_RamO");
  4161.     case COCO_READ_RAML:       return ("Read_RamL");
  4162.     case COCO_FILL_RAMIL:       return ("Fill_RamIL"); 
  4163.     case COCO_FILL_RAMIH:       return ("Fill_RamIH");
  4164.     case COCO_FILL_RAMO:       return ("Fill_RamO");
  4165.     case COCO_FILL_RAML:       return ("Fill_RamL");
  4166.     case COCO_CONVERT_PIXLE:   return ("Convert_Pixle");
  4167.     case COCO_CONVERT_TEST:       return ("Convert_Test");
  4168.     case COCO_SET_SINGLE_DMA:  return ("Set_Single_Dma");
  4169.     case COCO_SET_PROG_DMA:    return ("Set_Prog_Dma");
  4170.     case COCO_BLOCK_FILL_RAMIL:  return ("Block_Fill_RamIL");
  4171.     case COCO_BLOCK_FILL_RAMIH:  return ("Block_Fill_RamIH");
  4172.     case COCO_BLOCK_FILL_RAML:   return ("Block_Fill_RamL");
  4173.     case COCO_BLOCK_FILL_RAMO:   return ("Block_Fill_RamO");
  4174.     case COCO_SETCMD_TRANSP:     return ("SetCmd_Transp");
  4175.     case COCO_SETCMD_CONVERT:    return ("SetCmd_Convert");
  4176.     case COCO_RESET:         return ("Reset");
  4177.     case COCO_RW_BUF:          return ("RW_Buff");
  4178.     case COCO_ISPCI:             return ("Is_PCI");
  4179.     default:             return ("Unknown");
  4180.     }
  4181.  
  4182. }
  4183.  
  4184.  
  4185. /*************************************************************************
  4186.  ***                   c o c o R e p o r t                             ***
  4187.  *************************************************************************
  4188.  *
  4189.  *  Name:       cocoReport
  4190.  *
  4191.  *  Purpose:    Prints out the bit setting in dmacfg and other status 
  4192.  *
  4193.  *  Returns:     None.
  4194.  *
  4195.  *************************************************************************/
  4196. static void
  4197. cocoReport ( card_t *cp, char *s )
  4198. {
  4199.     register uint_t   dmacfg, dmabits, dmacmd, ram;
  4200.     register int      dmastat, dmatype;
  4201.  
  4202.     dmacmd  = cp->dmacmd;
  4203.     dmabits = cp->dmabits;
  4204.     dmastat = cp->dmastat;
  4205.     dmatype = cp->dmatype;
  4206.  
  4207.     printf ("%s: ", s ); 
  4208.     
  4209.         printf ("dmabits: " );
  4210.         if ( dmabits & DMAREG_WEN ) printf ("|Wen");
  4211.         if ( dmabits & DMAREG_REN ) printf ("|Ren");
  4212.         if ( dmabits & DMAREG_PREN) printf ("|Pren");
  4213.         if ( dmabits & DMAREG_PWEN) printf ("|Pwen");
  4214.         if ( dmabits & DMAREG_FILL) printf ("|Reg_Fill");
  4215.         if ( dmabits & DMAREG_INTWEN) printf ("|IntWen");
  4216.         if ( dmabits & DMAREG_INTREN) printf ("|IntRen");
  4217.         if ( dmabits & DMAREG_INTPWEN ) printf ("|IntPWen");
  4218.         if ( dmabits & DMAREG_INTPREN ) printf ("|IntPRen");
  4219.     ram = dmabits & 0x0f000000; 
  4220.         if ( ram == COCO_FILLRAML)  printf ("|Fill_RamL");
  4221.         if ( ram == COCO_FILLRAMIL) printf ("|Fill_RamIL");
  4222.         if ( ram == COCO_FILLRAMIH) printf ("|Fill_RamIH");
  4223.         if ( ram == COCO_FILLRAMO)  printf ("|Fill_RamO");
  4224.     if ( ram == COCO_TRANSP)    printf ("|Transp");
  4225.     if ( ram == COCO_CONVERT)   printf ("|Convrt");
  4226.  
  4227.     printf ("  dmastat: ", dmastat);
  4228.     if ( dmastat == DMA_IDLE )     printf ("Idle");
  4229.     if ( dmastat == DMA_LUT_WAIT ) printf ("Dma_Lut_Wait");
  4230.     if ( dmastat == DMA_READ_WAIT ) printf ("Dma_Read_Wait");
  4231.     if ( dmastat == DMA_WRITE_WAIT ) printf ("Dma_Write_Wait");
  4232.     if ( dmastat == DMA_RW_WAIT )    printf ("Dma_RW_Wait");
  4233.     printf ("\n");
  4234. }
  4235.  
  4236.  
  4237. /*************************************************************************
  4238.  ***                   c o c o S h o w C h a i n                       ***
  4239.  *************************************************************************
  4240.  *
  4241.  *  Name:       cocoShowChain
  4242.  *
  4243.  *  Purpose:    Displays contents of a chain list 
  4244.  *
  4245.  *  Returns:    None. 
  4246.  *
  4247.  *************************************************************************/
  4248.  
  4249. static void 
  4250. cocoShowChain( char *title, coco_dmapage_t *dmaPg )
  4251. {
  4252.     register int  i, tot_bytes, tot_words;
  4253.     register long all_bytes;
  4254.  
  4255.     printf ("--- %s ---\n", title );
  4256.     all_bytes = 0;
  4257.         for (i = 0;; i++ ) {
  4258.         tot_words = dmaPg[i].size;
  4259.         tot_bytes = ( (tot_words &~END_OF_CHAIN) +1) * sizeof(uint_t);
  4260.         all_bytes += tot_bytes;
  4261.         printf ("addr = 0x%x, size = %d  next addr = 0x%x %s\n",
  4262.         dmaPg[i].addr, tot_bytes,  dmaPg[i].nextaddr,
  4263.         tot_words & END_OF_CHAIN ? "[ End ]":" " );
  4264.  
  4265.         if ( tot_words & END_OF_CHAIN ) 
  4266.             break;
  4267.         }
  4268.     printf ("--- Total of %d entries, %d bytes ---\n\n", i, all_bytes );
  4269.  
  4270. }
  4271.  
  4272. /*************************************************************************
  4273.  ***                   c o c o D u m p A m c c                         ***
  4274.  *************************************************************************
  4275.  *
  4276.  *  Name:       cocoDumpAmcc
  4277.  *
  4278.  *  Purpose:    Dumps Amcc registers for debugging purpose. 
  4279.  *
  4280.  *  Returns:    None.
  4281.  *
  4282.  *************************************************************************/
  4283.  
  4284. static void
  4285. cocoDumpAmcc ( card_t *cp )
  4286. {
  4287.     register caddr_t  amcc_adr, norm_adr, cfg_adr;
  4288.     register uint_t   dmacfg, xil_stat, war, wcnt, rar, rcnt, mbef;
  4289.  
  4290.     amcc_adr = cp->amcc_adr;
  4291.     norm_adr = cp->norm_adr;
  4292.     cfg_adr  = cp->conf_adr;
  4293.     dmacfg   = cp->dmacfg;
  4294.  
  4295.         /*  disable any Dma and read in Xilinx status */
  4296.         Out32(cfg_adr, dmacfg | DMAREG_STAT );
  4297.         /* xil_stat = Inp32(norm_adr); */
  4298.     war     = Inp32(amcc_adr+AMCC_OP_REG_MWAR); 
  4299.     wcnt    = Inp32(amcc_adr+AMCC_OP_REG_MWTC); 
  4300.     rar     = Inp32(amcc_adr+AMCC_OP_REG_MRAR);
  4301.     rcnt    = Inp32(amcc_adr+AMCC_OP_REG_MRTC);
  4302.     mbef    = Inp32(amcc_adr+AMCC_OP_REG_MBEF);
  4303.     
  4304.     wcnt &= 0x01ffffff;
  4305.     rcnt &= 0x01ffffff;
  4306.     printf ("***  cocoDumpAmcc ***\n");
  4307.     printf ("WAR  = 0x%x     WTC = %d [ 0x%x ]\n", war, wcnt, wcnt );
  4308.     printf ("RAR  = 0x%x     RTC = %d [ 0x%x ]\n", rar, rcnt, rcnt );
  4309.     /* printf ("MBEF = 0x%x  Xilinx = 0x%x\n", mbef, xil_stat ); */
  4310. }
  4311.  
  4312. /*************************************************************************
  4313.  ***                   c o c o S h o w A l e n l i s t                 ***
  4314.  *************************************************************************
  4315.  *
  4316.  *  Name:       cocoShowAlenlist
  4317.  *
  4318.  *  Purpose:    Displayes the contents of a given Alenlist 
  4319.  *
  4320.  *  Returns:    None.
  4321.  *
  4322.  *************************************************************************/
  4323. static void
  4324. cocoShowAlenlist ( caddr_t title, alenlist_t  al )
  4325. {
  4326.         size_t              size; 
  4327.     long            tot_bytes;
  4328.         alenaddr_t          addr;
  4329.     register int        count, i;
  4330.  
  4331.     /*  reset the cursor for the alenlist  */
  4332.  
  4333.     alenlist_cursor_init ( al, NULL, NULL );
  4334.     printf ("cocoShowAlenlist: --- %s ---\n", title );
  4335.  
  4336.     tot_bytes = 0;
  4337.     count     = 0;
  4338.     for ( ;; ) {
  4339.                 if ( alenlist_get(al, NULL, NBPP, &addr, &size, 0) != 
  4340.                       ALENLIST_SUCCESS ) {
  4341.             break;
  4342.         }
  4343.         printf ("addr = 0x%x,  size = %d ...[%d]\n",addr, size, count );
  4344.         tot_bytes += size;
  4345.         count++;
  4346.     }
  4347.     printf ("--- Total of %d bytes [ %d entries ]---\n\n", 
  4348.         tot_bytes, count );
  4349.  
  4350.     /*  reset the cursor now   */
  4351.         alenlist_cursor_init ( al, NULL, NULL );
  4352. }
  4353.  
  4354.  
  4355. /*************************************************************************
  4356.  ***                   c o c o A l e n l i s t S i z e                 ***
  4357.  *************************************************************************
  4358.  *
  4359.  *  Name:       cocoAlenlistSize
  4360.  *
  4361.  *  Purpose:    Returns number of pairs in a given alenlist. 
  4362.  *
  4363.  *  Returns:    Number of address/size entries 
  4364.  *
  4365.  *************************************************************************/
  4366. static int 
  4367. cocoAlenlistSize ( alenlist_t  al )
  4368. {
  4369.     register int        count;
  4370.         size_t              size;
  4371.         alenaddr_t          addr;
  4372.  
  4373.         alenlist_cursor_init ( al, NULL, NULL );
  4374.     count = 0;
  4375.         for ( ;; ) {
  4376.                 if ( alenlist_get(al, NULL, NBPP, &addr, &size, 0) !=
  4377.                                   ALENLIST_SUCCESS ) {
  4378.                         break;
  4379.                 }
  4380.                 count++;
  4381.         }
  4382.         alenlist_cursor_init ( al, NULL, NULL );
  4383.  
  4384.     return (count);
  4385. }
  4386.  
  4387. /*************************************************************************
  4388.  ***                   c o c o _ c o p y i n _ b u f                   ***
  4389.  *************************************************************************
  4390.  *
  4391.  *  Name:       coco_copyin_buf 
  4392.  *
  4393.  *  Purpose:    Copyes the correct coco_buf_t structure to kernel space
  4394.  *        from user's space.
  4395.  *
  4396.  *  Returns:    0 or errno 
  4397.  *
  4398.  *************************************************************************/
  4399. static int
  4400. coco_copyin_buf ( card_t *cp, void *arg, coco_buf_t *coco_buf )
  4401. {
  4402.     coco_buf32_t  coco_buf32;
  4403.  
  4404.     /*  32bit application   */
  4405.         if ( cp->user_abi == ABI_IRIX5_N32 ) {
  4406.  
  4407.            if ( copyin( (void *)arg, (void *)&coco_buf32, 
  4408.             sizeof(coco_buf32_t) ) )
  4409.                 return (EFAULT);
  4410.  
  4411.             coco_buf->buf_size = coco_buf32.buf_size;
  4412.             coco_buf->buf      = (uint_t *)coco_buf32.buf;
  4413.         return(0);
  4414.     }
  4415.  
  4416.     /*  64-bit application   */
  4417.         if ( copyin( (void *)arg, (void *)coco_buf, sizeof(coco_buf_t) ) )
  4418.              return (EFAULT);
  4419.  
  4420.     return(0);
  4421. }
  4422.  
  4423.  
  4424. /*************************************************************************
  4425.  ***                   c o c o _ c o p y i n _ r w                     ***
  4426.  *************************************************************************
  4427.  *
  4428.  *  Name:       coco_copyin_rw 
  4429.  *
  4430.  *  Purpose:    Copyes the correct coco_rw_t structure to kernel space
  4431.  *              from user's space.
  4432.  *
  4433.  *  Returns:    0 or errno
  4434.  *
  4435.  *************************************************************************/
  4436. static int
  4437. coco_copyin_rw ( card_t *cp, caddr_t arg, coco_rw_t *coco_rw )
  4438. {
  4439.         coco_rw32_t  coco_rw32;
  4440.  
  4441.         /*  32bit application   */
  4442.         if ( cp->user_abi == ABI_IRIX5_N32 ) {
  4443.  
  4444.            if ( copyin( (char *)arg, &coco_rw32, sizeof(coco_rw32_t) ) )
  4445.                 return (EFAULT);
  4446.  
  4447.            coco_rw->buf_size     = coco_rw32.buf_size;
  4448.            coco_rw->adjust_chain = coco_rw32.buf_size;
  4449.            coco_rw->r_buf        = (uint_t *)coco_rw32.r_buf;
  4450.            coco_rw->w_buf        = (uint_t *)coco_rw32.w_buf;
  4451.            return(0);
  4452.         }
  4453.  
  4454.         /*  64-bit application   */
  4455.         if ( copyin( (char *)arg, coco_rw, sizeof(coco_rw_t) ) )
  4456.              return (EFAULT);
  4457.  
  4458.         return(0);
  4459. }
  4460.  
  4461.  
  4462. #ifdef DEBUGTIME
  4463. /*************************************************************************
  4464.  ***                   c o c o R e p o r t T i m e                     ***
  4465.  *************************************************************************
  4466.  *
  4467.  *  Name:       cocoReportTime
  4468.  *
  4469.  *  Purpose:    Displays start, intr and end time of Dma 
  4470.  *
  4471.  *  Returns:    None.
  4472.  *
  4473.  *************************************************************************/
  4474. static void
  4475. cocoReportTime ( caddr_t title, card_t *cp, int final ) 
  4476. {
  4477.  
  4478.     register struct timespec  *tv;
  4479.     struct timespec  dtv;
  4480.     coco_timeval_t  st;
  4481.     coco_timeval_t  et;
  4482.     coco_timeval_t  dt;
  4483.  
  4484.     /*  report start and interrupt of DMA   */
  4485.     if ( final == 0 ) {
  4486.          cocoDiffTime ( &cp->start_time, &cp->intr_time, &dtv );
  4487.          cocoConvTime ( &dtv, &dt );
  4488.          cocoConvTime ( &cp->start_time, &st );
  4489.          cocoConvTime ( &cp->intr_time, &et );
  4490.     
  4491.          printf ("\n%s: %s DMA, %d Bytes\n",
  4492.              title, cp->dmatype == DMA_PROG ? "Chain":"Single", cp->dmasize );
  4493.  
  4494.          printf ("Start:\t%8dm %8du %8dn\n",
  4495.                 st.coco_msec, st.coco_usec, st.coco_nsec);
  4496.          printf ("Intrp:\t%8dm %8du %8dn\n",
  4497.                 et.coco_msec, et.coco_usec, et.coco_nsec);
  4498.          printf ("Diff:\t%8dm %8du %8dn\n",
  4499.                 dt.coco_msec, dt.coco_usec, dt.coco_nsec );
  4500.          return;
  4501.     }
  4502.  
  4503.  
  4504.     /*  report the time difference of call came in and return time */
  4505.         cocoDiffTime ( &cp->call_time, &cp->ret_time, &dtv );
  4506.         cocoConvTime ( &dtv, &dt );
  4507.         cocoConvTime ( &cp->call_time, &st );
  4508.         cocoConvTime ( &cp->ret_time, &et );
  4509.  
  4510.     printf ("\n%s:  final Call analysis\n", title );
  4511.     printf ("Call:\t%8dm %8du %8dn\n",
  4512.                 st.coco_msec, st.coco_usec, st.coco_nsec );
  4513.     printf ("Ret:\t%8dm %8du %8dn\n",
  4514.                 et.coco_msec, et.coco_usec, et.coco_nsec );
  4515.     printf ("Diff:\t%8dm %8du %8dn\n",
  4516.                 dt.coco_msec, dt.coco_usec, dt.coco_nsec );
  4517.  
  4518. }
  4519. #endif
  4520.  
  4521.  
  4522. /*************************************************************************
  4523.  ***                   c o c o D i f f T i m e                         ***
  4524.  *************************************************************************
  4525.  *
  4526.  *  Name:       cocoDiffTime   
  4527.  *
  4528.  *  Purpose:    Given two timespec struct, it calculates the difference 
  4529.  *
  4530.  *  Returns:    None.
  4531.  *
  4532.  *************************************************************************/
  4533.  
  4534. static void
  4535. cocoDiffTime ( struct timespec *st, struct timespec *et, struct timespec *dt )
  4536. {
  4537.  
  4538.         register long   s_sec, e_sec;
  4539.         register long   s_totn, e_totn, diff_n;
  4540.  
  4541.         s_sec    = st->tv_sec;
  4542.     s_totn   = (s_sec * 1000000000L) + st->tv_nsec; 
  4543.  
  4544.         e_sec    = et->tv_sec;
  4545.     e_totn   = (e_sec * 1000000000L) + et->tv_nsec;
  4546.  
  4547.     diff_n   = e_totn - s_totn;
  4548.  
  4549.     dt->tv_sec = 0;
  4550.     dt->tv_nsec = diff_n;
  4551.  
  4552.     if ( diff_n > 1000000000L ) {
  4553.          dt->tv_sec  = diff_n  / 1000000000L;
  4554.          dt->tv_nsec = diff_n  % 1000000000L;
  4555.     }
  4556. }
  4557.  
  4558.  
  4559. /*************************************************************************
  4560.  ***                   c o c o C o n v T i m e                         ***
  4561.  *************************************************************************
  4562.  *
  4563.  *  Name:       cocoConvTime 
  4564.  *
  4565.  *  Purpose:    Converts a timespec_t to coco_timeval_t 
  4566.  *
  4567.  *  Returns:    None.
  4568.  *
  4569.  *************************************************************************/
  4570. static void
  4571. cocoConvTime ( struct timespec *ts, coco_timeval_t *ct )
  4572. {
  4573.     long   totn, sec, msec, usec, nsec;
  4574.  
  4575.     totn = (ts->tv_sec * 1000000000L) + ts->tv_nsec;
  4576.     sec = msec = usec = nsec = 0;
  4577.  
  4578.     /*  round up nano to micro */ 
  4579.     if ( totn > 1000L ) {
  4580.         usec = totn / 1000L;
  4581.         nsec = totn % 1000L;
  4582.     }
  4583.  
  4584.     /*  round up micro to mili  */
  4585.     if ( usec > 1000L ) {
  4586.         msec = usec / 1000L;
  4587.         usec = usec % 1000L;
  4588.     }
  4589.  
  4590.  
  4591.     /*  round up mili to seconds  */
  4592.     if ( msec > 1000L ) {
  4593.         sec  = msec / 1000L;
  4594.         msec = msec % 1000L;   
  4595.     }
  4596.  
  4597.     ct->coco_sec  = sec;
  4598.     ct->coco_msec = msec;
  4599.     ct->coco_usec = usec;
  4600.     ct->coco_nsec = nsec;
  4601.  
  4602. }    
  4603.  
  4604.  
  4605. /*************************************************************************
  4606.  ***                   c o c o M k H w G r a p h                       ***
  4607.  *************************************************************************
  4608.  *
  4609.  *  Name:       cocoMakeHwGraph
  4610.  *
  4611.  *  Purpose:    Make Nodes off of /hw for our card.     
  4612.  *
  4613.  *  Returns:    None.
  4614.  *
  4615.  *************************************************************************/
  4616.  
  4617. static void
  4618. cocoMakeHwGraph ( card_t *cp )
  4619. {
  4620.     register int  ret, ctl;
  4621.     char   cname[25];
  4622.  
  4623.     ctl = device_controller_num_get ( cp->vhdl );
  4624.      sprintf ( cname, "coco%d", ctl );
  4625.     
  4626.         ret =  hwgraph_edge_add ( hwgraph_root, cp->vhdl, cname ); 
  4627.         if ( ret != GRAPH_SUCCESS ) {
  4628.             cmn_err (CE_WARN, "cocoMakeHwGraph: Cannot create node %s", cname );
  4629.             return;
  4630.     }
  4631.  
  4632.     cmn_err (CE_NOTE, "cocoMakeHwGraph: Created node /hw/%s", cname );
  4633. }
  4634.  
  4635.