Commit 9f0b7b10 authored by Doug Ledford's avatar Doug Ledford

Initial initio a100 driver DMA mapping changes + selected cleanups

* 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
*          - Remove limit on number of controllers
*          - Port to DMA mapping API
*          - Clean up interrupt handler registration
*          - Fix memory leaks
*          - Fix allocation of scsi host structs and private data
parent 2ffe5f2f
...@@ -66,12 +66,24 @@ ...@@ -66,12 +66,24 @@
* 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up
* 01/31/99 bv - v1.02b Use mdelay instead of waitForPause * 01/31/99 bv - v1.02b Use mdelay instead of waitForPause
* 08/08/99 bv - v1.02c Use waitForPause again. * 08/08/99 bv - v1.02c Use waitForPause again.
* 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
* - Remove limit on number of controllers
* - Port to DMA mapping API
* - Clean up interrupt handler registration
* - Fix memory leaks
* - Fix allocation of scsi host structs and private data
**************************************************************************/ **************************************************************************/
#include <linux/version.h> #include <linux/version.h>
#include <linux/jiffies.h> #include <linux/module.h>
#include <asm/irq.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <asm/io.h> #include <asm/io.h>
#include "i60uscsi.h" #include <linux/blkdev.h>
#include "scsi.h"
#include "hosts.h"
#include "inia100.h"
#define JIFFIES_TO_MS(t) ((t) * 1000 / HZ) #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
#define MS_TO_JIFFIES(j) ((j * HZ) / 1000) #define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
...@@ -98,10 +110,7 @@ ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp); ...@@ -98,10 +110,7 @@ ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb); extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
/* ---- INTERNAL VARIABLES ---- */ /* ---- INTERNAL VARIABLES ---- */
ORC_HCS orc_hcs[MAX_SUPPORTED_ADAPTERS]; static INIA100_ADPT_STRUCT *inia100_adpt;
static INIA100_ADPT_STRUCT inia100_adpt[MAX_SUPPORTED_ADAPTERS];
/* set by inia100_setup according to the command line */
int orc_num_scb;
NVRAM nvram, *nvramp = &nvram; NVRAM nvram, *nvramp = &nvram;
static UCHAR dftNvRam[64] = static UCHAR dftNvRam[64] =
...@@ -300,7 +309,7 @@ UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn) ...@@ -300,7 +309,7 @@ UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
/***************************************************************************/ /***************************************************************************/
void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp) void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
{ {
scbp->SCB_Status = SCB_POST; scbp->SCB_Status = ORCSCB_POST;
ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx); ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
return; return;
} }
...@@ -439,17 +448,11 @@ void setup_SCBs(ORC_HCS * hcsp) ...@@ -439,17 +448,11 @@ void setup_SCBs(ORC_HCS * hcsp)
{ {
ORC_SCB *pVirScb; ORC_SCB *pVirScb;
int i; int i;
UCHAR j;
ESCB *pVirEscb; ESCB *pVirEscb;
PVOID pPhysEscb; dma_addr_t pPhysEscb;
PVOID tPhysEscb;
j = 0;
pVirScb = NULL;
tPhysEscb = (PVOID) NULL;
pPhysEscb = (PVOID) NULL;
/* Setup SCB HCS_Base and SCB Size registers */ /* Setup SCB HCS_Base and SCB Size registers */
ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, orc_num_scb); /* Total number of SCBs */ ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, ORC_MAXQUEUE); /* Total number of SCBs */
/* SCB HCS_Base address 0 */ /* SCB HCS_Base address 0 */
ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray); ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
/* SCB HCS_Base address 1 */ /* SCB HCS_Base address 1 */
...@@ -459,8 +462,8 @@ void setup_SCBs(ORC_HCS * hcsp) ...@@ -459,8 +462,8 @@ void setup_SCBs(ORC_HCS * hcsp)
pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray; pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
pVirEscb = (ESCB *) hcsp->HCS_virEscbArray; pVirEscb = (ESCB *) hcsp->HCS_virEscbArray;
for (i = 0; i < orc_num_scb; i++) { for (i = 0; i < ORC_MAXQUEUE; i++) {
pPhysEscb = (PVOID) (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i)); pPhysEscb = (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
pVirScb->SCB_SGPAddr = (U32) pPhysEscb; pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
pVirScb->SCB_SensePAddr = (U32) pPhysEscb; pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
pVirScb->SCB_EScb = pVirEscb; pVirScb->SCB_EScb = pVirEscb;
...@@ -534,7 +537,7 @@ int init_orchid(ORC_HCS * hcsp) ...@@ -534,7 +537,7 @@ int init_orchid(ORC_HCS * hcsp)
readBytep = (UCHAR *) & (nvramp->Target00Config); readBytep = (UCHAR *) & (nvramp->Target00Config);
for (i = 0; i < 16; readBytep++, i++) { for (i = 0; i < 16; readBytep++, i++) {
hcsp->TargetFlag[i] = *readBytep; hcsp->TargetFlag[i] = *readBytep;
hcsp->MaximumTags[i] = orc_num_scb; hcsp->MaximumTags[i] = ORC_MAXTAGS;
} /* for */ } /* for */
if (nvramp->SCSI0Config & NCC_BUSRESET) { /* Reset SCSI bus */ if (nvramp->SCSI0Config & NCC_BUSRESET) { /* Reset SCSI bus */
...@@ -578,7 +581,7 @@ int orc_reset_scsi_bus(ORC_HCS * pHCB) ...@@ -578,7 +581,7 @@ int orc_reset_scsi_bus(ORC_HCS * pHCB)
Output : None. Output : None.
Return : pSRB - Pointer to SCSI request block. Return : pSRB - Pointer to SCSI request block.
*****************************************************************************/ *****************************************************************************/
int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags) int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags)
{ /* I need Host Control Block Information */ { /* I need Host Control Block Information */
ORC_SCB *pScb; ORC_SCB *pScb;
ESCB *pVirEscb; ESCB *pVirEscb;
...@@ -595,14 +598,14 @@ int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned ...@@ -595,14 +598,14 @@ int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned
initAFlag(pHCB); initAFlag(pHCB);
/* device reset */ /* device reset */
for (i = 0; i < orc_num_scb; i++) { for (i = 0; i < ORC_MAXQUEUE; i++) {
pVirEscb = pVirScb->SCB_EScb; pVirEscb = pVirScb->SCB_EScb;
if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt))
break; break;
pVirScb++; pVirScb++;
} }
if (i == orc_num_scb) { if (i == ORC_MAXQUEUE) {
printk("Unable to Reset - No SCB Found\n"); printk("Unable to Reset - No SCB Found\n");
spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
return (SCSI_RESET_NOT_RUNNING); return (SCSI_RESET_NOT_RUNNING);
...@@ -624,7 +627,7 @@ int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned ...@@ -624,7 +627,7 @@ int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned
pVirEscb->SCB_Srb = 0; pVirEscb->SCB_Srb = 0;
if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
pVirEscb->SCB_Srb = (unsigned char *) SCpnt; pVirEscb->SCB_Srb = SCpnt;
} }
orc_exec_scb(pHCB, pScb); /* Start execute SCB */ orc_exec_scb(pHCB, pScb); /* Start execute SCB */
spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
...@@ -640,7 +643,6 @@ ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp) ...@@ -640,7 +643,6 @@ ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
ULONG idx; ULONG idx;
UCHAR index; UCHAR index;
UCHAR i; UCHAR i;
ULONG flags;
Ch = hcsp->HCS_Index; Ch = hcsp->HCS_Index;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
...@@ -687,6 +689,29 @@ void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp) ...@@ -687,6 +689,29 @@ void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
} }
/***************************************************************************/
void orc_release_dma(ORC_HCS * hcsp, ORC_SCB * scbp)
{
ESCB *pEScb;
Scsi_Cmnd *SCpnt;
struct scatterlist *pSrbSG;
ORC_SG *pSG;
pEScb = scbp->SCB_EScb;
SCpnt = pEScb->SCB_Srb;
pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
if (SCpnt->use_sg) {
pSrbSG = (struct scatterlist *)SCpnt->request_buffer;
pci_unmap_sg(hcsp->pdev, pSrbSG, SCpnt->use_sg,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
} else {
pci_unmap_single(hcsp->pdev, (U32)SCpnt->host_scribble,
SCpnt->request_bufflen,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
}
}
/***************************************************************************** /*****************************************************************************
Function name : Addinia100_into_Adapter_table Function name : Addinia100_into_Adapter_table
Description : This function will scan PCI bus to get all Orchid card Description : This function will scan PCI bus to get all Orchid card
...@@ -695,33 +720,29 @@ void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp) ...@@ -695,33 +720,29 @@ void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
Return : SUCCESSFUL - Successful scan Return : SUCCESSFUL - Successful scan
ohterwise - No drives founded ohterwise - No drives founded
*****************************************************************************/ *****************************************************************************/
int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, struct pci_dev *pdev,
BYTE bBus, BYTE bDevice) int iAdapters)
{ {
unsigned int i, j; unsigned int i, j;
for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { for (i = 0; i < iAdapters; i++) {
if (inia100_adpt[i].ADPT_BIOS < wBIOS) if (inia100_adpt[i].ADPT_BIOS < wBIOS)
continue; continue;
if (inia100_adpt[i].ADPT_BIOS == wBIOS) { if (inia100_adpt[i].ADPT_BIOS == wBIOS) {
if (inia100_adpt[i].ADPT_BASE == wBASE) { if (inia100_adpt[i].ADPT_BASE == wBASE) {
if (inia100_adpt[i].ADPT_Bus != 0xFF) if (inia100_adpt[i].ADPT_pdev->bus->number != 0xFF)
return (FAILURE); return (FAILURE);
} else if (inia100_adpt[i].ADPT_BASE < wBASE) } else if (inia100_adpt[i].ADPT_BASE < wBASE)
continue; continue;
} }
for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) { for (j = iAdapters - 1; j > i; j--) {
inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE; inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE;
inia100_adpt[j].ADPT_INTR = inia100_adpt[j - 1].ADPT_INTR;
inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS; inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS;
inia100_adpt[j].ADPT_Bus = inia100_adpt[j - 1].ADPT_Bus; inia100_adpt[j].ADPT_pdev = inia100_adpt[j - 1].ADPT_pdev;
inia100_adpt[j].ADPT_Device = inia100_adpt[j - 1].ADPT_Device;
} }
inia100_adpt[i].ADPT_BASE = wBASE; inia100_adpt[i].ADPT_BASE = wBASE;
inia100_adpt[i].ADPT_INTR = bInterrupt;
inia100_adpt[i].ADPT_BIOS = wBIOS; inia100_adpt[i].ADPT_BIOS = wBIOS;
inia100_adpt[i].ADPT_Bus = bBus; inia100_adpt[i].ADPT_pdev = pdev;
inia100_adpt[i].ADPT_Device = bDevice;
return (SUCCESSFUL); return (SUCCESSFUL);
} }
return (FAILURE); return (FAILURE);
...@@ -733,20 +754,23 @@ int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, ...@@ -733,20 +754,23 @@ int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
Description : This function will scan PCI bus to get all Orchid card Description : This function will scan PCI bus to get all Orchid card
Input : None. Input : None.
Output : None. Output : None.
Return : SUCCESSFUL - Successful scan Return : 0 on success, 1 on failure
ohterwise - No drives founded
*****************************************************************************/ *****************************************************************************/
void init_inia100Adapter_table(void) int init_inia100Adapter_table(int iAdapters)
{ {
int i; int i;
for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */ inia100_adpt = kmalloc(sizeof(INIA100_ADPT_STRUCT) * iAdapters,
GFP_KERNEL);
if(inia100_adpt == NULL)
return 1;
for (i = 0; i < iAdapters; i++) {/* Initialize adapter structure */
inia100_adpt[i].ADPT_BIOS = 0xffff; inia100_adpt[i].ADPT_BIOS = 0xffff;
inia100_adpt[i].ADPT_BASE = 0xffff; inia100_adpt[i].ADPT_BASE = 0xffff;
inia100_adpt[i].ADPT_INTR = 0xff; inia100_adpt[i].ADPT_pdev = NULL;
inia100_adpt[i].ADPT_Bus = 0xff;
inia100_adpt[i].ADPT_Device = 0xff;
} }
return 0;
} }
/***************************************************************************** /*****************************************************************************
...@@ -760,7 +784,7 @@ void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx) ...@@ -760,7 +784,7 @@ void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx)
{ {
pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE; /* Supply base address */ pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE; /* Supply base address */
pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */ pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */
pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */ pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_pdev->irq; /* Supply interrupt line */
return; return;
} }
...@@ -805,7 +829,7 @@ int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb) ...@@ -805,7 +829,7 @@ int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
Output : None. Output : None.
Return : pSRB - Pointer to SCSI request block. Return : pSRB - Pointer to SCSI request block.
*****************************************************************************/ *****************************************************************************/
int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt) int orc_abort_srb(ORC_HCS * hcsp, Scsi_Cmnd *SCpnt)
{ {
ESCB *pVirEscb; ESCB *pVirEscb;
ORC_SCB *pVirScb; ORC_SCB *pVirScb;
...@@ -816,9 +840,9 @@ int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt) ...@@ -816,9 +840,9 @@ int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt)
pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray; pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
for (i = 0; i < orc_num_scb; i++, pVirScb++) { for (i = 0; i < ORC_MAXQUEUE; i++, pVirScb++) {
pVirEscb = pVirScb->SCB_EScb; pVirEscb = pVirScb->SCB_EScb;
if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) { if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) {
if (pVirScb->SCB_TagMsg == 0) { if (pVirScb->SCB_TagMsg == 0) {
spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
return (SCSI_ABORT_BUSY); return (SCSI_ABORT_BUSY);
......
/**************************************************************************
* Initio A100 device driver for Linux.
*
* Copyright (c) 1994-1998 Initio Corporation
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* --------------------------------------------------------------------------
*
* 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,
* without modification, immediately at the beginning of the file.
* 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.
*
* Where this Software is combined with software released under the terms of
* the GNU General Public License ("GPL") and the terms of the GPL would require the
* combined work to also be released under the terms of the GPL, the terms
* and conditions of this License will apply in addition to those of the
* GPL with the exception of any terms or conditions of this License that
* conflict with, or are expressly prohibited by, the GPL.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
**************************************************************************
*
* Module: inia100.h
* Description: INI-A100U2W LINUX device driver header
* Revision History:
* 06/18/98 HL, Initial Version 1.02
* 12/19/98 bv, v1.02a Use spinlocks for 2.1.95 and up.
**************************************************************************/
#include <linux/config.h>
#include <linux/types.h>
#define ULONG unsigned long
#define PVOID void *
#define USHORT unsigned short
#define UCHAR unsigned char
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
#define UBYTE unsigned char
#define UWORD unsigned short
#define UDWORD unsigned long
#define U32 u32
#ifndef NULL
#define NULL 0 /* zero */
#endif
#ifndef TRUE
#define TRUE (1) /* boolean true */
#endif
#ifndef FALSE
#define FALSE (0) /* boolean false */
#endif
#ifndef FAILURE
#define FAILURE (-1)
#endif
#if 1
#define ORC_MAXQUEUE 245
#else
#define ORC_MAXQUEUE 25
#endif
#define TOTAL_SG_ENTRY 32
#define MAX_TARGETS 16
#define IMAX_CDB 15
#define SENSE_SIZE 14
#define MAX_SUPPORTED_ADAPTERS 4
#define SUCCESSFUL 0x00
#define I920_DEVICE_ID 0x0002 /* Initio's inic-950 product ID */
/************************************************************************/
/* Scatter-Gather Element Structure */
/************************************************************************/
typedef struct ORC_SG_Struc {
U32 SG_Ptr; /* Data Pointer */
U32 SG_Len; /* Data Length */
} ORC_SG;
typedef struct inia100_Adpt_Struc {
UWORD ADPT_BIOS; /* 0 */
UWORD ADPT_BASE; /* 1 */
UBYTE ADPT_Bus; /* 2 */
UBYTE ADPT_Device; /* 3 */
UBYTE ADPT_INTR; /* 4 */
} INIA100_ADPT_STRUCT;
/* SCSI related definition */
#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */
#define DISC_ALLOW 0xC0 /* Disconnect is allowed */
#define ORC_OFFSET_SCB 16
#define ORC_MAX_SCBS 250
#define MAX_CHANNELS 2
#define MAX_ESCB_ELE 64
#define TCF_DRV_255_63 0x0400
/********************************************************/
/* Orchid Configuration Register Set */
/********************************************************/
#define ORC_PVID 0x00 /* Vendor ID */
#define ORC_VENDOR_ID 0x1101 /* Orchid vendor ID */
#define ORC_PDID 0x02 /* Device ID */
#define ORC_DEVICE_ID 0x1060 /* Orchid device ID */
#define ORC_COMMAND 0x04 /* Command */
#define BUSMS 0x04 /* BUS MASTER Enable */
#define IOSPA 0x01 /* IO Space Enable */
#define ORC_STATUS 0x06 /* Status register */
#define ORC_REVISION 0x08 /* Revision number */
#define ORC_BASE 0x10 /* Base address */
#define ORC_BIOS 0x50 /* Expansion ROM base address */
#define ORC_INT_NUM 0x3C /* Interrupt line */
#define ORC_INT_PIN 0x3D /* Interrupt pin */
/********************************************************/
/* Orchid Host Command Set */
/********************************************************/
#define ORC_CMD_NOP 0x00 /* Host command - NOP */
#define ORC_CMD_VERSION 0x01 /* Host command - Get F/W version */
#define ORC_CMD_ECHO 0x02 /* Host command - ECHO */
#define ORC_CMD_SET_NVM 0x03 /* Host command - Set NVRAM */
#define ORC_CMD_GET_NVM 0x04 /* Host command - Get NVRAM */
#define ORC_CMD_GET_BUS_STATUS 0x05 /* Host command - Get SCSI bus status */
#define ORC_CMD_ABORT_SCB 0x06 /* Host command - Abort SCB */
#define ORC_CMD_ISSUE_SCB 0x07 /* Host command - Issue SCB */
/********************************************************/
/* Orchid Register Set */
/********************************************************/
#define ORC_GINTS 0xA0 /* Global Interrupt Status */
#define QINT 0x04 /* Reply Queue Interrupt */
#define ORC_GIMSK 0xA1 /* Global Interrupt MASK */
#define MQINT 0x04 /* Mask Reply Queue Interrupt */
#define ORC_GCFG 0xA2 /* Global Configure */
#define EEPRG 0x01 /* Enable EEPROM programming */
#define ORC_GSTAT 0xA3 /* Global status */
#define WIDEBUS 0x10 /* Wide SCSI Devices connected */
#define ORC_HDATA 0xA4 /* Host Data */
#define ORC_HCTRL 0xA5 /* Host Control */
#define SCSIRST 0x80 /* SCSI bus reset */
#define HDO 0x40 /* Host data out */
#define HOSTSTOP 0x02 /* Host stop RISC engine */
#define DEVRST 0x01 /* Device reset */
#define ORC_HSTUS 0xA6 /* Host Status */
#define HDI 0x02 /* Host data in */
#define RREADY 0x01 /* RISC engine is ready to receive */
#define ORC_NVRAM 0xA7 /* Nvram port address */
#define SE2CS 0x008
#define SE2CLK 0x004
#define SE2DO 0x002
#define SE2DI 0x001
#define ORC_PQUEUE 0xA8 /* Posting queue FIFO */
#define ORC_PQCNT 0xA9 /* Posting queue FIFO Cnt */
#define ORC_RQUEUE 0xAA /* Reply queue FIFO */
#define ORC_RQUEUECNT 0xAB /* Reply queue FIFO Cnt */
#define ORC_FWBASEADR 0xAC /* Firmware base address */
#define ORC_EBIOSADR0 0xB0 /* External Bios address */
#define ORC_EBIOSADR1 0xB1 /* External Bios address */
#define ORC_EBIOSADR2 0xB2 /* External Bios address */
#define ORC_EBIOSDATA 0xB3 /* External Bios address */
#define ORC_SCBSIZE 0xB7 /* SCB size register */
#define ORC_SCBBASE0 0xB8 /* SCB base address 0 */
#define ORC_SCBBASE1 0xBC /* SCB base address 1 */
#define ORC_RISCCTL 0xE0 /* RISC Control */
#define PRGMRST 0x002
#define DOWNLOAD 0x001
#define ORC_PRGMCTR0 0xE2 /* RISC program counter */
#define ORC_PRGMCTR1 0xE3 /* RISC program counter */
#define ORC_RISCRAM 0xEC /* RISC RAM data port 4 bytes */
typedef struct orc_extended_scb { /* Extended SCB */
ORC_SG ESCB_SGList[TOTAL_SG_ENTRY]; /*0 Start of SG list */
unsigned char *SCB_Srb; /*50 SRB Pointer */
// Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */
} ESCB;
/***********************************************************************
SCSI Control Block
************************************************************************/
typedef struct orc_scb { /* Scsi_Ctrl_Blk */
UBYTE SCB_Opcode; /*00 SCB command code&residual */
UBYTE SCB_Flags; /*01 SCB Flags */
UBYTE SCB_Target; /*02 Target Id */
UBYTE SCB_Lun; /*03 Lun */
U32 SCB_Reserved0; /*04 Reserved for ORCHID must 0 */
U32 SCB_XferLen; /*08 Data Transfer Length */
U32 SCB_Reserved1; /*0C Reserved for ORCHID must 0 */
U32 SCB_SGLen; /*10 SG list # * 8 */
U32 SCB_SGPAddr; /*14 SG List Buf physical Addr */
U32 SCB_SGPAddrHigh; /*18 SG Buffer high physical Addr */
UBYTE SCB_HaStat; /*1C Host Status */
UBYTE SCB_TaStat; /*1D Target Status */
UBYTE SCB_Status; /*1E SCB status */
UBYTE SCB_Link; /*1F Link pointer, default 0xFF */
UBYTE SCB_SenseLen; /*20 Sense Allocation Length */
UBYTE SCB_CDBLen; /*21 CDB Length */
UBYTE SCB_Ident; /*22 Identify */
UBYTE SCB_TagMsg; /*23 Tag Message */
UBYTE SCB_CDB[IMAX_CDB]; /*24 SCSI CDBs */
UBYTE SCB_ScbIdx; /*3C Index for this ORCSCB */
U32 SCB_SensePAddr; /*34 Sense Buffer physical Addr */
ESCB *SCB_EScb; /*38 Extended SCB Pointer */
#ifndef ALPHA
UBYTE SCB_Reserved2[4]; /*3E Reserved for Driver use */
#endif
} ORC_SCB;
/* Opcodes of ORCSCB_Opcode */
#define ORC_EXECSCSI 0x00 /* SCSI initiator command with residual */
#define ORC_BUSDEVRST 0x01 /* SCSI Bus Device Reset */
/* Status of ORCSCB_Status */
#define SCB_COMPLETE 0x00 /* SCB request completed */
#define SCB_POST 0x01 /* SCB is posted by the HOST */
/* Bit Definition for ORCSCB_Flags */
#define SCF_DISINT 0x01 /* Disable HOST interrupt */
#define SCF_DIR 0x18 /* Direction bits */
#define SCF_NO_DCHK 0x00 /* Direction determined by SCSI */
#define SCF_DIN 0x08 /* From Target to Initiator */
#define SCF_DOUT 0x10 /* From Initiator to Target */
#define SCF_NO_XF 0x18 /* No data transfer */
#define SCF_POLL 0x40
/* Error Codes for ORCSCB_HaStat */
#define HOST_SEL_TOUT 0x11
#define HOST_DO_DU 0x12
#define HOST_BUS_FREE 0x13
#define HOST_BAD_PHAS 0x14
#define HOST_INV_CMD 0x16
#define HOST_SCSI_RST 0x1B
#define HOST_DEV_RST 0x1C
/* Error Codes for ORCSCB_TaStat */
#define TARGET_CHK_COND 0x02
#define TARGET_BUSY 0x08
#define TARGET_TAG_FULL 0x28
/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
#define MSG_STAG 0x20
#define MSG_HTAG 0x21
#define MSG_OTAG 0x22
#define MSG_IGNOREWIDE 0x23
#define MSG_IDENT 0x80
#define MSG_DISC 0x40 /* Disconnect allowed */
/* SCSI MESSAGE */
#define MSG_EXTEND 0x01
#define MSG_SDP 0x02
#define MSG_ABORT 0x06
#define MSG_REJ 0x07
#define MSG_NOP 0x08
#define MSG_PARITY 0x09
#define MSG_DEVRST 0x0C
#define MSG_STAG 0x20
/***********************************************************************
Target Device Control Structure
**********************************************************************/
typedef struct ORC_Tar_Ctrl_Struc {
UBYTE TCS_DrvDASD; /* 6 */
UBYTE TCS_DrvSCSI; /* 7 */
UBYTE TCS_DrvHead; /* 8 */
UWORD TCS_DrvFlags; /* 4 */
UBYTE TCS_DrvSector; /* 7 */
} ORC_TCS, *PORC_TCS;
/* Bit Definition for TCF_DrvFlags */
#define TCS_DF_NODASD_SUPT 0x20 /* Suppress OS/2 DASD Mgr support */
#define TCS_DF_NOSCSI_SUPT 0x40 /* Suppress OS/2 SCSI Mgr support */
/***********************************************************************
Host Adapter Control Structure
************************************************************************/
typedef struct ORC_Ha_Ctrl_Struc {
USHORT HCS_Base; /* 00 */
UBYTE HCS_Index; /* 02 */
UBYTE HCS_Intr; /* 04 */
UBYTE HCS_SCSI_ID; /* 06 H/A SCSI ID */
UBYTE HCS_BIOS; /* 07 BIOS configuration */
UBYTE HCS_Flags; /* 0B */
UBYTE HCS_HAConfig1; /* 1B SCSI0MAXTags */
UBYTE HCS_MaxTar; /* 1B SCSI0MAXTags */
USHORT HCS_Units; /* Number of units this adapter */
USHORT HCS_AFlags; /* Adapter info. defined flags */
ULONG HCS_Timeout; /* Adapter timeout value */
PVOID HCS_virScbArray; /* 28 Virtual Pointer to SCB array */
U32 HCS_physScbArray; /* Scb Physical address */
PVOID HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */
U32 HCS_physEscbArray; /* scatter list Physical address */
UBYTE TargetFlag[16]; /* 30 target configuration, TCF_EN_TAG */
UBYTE MaximumTags[16]; /* 40 ORC_MAX_SCBS */
UBYTE ActiveTags[16][16]; /* 50 */
ORC_TCS HCS_Tcs[16]; /* 28 */
U32 BitAllocFlag[MAX_CHANNELS][8]; /* Max STB is 256, So 256/32 */
spinlock_t BitAllocFlagLock;
ULONG pSRB_head;
ULONG pSRB_tail;
spinlock_t pSRB_lock;
} ORC_HCS;
/* Bit Definition for HCS_Flags */
#define HCF_SCSI_RESET 0x01 /* SCSI BUS RESET */
#define HCF_PARITY 0x02 /* parity card */
#define HCF_LVDS 0x10 /* parity card */
/* Bit Definition for TargetFlag */
#define TCF_EN_255 0x08
#define TCF_EN_TAG 0x10
#define TCF_BUSY 0x20
#define TCF_DISCONNECT 0x40
#define TCF_SPIN_UP 0x80
/* Bit Definition for HCS_AFlags */
#define HCS_AF_IGNORE 0x01 /* Adapter ignore */
#define HCS_AF_DISABLE_RESET 0x10 /* Adapter disable reset */
#define HCS_AF_DISABLE_ADPT 0x80 /* Adapter disable */
/*---------------------------------------*/
/* TimeOut for RESET to complete (30s) */
/* */
/* After a RESET the drive is checked */
/* every 200ms. */
/*---------------------------------------*/
#define DELAYED_RESET_MAX (30*1000L)
#define DELAYED_RESET_INTERVAL 200L
/*----------------------------------------------*/
/* TimeOut for IRQ from last interrupt (5s) */
/*----------------------------------------------*/
#define IRQ_TIMEOUT_INTERVAL (5*1000L)
/*----------------------------------------------*/
/* Retry Delay interval (200ms) */
/*----------------------------------------------*/
#define DELAYED_RETRY_INTERVAL 200L
#define INQUIRY_SIZE 36
#define CAPACITY_SIZE 8
#define DEFAULT_SENSE_LEN 14
#define DEVICE_NOT_FOUND 0x86
/*----------------------------------------------*/
/* Definition for PCI device */
/*----------------------------------------------*/
#define MAX_PCI_DEVICES 21
#define MAX_PCI_BUSES 8
typedef struct Adpt_Struc {
USHORT ADPT_BIOS; /* 0 */
UBYTE ADPT_BASE; /* 1 */
UBYTE ADPT_Bus; /* 2 */
UBYTE ADPT_Device; /* 3 */
UBYTE ADPT_Reserved[3];
} JACS, *PJACS;
typedef struct _NVRAM {
/*----------header ---------------*/
UCHAR SubVendorID0; /* 00 - Sub Vendor ID */
UCHAR SubVendorID1; /* 00 - Sub Vendor ID */
UCHAR SubSysID0; /* 02 - Sub System ID */
UCHAR SubSysID1; /* 02 - Sub System ID */
UCHAR SubClass; /* 04 - Sub Class */
UCHAR VendorID0; /* 05 - Vendor ID */
UCHAR VendorID1; /* 05 - Vendor ID */
UCHAR DeviceID0; /* 07 - Device ID */
UCHAR DeviceID1; /* 07 - Device ID */
UCHAR Reserved0[2]; /* 09 - Reserved */
UCHAR Revision; /* 0B - Revision of data structure */
/* ----Host Adapter Structure ---- */
UCHAR NumOfCh; /* 0C - Number of SCSI channel */
UCHAR BIOSConfig1; /* 0D - BIOS configuration 1 */
UCHAR BIOSConfig2; /* 0E - BIOS boot channel&target ID */
UCHAR BIOSConfig3; /* 0F - BIOS configuration 3 */
/* ----SCSI channel Structure ---- */
/* from "CTRL-I SCSI Host Adapter SetUp menu " */
UCHAR SCSI0Id; /* 10 - Channel 0 SCSI ID */
UCHAR SCSI0Config; /* 11 - Channel 0 SCSI configuration */
UCHAR SCSI0MaxTags; /* 12 - Channel 0 Maximum tags */
UCHAR SCSI0ResetTime; /* 13 - Channel 0 Reset recovering time */
UCHAR ReservedforChannel0[2]; /* 14 - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR Target00Config; /* 16 - Channel 0 Target 0 config */
UCHAR Target01Config; /* 17 - Channel 0 Target 1 config */
UCHAR Target02Config; /* 18 - Channel 0 Target 2 config */
UCHAR Target03Config; /* 19 - Channel 0 Target 3 config */
UCHAR Target04Config; /* 1A - Channel 0 Target 4 config */
UCHAR Target05Config; /* 1B - Channel 0 Target 5 config */
UCHAR Target06Config; /* 1C - Channel 0 Target 6 config */
UCHAR Target07Config; /* 1D - Channel 0 Target 7 config */
UCHAR Target08Config; /* 1E - Channel 0 Target 8 config */
UCHAR Target09Config; /* 1F - Channel 0 Target 9 config */
UCHAR Target0AConfig; /* 20 - Channel 0 Target A config */
UCHAR Target0BConfig; /* 21 - Channel 0 Target B config */
UCHAR Target0CConfig; /* 22 - Channel 0 Target C config */
UCHAR Target0DConfig; /* 23 - Channel 0 Target D config */
UCHAR Target0EConfig; /* 24 - Channel 0 Target E config */
UCHAR Target0FConfig; /* 25 - Channel 0 Target F config */
UCHAR SCSI1Id; /* 26 - Channel 1 SCSI ID */
UCHAR SCSI1Config; /* 27 - Channel 1 SCSI configuration */
UCHAR SCSI1MaxTags; /* 28 - Channel 1 Maximum tags */
UCHAR SCSI1ResetTime; /* 29 - Channel 1 Reset recovering time */
UCHAR ReservedforChannel1[2]; /* 2A - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR Target10Config; /* 2C - Channel 1 Target 0 config */
UCHAR Target11Config; /* 2D - Channel 1 Target 1 config */
UCHAR Target12Config; /* 2E - Channel 1 Target 2 config */
UCHAR Target13Config; /* 2F - Channel 1 Target 3 config */
UCHAR Target14Config; /* 30 - Channel 1 Target 4 config */
UCHAR Target15Config; /* 31 - Channel 1 Target 5 config */
UCHAR Target16Config; /* 32 - Channel 1 Target 6 config */
UCHAR Target17Config; /* 33 - Channel 1 Target 7 config */
UCHAR Target18Config; /* 34 - Channel 1 Target 8 config */
UCHAR Target19Config; /* 35 - Channel 1 Target 9 config */
UCHAR Target1AConfig; /* 36 - Channel 1 Target A config */
UCHAR Target1BConfig; /* 37 - Channel 1 Target B config */
UCHAR Target1CConfig; /* 38 - Channel 1 Target C config */
UCHAR Target1DConfig; /* 39 - Channel 1 Target D config */
UCHAR Target1EConfig; /* 3A - Channel 1 Target E config */
UCHAR Target1FConfig; /* 3B - Channel 1 Target F config */
UCHAR reserved[3]; /* 3C - Reserved */
/* ---------- CheckSum ---------- */
UCHAR CheckSum; /* 3F - Checksum of NVRam */
} NVRAM, *PNVRAM;
/* Bios Configuration for nvram->BIOSConfig1 */
#define NBC_BIOSENABLE 0x01 /* BIOS enable */
#define NBC_CDROM 0x02 /* Support bootable CDROM */
#define NBC_REMOVABLE 0x04 /* Support removable drive */
/* Bios Configuration for nvram->BIOSConfig2 */
#define NBB_TARGET_MASK 0x0F /* Boot SCSI target ID number */
#define NBB_CHANL_MASK 0xF0 /* Boot SCSI channel number */
/* Bit definition for nvram->SCSIConfig */
#define NCC_BUSRESET 0x01 /* Reset SCSI bus at power up */
#define NCC_PARITYCHK 0x02 /* SCSI parity enable */
#define NCC_LVDS 0x10 /* Enable LVDS */
#define NCC_ACTTERM1 0x20 /* Enable active terminator 1 */
#define NCC_ACTTERM2 0x40 /* Enable active terminator 2 */
#define NCC_AUTOTERM 0x80 /* Enable auto termination */
/* Bit definition for nvram->TargetxConfig */
#define NTC_PERIOD 0x07 /* Maximum Sync. Speed */
#define NTC_1GIGA 0x08 /* 255 head / 63 sectors (64/32) */
#define NTC_NO_SYNC 0x10 /* NO SYNC. NEGO */
#define NTC_NO_WIDESYNC 0x20 /* NO WIDE SYNC. NEGO */
#define NTC_DISC_ENABLE 0x40 /* Enable SCSI disconnect */
#define NTC_SPINUP 0x80 /* Start disk drive */
/* Default NVRam values */
#define NBC_DEFAULT (NBC_ENABLE)
#define NCC_DEFAULT (NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK)
#define NCC_MAX_TAGS 0x20 /* Maximum tags per target */
#define NCC_RESET_TIME 0x0A /* SCSI RESET recovering time */
#define NTC_DEFAULT (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
typedef union { /* Union define for mechanism 1 */
struct {
unsigned char RegNum;
unsigned char FcnNum:3;
unsigned char DeviceNum:5;
unsigned char BusNum;
unsigned char Reserved:7;
unsigned char Enable:1;
} sConfigAdr;
unsigned long lConfigAdr;
} CONFIG_ADR;
typedef union { /* Union define for mechanism 2 */
struct {
unsigned char RegNum;
unsigned char DeviceNum;
unsigned short Reserved;
} sHostAdr;
unsigned long lHostAdr;
} HOST_ADR;
#define ORC_RD(x,y) (UCHAR)(inb( (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_RDLONG(x,y) (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_WR( adr,data) outb( (UCHAR)(data), (int)(adr))
#define ORC_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr))
#define ORC_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr))
#define SCSI_ABORT_SNOOZE 0
#define SCSI_ABORT_SUCCESS 1
#define SCSI_ABORT_PENDING 2
#define SCSI_ABORT_BUSY 3
#define SCSI_ABORT_NOT_RUNNING 4
#define SCSI_ABORT_ERROR 5
#define SCSI_RESET_SNOOZE 0
#define SCSI_RESET_PUNT 1
#define SCSI_RESET_SUCCESS 2
#define SCSI_RESET_PENDING 3
#define SCSI_RESET_WAKEUP 4
#define SCSI_RESET_NOT_RUNNING 5
#define SCSI_RESET_ERROR 6
#define SCSI_RESET_SYNCHRONOUS 0x01
#define SCSI_RESET_ASYNCHRONOUS 0x02
#define SCSI_RESET_SUGGEST_BUS_RESET 0x04
#define SCSI_RESET_SUGGEST_HOST_RESET 0x08
#define SCSI_RESET_BUS_RESET 0x100
#define SCSI_RESET_HOST_RESET 0x200
#define SCSI_RESET_ACTION 0xff
...@@ -59,6 +59,12 @@ ...@@ -59,6 +59,12 @@
* adapters * adapters
* 09/24/98 hl - v1.02 initial production release. * 09/24/98 hl - v1.02 initial production release.
* 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up. * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up.
* 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
* - Remove limit on number of controllers
* - Port to DMA mapping API
* - Clean up interrupt handler registration
* - Fix memory leaks
* - Fix allocation of scsi host structs and private data
**************************************************************************/ **************************************************************************/
#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
...@@ -67,11 +73,8 @@ ...@@ -67,11 +73,8 @@
#include <linux/version.h> #include <linux/version.h>
#endif #endif
#error Please convert me to Documentation/DMA-mapping.txt
#include <linux/module.h> #include <linux/module.h>
#include <stdarg.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -100,45 +103,35 @@ static Scsi_Host_Template driver_template = INIA100; ...@@ -100,45 +103,35 @@ static Scsi_Host_Template driver_template = INIA100;
char *inia100_Copyright = "Copyright (C) 1998-99"; char *inia100_Copyright = "Copyright (C) 1998-99";
char *inia100_InitioName = "by Initio Corporation"; char *inia100_InitioName = "by Initio Corporation";
char *inia100_ProductName = "INI-A100U2W"; char *inia100_ProductName = "INI-A100U2W";
char *inia100_Version = "v1.02c"; char *inia100_Version = "v1.02d";
/* set by inia100_setup according to the command line */ /* set by inia100_setup according to the command line */
static int setup_called = 0; static int setup_called = 0;
static int orc_num_ch = MAX_SUPPORTED_ADAPTERS; /* Maximum 4 adapters */
/* ---- INTERNAL VARIABLES ---- */ /* ---- INTERNAL VARIABLES ---- */
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
static char *setup_str = (char *) NULL; static char *setup_str = (char *) NULL;
static struct inia100_Adpt_Struc *inia100_adpt;
static void inia100_intr0(int irq, void *dev_id, struct pt_regs *); static void inia100_intr(int, void *, struct pt_regs *);
static void inia100_intr1(int irq, void *dev_id, struct pt_regs *);
static void inia100_intr2(int irq, void *dev_id, struct pt_regs *);
static void inia100_intr3(int irq, void *dev_id, struct pt_regs *);
static void inia100_intr4(int irq, void *dev_id, struct pt_regs *);
static void inia100_intr5(int irq, void *dev_id, struct pt_regs *);
static void inia100_intr6(int irq, void *dev_id, struct pt_regs *);
static void inia100_intr7(int irq, void *dev_id, struct pt_regs *);
static void inia100_panic(char *msg); static void inia100_panic(char *msg);
void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
/* ---- EXTERNAL VARIABLES ---- */ /* ---- EXTERNAL FUNCTIONS ---- */
extern int Addinia100_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE); extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
extern void init_inia100Adapter_table(void); extern int Addinia100_into_Adapter_table(WORD, WORD, struct pci_dev *, int);
extern int init_inia100Adapter_table(int);
extern ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp); extern ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
extern void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp); extern void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp); extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
extern void orc_release_dma(ORC_HCS * hcsp, ORC_SCB * scbp);
extern void orc_interrupt(ORC_HCS * hcsp); extern void orc_interrupt(ORC_HCS * hcsp);
extern int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags); extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags);
extern int orc_reset_scsi_bus(ORC_HCS * pHCB); extern int orc_reset_scsi_bus(ORC_HCS * pHCB);
extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb); extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb);
extern int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt); extern int orc_abort_srb(ORC_HCS * hcsp, Scsi_Cmnd *SCpnt);
extern void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx); extern void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx);
extern int init_orchid(ORC_HCS * hcsp); extern int init_orchid(ORC_HCS * hcsp);
extern int orc_num_scb;
extern ORC_HCS orc_hcs[];
/***************************************************************************** /*****************************************************************************
Function name : inia100AppendSRBToQueue Function name : inia100AppendSRBToQueue
Description : This function will push current request into save list Description : This function will push current request into save list
...@@ -209,94 +202,90 @@ void inia100_setup(char *str, int *ints) ...@@ -209,94 +202,90 @@ void inia100_setup(char *str, int *ints)
*****************************************************************************/ *****************************************************************************/
int orc_ReturnNumberOfAdapters(void) int orc_ReturnNumberOfAdapters(void)
{ {
unsigned int i, iAdapters; unsigned int iAdapters;
iAdapters = 0; iAdapters = 0;
/* /*
* PCI-bus probe. * PCI-bus probe.
*/ */
if (pcibios_present()) { if (pcibios_present()) {
struct { /*
unsigned short vendor_id; * Note: I removed the struct pci_device_list stuff since this
unsigned short device_id; * driver only cares about one device ID. If that changes in
} const inia100_pci_devices[] = * the future it can be added in with only a very moderate
{ * amount of work. It made the double scan of the device list
{ORC_VENDOR_ID, I920_DEVICE_ID}, * for getting a count and allocating the device list easier
{ORC_VENDOR_ID, ORC_DEVICE_ID} * to not have the for(i ... ) loop in there....
}; */
unsigned int dRegValue; unsigned int dRegValue;
WORD wBIOS, wBASE; WORD wBIOS, wBASE;
BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum;
#ifdef MMAPIO #ifdef MMAPIO
unsigned long page_offset, base; unsigned long page_offset, base;
#endif #endif
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
bPCIBusNum = 0; /*
bPCIDeviceNum = 0; * Get a count of adapters that we expect to be able to use.
init_inia100Adapter_table(); * Pass that count to init_inia100Adapter_table() for malloc
for (i = 0; i < NUMBER(inia100_pci_devices); i++) { * reasons.
pdev = NULL; */
while ((pdev = pci_find_device(inia100_pci_devices[i].vendor_id, pdev = NULL;
inia100_pci_devices[i].device_id, while((pdev=pci_find_device(ORC_VENDOR_ID, ORC_DEVICE_ID, pdev)))
pdev))) {
{ if (pci_enable_device(pdev))
if (pci_enable_device(pdev)) continue;
continue; if (pci_set_dma_mask(pdev, (u64)0xffffffff)) {
if (iAdapters >= MAX_SUPPORTED_ADAPTERS) printk(KERN_WARNING "Unable to set 32bit DMA "
break; /* Never greater than maximum */ "on inia100 adapter, ignoring.\n");
continue;
if (i == 0) { }
/* iAdapters++;
printk("inia100: The RAID controller is not supported by\n"); }
printk("inia100: this driver, we are ignoring it.\n"); if(init_inia100Adapter_table(iAdapters))
*/ return 0;
} else { /*
/* * Now go through the adapters again actually setting them up
* Read sundry information from PCI BIOS. * and putting them in the table this time.
*/ */
bPCIBusNum = pdev->bus->number; pdev = NULL;
bPCIDeviceNum = pdev->devfn; while((pdev=pci_find_device(ORC_VENDOR_ID, ORC_DEVICE_ID, pdev)))
dRegValue = pci_resource_start(pdev, 0); {
if (dRegValue == -1) { /* Check return code */ /*
printk("\n\rinia100: orchid read configuration error.\n"); * Read sundry information from PCI BIOS.
return (0); /* Read configuration space error */ */
} dRegValue = pci_resource_start(pdev, 0);
if (dRegValue == -1) { /* Check return code */
/* <02> read from base address + 0x50 offset to get the wBIOS balue. */ printk("\n\rinia100: orchid read configuration error.\n");
wBASE = (WORD) dRegValue; iAdapters--;
continue; /* Read configuration space error */
/* Now read the interrupt line value */ }
dRegValue = pdev->irq;
bInterrupt = dRegValue; /* Assign interrupt line */ /* <02> read from base address + 0x50 offset to get the wBIOS balue. */
wBASE = (WORD) dRegValue;
wBIOS = ORC_RDWORD(wBASE, 0x50);
/* Now read the interrupt line value */
pci_set_master(pdev); dRegValue = pdev->irq;
wBIOS = ORC_RDWORD(wBASE, 0x50);
pci_set_master(pdev);
#ifdef MMAPIO #ifdef MMAPIO
base = wBASE & PAGE_MASK; base = wBASE & PAGE_MASK;
page_offset = wBASE - base; page_offset = wBASE - base;
/* /*
* replace the next line with this one if you are using 2.1.x: * replace the next line with this one if you are using 2.1.x:
* temp_p->maddr = ioremap(base, page_offset + 256); * temp_p->maddr = ioremap(base, page_offset + 256);
*/ */
wBASE = ioremap(base, page_offset + 256); wBASE = ioremap(base, page_offset + 256);
if (wBASE) { if (wBASE) {
wBASE += page_offset; wBASE += page_offset;
} }
#endif #endif
if (Addinia100_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, Addinia100_into_Adapter_table(wBIOS, wBASE, pdev, iAdapters);
bPCIDeviceNum) == SUCCESSFUL) } /* while(pdev=....) */
iAdapters++;
}
} /* while(pdev=....) */
} /* for PCI_DEVICES */
} /* PCI BIOS present */ } /* PCI BIOS present */
return (iAdapters); return (iAdapters);
} }
...@@ -317,8 +306,9 @@ int inia100_detect(Scsi_Host_Template * tpnt) ...@@ -317,8 +306,9 @@ int inia100_detect(Scsi_Host_Template * tpnt)
int ok = 0, iAdapters; int ok = 0, iAdapters;
ULONG dBiosAdr; ULONG dBiosAdr;
BYTE *pbBiosAdr; BYTE *pbBiosAdr;
struct pci_dev *pdev;
tpnt->proc_name = "INIA100"; tpnt->proc_name = "inia100";
if (setup_called) { if (setup_called) {
/* Setup by inia100_setup */ /* Setup by inia100_setup */
printk("inia100: processing commandline: "); printk("inia100: processing commandline: ");
...@@ -330,44 +320,38 @@ int inia100_detect(Scsi_Host_Template * tpnt) ...@@ -330,44 +320,38 @@ int inia100_detect(Scsi_Host_Template * tpnt)
if (iAdapters == 0) /* If no orc founded, return */ if (iAdapters == 0) /* If no orc founded, return */
return (0); return (0);
orc_num_ch = (iAdapters > orc_num_ch) ? orc_num_ch : iAdapters;
orc_num_scb = ORC_MAXQUEUE;
/* clear the memory needed for HCS */
i = orc_num_ch * sizeof(ORC_HCS);
memset((unsigned char *) &orc_hcs[0], 0, i); /* Initialize orc_hcs 0 */
#if 0 #if 0
printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n", printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n",
orc_num_scb, orc_num_ch, sizeof(ORC_HCS), sizeof(ORC_SCB), sizeof(ESCB)); orc_num_scb, orc_num_ch, sizeof(ORC_HCS), sizeof(ORC_SCB), sizeof(ESCB));
#endif #endif
for (i = 0, pHCB = &orc_hcs[0]; /* Get pointer for control block */ for (i = 0; i < iAdapters; i++) {
i < orc_num_ch; pdev = inia100_adpt[i].ADPT_pdev;
i++, pHCB++) { hreg = scsi_register(tpnt, sizeof(ORC_HCS));
if (hreg == NULL) {
pHCB->pSRB_head = NULL; /* Initial SRB save queue */ goto out_disable;
pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ }
pHCB = (ORC_HCS *)hreg->hostdata;
pHCB->pdev = pdev;
pHCB->pSRB_head = NULL; /* Initial SRB save queue */
pHCB->pSRB_tail = NULL; /* Initial SRB save queue */
pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */
pHCB->BitAllocFlagLock = SPIN_LOCK_UNLOCKED; pHCB->BitAllocFlagLock = SPIN_LOCK_UNLOCKED;
/* Get total memory needed for SCB */ /* Get total memory needed for SCB */
sz = orc_num_scb * sizeof(ORC_SCB); sz = ORC_MAXQUEUE * sizeof(ORC_SCB);
if ((pHCB->HCS_virScbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) { if ((pHCB->HCS_virScbArray = (PVOID) pci_alloc_consistent(pdev, sz, &pHCB->HCS_physScbArray)) == NULL) {
printk("inia100: SCB memory allocation error\n"); printk("inia100: SCB memory allocation error\n");
return (0); goto out_unregister;
} }
memset((unsigned char *) pHCB->HCS_virScbArray, 0, sz); memset((unsigned char *) pHCB->HCS_virScbArray, 0, sz);
pHCB->HCS_physScbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virScbArray);
/* Get total memory needed for ESCB */ /* Get total memory needed for ESCB */
sz = orc_num_scb * sizeof(ESCB); sz = ORC_MAXQUEUE * sizeof(ESCB);
if ((pHCB->HCS_virEscbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) { if ((pHCB->HCS_virEscbArray = (PVOID) pci_alloc_consistent(pdev, sz, &pHCB->HCS_physEscbArray)) == NULL) {
printk("inia100: ESCB memory allocation error\n"); printk("inia100: ESCB memory allocation error\n");
/* ?? does pHCB->HCS_virtScbArray leak ??*/ goto out_unalloc;
return (0);
} }
memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz); memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz);
pHCB->HCS_physEscbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virEscbArray);
get_orcPCIConfig(pHCB, i); get_orcPCIConfig(pHCB, i);
...@@ -378,30 +362,24 @@ int inia100_detect(Scsi_Host_Template * tpnt) ...@@ -378,30 +362,24 @@ int inia100_detect(Scsi_Host_Template * tpnt)
if (init_orchid(pHCB)) { /* Initial orchid chip */ if (init_orchid(pHCB)) { /* Initial orchid chip */
printk("inia100: initial orchid fail!!\n"); printk("inia100: initial orchid fail!!\n");
return (0); goto out_unalloc;
} }
request_region(pHCB->HCS_Base, 256, "inia100"); /* Register */ request_region(pHCB->HCS_Base, 256, "inia100"); /* Register */
hreg = scsi_register(tpnt, sizeof(ORC_HCS));
if (hreg == NULL) {
release_region(pHCB->HCS_Base, 256); /* Register */
return 0;
}
hreg->io_port = pHCB->HCS_Base; hreg->io_port = pHCB->HCS_Base;
hreg->n_io_port = 0xff; hreg->n_io_port = 0xff;
hreg->can_queue = orc_num_scb; /* 03/05/98 */ hreg->can_queue = ORC_MAXQUEUE; /* 03/05/98 */
hreg->unique_id = pHCB->HCS_Base; hreg->unique_id = pHCB->HCS_Base;
hreg->max_id = pHCB->HCS_MaxTar; hreg->max_id = pHCB->HCS_MaxTar;
hreg->max_lun = 32; /* 10/21/97 */ hreg->max_lun = 16; /* 10/21/97 */
/* /*
hreg->max_lun = 8; hreg->max_lun = 8;
hreg->max_channel = 1; hreg->max_channel = 1;
*/ */
hreg->irq = pHCB->HCS_Intr; hreg->irq = pHCB->HCS_Intr;
hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */
hreg->base = (unsigned long)pHCB;
#if 1 #if 1
hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */ hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */
...@@ -410,36 +388,7 @@ int inia100_detect(Scsi_Host_Template * tpnt) ...@@ -410,36 +388,7 @@ int inia100_detect(Scsi_Host_Template * tpnt)
#endif #endif
/* Initial orc chip */ /* Initial orc chip */
switch (i) { ok = request_irq(pHCB->HCS_Intr, inia100_intr, SA_SHIRQ, "inia100", hreg);
case 0:
ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 1:
ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 2:
ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 3:
ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 4:
ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 5:
ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 6:
ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
case 7:
ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg);
break;
default:
inia100_panic("inia100: Too many host adapters\n");
break;
}
if (ok < 0) { if (ok < 0) {
if (ok == -EINVAL) { if (ok == -EINVAL) {
printk("inia100: bad IRQ %d.\n", pHCB->HCS_Intr); printk("inia100: bad IRQ %d.\n", pHCB->HCS_Intr);
...@@ -453,13 +402,34 @@ int inia100_detect(Scsi_Host_Template * tpnt) ...@@ -453,13 +402,34 @@ int inia100_detect(Scsi_Host_Template * tpnt)
printk(" Contact author.\n"); printk(" Contact author.\n");
} }
} }
inia100_panic("inia100: driver needs an IRQ.\n"); goto out_irq;
} }
} }
tpnt->this_id = -1; tpnt->this_id = -1;
tpnt->can_queue = 1; tpnt->can_queue = 1;
kfree(inia100_adpt);
return 1; return 1;
out_irq:
release_region(pHCB->HCS_Base, 256);
out_unalloc:
if(pHCB->HCS_virEscbArray) {
pci_free_consistent(pHCB->pdev, ORC_MAXQUEUE * sizeof(ESCB),
pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
pHCB->HCS_virEscbArray = NULL;
}
if(pHCB->HCS_virScbArray) {
pci_free_consistent(pHCB->pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
pHCB->HCS_virScbArray = NULL;
}
out_unregister:
scsi_unregister(hreg);
out_disable:
pci_disable_device(pdev);
kfree(inia100_adpt);
return i;
} }
/***************************************************************************** /*****************************************************************************
...@@ -473,7 +443,7 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt) ...@@ -473,7 +443,7 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt)
{ /* Create corresponding SCB */ { /* Create corresponding SCB */
struct scatterlist *pSrbSG; struct scatterlist *pSrbSG;
ORC_SG *pSG; /* Pointer to SG list */ ORC_SG *pSG; /* Pointer to SG list */
int i; int i, count_sg;
U32 TotalLen; U32 TotalLen;
ESCB *pEScb; ESCB *pEScb;
...@@ -493,16 +463,21 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt) ...@@ -493,16 +463,21 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt)
pSG = (ORC_SG *) & pEScb->ESCB_SGList[0]; pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
if (SCpnt->use_sg) { if (SCpnt->use_sg) {
TotalLen = 0; TotalLen = 0;
pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8);
pSrbSG = (struct scatterlist *) SCpnt->request_buffer; pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) { count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg,
pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address)); scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
pSG->SG_Len = (U32) pSrbSG->length; pSCB->SCB_SGLen = (U32) (count_sg * 8);
TotalLen += (U32) pSrbSG->length; for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) {
pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG);
pSG->SG_Len = (U32) sg_dma_len(pSrbSG);
TotalLen += (U32) sg_dma_len(pSrbSG);
} }
} else { /* Non SG */ } else { /* Non SG */
pSCB->SCB_SGLen = 0x8; pSCB->SCB_SGLen = 0x8;
pSG->SG_Ptr = (U32) (VIRT_TO_BUS(SCpnt->request_buffer)); pSG->SG_Ptr = (U32) pci_map_single(pHCB->pdev,
SCpnt->request_buffer, SCpnt->request_bufflen,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
SCpnt->host_scribble = (void *)pSG->SG_Ptr;
pSG->SG_Len = (U32) SCpnt->request_bufflen; pSG->SG_Len = (U32) SCpnt->request_bufflen;
} }
} }
...@@ -538,12 +513,7 @@ int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -538,12 +513,7 @@ int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
register ORC_SCB *pSCB; register ORC_SCB *pSCB;
ORC_HCS *pHCB; /* Point to Host adapter control block */ ORC_HCS *pHCB; /* Point to Host adapter control block */
if (SCpnt->lun > 16) { pHCB = (ORC_HCS *) SCpnt->host->hostdata;
SCpnt->result = (DID_TIME_OUT << 16);
done(SCpnt); /* Notify system DONE */
return (0);
}
pHCB = (ORC_HCS *) SCpnt->host->base;
SCpnt->scsi_done = done; SCpnt->scsi_done = done;
/* Get free SCSI control block */ /* Get free SCSI control block */
if ((pSCB = orc_alloc_scb(pHCB)) == NULL) { if ((pSCB = orc_alloc_scb(pHCB)) == NULL) {
...@@ -557,19 +527,6 @@ int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -557,19 +527,6 @@ int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return (0); return (0);
} }
/*****************************************************************************
Function name : inia100_command
Description : We only support command in interrupt-driven fashion
Input : pHCB - Pointer to host adapter structure
Output : None.
Return : pSRB - Pointer to SCSI request block.
*****************************************************************************/
int inia100_command(Scsi_Cmnd * SCpnt)
{
printk("inia100: interrupt driven driver; use inia100_queue()\n");
return -1;
}
/***************************************************************************** /*****************************************************************************
Function name : inia100_abort Function name : inia100_abort
Description : Abort a queued command. Description : Abort a queued command.
...@@ -582,8 +539,8 @@ int inia100_abort(Scsi_Cmnd * SCpnt) ...@@ -582,8 +539,8 @@ int inia100_abort(Scsi_Cmnd * SCpnt)
{ {
ORC_HCS *hcsp; ORC_HCS *hcsp;
hcsp = (ORC_HCS *) SCpnt->host->base; hcsp = (ORC_HCS *) SCpnt->host->hostdata;
return orc_abort_srb(hcsp, (ULONG) SCpnt); return orc_abort_srb(hcsp, SCpnt);
} }
/***************************************************************************** /*****************************************************************************
...@@ -597,12 +554,12 @@ int inia100_abort(Scsi_Cmnd * SCpnt) ...@@ -597,12 +554,12 @@ int inia100_abort(Scsi_Cmnd * SCpnt)
int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
{ /* I need Host Control Block Information */ { /* I need Host Control Block Information */
ORC_HCS *pHCB; ORC_HCS *pHCB;
pHCB = (ORC_HCS *) SCpnt->host->base; pHCB = (ORC_HCS *) SCpnt->host->hostdata;
if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
return orc_reset_scsi_bus(pHCB); return orc_reset_scsi_bus(pHCB);
else else
return orc_device_reset(pHCB, (ULONG) SCpnt, SCpnt->target, reset_flags); return orc_device_reset(pHCB, SCpnt, SCpnt->target, reset_flags);
} }
...@@ -627,6 +584,7 @@ void inia100SCBPost(BYTE * pHcb, BYTE * pScb) ...@@ -627,6 +584,7 @@ void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
pEScb = pSCB->SCB_EScb; pEScb = pSCB->SCB_EScb;
if ((pSRB = (Scsi_Cmnd *) pEScb->SCB_Srb) == 0) { if ((pSRB = (Scsi_Cmnd *) pEScb->SCB_Srb) == 0) {
printk("inia100SCBPost: SRB pointer is empty\n"); printk("inia100SCBPost: SRB pointer is empty\n");
orc_release_dma(pHCB, pSCB);
orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */ orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */
return; return;
} }
...@@ -676,10 +634,14 @@ void inia100SCBPost(BYTE * pHcb, BYTE * pScb) ...@@ -676,10 +634,14 @@ void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
/* Find the next pending SRB */ /* Find the next pending SRB */
if ((pSRB = inia100PopSRBFromQueue(pHCB)) != NULL) { /* Assume resend will success */ if ((pSRB = inia100PopSRBFromQueue(pHCB)) != NULL) { /* Assume resend will success */
/* Reuse old SCB */ /*
* We must free the pci DMA mappings before reusing the scb
*/
orc_release_dma(pHCB, pSCB);
inia100BuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */ inia100BuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */
orc_exec_scb(pHCB, pSCB); /* Start execute SCB */ orc_exec_scb(pHCB, pSCB); /* Start execute SCB */
} else { /* No Pending SRB */ } else {
orc_release_dma(pHCB, pSCB);
orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */ orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */
} }
return; return;
...@@ -697,7 +659,7 @@ int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) ...@@ -697,7 +659,7 @@ int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
ORC_HCS *pHcb; /* Point to Host adapter control block */ ORC_HCS *pHcb; /* Point to Host adapter control block */
ORC_TCS *pTcb; ORC_TCS *pTcb;
pHcb = (ORC_HCS *) disk->device->host->base; pHcb = (ORC_HCS *) disk->device->host->hostdata;
pTcb = &pHcb->HCS_Tcs[disk->device->id]; pTcb = &pHcb->HCS_Tcs[disk->device->id];
if (pTcb->TCS_DrvHead) { if (pTcb->TCS_DrvHead) {
...@@ -719,62 +681,19 @@ int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) ...@@ -719,62 +681,19 @@ int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
} }
static void subIntr(ORC_HCS * pHCB, int irqno, struct Scsi_Host *dev)
{
unsigned long flags;
spin_lock_irqsave(dev->host_lock, flags);
if (pHCB->HCS_Intr != irqno) {
spin_unlock_irqrestore(dev->host_lock, flags);
return;
}
orc_interrupt(pHCB);
spin_unlock_irqrestore(dev->host_lock, flags);
}
/* /*
* Interrupts handler (main routine of the driver) * Interrupt handler (main routine of the driver)
*/ */
static void inia100_intr0(int irqno, void *dev_id, struct pt_regs *regs) static void inia100_intr(int irqno, void *devid, struct pt_regs *regs)
{ {
subIntr(&orc_hcs[0], irqno, dev_id); struct Scsi_Host *host = (struct Scsi_Host *)devid;
} ORC_HCS *pHcb;
unsigned long flags;
static void inia100_intr1(int irqno, void *dev_id, struct pt_regs *regs)
{
subIntr(&orc_hcs[1], irqno, dev_id);
}
static void inia100_intr2(int irqno, void *dev_id, struct pt_regs *regs)
{
subIntr(&orc_hcs[2], irqno, dev_id);
}
static void inia100_intr3(int irqno, void *dev_id, struct pt_regs *regs)
{
subIntr(&orc_hcs[3], irqno, dev_id);
}
static void inia100_intr4(int irqno, void *dev_id, struct pt_regs *regs)
{
subIntr(&orc_hcs[4], irqno, dev_id);
}
static void inia100_intr5(int irqno, void *dev_id, struct pt_regs *regs)
{
subIntr(&orc_hcs[5], irqno, dev_id);
}
static void inia100_intr6(int irqno, void *dev_id, struct pt_regs *regs) pHcb = (ORC_HCS *)host->hostdata; /* Host adapter control block */
{ spin_lock_irqsave(host->host_lock, flags);
subIntr(&orc_hcs[6], irqno, dev_id); orc_interrupt(pHcb);
} spin_unlock_irqrestore(host->host_lock, flags);
static void inia100_intr7(int irqno, void *dev_id, struct pt_regs *regs)
{
subIntr(&orc_hcs[7], irqno, dev_id);
} }
/* /*
...@@ -791,8 +710,21 @@ static void inia100_panic(char *msg) ...@@ -791,8 +710,21 @@ static void inia100_panic(char *msg)
*/ */
int inia100_release(struct Scsi_Host *hreg) int inia100_release(struct Scsi_Host *hreg)
{ {
ORC_HCS *pHCB = (ORC_HCS *)hreg->hostdata;
free_irq(hreg->irq, hreg); free_irq(hreg->irq, hreg);
release_region(hreg->io_port, 256); release_region(hreg->io_port, 256);
if(pHCB->HCS_virEscbArray) {
pci_free_consistent(pHCB->pdev, ORC_MAXQUEUE * sizeof(ESCB),
pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
pHCB->HCS_virEscbArray = NULL;
}
if(pHCB->HCS_virScbArray) {
pci_free_consistent(pHCB->pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
pHCB->HCS_virScbArray = NULL;
}
pci_disable_device(pHCB->pdev);
return 0; return 0;
} }
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
* Revision History: * Revision History:
* 06/18/98 HL, Initial production Version 1.02 * 06/18/98 HL, Initial production Version 1.02
* 12/19/98 bv, Use spinlocks for 2.1.95 and up * 12/19/98 bv, Use spinlocks for 2.1.95 and up
* 06/25/02 Doug Ledford <dledford@redhat.com>
* - This and the i60uscsi.h file are almost identical,
* merged them into a single header used by both .c files.
****************************************************************************/ ****************************************************************************/
#ifndef CVT_LINUX_VERSION #ifndef CVT_LINUX_VERSION
...@@ -68,13 +71,14 @@ ...@@ -68,13 +71,14 @@
#include <linux/version.h> #include <linux/version.h>
#endif #endif
#include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h>
#include "sd.h" #include "sd.h"
extern int inia100_detect(Scsi_Host_Template *); extern int inia100_detect(Scsi_Host_Template *);
extern int inia100_release(struct Scsi_Host *); extern int inia100_release(struct Scsi_Host *);
extern int inia100_command(Scsi_Cmnd *);
extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
extern int inia100_abort(Scsi_Cmnd *); extern int inia100_abort(Scsi_Cmnd *);
extern int inia100_reset(Scsi_Cmnd *, unsigned int); extern int inia100_reset(Scsi_Cmnd *, unsigned int);
...@@ -86,13 +90,13 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ ...@@ -86,13 +90,13 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
#define INIA100 { \ #define INIA100 { \
next: NULL, \ next: NULL, \
module: NULL, \ module: NULL, \
proc_name: "INIA100", \ proc_name: "inia100", \
proc_info: NULL, \ proc_info: NULL, \
name: inia100_REVID, \ name: inia100_REVID, \
detect: inia100_detect, \ detect: inia100_detect, \
release: inia100_release, \ release: inia100_release, \
info: NULL, \ info: NULL, \
command: inia100_command, \ command: NULL, \
queuecommand: inia100_queue, \ queuecommand: inia100_queue, \
eh_strategy_handler: NULL, \ eh_strategy_handler: NULL, \
eh_abort_handler: NULL, \ eh_abort_handler: NULL, \
...@@ -112,7 +116,6 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ ...@@ -112,7 +116,6 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
use_clustering: ENABLE_CLUSTERING, \ use_clustering: ENABLE_CLUSTERING, \
} }
#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
#define ULONG unsigned long #define ULONG unsigned long
#define PVOID void * #define PVOID void *
#define USHORT unsigned short #define USHORT unsigned short
...@@ -139,15 +142,16 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ ...@@ -139,15 +142,16 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
#endif #endif
#if 1 #if 1
#define ORC_MAXQUEUE 245 #define ORC_MAXQUEUE 245
#define ORC_MAXTAGS 64
#else #else
#define ORC_MAXQUEUE 25 #define ORC_MAXQUEUE 25
#define ORC_MAXTAGS 8
#endif #endif
#define TOTAL_SG_ENTRY 32 #define TOTAL_SG_ENTRY 32
#define MAX_TARGETS 16 #define MAX_TARGETS 16
#define IMAX_CDB 15 #define IMAX_CDB 15
#define SENSE_SIZE 14 #define SENSE_SIZE 14
#define MAX_SUPPORTED_ADAPTERS 4
#define SUCCESSFUL 0x00 #define SUCCESSFUL 0x00
#define I920_DEVICE_ID 0x0002 /* Initio's inic-950 product ID */ #define I920_DEVICE_ID 0x0002 /* Initio's inic-950 product ID */
...@@ -160,6 +164,12 @@ typedef struct ORC_SG_Struc { ...@@ -160,6 +164,12 @@ typedef struct ORC_SG_Struc {
U32 SG_Len; /* Data Length */ U32 SG_Len; /* Data Length */
} ORC_SG; } ORC_SG;
typedef struct inia100_Adpt_Struc {
UWORD ADPT_BIOS; /* 0 */
UWORD ADPT_BASE; /* 1 */
struct pci_dev *ADPT_pdev; /* 2 */
} INIA100_ADPT_STRUCT;
/* SCSI related definition */ /* SCSI related definition */
#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ #define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */
...@@ -374,9 +384,9 @@ typedef struct ORC_Ha_Ctrl_Struc { ...@@ -374,9 +384,9 @@ typedef struct ORC_Ha_Ctrl_Struc {
USHORT HCS_AFlags; /* Adapter info. defined flags */ USHORT HCS_AFlags; /* Adapter info. defined flags */
ULONG HCS_Timeout; /* Adapter timeout value */ ULONG HCS_Timeout; /* Adapter timeout value */
PVOID HCS_virScbArray; /* 28 Virtual Pointer to SCB array */ PVOID HCS_virScbArray; /* 28 Virtual Pointer to SCB array */
U32 HCS_physScbArray; /* Scb Physical address */ dma_addr_t HCS_physScbArray; /* Scb Physical address */
PVOID HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */ PVOID HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */
U32 HCS_physEscbArray; /* scatter list Physical address */ dma_addr_t HCS_physEscbArray; /* scatter list Physical address */
UBYTE TargetFlag[16]; /* 30 target configuration, TCF_EN_TAG */ UBYTE TargetFlag[16]; /* 30 target configuration, TCF_EN_TAG */
UBYTE MaximumTags[16]; /* 40 ORC_MAX_SCBS */ UBYTE MaximumTags[16]; /* 40 ORC_MAX_SCBS */
UBYTE ActiveTags[16][16]; /* 50 */ UBYTE ActiveTags[16][16]; /* 50 */
...@@ -386,6 +396,7 @@ typedef struct ORC_Ha_Ctrl_Struc { ...@@ -386,6 +396,7 @@ typedef struct ORC_Ha_Ctrl_Struc {
Scsi_Cmnd *pSRB_head; Scsi_Cmnd *pSRB_head;
Scsi_Cmnd *pSRB_tail; Scsi_Cmnd *pSRB_tail;
spinlock_t pSRB_lock; spinlock_t pSRB_lock;
struct pci_dev *pdev;
} ORC_HCS; } ORC_HCS;
/* Bit Definition for HCS_Flags */ /* Bit Definition for HCS_Flags */
...@@ -438,3 +449,148 @@ typedef struct ORC_Ha_Ctrl_Struc { ...@@ -438,3 +449,148 @@ typedef struct ORC_Ha_Ctrl_Struc {
/*----------------------------------------------*/ /*----------------------------------------------*/
#define MAX_PCI_DEVICES 21 #define MAX_PCI_DEVICES 21
#define MAX_PCI_BUSES 8 #define MAX_PCI_BUSES 8
typedef struct Adpt_Struc {
USHORT ADPT_BIOS; /* 0 */
UBYTE ADPT_BASE; /* 1 */
UBYTE ADPT_Bus; /* 2 */
UBYTE ADPT_Device; /* 3 */
UBYTE ADPT_Reserved[3];
} JACS, *PJACS;
typedef struct _NVRAM {
/*----------header ---------------*/
UCHAR SubVendorID0; /* 00 - Sub Vendor ID */
UCHAR SubVendorID1; /* 00 - Sub Vendor ID */
UCHAR SubSysID0; /* 02 - Sub System ID */
UCHAR SubSysID1; /* 02 - Sub System ID */
UCHAR SubClass; /* 04 - Sub Class */
UCHAR VendorID0; /* 05 - Vendor ID */
UCHAR VendorID1; /* 05 - Vendor ID */
UCHAR DeviceID0; /* 07 - Device ID */
UCHAR DeviceID1; /* 07 - Device ID */
UCHAR Reserved0[2]; /* 09 - Reserved */
UCHAR Revision; /* 0B - Revision of data structure */
/* ----Host Adapter Structure ---- */
UCHAR NumOfCh; /* 0C - Number of SCSI channel */
UCHAR BIOSConfig1; /* 0D - BIOS configuration 1 */
UCHAR BIOSConfig2; /* 0E - BIOS boot channel&target ID */
UCHAR BIOSConfig3; /* 0F - BIOS configuration 3 */
/* ----SCSI channel Structure ---- */
/* from "CTRL-I SCSI Host Adapter SetUp menu " */
UCHAR SCSI0Id; /* 10 - Channel 0 SCSI ID */
UCHAR SCSI0Config; /* 11 - Channel 0 SCSI configuration */
UCHAR SCSI0MaxTags; /* 12 - Channel 0 Maximum tags */
UCHAR SCSI0ResetTime; /* 13 - Channel 0 Reset recovering time */
UCHAR ReservedforChannel0[2]; /* 14 - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR Target00Config; /* 16 - Channel 0 Target 0 config */
UCHAR Target01Config; /* 17 - Channel 0 Target 1 config */
UCHAR Target02Config; /* 18 - Channel 0 Target 2 config */
UCHAR Target03Config; /* 19 - Channel 0 Target 3 config */
UCHAR Target04Config; /* 1A - Channel 0 Target 4 config */
UCHAR Target05Config; /* 1B - Channel 0 Target 5 config */
UCHAR Target06Config; /* 1C - Channel 0 Target 6 config */
UCHAR Target07Config; /* 1D - Channel 0 Target 7 config */
UCHAR Target08Config; /* 1E - Channel 0 Target 8 config */
UCHAR Target09Config; /* 1F - Channel 0 Target 9 config */
UCHAR Target0AConfig; /* 20 - Channel 0 Target A config */
UCHAR Target0BConfig; /* 21 - Channel 0 Target B config */
UCHAR Target0CConfig; /* 22 - Channel 0 Target C config */
UCHAR Target0DConfig; /* 23 - Channel 0 Target D config */
UCHAR Target0EConfig; /* 24 - Channel 0 Target E config */
UCHAR Target0FConfig; /* 25 - Channel 0 Target F config */
UCHAR SCSI1Id; /* 26 - Channel 1 SCSI ID */
UCHAR SCSI1Config; /* 27 - Channel 1 SCSI configuration */
UCHAR SCSI1MaxTags; /* 28 - Channel 1 Maximum tags */
UCHAR SCSI1ResetTime; /* 29 - Channel 1 Reset recovering time */
UCHAR ReservedforChannel1[2]; /* 2A - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR Target10Config; /* 2C - Channel 1 Target 0 config */
UCHAR Target11Config; /* 2D - Channel 1 Target 1 config */
UCHAR Target12Config; /* 2E - Channel 1 Target 2 config */
UCHAR Target13Config; /* 2F - Channel 1 Target 3 config */
UCHAR Target14Config; /* 30 - Channel 1 Target 4 config */
UCHAR Target15Config; /* 31 - Channel 1 Target 5 config */
UCHAR Target16Config; /* 32 - Channel 1 Target 6 config */
UCHAR Target17Config; /* 33 - Channel 1 Target 7 config */
UCHAR Target18Config; /* 34 - Channel 1 Target 8 config */
UCHAR Target19Config; /* 35 - Channel 1 Target 9 config */
UCHAR Target1AConfig; /* 36 - Channel 1 Target A config */
UCHAR Target1BConfig; /* 37 - Channel 1 Target B config */
UCHAR Target1CConfig; /* 38 - Channel 1 Target C config */
UCHAR Target1DConfig; /* 39 - Channel 1 Target D config */
UCHAR Target1EConfig; /* 3A - Channel 1 Target E config */
UCHAR Target1FConfig; /* 3B - Channel 1 Target F config */
UCHAR reserved[3]; /* 3C - Reserved */
/* ---------- CheckSum ---------- */
UCHAR CheckSum; /* 3F - Checksum of NVRam */
} NVRAM, *PNVRAM;
/* Bios Configuration for nvram->BIOSConfig1 */
#define NBC_BIOSENABLE 0x01 /* BIOS enable */
#define NBC_CDROM 0x02 /* Support bootable CDROM */
#define NBC_REMOVABLE 0x04 /* Support removable drive */
/* Bios Configuration for nvram->BIOSConfig2 */
#define NBB_TARGET_MASK 0x0F /* Boot SCSI target ID number */
#define NBB_CHANL_MASK 0xF0 /* Boot SCSI channel number */
/* Bit definition for nvram->SCSIConfig */
#define NCC_BUSRESET 0x01 /* Reset SCSI bus at power up */
#define NCC_PARITYCHK 0x02 /* SCSI parity enable */
#define NCC_LVDS 0x10 /* Enable LVDS */
#define NCC_ACTTERM1 0x20 /* Enable active terminator 1 */
#define NCC_ACTTERM2 0x40 /* Enable active terminator 2 */
#define NCC_AUTOTERM 0x80 /* Enable auto termination */
/* Bit definition for nvram->TargetxConfig */
#define NTC_PERIOD 0x07 /* Maximum Sync. Speed */
#define NTC_1GIGA 0x08 /* 255 head / 63 sectors (64/32) */
#define NTC_NO_SYNC 0x10 /* NO SYNC. NEGO */
#define NTC_NO_WIDESYNC 0x20 /* NO WIDE SYNC. NEGO */
#define NTC_DISC_ENABLE 0x40 /* Enable SCSI disconnect */
#define NTC_SPINUP 0x80 /* Start disk drive */
/* Default NVRam values */
#define NBC_DEFAULT (NBC_ENABLE)
#define NCC_DEFAULT (NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK)
#define NCC_MAX_TAGS 0x20 /* Maximum tags per target */
#define NCC_RESET_TIME 0x0A /* SCSI RESET recovering time */
#define NTC_DEFAULT (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
typedef union { /* Union define for mechanism 1 */
struct {
unsigned char RegNum;
unsigned char FcnNum:3;
unsigned char DeviceNum:5;
unsigned char BusNum;
unsigned char Reserved:7;
unsigned char Enable:1;
} sConfigAdr;
unsigned long lConfigAdr;
} CONFIG_ADR;
typedef union { /* Union define for mechanism 2 */
struct {
unsigned char RegNum;
unsigned char DeviceNum;
unsigned short Reserved;
} sHostAdr;
unsigned long lHostAdr;
} HOST_ADR;
#define ORC_RD(x,y) (UCHAR)(inb( (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_RDLONG(x,y) (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_WR( adr,data) outb( (UCHAR)(data), (int)(adr))
#define ORC_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr))
#define ORC_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment