From 0141cae4d37c6e204c55c7748c31b624c77314df Mon Sep 17 00:00:00 2001 From: msmith Date: Wed, 11 Nov 1998 21:32:56 +0000 Subject: Consign the 'amd' driver to the Attic. --- sys/pci/tek390.c | 1709 ------------------------------------------------------ 1 file changed, 1709 deletions(-) delete mode 100644 sys/pci/tek390.c (limited to 'sys') diff --git a/sys/pci/tek390.c b/sys/pci/tek390.c deleted file mode 100644 index 9be42e2..0000000 --- a/sys/pci/tek390.c +++ /dev/null @@ -1,1709 +0,0 @@ -/*********************************************************************** - * 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 , 1996-12-17 */ -/**************************************************************************/ - -/* #define REL_2_1_0 */ -#define REL_2_1_5 - -#define DC390_DEBUG - -#include - -/* XXX this doesn't actually compile unless KERNEL is defined. */ -#ifdef KERNEL -#include -#include -#include -#include - -#include -#include -#endif /* KERNEL */ - -#include -#include - -#include - -#include - -#include - -#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; ipcmd != 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; ipNextSRB; -/* 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 - - -/*********************************************************************** - * 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; iDCBmap[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); -} - -- cgit v1.1