The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pci/tek390.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /***********************************************************************
    2  *      FILE NAME : TEK390.C                                           *
    3  *           BY   : C.L. Huang  (ching@tekram.com.tw)                  *
    4  *      Description: Device Driver for Tekram DC-390(T) PCI SCSI       *
    5  *                   Bus Master Host Adapter                           *
    6  * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.                  *
    7  ***********************************************************************/
    8 /***********************************************************************
    9  *      HISTORY:                                                       *
   10  *                                                                     *
   11  *      REV#    DATE    NAME    DESCRIPTION                            *
   12  *      1.00  07/02/96  CLH     First release for RELEASE-2.1.0        *
   13  *      1.01  08/20/96  CLH     Update for RELEASE-2.1.5               *
   14  *                                                                     *
   15  ***********************************************************************/
   16 
   17 /**************************************************************************
   18  *
   19  *
   20  * Redistribution and use in source and binary forms, with or without
   21  * modification, are permitted provided that the following conditions
   22  * are met:
   23  * 1. Redistributions of source code must retain the above copyright
   24  *    notice, this list of conditions and the following disclaimer.
   25  * 2. Redistributions in binary form must reproduce the above copyright
   26  *    notice, this list of conditions and the following disclaimer in the
   27  *    documentation and/or other materials provided with the distribution.
   28  * 3. The name of the author may not be used to endorse or promote products
   29  *    derived from this software without specific prior written permission.
   30  *
   31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   34  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   41  *
   42  **************************************************************************/
   43 
   44 /**************************************************************************/
   45 /* Imported into FreeBSD source repository, and updated to compile under  */
   46 /* FreeBSD-3.0-DEVELOPMENT, by Stefan Esser <se@FreeBSD.Org>, 1996-12-17  */
   47 /**************************************************************************/
   48 
   49 /* #define REL_2_1_0 */
   50 #define REL_2_1_5
   51 
   52 #define DC390_DEBUG
   53 
   54 #include <sys/param.h>
   55 
   56 /* XXX this doesn't actually compile unless KERNEL is defined. */
   57 #ifdef KERNEL
   58 #include <sys/systm.h>
   59 #include <sys/malloc.h>
   60 #include <sys/buf.h>
   61 #include <sys/kernel.h>
   62 
   63 #include <vm/vm.h>
   64 #include <vm/pmap.h>
   65 #endif /* KERNEL */
   66 
   67 #include <pci/pcivar.h>
   68 #include <pci/pcireg.h>
   69 
   70 #include <scsi/scsiconf.h>
   71 
   72 #include <machine/clock.h>
   73 
   74 #include <pci/tek390.h>
   75 
   76 #define INT32     int32
   77 #define U_INT32   u_int32
   78 
   79 
   80 #define OutB(val, port)                 outb(port, val)
   81 #define OutW(val, port)                 outw(port, val)
   82 #define OutL(val, port)                 outl(port, val)
   83 
   84 #define PCI_DEVICE_ID_AMD53C974         0x20201022ul
   85 #define PCI_BASE_ADDR0                  0x10
   86 
   87 
   88 #ifdef  REL_2_1_0
   89 static int  DC390_Interrupt (PACB pACB);
   90 #endif
   91 #ifdef  REL_2_1_5
   92 static void DC390_Interrupt (PACB pACB);
   93 #endif
   94 static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );
   95 static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
   96 static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
   97 static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
   98 static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
   99 static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  100 static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  101 static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  102 static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  103 static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  104 static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  105 static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  106 static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  107 static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  108 static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);
  109 
  110 static void SetXferRate( PACB pACB, PDCB pDCB );
  111 static void DC390_Disconnect( PACB pACB );
  112 static void DC390_Reselect( PACB pACB );
  113 static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
  114 static void DoingSRB_Done( PACB pACB );
  115 static void DC390_ScsiRstDetect( PACB pACB );
  116 static void DC390_ResetSCSIBus( PACB pACB );
  117 static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
  118 static void EnableMsgOut2( PACB pACB, PSRB pSRB );
  119 static void EnableMsgOut( PACB pACB, PSRB pSRB );
  120 static void DC390_InvalidCmd( PACB pACB );
  121 
  122 static void DC390_timeout( void *arg1);
  123 static void DC390_reset (PACB pACB);
  124 static PUCHAR  phystovirt( PSRB pSRB, ULONG xferCnt );
  125 
  126 void   DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd );
  127 void   DC390_initSRB( PSRB psrb );
  128 void   DC390_linkSRB( PACB pACB );
  129 void   DC390_initACB( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index );
  130 int    DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index,
  131                           pcici_t config_id );
  132 void   DC390_EnableCfg( USHORT mechnum, UCHAR regval );
  133 void   DC390_DisableCfg( USHORT mechnum );
  134 UCHAR  DC390_inByte( USHORT mechnum, UCHAR regval );
  135 USHORT DC390_inWord( USHORT mechnum, UCHAR regval );
  136 ULONG  DC390_inDword(USHORT mechnum, UCHAR regval );
  137 void   DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval );
  138 void   DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval );
  139 void   DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry );
  140 UCHAR  DC390_EEpromInDO( USHORT mechnum );
  141 USHORT EEpromGetData1( USHORT mechnum );
  142 void   DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd );
  143 void   DC390_ReadEEprom( USHORT mechnum, USHORT index );
  144 USHORT DC390_DefaultEEprom( USHORT mechnum, USHORT index );
  145 USHORT DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index );
  146 USHORT DC390_ToMech( USHORT Mechnum, pcici_t config_id );
  147 
  148 
  149 #ifdef KERNEL
  150 
  151 static  char*   trmamd_probe( pcici_t tag, pcidi_t type);
  152 static  void    trmamd_attach( pcici_t tag, int unit);
  153 
  154 #ifdef  REL_2_1_0
  155 static  int32   trmamd_scsi_cmd( struct scsi_xfer *sx);
  156 #endif
  157 
  158 #ifdef  REL_2_1_5
  159 static  int32_t trmamd_scsi_cmd( struct scsi_xfer *sx);
  160 #endif
  161 
  162 static  void    trmamd_min_phys( struct buf *pbuf);
  163 
  164 #ifdef  REL_2_1_0
  165 static  u_int32 trmamd_info( int unit );
  166 #endif
  167 
  168 #endif /* KERNEL */
  169 
  170 
  171 static u_long   trmamd_count;
  172 
  173 struct  pci_device   trmamd_device = {
  174         "amd",
  175         trmamd_probe,
  176         trmamd_attach,
  177         &trmamd_count,
  178         NULL
  179 };
  180 
  181 DATA_SET (pcidevice_set, trmamd_device);
  182 
  183 
  184 
  185 struct scsi_adapter trmamd_switch =
  186 {
  187         trmamd_scsi_cmd,
  188         trmamd_min_phys,
  189         0,
  190         0,
  191 #ifdef  REL_2_1_0
  192         trmamd_info,
  193 #endif
  194 #ifdef  REL_2_1_5
  195         0,
  196 #endif
  197         "amd",
  198 };
  199 
  200 struct scsi_device trmamd_dev =
  201 {
  202         NULL,                   /* Use default error handler */
  203         NULL,                   /* have a queue, served by this */
  204         NULL,                   /* have no async handler */
  205         NULL,                   /* Use default 'done' routine */
  206         "amd",
  207 };
  208 
  209 
  210 static PACB     pACB0[MAX_ADAPTER_NUM]={0};
  211 static PACB     pACB_start= NULL;
  212 static PACB     pACB_current = NULL;
  213 static PDCB     pPrevDCB = NULL;
  214 static USHORT   adapterCnt = 0;
  215 static USHORT   CurrSyncOffset = 0;
  216 static USHORT   mech2Agent;
  217 static ULONG    mech1addr;
  218 static UCHAR    mech2bus, mech2CfgSPenR, CurrentID, CurrentLUN;
  219 
  220 static PVOID DC390_phase0[]={
  221        DC390_DataOut_0,
  222        DC390_DataIn_0,
  223        DC390_Command_0,
  224        DC390_Status_0,
  225        DC390_Nop_0,
  226        DC390_Nop_0,
  227        DC390_MsgOut_0,
  228        DC390_MsgIn_0,
  229        DC390_Nop_1
  230        };
  231 
  232 static PVOID DC390_phase1[]={
  233        DC390_DataOutPhase,
  234        DC390_DataInPhase,
  235        DC390_CommandPhase,
  236        DC390_StatusPhase,
  237        DC390_Nop_0,
  238        DC390_Nop_0,
  239        DC390_MsgOutPhase,
  240        DC390_MsgInPhase,
  241        DC390_Nop_1,
  242        };
  243 
  244 UCHAR  eepromBuf[MAX_ADAPTER_NUM][128];
  245 
  246 
  247 UCHAR  clock_period1[] = {4, 5, 6, 7 ,8, 10, 13, 20};
  248 
  249 UCHAR  baddevname1[2][28] ={
  250        "SEAGATE ST3390N  ???    9546",
  251        "HP      C3323-300       4269"};
  252 
  253 #define BADDEVCNT       2
  254 
  255 
  256 /***********************************************************************
  257  *
  258  *
  259  *
  260  **********************************************************************/
  261 static PSRB
  262 GetSRB( PACB pACB )
  263 {
  264     int    flags;
  265     PSRB   pSRB;
  266 
  267     flags = splbio();
  268 
  269     pSRB = pACB->pFreeSRB;
  270     if( pSRB )
  271     {
  272         pACB->pFreeSRB = pSRB->pNextSRB;
  273         pSRB->pNextSRB = NULL;
  274     }
  275     splx(flags);
  276     return( pSRB );
  277 }
  278 
  279 
  280 static void
  281 RewaitSRB0( PDCB pDCB, PSRB pSRB )
  282 {
  283     PSRB   psrb1;
  284     int    flags;
  285 
  286     flags = splbio();
  287 
  288     if( (psrb1 = pDCB->pWaitingSRB) )
  289     {
  290         pSRB->pNextSRB = psrb1;
  291         pDCB->pWaitingSRB = pSRB;
  292     }
  293     else
  294     {
  295         pSRB->pNextSRB = NULL;
  296         pDCB->pWaitingSRB = pSRB;
  297         pDCB->pWaitLast = pSRB;
  298     }
  299     splx(flags);
  300 }
  301 
  302 
  303 static void
  304 RewaitSRB( PDCB pDCB, PSRB pSRB )
  305 {
  306     PSRB   psrb1;
  307     int    flags;
  308     UCHAR  bval;
  309 
  310     flags = splbio();
  311 
  312     pDCB->GoingSRBCnt--;
  313     psrb1 = pDCB->pGoingSRB;
  314     if( pSRB == psrb1 )
  315     {
  316         pDCB->pGoingSRB = psrb1->pNextSRB;
  317     }
  318     else
  319     {
  320         while( pSRB != psrb1->pNextSRB )
  321             psrb1 = psrb1->pNextSRB;
  322         psrb1->pNextSRB = pSRB->pNextSRB;
  323         if( pSRB == pDCB->pGoingLast )
  324             pDCB->pGoingLast = psrb1;
  325     }
  326     if( (psrb1 = pDCB->pWaitingSRB) )
  327     {
  328         pSRB->pNextSRB = psrb1;
  329         pDCB->pWaitingSRB = pSRB;
  330     }
  331     else
  332     {
  333         pSRB->pNextSRB = NULL;
  334         pDCB->pWaitingSRB = pSRB;
  335         pDCB->pWaitLast = pSRB;
  336     }
  337 
  338     bval = pSRB->TagNumber;
  339     pDCB->TagMask &= (~(1 << bval));      /* Free TAG number */
  340     splx(flags);
  341 }
  342 
  343 
  344 static void
  345 DoWaitingSRB( PACB pACB )
  346 {
  347     int    flags;
  348     PDCB   ptr, ptr1;
  349     PSRB   pSRB;
  350 
  351     flags = splbio();
  352 
  353     if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
  354     {
  355         ptr = pACB->pDCBRunRobin;
  356         if( !ptr )
  357         {
  358             ptr = pACB->pLinkDCB;
  359             pACB->pDCBRunRobin = ptr;
  360         }
  361         ptr1 = ptr;
  362         for( ;ptr1; )
  363         {
  364             pACB->pDCBRunRobin = ptr1->pNextDCB;
  365             if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) ||
  366                 !( pSRB = ptr1->pWaitingSRB ) )
  367             {
  368                 if(pACB->pDCBRunRobin == ptr)
  369                     break;
  370                 ptr1 = ptr1->pNextDCB;
  371             }
  372             else
  373             {
  374                 if( !DC390_StartSCSI(pACB, ptr1, pSRB) )
  375                 {
  376                     ptr1->GoingSRBCnt++;
  377                     if( ptr1->pWaitLast == pSRB )
  378                     {
  379                         ptr1->pWaitingSRB = NULL;
  380                         ptr1->pWaitLast = NULL;
  381                     }
  382                     else
  383                     {
  384                         ptr1->pWaitingSRB = pSRB->pNextSRB;
  385                     }
  386                     pSRB->pNextSRB = NULL;
  387 
  388                     if( ptr1->pGoingSRB )
  389                         ptr1->pGoingLast->pNextSRB = pSRB;
  390                     else
  391                         ptr1->pGoingSRB = pSRB;
  392                     ptr1->pGoingLast = pSRB;
  393                 }
  394                 break;
  395             }
  396         }
  397     }
  398     splx(flags);
  399     return;
  400 }
  401 
  402 
  403 static void
  404 SRBwaiting( PDCB pDCB, PSRB pSRB)
  405 {
  406     if( pDCB->pWaitingSRB )
  407     {
  408         pDCB->pWaitLast->pNextSRB = pSRB;
  409         pDCB->pWaitLast = pSRB;
  410         pSRB->pNextSRB = NULL;
  411     }
  412     else
  413     {
  414         pDCB->pWaitingSRB = pSRB;
  415         pDCB->pWaitLast = pSRB;
  416     }
  417 }
  418 
  419 
  420 static void
  421 SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB )
  422 {
  423     int    flags;
  424     PDCB   pDCB;
  425 
  426     flags = splbio();
  427 
  428     pDCB = pSRB->pSRBDCB;
  429     if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
  430         (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )
  431     {
  432         SRBwaiting(pDCB, pSRB);
  433         goto SND_EXIT;
  434     }
  435 
  436     if( pDCB->pWaitingSRB )
  437     {
  438         SRBwaiting(pDCB, pSRB);
  439 /*      pSRB = GetWaitingSRB(pDCB); */
  440         pSRB = pDCB->pWaitingSRB;
  441         pDCB->pWaitingSRB = pSRB->pNextSRB;
  442         pSRB->pNextSRB = NULL;
  443     }
  444 
  445     if( !DC390_StartSCSI(pACB, pDCB, pSRB) )
  446     {
  447         pDCB->GoingSRBCnt++;
  448         if( pDCB->pGoingSRB )
  449         {
  450             pDCB->pGoingLast->pNextSRB = pSRB;
  451             pDCB->pGoingLast = pSRB;
  452         }
  453         else
  454         {
  455             pDCB->pGoingSRB = pSRB;
  456             pDCB->pGoingLast = pSRB;
  457         }
  458     }
  459     else
  460         RewaitSRB0( pDCB, pSRB );
  461 
  462 SND_EXIT:
  463     splx(flags);
  464     return;
  465 }
  466 
  467 
  468 /***********************************************************************
  469  * Function : static int32 dc390_scsi_cmd (struct scsi_xfer *cmd)
  470  * Purpose : enqueues a SCSI command
  471  ***********************************************************************/
  472 
  473 #ifdef  REL_2_1_0
  474 int32
  475 #endif
  476 #ifdef  REL_2_1_5
  477 int32_t
  478 #endif
  479 trmamd_scsi_cmd ( PSCSICMD cmd )
  480 {
  481     USHORT ioport, i;
  482     PSCSICMD  pcmd;
  483     PSCLINK   plink;
  484     PACB   pACB;
  485     PDCB   pDCB;
  486     PSRB   pSRB;
  487     int    flags, cflags, unit, CurrPgVaddr;
  488     ULONG  sglen, pglen, datalen, CurrPgPaddr, NextPgPaddr;
  489     PUCHAR ptr,ptr1;
  490     PSEG   psg;
  491     UCHAR  sgc, sstatus;
  492 
  493     plink = cmd->sc_link;
  494     unit = plink->adapter_unit;
  495     pACB = pACB0[unit];
  496     ioport = pACB->IOPortBase;
  497 
  498 #ifdef DC390_DEBUG0
  499         printf("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmd->opcode,
  500                 plink->target, plink->lun);
  501 #endif
  502 
  503     if( pACB->scan_devices )
  504     {
  505         if( (plink->target > CurrentID) ||
  506             (plink->target == CurrentID) && (plink->lun >= CurrentLUN) )
  507         {
  508             CurrentID = plink->target;
  509             CurrentLUN = plink->lun;
  510         }
  511         else
  512         {
  513             pACB->scan_devices = 0;
  514             pPrevDCB->pNextDCB = pACB->pLinkDCB;
  515         }
  516     }
  517 
  518     if ( ( plink->target > pACB->max_id ) || ( plink->lun > pACB->max_lun ) )
  519     {
  520 #ifdef DC390_DEBUG0
  521         printf("DC390: Ignore target %d lun %d\n",
  522                 plink->target, plink->lun);
  523 #endif
  524         cmd->error = XS_DRIVER_STUFFUP;
  525         return( COMPLETE );
  526     }
  527 
  528     if( (pACB->scan_devices) && !(pACB->DCBmap[plink->target] & (1 << plink->lun)) )
  529     {
  530         if( pACB->DeviceCnt < MAX_DEVICES )
  531         {
  532             pACB->DCBmap[plink->target] |= (1 << plink->lun);
  533             pDCB = pACB->pDCB_free;
  534 #ifdef DC390_DEBUG0
  535             printf("pDCB=%8x,ID=%2x,", (UINT) pDCB, plink->target);
  536 #endif
  537             DC390_initDCB( pACB, pDCB, cmd );
  538         }
  539         else    /* ???? */
  540         {
  541 #ifdef DC390_DEBUG0
  542             printf("DC390: Ignore target %d lun %d\n",
  543                     plink->target, plink->lun);
  544 #endif
  545             cmd->error = XS_DRIVER_STUFFUP;
  546             return( COMPLETE );
  547         }
  548     }
  549     else if( !(pACB->scan_devices) && !(pACB->DCBmap[plink->target] & (1 << plink->lun)) )
  550     {
  551 #ifdef DC390_DEBUG0
  552         printf("DC390: Ignore target %d lun %d\n",
  553                 plink->target, plink->lun);
  554 #endif
  555         cmd->error = XS_DRIVER_STUFFUP;
  556         return( COMPLETE );
  557     }
  558     else
  559     {
  560         pDCB = pACB->pLinkDCB;
  561         while( (pDCB->UnitSCSIID != plink->target) ||
  562                (pDCB->UnitSCSILUN != plink->lun) )
  563         {
  564             pDCB = pDCB->pNextDCB;
  565         }
  566 #ifdef DC390_DEBUG0
  567             printf("pDCB=%8x,ID=%2x,", (UINT) pDCB, plink->target);
  568 #endif
  569     }
  570 
  571     cflags = cmd->flags;
  572     if(cflags & SCSI_RESET)
  573     {
  574         DC390_reset (pACB);
  575         cmd->error = XS_NOERROR;
  576         return(COMPLETE);
  577     }
  578 
  579     if( cflags & ITSDONE )
  580     {
  581         printf("DC390: Is it done?\n");
  582         cmd->flags &= ~ITSDONE;
  583     }
  584     if( !(cflags & INUSE) )
  585     {
  586         printf("DC390: In Use?\n");
  587         cmd->flags |= INUSE;
  588     }
  589 
  590     cmd->error = 0;
  591     cmd->resid = 0;
  592 
  593     flags = splbio();
  594 
  595     pcmd = cmd;
  596 
  597     pSRB = GetSRB( pACB );
  598 
  599     if( !pSRB )
  600     {
  601         pcmd->error = XS_DRIVER_STUFFUP;
  602         splx(flags);
  603         return( TRY_AGAIN_LATER);
  604     }
  605 
  606 /*  BuildSRB(pSRB); */
  607 
  608     pSRB->pSRBDCB = pDCB;
  609     pSRB->pcmd = pcmd;
  610     ptr = (PUCHAR) pSRB->CmdBlock;
  611     ptr1 = (PUCHAR) pcmd->cmd;
  612     pSRB->ScsiCmdLen = pcmd->cmdlen;
  613     for(i=0; i< pcmd->cmdlen; i++)
  614     {
  615         *ptr = *ptr1;
  616         ptr++;
  617         ptr1++;
  618     }
  619     if( pcmd->datalen )
  620     {
  621         psg = (PSEG) &pSRB->SGsegment[0];
  622         pSRB->pSegmentList = psg;
  623         sgc = 0;
  624 
  625         /* Set up the scatter gather list */
  626         datalen = pcmd->datalen;
  627         CurrPgVaddr = (int) pcmd->data;
  628         CurrPgPaddr = vtophys(CurrPgVaddr);
  629 
  630         while ((datalen) && (sgc < MAX_SG_ENTRY))
  631         {
  632             sglen = 0;
  633             psg->SGXPtr = CurrPgPaddr;
  634             NextPgPaddr = CurrPgPaddr;
  635             while ((datalen) && (CurrPgPaddr == NextPgPaddr))
  636             {
  637                 /*
  638                  * This page is contiguous (physically) with the the last,
  639                  * just extend the length
  640                  */
  641 
  642                 NextPgPaddr = (CurrPgPaddr & (~(PAGELEN - 1))) + PAGELEN;
  643                 pglen = NextPgPaddr - CurrPgPaddr;
  644 
  645                 if( datalen < pglen )
  646                     pglen = datalen;
  647                 sglen += pglen;
  648                 datalen -= pglen;
  649                 CurrPgVaddr = (CurrPgVaddr & (~(PAGELEN - 1))) + PAGELEN;
  650                 if( datalen )
  651                     CurrPgPaddr = vtophys(CurrPgVaddr);
  652             }
  653             /*
  654                next page isn't contiguous, finish this segment
  655              */
  656             psg->SGXLen = sglen;
  657             psg++;
  658             sgc++;
  659         }
  660         pSRB->SGcount = sgc;
  661 
  662         if (datalen)
  663         {
  664             printf("DC390: Out Of Segment Buffer!\n");
  665             pSRB->pNextSRB = pACB->pFreeSRB;
  666             pACB->pFreeSRB = pSRB;
  667             pcmd->error = XS_DRIVER_STUFFUP;
  668             splx(flags);
  669             return (HAD_ERROR);
  670         }
  671     }
  672     else
  673         pSRB->SGcount = 0;
  674 
  675     pSRB->SGIndex = 0;
  676     pSRB->AdaptStatus = 0;
  677     pSRB->TargetStatus = 0;
  678     pSRB->MsgCnt = 0;
  679     if( pDCB->DevType != SCSI_SEQACESS )
  680         pSRB->RetryCnt = 1;
  681     else
  682         pSRB->RetryCnt = 0;
  683     pSRB->SRBStatus = 0;
  684     pSRB->SRBFlag = 0;
  685     pSRB->SRBState = 0;
  686     pSRB->TotalXferredLen = 0;
  687     pSRB->SGPhysAddr = 0;
  688     pSRB->SGToBeXferLen = 0;
  689     pSRB->ScsiPhase = 0;
  690     pSRB->EndMessage = 0;
  691     splx(flags);
  692 
  693     if( !(cflags & SCSI_NOMASK) )
  694     {
  695         flags = splbio();
  696         SendSRB( pcmd, pACB, pSRB );
  697         timeout(DC390_timeout, (caddr_t)pSRB, (pcmd->timeout * hz)/1000);
  698         splx(flags);
  699         return( SUCCESSFULLY_QUEUED);
  700     }
  701     else
  702     {
  703         SendSRB( pcmd, pACB, pSRB );
  704         do
  705         {
  706             while(--pcmd->timeout)
  707             {
  708                 DELAY(1000);
  709                 sstatus = inb( ioport+Scsi_Status );
  710                 if( sstatus & INTERRUPT )
  711                     break;
  712             }
  713             if( pcmd->timeout == 0 )
  714             {
  715                 return(HAD_ERROR);
  716             }
  717             else
  718             {
  719                 DC390_Interrupt( pACB );
  720             }
  721         }
  722         while( !(pcmd->flags & ITSDONE) );
  723         if( pcmd->error == XS_TIMEOUT)
  724             return(HAD_ERROR);
  725         else
  726             return(COMPLETE);
  727     }
  728 }
  729 
  730 
  731 void
  732 trmamd_min_phys( struct buf *bp )
  733 {
  734     if (bp->b_bcount > ((MAX_SG_ENTRY - 1) * PAGELEN))
  735         bp->b_bcount = ((MAX_SG_ENTRY - 1) * PAGELEN);
  736 }
  737 
  738 
  739 #ifdef  REL_2_1_0
  740 u_int32
  741 trmamd_info( int unit )
  742 {
  743         return (MAX_CMD_PER_LUN);       /* outstanding requests at a time per device */
  744 }
  745 #endif
  746 
  747 
  748 static PUCHAR  phystovirt( PSRB pSRB, ULONG xferCnt )
  749 {
  750     int  dataPtr;
  751     PSCSICMD  pcmd;
  752     UCHAR     i;
  753     PSEG      pseg;
  754 
  755     pcmd = pSRB->pcmd;
  756     dataPtr = (int) pcmd->data;
  757     pseg = pSRB->SGsegment;
  758     for(i=0; i < pSRB->SGIndex; i++)
  759     {
  760         dataPtr += (int) pseg->SGXLen;
  761         pseg++;
  762     }
  763     dataPtr += (int) xferCnt;
  764     return( (PUCHAR) dataPtr);
  765 }
  766 
  767 
  768 /***********************************************************************
  769  * Function : int DC390_abort (SCSICMD *cmd)
  770  *
  771  * Purpose : Abort an errant SCSI command
  772  *
  773  * Inputs : cmd - command to abort
  774  *
  775  * Returns : 0 on success, -1 on failure.
  776  ***********************************************************************/
  777 /*
  778 int
  779 DC390_abort (SCSICMD *cmd)
  780 {
  781     int   flags;
  782     PACB  pACB;
  783     PDCB  pDCB, pdcb;
  784     PSRB  pSRB, psrb;
  785     USHORT count, i;
  786     PSCSICMD  pcmd, pcmd1;
  787     int   status;
  788 
  789 
  790 #ifdef DC390_DEBUG0
  791     printf("DC390 : Abort Cmd.");
  792 #endif
  793 
  794     flags = splbio();
  795 
  796     pACB = (PACB) cmd->host->hostdata;
  797     pDCB = pACB->pLinkDCB;
  798     pdcb = pDCB;
  799     while( (pDCB->UnitSCSIID != cmd->sc_link->target) ||
  800            (pDCB->UnitSCSILUN != cmd->sc_link->lun) )
  801     {
  802         pDCB = pDCB->pNextDCB;
  803         if( pDCB == pdcb )
  804             goto  NOT_RUN;
  805     }
  806 
  807 
  808     pSRB = pDCB->pWaitingSRB;
  809     if( !pSRB )
  810         goto  ON_GOING;
  811     if( pSRB->pcmd == cmd )
  812     {
  813         pDCB->pWaitingSRB = pSRB->pNextSRB;
  814         goto  IN_WAIT;
  815     }
  816     else
  817     {
  818         psrb = pSRB;
  819         while( psrb->pNextSRB->pcmd != cmd )
  820         {
  821             psrb = psrb->pNextSRB;
  822             if( !psrb )
  823                 goto ON_GOING;
  824         }
  825         pSRB = psrb->pNextSRB;
  826         psrb->pNextSRB = pSRB->pNextSRB;
  827         if( pSRB == pDCB->pWaitLast )
  828             pDCB->pWaitLast = psrb;
  829 IN_WAIT:
  830         pSRB->pNextSRB = pACB->pFreeSRB;
  831         pACB->pFreeSRB = pSRB;
  832         cmd->next = NULL;
  833         status = SCSI_ABORT_SUCCESS;
  834         goto  ABO_X;
  835     }
  836 
  837 ON_GOING:
  838     pSRB = pDCB->pGoingSRB;
  839     for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
  840     {
  841         if( pSRB->pcmd != cmd )
  842             pSRB = pSRB->pNextSRB;
  843         else
  844         {
  845             if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
  846             {
  847                 status = SCSI_ABORT_BUSY;
  848                 goto  ABO_X;
  849             }
  850             else
  851             {
  852                 status = SCSI_ABORT_SNOOZE;
  853                 goto  ABO_X;
  854             }
  855         }
  856     }
  857 
  858 NOT_RUN:
  859     status = SCSI_ABORT_NOT_RUNNING;
  860 
  861 ABO_X:
  862     cmd->error = XS_NOERROR;
  863     scsi_done(cmd);
  864     splx(flags);
  865     return( status );
  866 }
  867 */
  868 
  869 static void
  870 ResetDevParam( PACB pACB )
  871 {
  872     PDCB   pDCB, pdcb;
  873 
  874     pDCB = pACB->pLinkDCB;
  875     if( pDCB == NULL )
  876         return;
  877     pdcb = pDCB;
  878     do
  879     {
  880         pDCB->SyncMode &= ~SYNC_NEGO_DONE;
  881         pDCB->SyncPeriod = 0;
  882         pDCB->SyncOffset = 0;
  883         pDCB->CtrlR3 = FAST_CLK;
  884         pDCB->CtrlR4 &= NEGATE_REQACKDATA;
  885         pDCB->CtrlR4 |= EATER_25NS;
  886         pDCB = pDCB->pNextDCB;
  887     }
  888     while( pdcb != pDCB );
  889 }
  890 
  891 
  892 static void
  893 RecoverSRB( PACB pACB )
  894 {
  895     PDCB   pDCB, pdcb;
  896     PSRB   psrb, psrb2;
  897     USHORT cnt, i;
  898 
  899     pDCB = pACB->pLinkDCB;
  900     if( pDCB == NULL )
  901         return;
  902     pdcb = pDCB;
  903     do
  904     {
  905         cnt = pdcb->GoingSRBCnt;
  906         psrb = pdcb->pGoingSRB;
  907         for (i=0; i<cnt; i++)
  908         {
  909             psrb2 = psrb;
  910             psrb = psrb->pNextSRB;
  911 /*          RewaitSRB( pDCB, psrb ); */
  912             if( pdcb->pWaitingSRB )
  913             {
  914                 psrb2->pNextSRB = pdcb->pWaitingSRB;
  915                 pdcb->pWaitingSRB = psrb2;
  916             }
  917             else
  918             {
  919                 pdcb->pWaitingSRB = psrb2;
  920                 pdcb->pWaitLast = psrb2;
  921                 psrb2->pNextSRB = NULL;
  922             }
  923         }
  924         pdcb->GoingSRBCnt = 0;
  925         pdcb->pGoingSRB = NULL;
  926         pdcb->TagMask = 0;
  927         pdcb = pdcb->pNextDCB;
  928     }
  929     while( pdcb != pDCB );
  930 }
  931 
  932 
  933 /***********************************************************************
  934  * Function : DC390_reset (PACB pACB)
  935  *
  936  * Purpose : perform a hard reset on the SCSI bus( and AMD chip).
  937  *
  938  * Inputs : cmd - command which caused the SCSI RESET
  939  *
  940  ***********************************************************************/
  941 
  942 static void
  943 DC390_reset (PACB pACB)
  944 {
  945     USHORT   ioport;
  946     int   flags;
  947     UCHAR    bval;
  948     USHORT  i;
  949 
  950 
  951 #ifdef DC390_DEBUG0
  952     printf("DC390: RESET,");
  953 #endif
  954 
  955     flags = splbio();
  956 
  957     ioport = pACB->IOPortBase;
  958     bval = inb(ioport+CtrlReg1);
  959     bval |= DIS_INT_ON_SCSI_RST;
  960     OutB(bval,ioport+CtrlReg1);  /* disable interrupt */
  961     DC390_ResetSCSIBus( pACB );
  962     for( i=0; i<500; i++ )
  963         DELAY(1000);
  964     bval = inb(ioport+CtrlReg1);
  965     bval &= ~DIS_INT_ON_SCSI_RST;
  966     OutB(bval,ioport+CtrlReg1); /* re-enable interrupt */
  967 
  968     bval = DMA_IDLE_CMD;
  969     OutB(bval,ioport+DMA_Cmd);
  970     bval = CLEAR_FIFO_CMD;
  971     OutB(bval,ioport+ScsiCmd);
  972 
  973     ResetDevParam( pACB );
  974     DoingSRB_Done( pACB );
  975     pACB->pActiveDCB = NULL;
  976 
  977     pACB->ACBFlag = 0;
  978     DoWaitingSRB( pACB );
  979     splx(flags);
  980     return;
  981 }
  982 
  983 
  984 void
  985 DC390_timeout( void *arg1)
  986 {
  987     PSRB  pSRB;
  988 
  989     pSRB = (PSRB) arg1;
  990 }
  991 
  992 
  993 #include <pci/scsiiom.c>
  994 
  995 
  996 /***********************************************************************
  997  * Function : static void DC390_initDCB
  998  *
  999  * Purpose :  initialize the internal structures for a given DCB
 1000  *
 1001  * Inputs : cmd - pointer to this scsi cmd request block structure
 1002  *
 1003  ***********************************************************************/
 1004 void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd )
 1005 {
 1006     PEEprom     prom;
 1007     UCHAR       bval;
 1008     USHORT      index;
 1009     PSCLINK     plink;
 1010 
 1011     if( pACB->DeviceCnt == 0 )
 1012     {
 1013         pACB->pLinkDCB = pDCB;
 1014         pACB->pDCBRunRobin = pDCB;
 1015         pDCB->pNextDCB = pDCB;
 1016         pPrevDCB = pDCB;
 1017     }
 1018     else
 1019         pPrevDCB->pNextDCB = pDCB;
 1020 
 1021     plink = cmd->sc_link;
 1022     pDCB->pDCBACB = pACB;
 1023     pDCB->UnitSCSIID = plink->target;
 1024     pDCB->UnitSCSILUN = plink->lun;
 1025     pDCB->pWaitingSRB = NULL;
 1026     pDCB->pGoingSRB = NULL;
 1027     pDCB->GoingSRBCnt = 0;
 1028     pDCB->pActiveSRB = NULL;
 1029     pDCB->TagMask = 0;
 1030     pDCB->MaxCommand = 1;
 1031     pDCB->AdaptIndex = pACB->AdapterIndex;
 1032     index = pACB->AdapterIndex;
 1033     pDCB->DCBFlag = 0;
 1034 
 1035     prom = (PEEprom) &eepromBuf[index][plink->target << 2];
 1036     pDCB->DevMode = prom->EE_MODE1;
 1037     pDCB->AdpMode = eepromBuf[index][EE_MODE2];
 1038 
 1039     if( pDCB->DevMode & EN_DISCONNECT_ )
 1040         bval = 0xC0;
 1041     else
 1042         bval = 0x80;
 1043     bval |= plink->lun;
 1044     pDCB->IdentifyMsg = bval;
 1045 
 1046     pDCB->SyncMode = 0;
 1047     if( pDCB->DevMode & SYNC_NEGO_ )
 1048     {
 1049         if( !(plink->lun) || CurrSyncOffset )
 1050             pDCB->SyncMode = SYNC_ENABLE;
 1051     }
 1052 
 1053     pDCB->SyncPeriod = 0;
 1054     pDCB->SyncOffset = 0;
 1055     pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2;
 1056 
 1057     pDCB->CtrlR1 = pACB->AdaptSCSIID;
 1058     if( pDCB->DevMode & PARITY_CHK_ )
 1059         pDCB->CtrlR1 |= PARITY_ERR_REPO;
 1060 
 1061     pDCB->CtrlR3 = FAST_CLK;
 1062 
 1063     pDCB->CtrlR4 = EATER_25NS;
 1064     if( pDCB->AdpMode & ACTIVE_NEGATION)
 1065         pDCB->CtrlR4 |= NEGATE_REQACKDATA;
 1066 }
 1067 
 1068 
 1069 /***********************************************************************
 1070  * Function : static void DC390_initSRB
 1071  *
 1072  * Purpose :  initialize the internal structures for a given SRB
 1073  *
 1074  * Inputs : psrb - pointer to this scsi request block structure
 1075  *
 1076  ***********************************************************************/
 1077 void DC390_initSRB( PSRB psrb )
 1078 {
 1079         psrb->PhysSRB = vtophys( psrb );
 1080 }
 1081 
 1082 
 1083 void DC390_linkSRB( PACB pACB )
 1084 {
 1085     USHORT  count, i;
 1086     PSRB    psrb;
 1087 
 1088     count = pACB->SRBCount;
 1089 
 1090     for( i=0; i< count; i++)
 1091     {
 1092         if( i != count - 1)
 1093             pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
 1094         else
 1095             pACB->SRB_array[i].pNextSRB = NULL;
 1096         psrb = (PSRB) &pACB->SRB_array[i];
 1097         DC390_initSRB( psrb );
 1098     }
 1099 }
 1100 
 1101 
 1102 /***********************************************************************
 1103  * Function : static void DC390_initACB
 1104  *
 1105  * Purpose :  initialize the internal structures for a given SCSI host
 1106  *
 1107  * Inputs : psh - pointer to this host adapter's structure
 1108  *
 1109  ***********************************************************************/
 1110 void DC390_initACB( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index )
 1111 {
 1112     USHORT  i;
 1113 
 1114 
 1115     pACB->max_id = 7;
 1116     if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] )
 1117         pACB->max_id--;
 1118     if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
 1119         pACB->max_lun = 7;
 1120     else
 1121         pACB->max_lun = 0;
 1122 
 1123     pACB->IOPortBase = (USHORT) io_port;
 1124     pACB->pLinkDCB = NULL;
 1125     pACB->pDCBRunRobin = NULL;
 1126     pACB->pActiveDCB = NULL;
 1127     pACB->pFreeSRB = pACB->SRB_array;
 1128     pACB->SRBCount = MAX_SRB_CNT;
 1129     pACB->AdapterIndex = index;
 1130     pACB->status = 0;
 1131     pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID];
 1132     pACB->HostID_Bit = (1 << pACB->AdaptSCSIID);
 1133     pACB->AdaptSCSILUN = 0;
 1134     pACB->DeviceCnt = 0;
 1135     pACB->IRQLevel = Irq;
 1136     pACB->TagMaxNum = (eepromBuf[index][EE_TAG_CMD_NUM]) << 2;
 1137     pACB->ACBFlag = 0;
 1138     pACB->scan_devices = 1;
 1139     pACB->Gmode2 = eepromBuf[index][EE_MODE2];
 1140     if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
 1141         pACB->LUNchk = 1;
 1142     pACB->pDCB_free = &pACB->DCB_array[0];
 1143     DC390_linkSRB( pACB );
 1144     pACB->pTmpSRB = &pACB->TmpSRB;
 1145     DC390_initSRB( pACB->pTmpSRB );
 1146     for(i=0; i<MAX_SCSI_ID; i++)
 1147         pACB->DCBmap[i] = 0;
 1148 
 1149     pACB->ScsiLink.adapter_unit = index;
 1150     pACB->ScsiLink.adapter_targ = pACB->AdaptSCSIID;
 1151     pACB->ScsiLink.fordriver    = 0;
 1152     pACB->ScsiLink.opennings = 2;
 1153     pACB->ScsiLink.adapter      = &trmamd_switch;
 1154     pACB->ScsiLink.device       = &trmamd_dev;
 1155     pACB->ScsiLink.flags        = 0;
 1156 }
 1157 
 1158 
 1159 /***********************************************************************
 1160  * Function : static int DC390_initAdapter
 1161  *
 1162  * Purpose :  initialize the SCSI chip ctrl registers
 1163  *
 1164  * Inputs : psh - pointer to this host adapter's structure
 1165  *
 1166  ***********************************************************************/
 1167 int DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index,
 1168                        pcici_t config_id )
 1169 {
 1170     USHORT ioport;
 1171     UCHAR  bval;
 1172 
 1173 #ifdef  CHECK_SHARE_INT
 1174     PACB   pacb;
 1175     USHORT used_irq = 0;
 1176 
 1177     pacb = pACB_start;
 1178     if( pacb != NULL )
 1179     {
 1180         for ( ; (pacb != (PACB) -1) ; )
 1181         {
 1182             if( pacb->IRQLevel == Irq )
 1183             {
 1184                 used_irq = 1;
 1185                 break;
 1186             }
 1187             else
 1188                 pacb = pacb->pNextACB;
 1189         }
 1190     }
 1191 
 1192     if( !used_irq )
 1193     {
 1194 #endif
 1195         if( !pci_map_int (config_id, (PVOID)DC390_Interrupt, pACB, &bio_imask) )
 1196         {
 1197             if(bootverbose)
 1198                 printf("DC390: register Interrupt handler error!\n");
 1199             return( -1 );
 1200         }
 1201 
 1202 #ifdef  CHECK_SHARE_INT
 1203     }
 1204 #endif
 1205 
 1206     ioport = (USHORT) io_port;
 1207     bval = 153;                         /* 250ms selection timeout */
 1208     OutB(bval,ioport+Scsi_TimeOut);
 1209 
 1210     bval = CLK_FREQ_40MHZ;              /* Conversion factor = 0 , 40MHz clock */
 1211     OutB(bval,ioport+Clk_Factor);
 1212 
 1213     bval = NOP_CMD;                     /* NOP cmd - clear command register */
 1214     OutB(bval,ioport+ScsiCmd);
 1215 
 1216     bval = EN_FEATURE+EN_SCSI2_CMD;     /* Enable Feature and SCSI-2 */
 1217     OutB(bval,ioport+CtrlReg2);
 1218 
 1219     bval = FAST_CLK;                    /* fast clock */
 1220     OutB(bval,ioport+CtrlReg3);
 1221 
 1222     bval = EATER_25NS;
 1223     if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION )
 1224          bval |= NEGATE_REQACKDATA;
 1225     OutB(bval,ioport+CtrlReg4);
 1226 
 1227     bval = DIS_INT_ON_SCSI_RST;         /* Disable SCSI bus reset interrupt */
 1228     OutB(bval,ioport+CtrlReg1);
 1229 
 1230     return(0);
 1231 }
 1232 
 1233 
 1234 void
 1235 DC390_EnableCfg( USHORT mechnum, UCHAR regval )
 1236 {
 1237     ULONG wlval;
 1238 
 1239     if(mechnum == 2)
 1240     {
 1241         OutB(mech2bus, PCI_CFG2_FORWARD_REG);
 1242         OutB(mech2CfgSPenR, PCI_CFG2_ENABLE_REG);
 1243     }
 1244     else
 1245     {
 1246         regval &= 0xFC;
 1247         wlval = mech1addr;
 1248         wlval |= (((ULONG)regval) & 0xff);
 1249         OutL(wlval, PCI_CFG1_ADDRESS_REG);
 1250     }
 1251 }
 1252 
 1253 
 1254 void
 1255 DC390_DisableCfg( USHORT mechnum )
 1256 {
 1257 
 1258     if(mechnum == 2)
 1259         OutB(0, PCI_CFG2_ENABLE_REG);
 1260     else
 1261         OutL(0, PCI_CFG1_ADDRESS_REG);
 1262 }
 1263 
 1264 
 1265 UCHAR
 1266 DC390_inByte( USHORT mechnum, UCHAR regval )
 1267 {
 1268     UCHAR bval;
 1269     USHORT wval;
 1270     int   flags;
 1271 
 1272     flags = splbio();
 1273     DC390_EnableCfg( mechnum, regval );
 1274     if(mechnum == 2)
 1275     {
 1276         wval = mech2Agent;
 1277         wval <<= 8;
 1278         wval |= ((USHORT) regval) & 0xff;
 1279         bval = inb(wval);
 1280     }
 1281     else
 1282     {
 1283         regval &= 3;
 1284         bval = inb(PCI_CFG1_DATA_REG | regval);
 1285     }
 1286     DC390_DisableCfg(mechnum);
 1287     splx(flags);
 1288     return(bval);
 1289 }
 1290 
 1291 
 1292 USHORT
 1293 DC390_inWord( USHORT mechnum, UCHAR regval )
 1294 {
 1295     USHORT wval;
 1296     int   flags;
 1297 
 1298     flags = splbio();
 1299     DC390_EnableCfg(mechnum,regval);
 1300     if(mechnum == 2)
 1301     {
 1302         wval = mech2Agent;
 1303         wval <<= 8;
 1304         wval |= regval;
 1305         wval = inw(wval);
 1306     }
 1307     else
 1308     {
 1309         regval &= 3;
 1310         wval = inw(PCI_CFG1_DATA_REG | regval);
 1311     }
 1312     DC390_DisableCfg(mechnum);
 1313     splx(flags);
 1314     return(wval);
 1315 }
 1316 
 1317 
 1318 ULONG
 1319 DC390_inDword(USHORT mechnum, UCHAR regval )
 1320 {
 1321     ULONG wlval;
 1322     int   flags;
 1323     USHORT wval;
 1324 
 1325     flags = splbio();
 1326     DC390_EnableCfg(mechnum,regval);
 1327     if(mechnum == 2)
 1328     {
 1329         wval = mech2Agent;
 1330         wval <<= 8;
 1331         wval |= regval;
 1332         wlval = inl(wval);
 1333     }
 1334     else
 1335     {
 1336         wlval = inl(PCI_CFG1_DATA_REG);
 1337     }
 1338     DC390_DisableCfg(mechnum);
 1339     splx(flags);
 1340     return(wlval);
 1341 }
 1342 
 1343 
 1344 void
 1345 DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
 1346 {
 1347 
 1348     USHORT wval;
 1349     int    flags;
 1350 
 1351     flags = splbio();
 1352     DC390_EnableCfg(mechnum,regval);
 1353     if(mechnum == 2)
 1354     {
 1355         wval = mech2Agent;
 1356         wval <<= 8;
 1357         wval |= regval;
 1358         OutB(bval, wval);
 1359     }
 1360     else
 1361     {
 1362         regval &= 3;
 1363         OutB(bval, PCI_CFG1_DATA_REG | regval);
 1364     }
 1365     DC390_DisableCfg(mechnum);
 1366     splx(flags);
 1367 }
 1368 
 1369 
 1370 void
 1371 DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
 1372 {
 1373 
 1374     UCHAR bval;
 1375 
 1376     bval = 0;
 1377     if(mode == ENABLE_CE)
 1378         *regval = 0xc0;
 1379     else
 1380         *regval = 0x80;
 1381     DC390_OutB(mechnum,*regval,bval);
 1382     if(mode == DISABLE_CE)
 1383         DC390_OutB(mechnum,*regval,bval);
 1384     DELAY(160);
 1385 }
 1386 
 1387 
 1388 void
 1389 DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
 1390 {
 1391     UCHAR bval;
 1392 
 1393     bval = 0;
 1394     if(Carry)
 1395     {
 1396         bval = 0x40;
 1397         *regval = 0x80;
 1398         DC390_OutB(mechnum,*regval,bval);
 1399     }
 1400     DELAY(160);
 1401     bval |= 0x80;
 1402     DC390_OutB(mechnum,*regval,bval);
 1403     DELAY(160);
 1404     bval = 0;
 1405     DC390_OutB(mechnum,*regval,bval);
 1406     DELAY(160);
 1407 }
 1408 
 1409 
 1410 UCHAR
 1411 DC390_EEpromInDO( USHORT mechnum )
 1412 {
 1413     UCHAR bval,regval;
 1414 
 1415     regval = 0x80;
 1416     bval = 0x80;
 1417     DC390_OutB(mechnum,regval,bval);
 1418     DELAY(160);
 1419     bval = 0x40;
 1420     DC390_OutB(mechnum,regval,bval);
 1421     DELAY(160);
 1422     regval = 0x0;
 1423     bval = DC390_inByte(mechnum,regval);
 1424     if(bval == 0x22)
 1425         return(1);
 1426     else
 1427         return(0);
 1428 }
 1429 
 1430 
 1431 USHORT
 1432 EEpromGetData1( USHORT mechnum )
 1433 {
 1434     UCHAR i;
 1435     UCHAR carryFlag;
 1436     USHORT wval;
 1437 
 1438     wval = 0;
 1439     for(i=0; i<16; i++)
 1440     {
 1441         wval <<= 1;
 1442         carryFlag = DC390_EEpromInDO(mechnum);
 1443         wval |= carryFlag;
 1444     }
 1445     return(wval);
 1446 }
 1447 
 1448 
 1449 void
 1450 DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
 1451 {
 1452     UCHAR i,j;
 1453     USHORT carryFlag;
 1454 
 1455     carryFlag = 1;
 1456     j = 0x80;
 1457     for(i=0; i<9; i++)
 1458     {
 1459         DC390_EEpromOutDI(mechnum,regval,carryFlag);
 1460         carryFlag = (EEpromCmd & j) ? 1 : 0;
 1461         j >>= 1;
 1462     }
 1463 }
 1464 
 1465 
 1466 void
 1467 DC390_ReadEEprom( USHORT mechnum, USHORT index )
 1468 {
 1469     UCHAR   regval,cmd;
 1470     PUSHORT ptr;
 1471     USHORT  i;
 1472 
 1473     ptr = (PUSHORT) &eepromBuf[index][0];
 1474     cmd = EEPROM_READ;
 1475     for(i=0; i<0x40; i++)
 1476     {
 1477         DC390_EnDisableCE(ENABLE_CE, mechnum, &regval);
 1478         DC390_Prepare(mechnum, &regval, cmd);
 1479         *ptr = EEpromGetData1(mechnum);
 1480         ptr++;
 1481         cmd++;
 1482         DC390_EnDisableCE(DISABLE_CE,mechnum,&regval);
 1483     }
 1484 }
 1485 
 1486 
 1487 USHORT
 1488 DC390_DefaultEEprom( USHORT mechnum, USHORT index )
 1489 {
 1490     PUCHAR  ptr;
 1491     USHORT  i;
 1492 
 1493     ptr = (PUCHAR) &eepromBuf[index][0];
 1494     bzero (ptr, sizeof eepromBuf[index]);
 1495     for(i=0; i<0x40; i++)
 1496     {
 1497         *ptr = (TAG_QUEUING_|EN_DISCONNECT_|SYNC_NEGO_|PARITY_CHK_);
 1498         ptr += 4;
 1499     }
 1500     eepromBuf[index][EE_ADAPT_SCSI_ID] = 7;
 1501     eepromBuf[index][EE_MODE2] = (LUN_CHECK|ACTIVE_NEGATION);
 1502     eepromBuf[index][EE_TAG_CMD_NUM] = 4;
 1503     return 0;
 1504 }
 1505 
 1506 
 1507 USHORT
 1508 DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index )
 1509 {
 1510     USHORT wval, rc, *ptr;
 1511     UCHAR  i;
 1512 
 1513     DC390_ReadEEprom( MechNum, index );
 1514     wval = 0;
 1515     ptr = (PUSHORT) &eepromBuf[index][0];
 1516     for(i=0; i<128 ;i+=2, ptr++)
 1517         wval += *ptr;
 1518     if( wval == 0x1234 )
 1519         rc = 0;
 1520     else
 1521         rc = DC390_DefaultEEprom( MechNum, index);
 1522     return( rc );
 1523 }
 1524 
 1525 
 1526 USHORT
 1527 DC390_ToMech( USHORT Mechnum, pcici_t config_id )
 1528 {
 1529 
 1530     if(Mechnum == 2)
 1531     {
 1532         mech2bus = config_id.cfg2.forward;      /* Bus num */
 1533         mech2Agent = config_id.cfg2.port >> 8;  /* Dev num */
 1534         mech2CfgSPenR = config_id.cfg2.enable;  /* Fun num */
 1535     }
 1536     else        /* use mech #1 method */
 1537     {
 1538         mech1addr = config_id.cfg1;
 1539     }
 1540     return(0);
 1541 }
 1542 
 1543 /***********************************************************************
 1544  * Function : static int DC390_init (struct Scsi_Host *host)
 1545  *
 1546  * Purpose :  initialize the internal structures for a given SCSI host
 1547  *
 1548  * Inputs : host - pointer to this host adapter's structure/
 1549  *
 1550  * Preconditions : when this function is called, the chip_type
 1551  *      field of the pACB structure MUST have been set.
 1552  ***********************************************************************/
 1553 
 1554 static int
 1555 DC390_init( ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum,
 1556              pcici_t config_id)
 1557 {
 1558     PACB  pACB;
 1559 
 1560     if( !DC390_CheckEEpromCheckSum( MechNum, index) )
 1561     {
 1562         pACB = (PACB) malloc (sizeof (struct _ACB), M_DEVBUF, M_WAITOK);
 1563         if( !pACB )
 1564         {
 1565             printf("DC390%d: cannot allocate ACB !\n", index);
 1566             return( -1 );
 1567         }
 1568         bzero (pACB, sizeof (struct _ACB));
 1569         DC390_initACB( pACB, io_port, Irq, index );
 1570         if( !DC390_initAdapter( pACB, io_port, Irq, index, config_id) )
 1571         {
 1572             if( !pACB_start )
 1573             {
 1574                 pACB_start = pACB;
 1575                 pACB_current = pACB;
 1576                 pACB->pNextACB = (PACB) -1;
 1577             }
 1578             else
 1579             {
 1580                 pACB_current->pNextACB = pACB;
 1581                 pACB_current = pACB;
 1582                 pACB->pNextACB = (PACB)  -1;
 1583             }
 1584             pACB0[index] = pACB;
 1585 
 1586 #ifdef DC390_DEBUG0
 1587         printf("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n",
 1588               (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array);
 1589         printf("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",
 1590               sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );
 1591 #endif
 1592 
 1593             return( 0 );
 1594         }
 1595         else
 1596         {
 1597             free( pACB, M_DEVBUF);
 1598             return( -1 );
 1599         }
 1600     }
 1601     else
 1602     {
 1603         printf("DC390_init: EEPROM reading error!\n");
 1604         return( -1 );
 1605     }
 1606 }
 1607 
 1608 
 1609 
 1610 void
 1611 trmamd_attach (pcici_t config_id, int unit)
 1612 {
 1613     struct scsibus_data *scbus;
 1614     UCHAR   irq;
 1615     USHORT  MechNum;
 1616     ULONG   io_port, wlval;
 1617     PACB    pACB = 0;
 1618     int     flags;
 1619 
 1620     if( unit >= MAX_ADAPTER_NUM )
 1621         return;
 1622 
 1623     if( pACB0[unit] )
 1624         return;
 1625 
 1626     CurrentID = 0;
 1627     CurrentLUN = 0;
 1628     MechNum = pci_mechanism;
 1629 
 1630 #ifdef DC390_DEBUG0
 1631     if(bootverbose)
 1632         printf("DC390: Mech=%2x,\n",(UCHAR) MechNum);
 1633 #endif
 1634 
 1635     if( !DC390_ToMech( MechNum, config_id ) )
 1636     {
 1637         wlval = DC390_inDword( MechNum, PCI_ID_REG);
 1638         if(wlval == PCI_DEVICE_ID_AMD53C974 )
 1639         {
 1640             io_port =DC390_inDword(MechNum,PCI_BASE_ADDR0) & 0xFFFE;
 1641             irq = DC390_inByte( MechNum, PCI_INTERRUPT_REG);
 1642 #ifdef DC390_DEBUG0
 1643             if(bootverbose)
 1644                 printf("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
 1645 #endif
 1646             if( !DC390_init( io_port, irq, (USHORT) unit, MechNum, config_id) )
 1647             {
 1648                 adapterCnt++;
 1649             }
 1650             else
 1651                 return;
 1652         }
 1653     }
 1654 
 1655     pACB = pACB0[unit];
 1656 
 1657 /*
 1658   Now let the generic SCSI driver look for the SCSI devices on the bus
 1659 */
 1660 
 1661     flags = splbio();
 1662 
 1663     scbus = scsi_alloc_bus();
 1664     if(!scbus)
 1665     {
 1666         splx(flags);
 1667         return;
 1668     }
 1669     scbus->adapter_link = &pACB->ScsiLink;
 1670     scbus->maxtarg = pACB->max_id;
 1671 
 1672 #ifdef  DC390_DEBUG
 1673     if(bootverbose)
 1674         printf("\nDC390: scanning for devices ...\n\n");
 1675 #endif
 1676 
 1677     scsi_attachdevs (scbus);
 1678     scbus = NULL;   /* Upper-level SCSI code owns this now */
 1679 
 1680 #ifdef  DC390_DEBUG
 1681     if(bootverbose)
 1682         printf("\n\nDC390: Attach devices return\n");
 1683 #endif
 1684 
 1685     splx(flags);
 1686 }
 1687 
 1688 
 1689 static  char*
 1690 trmamd_probe (pcici_t tag, pcidi_t type)
 1691 {
 1692         if( type == PCI_DEVICE_ID_AMD53C974 )
 1693             return ("amd 53c974 scsi");
 1694         else
 1695             return (NULL);
 1696 }
 1697 

Cache object: c347c721bc0820929915cae4ef697f51


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.