diff options
author | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-21 00:55:32 +0000 |
---|---|---|
committer | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-21 00:55:32 +0000 |
commit | 76b5366091f76c9bc73570149ef5055648fc2c39 (patch) | |
tree | 590d020e0f2a5bea6e09d66d951a674443b21d67 /sys/pci/tek390.c | |
parent | 4b4d01da6f07f7754ff6a6e4f5223e9f0984d1a6 (diff) |
Notes
Diffstat (limited to 'sys/pci/tek390.c')
-rw-r--r-- | sys/pci/tek390.c | 1709 |
1 files changed, 1709 insertions, 0 deletions
diff --git a/sys/pci/tek390.c b/sys/pci/tek390.c new file mode 100644 index 000000000000..9be42e23bba1 --- /dev/null +++ b/sys/pci/tek390.c @@ -0,0 +1,1709 @@ +/*********************************************************************** + * FILE NAME : TEK390.C * + * BY : C.L. Huang (ching@tekram.com.tw) * + * Description: Device Driver for Tekram DC-390(T) PCI SCSI * + * Bus Master Host Adapter * + * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * + ***********************************************************************/ +/*********************************************************************** + * HISTORY: * + * * + * REV# DATE NAME DESCRIPTION * + * 1.00 07/02/96 CLH First release for RELEASE-2.1.0 * + * 1.01 08/20/96 CLH Update for RELEASE-2.1.5 * + * * + ***********************************************************************/ + +/************************************************************************** + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************/ + +/**************************************************************************/ +/* Imported into FreeBSD source repository, and updated to compile under */ +/* FreeBSD-3.0-DEVELOPMENT, by Stefan Esser <se@FreeBSD.Org>, 1996-12-17 */ +/**************************************************************************/ + +/* #define REL_2_1_0 */ +#define REL_2_1_5 + +#define DC390_DEBUG + +#include <sys/param.h> + +/* XXX this doesn't actually compile unless KERNEL is defined. */ +#ifdef KERNEL +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/kernel.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#endif /* KERNEL */ + +#include <pci/pcivar.h> +#include <pci/pcireg.h> + +#include <scsi/scsiconf.h> + +#include <machine/clock.h> + +#include <pci/tek390.h> + +#define INT32 int32 +#define U_INT32 u_int32 + + +#define OutB(val, port) outb(port, val) +#define OutW(val, port) outw(port, val) +#define OutL(val, port) outl(port, val) + +#define PCI_DEVICE_ID_AMD53C974 0x20201022ul +#define PCI_BASE_ADDR0 0x10 + + +#ifdef REL_2_1_0 +static int DC390_Interrupt (PACB pACB); +#endif +#ifdef REL_2_1_5 +static void DC390_Interrupt (PACB pACB); +#endif +static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus); + +static void SetXferRate( PACB pACB, PDCB pDCB ); +static void DC390_Disconnect( PACB pACB ); +static void DC390_Reselect( PACB pACB ); +static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DoingSRB_Done( PACB pACB ); +static void DC390_ScsiRstDetect( PACB pACB ); +static void DC390_ResetSCSIBus( PACB pACB ); +static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void EnableMsgOut2( PACB pACB, PSRB pSRB ); +static void EnableMsgOut( PACB pACB, PSRB pSRB ); +static void DC390_InvalidCmd( PACB pACB ); + +/* + * XXX No timeouts are scheduled in this driver as the timeout handler + * doesn't do anything yet!!! + */ +static void DC390_reset (PACB pACB); +static PUCHAR phystovirt( PSRB pSRB, ULONG xferCnt ); + +static void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ); +static void DC390_initSRB( PSRB psrb ); +static void DC390_linkSRB( PACB pACB ); +static void DC390_initACB( PACB pACB, ULONG io_port, UCHAR Irq, + USHORT index ); +static int DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, + USHORT index, pcici_t config_id ); +void DC390_EnableCfg( USHORT mechnum, UCHAR regval ); +void DC390_DisableCfg( USHORT mechnum ); +UCHAR DC390_inByte( USHORT mechnum, UCHAR regval ); +USHORT DC390_inWord( USHORT mechnum, UCHAR regval ); +ULONG DC390_inDword(USHORT mechnum, UCHAR regval ); +void DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ); +static void DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ); +static void DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ); +static UCHAR DC390_EEpromInDO( USHORT mechnum ); +static USHORT EEpromGetData1( USHORT mechnum ); +static void DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ); +static void DC390_ReadEEprom( USHORT mechnum, USHORT index ); +static USHORT DC390_DefaultEEprom( USHORT mechnum, USHORT index ); +static USHORT DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index ); +static USHORT DC390_ToMech( USHORT Mechnum, pcici_t config_id ); + + +#ifdef KERNEL + +static char* trmamd_probe( pcici_t tag, pcidi_t type); +static void trmamd_attach( pcici_t tag, int unit); + +#ifdef REL_2_1_0 +static int32 trmamd_scsi_cmd( struct scsi_xfer *sx); +#endif + +#ifdef REL_2_1_5 +static int32_t trmamd_scsi_cmd( struct scsi_xfer *sx); +#endif + +static void trmamd_min_phys( struct buf *pbuf); + +#ifdef REL_2_1_0 +static u_int32 trmamd_info( int unit ); +#endif + +#endif /* KERNEL */ + + +static u_long trmamd_count; + +static struct pci_device trmamd_device = { + "amd", + trmamd_probe, + trmamd_attach, + &trmamd_count, + NULL +}; + +DATA_SET (pcidevice_set, trmamd_device); + + + +static struct scsi_adapter trmamd_switch = +{ + trmamd_scsi_cmd, + trmamd_min_phys, + 0, + 0, +#ifdef REL_2_1_0 + trmamd_info, +#endif +#ifdef REL_2_1_5 + 0, +#endif + "amd", +}; + +static struct scsi_device trmamd_dev = +{ + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "amd", +}; + + +static PACB pACB0[MAX_ADAPTER_NUM]={0}; +static PACB pACB_start= NULL; +static PACB pACB_current = NULL; +static PDCB pPrevDCB = NULL; +static USHORT adapterCnt = 0; +static USHORT CurrSyncOffset = 0; +static UCHAR CurrentID, CurrentLUN; + +static PVOID DC390_phase0[]={ + DC390_DataOut_0, + DC390_DataIn_0, + DC390_Command_0, + DC390_Status_0, + DC390_Nop_0, + DC390_Nop_0, + DC390_MsgOut_0, + DC390_MsgIn_0, + DC390_Nop_1 + }; + +static PVOID DC390_phase1[]={ + DC390_DataOutPhase, + DC390_DataInPhase, + DC390_CommandPhase, + DC390_StatusPhase, + DC390_Nop_0, + DC390_Nop_0, + DC390_MsgOutPhase, + DC390_MsgInPhase, + DC390_Nop_1, + }; + +static UCHAR eepromBuf[MAX_ADAPTER_NUM][128]; + + +static UCHAR clock_period1[] = {4, 5, 6, 7 ,8, 10, 13, 20}; + +static UCHAR baddevname1[2][28] ={ + "SEAGATE ST3390N ??? 9546", + "HP C3323-300 4269"}; + +#define BADDEVCNT 2 + + +/*********************************************************************** + * + * + * + **********************************************************************/ +static PSRB +GetSRB( PACB pACB ) +{ + int flags; + PSRB pSRB; + + flags = splbio(); + + pSRB = pACB->pFreeSRB; + if( pSRB ) + { + pACB->pFreeSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + splx(flags); + return( pSRB ); +} + + +static void +RewaitSRB0( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + int flags; + + flags = splbio(); + + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + splx(flags); +} + + +static void +RewaitSRB( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + int flags; + UCHAR bval; + + flags = splbio(); + + pDCB->GoingSRBCnt--; + psrb1 = pDCB->pGoingSRB; + if( pSRB == psrb1 ) + { + pDCB->pGoingSRB = psrb1->pNextSRB; + } + else + { + while( pSRB != psrb1->pNextSRB ) + psrb1 = psrb1->pNextSRB; + psrb1->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb1; + } + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + + bval = pSRB->TagNumber; + pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ + splx(flags); +} + + +static void +DoWaitingSRB( PACB pACB ) +{ + int flags; + PDCB ptr, ptr1; + PSRB pSRB; + + flags = splbio(); + + if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + { + ptr = pACB->pDCBRunRobin; + if( !ptr ) + { + ptr = pACB->pLinkDCB; + pACB->pDCBRunRobin = ptr; + } + ptr1 = ptr; + for( ;ptr1; ) + { + pACB->pDCBRunRobin = ptr1->pNextDCB; + if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || + !( pSRB = ptr1->pWaitingSRB ) ) + { + if(pACB->pDCBRunRobin == ptr) + break; + ptr1 = ptr1->pNextDCB; + } + else + { + if( !DC390_StartSCSI(pACB, ptr1, pSRB) ) + { + ptr1->GoingSRBCnt++; + if( ptr1->pWaitLast == pSRB ) + { + ptr1->pWaitingSRB = NULL; + ptr1->pWaitLast = NULL; + } + else + { + ptr1->pWaitingSRB = pSRB->pNextSRB; + } + pSRB->pNextSRB = NULL; + + if( ptr1->pGoingSRB ) + ptr1->pGoingLast->pNextSRB = pSRB; + else + ptr1->pGoingSRB = pSRB; + ptr1->pGoingLast = pSRB; + } + break; + } + } + } + splx(flags); + return; +} + + +static void +SRBwaiting( PDCB pDCB, PSRB pSRB) +{ + if( pDCB->pWaitingSRB ) + { + pDCB->pWaitLast->pNextSRB = pSRB; + pDCB->pWaitLast = pSRB; + pSRB->pNextSRB = NULL; + } + else + { + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } +} + + +static void +SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ) +{ + int flags; + PDCB pDCB; + + flags = splbio(); + + pDCB = pSRB->pSRBDCB; + if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || + (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) + { + SRBwaiting(pDCB, pSRB); + goto SND_EXIT; + } + + if( pDCB->pWaitingSRB ) + { + SRBwaiting(pDCB, pSRB); +/* pSRB = GetWaitingSRB(pDCB); */ + pSRB = pDCB->pWaitingSRB; + pDCB->pWaitingSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + + if( !DC390_StartSCSI(pACB, pDCB, pSRB) ) + { + pDCB->GoingSRBCnt++; + if( pDCB->pGoingSRB ) + { + pDCB->pGoingLast->pNextSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + else + { + pDCB->pGoingSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + } + else + RewaitSRB0( pDCB, pSRB ); + +SND_EXIT: + splx(flags); + return; +} + + +/*********************************************************************** + * Function : static int32 dc390_scsi_cmd (struct scsi_xfer *cmd) + * Purpose : enqueues a SCSI command + ***********************************************************************/ + +#ifdef REL_2_1_0 +int32 +#endif +#ifdef REL_2_1_5 +int32_t +#endif +trmamd_scsi_cmd ( PSCSICMD cmd ) +{ + USHORT ioport, i; + PSCSICMD pcmd; + PSCLINK plink; + PACB pACB; + PDCB pDCB; + PSRB pSRB; + int flags, cflags, unit, CurrPgVaddr; + ULONG sglen, pglen, datalen, CurrPgPaddr, NextPgPaddr; + PUCHAR ptr,ptr1; + PSEG psg; + UCHAR sgc, sstatus; + + plink = cmd->sc_link; + unit = plink->adapter_unit; + pACB = pACB0[unit]; + ioport = pACB->IOPortBase; + +#ifdef DC390_DEBUG0 + printf("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmd->opcode, + plink->target, plink->lun); +#endif + + if( pACB->scan_devices ) + { + if( (plink->target > CurrentID) || + (plink->target == CurrentID) && (plink->lun >= CurrentLUN) ) + { + CurrentID = plink->target; + CurrentLUN = plink->lun; + } + else + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + } + + if ( ( plink->target > pACB->max_id ) || ( plink->lun > pACB->max_lun ) ) + { +#ifdef DC390_DEBUG0 + printf("DC390: Ignore target %d lun %d\n", + plink->target, plink->lun); +#endif + cmd->error = XS_DRIVER_STUFFUP; + return( COMPLETE ); + } + + if( (pACB->scan_devices) && !(pACB->DCBmap[plink->target] & (1 << plink->lun)) ) + { + if( pACB->DeviceCnt < MAX_DEVICES ) + { + pACB->DCBmap[plink->target] |= (1 << plink->lun); + pDCB = pACB->pDCB_free; +#ifdef DC390_DEBUG0 + printf("pDCB=%8x,ID=%2x,", (UINT) pDCB, plink->target); +#endif + DC390_initDCB( pACB, pDCB, cmd ); + } + else /* ???? */ + { +#ifdef DC390_DEBUG0 + printf("DC390: Ignore target %d lun %d\n", + plink->target, plink->lun); +#endif + cmd->error = XS_DRIVER_STUFFUP; + return( COMPLETE ); + } + } + else if( !(pACB->scan_devices) && !(pACB->DCBmap[plink->target] & (1 << plink->lun)) ) + { +#ifdef DC390_DEBUG0 + printf("DC390: Ignore target %d lun %d\n", + plink->target, plink->lun); +#endif + cmd->error = XS_DRIVER_STUFFUP; + return( COMPLETE ); + } + else + { + pDCB = pACB->pLinkDCB; + while( (pDCB->UnitSCSIID != plink->target) || + (pDCB->UnitSCSILUN != plink->lun) ) + { + pDCB = pDCB->pNextDCB; + } +#ifdef DC390_DEBUG0 + printf("pDCB=%8x,ID=%2x,", (UINT) pDCB, plink->target); +#endif + } + + cflags = cmd->flags; + if(cflags & SCSI_RESET) + { + DC390_reset (pACB); + cmd->error = XS_NOERROR; + return(COMPLETE); + } + + if( cflags & ITSDONE ) + { + printf("DC390: Is it done?\n"); + cmd->flags &= ~ITSDONE; + } + if( !(cflags & INUSE) ) + { + printf("DC390: In Use?\n"); + cmd->flags |= INUSE; + } + + cmd->error = 0; + cmd->resid = 0; + + flags = splbio(); + + pcmd = cmd; + + pSRB = GetSRB( pACB ); + + if( !pSRB ) + { + pcmd->error = XS_DRIVER_STUFFUP; + splx(flags); + return( TRY_AGAIN_LATER); + } + +/* BuildSRB(pSRB); */ + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmd; + pSRB->ScsiCmdLen = pcmd->cmdlen; + for(i=0; i< pcmd->cmdlen; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->datalen ) + { + psg = (PSEG) &pSRB->SGsegment[0]; + pSRB->pSegmentList = psg; + sgc = 0; + + /* Set up the scatter gather list */ + datalen = pcmd->datalen; + CurrPgVaddr = (int) pcmd->data; + CurrPgPaddr = vtophys(CurrPgVaddr); + + while ((datalen) && (sgc < MAX_SG_ENTRY)) + { + sglen = 0; + psg->SGXPtr = CurrPgPaddr; + NextPgPaddr = CurrPgPaddr; + while ((datalen) && (CurrPgPaddr == NextPgPaddr)) + { + /* + * This page is contiguous (physically) with the the last, + * just extend the length + */ + + NextPgPaddr = (CurrPgPaddr & (~(PAGELEN - 1))) + PAGELEN; + pglen = NextPgPaddr - CurrPgPaddr; + + if( datalen < pglen ) + pglen = datalen; + sglen += pglen; + datalen -= pglen; + CurrPgVaddr = (CurrPgVaddr & (~(PAGELEN - 1))) + PAGELEN; + if( datalen ) + CurrPgPaddr = vtophys(CurrPgVaddr); + } + /* + next page isn't contiguous, finish this segment + */ + psg->SGXLen = sglen; + psg++; + sgc++; + } + pSRB->SGcount = sgc; + + if (datalen) + { + printf("DC390: Out Of Segment Buffer!\n"); + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pcmd->error = XS_DRIVER_STUFFUP; + splx(flags); + return (HAD_ERROR); + } + } + else + pSRB->SGcount = 0; + + pSRB->SGIndex = 0; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != SCSI_SEQACESS ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->SRBState = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGPhysAddr = 0; + pSRB->SGToBeXferLen = 0; + pSRB->ScsiPhase = 0; + pSRB->EndMessage = 0; + splx(flags); + + if( !(cflags & SCSI_NOMASK) ) + { + flags = splbio(); + SendSRB( pcmd, pACB, pSRB ); + splx(flags); + return( SUCCESSFULLY_QUEUED); + } + else + { + SendSRB( pcmd, pACB, pSRB ); + do + { + while(--pcmd->timeout) + { + DELAY(1000); + sstatus = inb( ioport+Scsi_Status ); + if( sstatus & INTERRUPT ) + break; + } + if( pcmd->timeout == 0 ) + { + return(HAD_ERROR); + } + else + { + DC390_Interrupt( pACB ); + } + } + while( !(pcmd->flags & ITSDONE) ); + if( pcmd->error == XS_TIMEOUT) + return(HAD_ERROR); + else + return(COMPLETE); + } +} + + +void +trmamd_min_phys( struct buf *bp ) +{ + if (bp->b_bcount > ((MAX_SG_ENTRY - 1) * PAGELEN)) + bp->b_bcount = ((MAX_SG_ENTRY - 1) * PAGELEN); +} + + +#ifdef REL_2_1_0 +u_int32 +trmamd_info( int unit ) +{ + return (MAX_CMD_PER_LUN); /* outstanding requests at a time per device */ +} +#endif + + +static PUCHAR phystovirt( PSRB pSRB, ULONG xferCnt ) +{ + int dataPtr; + PSCSICMD pcmd; + UCHAR i; + PSEG pseg; + + pcmd = pSRB->pcmd; + dataPtr = (int) pcmd->data; + pseg = pSRB->SGsegment; + for(i=0; i < pSRB->SGIndex; i++) + { + dataPtr += (int) pseg->SGXLen; + pseg++; + } + dataPtr += (int) xferCnt; + return( (PUCHAR) dataPtr); +} + + +/*********************************************************************** + * Function : int DC390_abort (SCSICMD *cmd) + * + * Purpose : Abort an errant SCSI command + * + * Inputs : cmd - command to abort + * + * Returns : 0 on success, -1 on failure. + ***********************************************************************/ +/* +int +DC390_abort (SCSICMD *cmd) +{ + int flags; + PACB pACB; + PDCB pDCB, pdcb; + PSRB pSRB, psrb; + USHORT count, i; + PSCSICMD pcmd, pcmd1; + int status; + + +#ifdef DC390_DEBUG0 + printf("DC390 : Abort Cmd."); +#endif + + flags = splbio(); + + pACB = (PACB) cmd->host->hostdata; + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + while( (pDCB->UnitSCSIID != cmd->sc_link->target) || + (pDCB->UnitSCSILUN != cmd->sc_link->lun) ) + { + pDCB = pDCB->pNextDCB; + if( pDCB == pdcb ) + goto NOT_RUN; + } + + + pSRB = pDCB->pWaitingSRB; + if( !pSRB ) + goto ON_GOING; + if( pSRB->pcmd == cmd ) + { + pDCB->pWaitingSRB = pSRB->pNextSRB; + goto IN_WAIT; + } + else + { + psrb = pSRB; + while( psrb->pNextSRB->pcmd != cmd ) + { + psrb = psrb->pNextSRB; + if( !psrb ) + goto ON_GOING; + } + pSRB = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pWaitLast ) + pDCB->pWaitLast = psrb; +IN_WAIT: + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + cmd->next = NULL; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + +ON_GOING: + pSRB = pDCB->pGoingSRB; + for( count = pDCB->GoingSRBCnt, i=0; i<count; i++) + { + if( pSRB->pcmd != cmd ) + pSRB = pSRB->pNextSRB; + else + { + if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) + { + status = SCSI_ABORT_BUSY; + goto ABO_X; + } + else + { + status = SCSI_ABORT_SNOOZE; + goto ABO_X; + } + } + } + +NOT_RUN: + status = SCSI_ABORT_NOT_RUNNING; + +ABO_X: + cmd->error = XS_NOERROR; + scsi_done(cmd); + splx(flags); + return( status ); +} +*/ + +static void +ResetDevParam( PACB pACB ) +{ + PDCB pDCB, pdcb; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + pDCB->SyncMode &= ~SYNC_NEGO_DONE; + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->CtrlR3 = FAST_CLK; + pDCB->CtrlR4 &= NEGATE_REQACKDATA; + pDCB->CtrlR4 |= EATER_25NS; + pDCB = pDCB->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +RecoverSRB( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for (i=0; i<cnt; i++) + { + psrb2 = psrb; + psrb = psrb->pNextSRB; +/* RewaitSRB( pDCB, psrb ); */ + if( pdcb->pWaitingSRB ) + { + psrb2->pNextSRB = pdcb->pWaitingSRB; + pdcb->pWaitingSRB = psrb2; + } + else + { + pdcb->pWaitingSRB = psrb2; + pdcb->pWaitLast = psrb2; + psrb2->pNextSRB = NULL; + } + } + pdcb->GoingSRBCnt = 0; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +/*********************************************************************** + * Function : DC390_reset (PACB pACB) + * + * Purpose : perform a hard reset on the SCSI bus( and AMD chip). + * + * Inputs : cmd - command which caused the SCSI RESET + * + ***********************************************************************/ + +static void +DC390_reset (PACB pACB) +{ + USHORT ioport; + int flags; + UCHAR bval; + USHORT i; + + +#ifdef DC390_DEBUG0 + printf("DC390: RESET,"); +#endif + + flags = splbio(); + + ioport = pACB->IOPortBase; + bval = inb(ioport+CtrlReg1); + bval |= DIS_INT_ON_SCSI_RST; + OutB(bval,ioport+CtrlReg1); /* disable interrupt */ + DC390_ResetSCSIBus( pACB ); + for( i=0; i<500; i++ ) + DELAY(1000); + bval = inb(ioport+CtrlReg1); + bval &= ~DIS_INT_ON_SCSI_RST; + OutB(bval,ioport+CtrlReg1); /* re-enable interrupt */ + + bval = DMA_IDLE_CMD; + OutB(bval,ioport+DMA_Cmd); + bval = CLEAR_FIFO_CMD; + OutB(bval,ioport+ScsiCmd); + + ResetDevParam( pACB ); + DoingSRB_Done( pACB ); + pACB->pActiveDCB = NULL; + + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + splx(flags); + return; +} + + +#include <pci/scsiiom.c> + + +/*********************************************************************** + * Function : static void DC390_initDCB + * + * Purpose : initialize the internal structures for a given DCB + * + * Inputs : cmd - pointer to this scsi cmd request block structure + * + ***********************************************************************/ +static void +DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ) +{ + PEEprom prom; + UCHAR bval; + USHORT index; + PSCLINK plink; + + if( pACB->DeviceCnt == 0 ) + { + pACB->pLinkDCB = pDCB; + pACB->pDCBRunRobin = pDCB; + pDCB->pNextDCB = pDCB; + pPrevDCB = pDCB; + } + else + pPrevDCB->pNextDCB = pDCB; + + plink = cmd->sc_link; + pDCB->pDCBACB = pACB; + pDCB->UnitSCSIID = plink->target; + pDCB->UnitSCSILUN = plink->lun; + pDCB->pWaitingSRB = NULL; + pDCB->pGoingSRB = NULL; + pDCB->GoingSRBCnt = 0; + pDCB->pActiveSRB = NULL; + pDCB->TagMask = 0; + pDCB->MaxCommand = 1; + pDCB->AdaptIndex = pACB->AdapterIndex; + index = pACB->AdapterIndex; + pDCB->DCBFlag = 0; + + prom = (PEEprom) &eepromBuf[index][plink->target << 2]; + pDCB->DevMode = prom->EE_MODE1; + pDCB->AdpMode = eepromBuf[index][EE_MODE2]; + + if( pDCB->DevMode & EN_DISCONNECT_ ) + bval = 0xC0; + else + bval = 0x80; + bval |= plink->lun; + pDCB->IdentifyMsg = bval; + + pDCB->SyncMode = 0; + if( pDCB->DevMode & SYNC_NEGO_ ) + { + if( !(plink->lun) || CurrSyncOffset ) + pDCB->SyncMode = SYNC_ENABLE; + } + + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2; + + pDCB->CtrlR1 = pACB->AdaptSCSIID; + if( pDCB->DevMode & PARITY_CHK_ ) + pDCB->CtrlR1 |= PARITY_ERR_REPO; + + pDCB->CtrlR3 = FAST_CLK; + + pDCB->CtrlR4 = EATER_25NS; + if( pDCB->AdpMode & ACTIVE_NEGATION) + pDCB->CtrlR4 |= NEGATE_REQACKDATA; +} + + +/*********************************************************************** + * Function : static void DC390_initSRB + * + * Purpose : initialize the internal structures for a given SRB + * + * Inputs : psrb - pointer to this scsi request block structure + * + ***********************************************************************/ +static void +DC390_initSRB( PSRB psrb ) +{ + psrb->PhysSRB = vtophys( psrb ); +} + + +static void +DC390_linkSRB( PACB pACB ) +{ + USHORT count, i; + PSRB psrb; + + count = pACB->SRBCount; + + for( i=0; i< count; i++) + { + if( i != count - 1) + pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; + else + pACB->SRB_array[i].pNextSRB = NULL; + psrb = (PSRB) &pACB->SRB_array[i]; + DC390_initSRB( psrb ); + } +} + + +/*********************************************************************** + * Function : static void DC390_initACB + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +static void +DC390_initACB( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index ) +{ + USHORT i; + + + pACB->max_id = 7; + if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] ) + pACB->max_id--; + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->max_lun = 7; + else + pACB->max_lun = 0; + + pACB->IOPortBase = (USHORT) io_port; + pACB->pLinkDCB = NULL; + pACB->pDCBRunRobin = NULL; + pACB->pActiveDCB = NULL; + pACB->pFreeSRB = pACB->SRB_array; + pACB->SRBCount = MAX_SRB_CNT; + pACB->AdapterIndex = index; + pACB->status = 0; + pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID]; + pACB->HostID_Bit = (1 << pACB->AdaptSCSIID); + pACB->AdaptSCSILUN = 0; + pACB->DeviceCnt = 0; + pACB->IRQLevel = Irq; + pACB->TagMaxNum = (eepromBuf[index][EE_TAG_CMD_NUM]) << 2; + pACB->ACBFlag = 0; + pACB->scan_devices = 1; + pACB->Gmode2 = eepromBuf[index][EE_MODE2]; + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->LUNchk = 1; + pACB->pDCB_free = &pACB->DCB_array[0]; + DC390_linkSRB( pACB ); + pACB->pTmpSRB = &pACB->TmpSRB; + DC390_initSRB( pACB->pTmpSRB ); + for(i=0; i<MAX_SCSI_ID; i++) + pACB->DCBmap[i] = 0; + + pACB->ScsiLink.adapter_unit = index; + pACB->ScsiLink.adapter_targ = pACB->AdaptSCSIID; + pACB->ScsiLink.fordriver = 0; + pACB->ScsiLink.opennings = 2; + pACB->ScsiLink.adapter = &trmamd_switch; + pACB->ScsiLink.device = &trmamd_dev; + pACB->ScsiLink.flags = 0; +} + + +/*********************************************************************** + * Function : static int DC390_initAdapter + * + * Purpose : initialize the SCSI chip ctrl registers + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +static int DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, + USHORT index, + pcici_t config_id ) +{ + USHORT ioport; + UCHAR bval; + +#ifdef CHECK_SHARE_INT + PACB pacb; + USHORT used_irq = 0; + + pacb = pACB_start; + if( pacb != NULL ) + { + for ( ; (pacb != (PACB) -1) ; ) + { + if( pacb->IRQLevel == Irq ) + { + used_irq = 1; + break; + } + else + pacb = pacb->pNextACB; + } + } + + if( !used_irq ) + { +#endif + if( !pci_map_int (config_id, (PVOID)DC390_Interrupt, pACB, &bio_imask) ) + { + if(bootverbose) + printf("DC390: register Interrupt handler error!\n"); + return( -1 ); + } + +#ifdef CHECK_SHARE_INT + } +#endif + + ioport = (USHORT) io_port; + bval = 153; /* 250ms selection timeout */ + OutB(bval,ioport+Scsi_TimeOut); + + bval = CLK_FREQ_40MHZ; /* Conversion factor = 0 , 40MHz clock */ + OutB(bval,ioport+Clk_Factor); + + bval = NOP_CMD; /* NOP cmd - clear command register */ + OutB(bval,ioport+ScsiCmd); + + bval = EN_FEATURE+EN_SCSI2_CMD; /* Enable Feature and SCSI-2 */ + OutB(bval,ioport+CtrlReg2); + + bval = FAST_CLK; /* fast clock */ + OutB(bval,ioport+CtrlReg3); + + bval = EATER_25NS; + if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION ) + bval |= NEGATE_REQACKDATA; + OutB(bval,ioport+CtrlReg4); + + bval = DIS_INT_ON_SCSI_RST; /* Disable SCSI bus reset interrupt */ + OutB(bval,ioport+CtrlReg1); + + return(0); +} + + +#ifdef PCI_COMPAT +static pcicfgregs *cfg; +#define DC390_EnableCfg(a,b) +#define DC390_DisableCfg(a) +#define DC390_inByte(a,reg) pci_cfgread(cfg,reg,1) +#define DC390_inWord(a,reg) pci_cfgread(cfg,reg,2) +#define DC390_inDword(a,reg) pci_cfgread(cfg,reg,4) +#define DC390_OutB(a,reg,val) pci_cfgwrite(cfg,reg,val,1) +#else + +void +DC390_EnableCfg( USHORT mechnum, UCHAR regval ) +{ + ULONG wlval; + + if(mechnum == 2) + { + OutB(mech2bus, PCI_CFG2_FORWARD_REG); + OutB(mech2CfgSPenR, PCI_CFG2_ENABLE_REG); + } + else + { + regval &= 0xFC; + wlval = mech1addr; + wlval |= (((ULONG)regval) & 0xff); + OutL(wlval, PCI_CFG1_ADDRESS_REG); + } +} + + +void +DC390_DisableCfg( USHORT mechnum ) +{ + + if(mechnum == 2) + OutB(0, PCI_CFG2_ENABLE_REG); + else + OutL(0, PCI_CFG1_ADDRESS_REG); +} + + +UCHAR +DC390_inByte( USHORT mechnum, UCHAR regval ) +{ + UCHAR bval; + USHORT wval; + int flags; + + flags = splbio(); + DC390_EnableCfg( mechnum, regval ); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= ((USHORT) regval) & 0xff; + bval = inb(wval); + } + else + { + regval &= 3; + bval = inb(PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + splx(flags); + return(bval); +} + + +USHORT +DC390_inWord( USHORT mechnum, UCHAR regval ) +{ + USHORT wval; + int flags; + + flags = splbio(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + wval = inw(wval); + } + else + { + regval &= 3; + wval = inw(PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + splx(flags); + return(wval); +} + + +ULONG +DC390_inDword(USHORT mechnum, UCHAR regval ) +{ + ULONG wlval; + int flags; + USHORT wval; + + flags = splbio(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + wlval = inl(wval); + } + else + { + wlval = inl(PCI_CFG1_DATA_REG); + } + DC390_DisableCfg(mechnum); + splx(flags); + return(wlval); +} + + +void +DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ) +{ + + USHORT wval; + int flags; + + flags = splbio(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + OutB(bval, wval); + } + else + { + regval &= 3; + OutB(bval, PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + splx(flags); +} + +#endif /PCI_COMPAT */ + +static void +DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ) +{ + + UCHAR bval; + + bval = 0; + if(mode == ENABLE_CE) + *regval = 0xc0; + else + *regval = 0x80; + DC390_OutB(mechnum,*regval,bval); + if(mode == DISABLE_CE) + DC390_OutB(mechnum,*regval,bval); + DELAY(160); +} + + +static void +DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ) +{ + UCHAR bval; + + bval = 0; + if(Carry) + { + bval = 0x40; + *regval = 0x80; + DC390_OutB(mechnum,*regval,bval); + } + DELAY(160); + bval |= 0x80; + DC390_OutB(mechnum,*regval,bval); + DELAY(160); + bval = 0; + DC390_OutB(mechnum,*regval,bval); + DELAY(160); +} + + +static UCHAR +DC390_EEpromInDO( USHORT mechnum ) +{ + UCHAR bval,regval; + + regval = 0x80; + bval = 0x80; + DC390_OutB(mechnum,regval,bval); + DELAY(160); + bval = 0x40; + DC390_OutB(mechnum,regval,bval); + DELAY(160); + regval = 0x0; + bval = DC390_inByte(mechnum,regval); + if(bval == 0x22) + return(1); + else + return(0); +} + + +static USHORT +EEpromGetData1( USHORT mechnum ) +{ + UCHAR i; + UCHAR carryFlag; + USHORT wval; + + wval = 0; + for(i=0; i<16; i++) + { + wval <<= 1; + carryFlag = DC390_EEpromInDO(mechnum); + wval |= carryFlag; + } + return(wval); +} + + +static void +DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ) +{ + UCHAR i,j; + USHORT carryFlag; + + carryFlag = 1; + j = 0x80; + for(i=0; i<9; i++) + { + DC390_EEpromOutDI(mechnum,regval,carryFlag); + carryFlag = (EEpromCmd & j) ? 1 : 0; + j >>= 1; + } +} + + +static void +DC390_ReadEEprom( USHORT mechnum, USHORT index ) +{ + UCHAR regval,cmd; + PUSHORT ptr; + USHORT i; + + ptr = (PUSHORT) &eepromBuf[index][0]; + cmd = EEPROM_READ; + for(i=0; i<0x40; i++) + { + DC390_EnDisableCE(ENABLE_CE, mechnum, ®val); + DC390_Prepare(mechnum, ®val, cmd); + *ptr = EEpromGetData1(mechnum); + ptr++; + cmd++; + DC390_EnDisableCE(DISABLE_CE,mechnum,®val); + } +} + + +static USHORT +DC390_DefaultEEprom( USHORT mechnum, USHORT index ) +{ + PUCHAR ptr; + USHORT i; + + ptr = (PUCHAR) &eepromBuf[index][0]; + bzero (ptr, sizeof eepromBuf[index]); + for(i=0; i<0x40; i++) + { + *ptr = (TAG_QUEUING_|EN_DISCONNECT_|SYNC_NEGO_|PARITY_CHK_); + ptr += 4; + } + eepromBuf[index][EE_ADAPT_SCSI_ID] = 7; + eepromBuf[index][EE_MODE2] = (LUN_CHECK|ACTIVE_NEGATION); + eepromBuf[index][EE_TAG_CMD_NUM] = 4; + return 0; +} + + +static USHORT +DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index ) +{ + USHORT wval, rc, *ptr; + UCHAR i; + + DC390_ReadEEprom( MechNum, index ); + wval = 0; + ptr = (PUSHORT) &eepromBuf[index][0]; + for(i=0; i<128 ;i+=2, ptr++) + wval += *ptr; + if( wval == 0x1234 ) + rc = 0; + else + rc = DC390_DefaultEEprom( MechNum, index); + return( rc ); +} + + +static USHORT +DC390_ToMech( USHORT Mechnum, pcici_t config_id ) +{ + +#ifdef PCI_COMPAT + cfg = config_id; +#else + if(Mechnum == 2) + { + mech2bus = config_id.cfg2.forward; /* Bus num */ + mech2Agent = config_id.cfg2.port >> 8; /* Dev num */ + mech2CfgSPenR = config_id.cfg2.enable; /* Fun num */ + } + else /* use mech #1 method */ + { + mech1addr = config_id.cfg1; + } +#endif /* PCI_COMPAT */ + return(0); +} + +/*********************************************************************** + * Function : static int DC390_init (struct Scsi_Host *host) + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : host - pointer to this host adapter's structure/ + * + * Preconditions : when this function is called, the chip_type + * field of the pACB structure MUST have been set. + ***********************************************************************/ + +static int +DC390_init( ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum, + pcici_t config_id) +{ + PACB pACB; + + if( !DC390_CheckEEpromCheckSum( MechNum, index) ) + { + pACB = (PACB) malloc (sizeof (struct _ACB), M_DEVBUF, M_WAITOK); + if( !pACB ) + { + printf("DC390%d: cannot allocate ACB !\n", index); + return( -1 ); + } + bzero (pACB, sizeof (struct _ACB)); + DC390_initACB( pACB, io_port, Irq, index ); + if( !DC390_initAdapter( pACB, io_port, Irq, index, config_id) ) + { + if( !pACB_start ) + { + pACB_start = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + else + { + pACB_current->pNextACB = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + pACB0[index] = pACB; + +#ifdef DC390_DEBUG0 + printf("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", + (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); + printf("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n", + sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) ); +#endif + + return( 0 ); + } + else + { + free( pACB, M_DEVBUF); + return( -1 ); + } + } + else + { + printf("DC390_init: EEPROM reading error!\n"); + return( -1 ); + } +} + + + +void +trmamd_attach (pcici_t config_id, int unit) +{ + struct scsibus_data *scbus; + UCHAR irq; + USHORT MechNum; + ULONG io_port, wlval; + PACB pACB = 0; + int flags; + + if( unit >= MAX_ADAPTER_NUM ) + return; + + if( pACB0[unit] ) + return; + + CurrentID = 0; + CurrentLUN = 0; + MechNum = pci_mechanism; + +#ifdef DC390_DEBUG0 + if(bootverbose) + printf("DC390: Mech=%2x,\n",(UCHAR) MechNum); +#endif + + if( !DC390_ToMech( MechNum, config_id ) ) + { + wlval = DC390_inDword( MechNum, PCI_ID_REG); + if(wlval == PCI_DEVICE_ID_AMD53C974 ) + { + io_port =DC390_inDword(MechNum,PCI_BASE_ADDR0) & 0xFFFE; + irq = DC390_inByte( MechNum, PCI_INTERRUPT_REG); +#ifdef DC390_DEBUG0 + if(bootverbose) + printf("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); +#endif + if( !DC390_init( io_port, irq, (USHORT) unit, MechNum, config_id) ) + { + adapterCnt++; + } + else + return; + } + } + + pACB = pACB0[unit]; + +/* + Now let the generic SCSI driver look for the SCSI devices on the bus +*/ + + flags = splbio(); + + scbus = scsi_alloc_bus(); + if(!scbus) + { + splx(flags); + return; + } + scbus->adapter_link = &pACB->ScsiLink; + scbus->maxtarg = pACB->max_id; + +#ifdef DC390_DEBUG + if(bootverbose) + printf("\nDC390: scanning for devices ...\n\n"); +#endif + + scsi_attachdevs (scbus); + scbus = NULL; /* Upper-level SCSI code owns this now */ + +#ifdef DC390_DEBUG + if(bootverbose) + printf("\n\nDC390: Attach devices return\n"); +#endif + + splx(flags); +} + + +static char* +trmamd_probe (pcici_t tag, pcidi_t type) +{ + if( type == PCI_DEVICE_ID_AMD53C974 ) + return ("amd 53c974 scsi"); + else + return (NULL); +} + |