Commit 379e85a6 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.37pre5

parent 8aac8fa6
......@@ -2072,6 +2072,20 @@ CONFIG_SCSI_NCR53C406A
and read Documentation/modules.txt. The module will be called
NCR53c406.o.
Tekram DC390W/U/F (T) SCSI support
CONFIG_SCSI_DC390W
This driver supports the Tekram DC390W/U/F (T) PCI SCSI host adapters with
the NCR/Symbios 53c825/875 chips. If you have a DC390 (T) adaptor with the
Am53C974A chip use the DC390(T) driver.
Tekram DC390(T) (AMD PCscsi) SCSI support
CONFIG_SCSI_DC390T
This driver supports the Tekram DC390(T) PCI SCSI Hostadapter with
the Am53C974A chip, and perhaps other cards using the same chip.
This driver does _not_ support the DC390W/U/F adaptor with the
NCR/Symbios chips.
AM53/79C974 PCI SCSI support
CONFIG_SCSI_AM53C974
This is support for the AM53/79C974 SCSI host adapters. Please read
......
......@@ -336,12 +336,6 @@ L: linux-kernel@vger.rutgers.edu
W: http://www-plateau.cs.berkeley.edu/people/chaffee
S: Maintained
DIGIBOARD DRIVER:
P: Christoph Lameter
M: clameter@fuller.edu
L: digiboard@list.fuller.edu
S: Maintained
DIGI INTL. EPCA DRIVER:
P: Daniel Taylor
M: support@dgii.com
......
......@@ -42,6 +42,13 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_EM86=y
# CONFIG_PNP_PARPORT is not set
#
# Plug and Play support
#
# CONFIG_PNP is not set
#
# Floppy, IDE, and other block devices
......@@ -72,9 +79,10 @@ CONFIG_BLK_DEV_RAM=y
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
CONFIG_INET=y
# CONFIG_IP_FORWARD is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ACCT is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
#
# (it is safe to leave these untouched)
......@@ -133,7 +141,6 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
CONFIG_SCSI_QLOGIC_ISP=y
......@@ -155,19 +162,22 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_EISA=y
# CONFIG_PCNET32 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
CONFIG_DE4X5=y
# CONFIG_DEC_ELCP is not set
# CONFIG_DGRS is not set
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
# CONFIG_DLCI is not set
# CONFIG_PLIP is not set
# CONFIG_PPP is not set
# CONFIG_NET_RADIO is not set
# CONFIG_LAPBETHER is not set
# CONFIG_SLIP is not set
# CONFIG_TR is not set
# CONFIG_LAPBETHER is not set
# CONFIG_X25_ASY is not set
#
# ISDN subsystem
......@@ -192,12 +202,16 @@ CONFIG_MSDOS_FS=y
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
CONFIG_ISO9660_FS=y
# CONFIG_HPFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_UFS_FS is not set
#
......@@ -206,12 +220,8 @@ CONFIG_ISO9660_FS=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=y
# CONFIG_DIGI is not set
# CONFIG_CYCLADES is not set
# CONFIG_STALDRV is not set
# CONFIG_RISCOM8 is not set
# CONFIG_ESPSERIAL is not set
# CONFIG_PRINTER is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_MOUSE=y
# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_BUSMOUSE is not set
......@@ -224,7 +234,6 @@ CONFIG_PSMOUSE=y
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
CONFIG_RTC_ARC=y
#
# Sound
......
......@@ -64,22 +64,6 @@ rdusp:
ret ($26)
.end rdusp
.align 3
.globl tbi
.ent tbi
tbi:
call_pal PAL_tbi
ret ($26)
.end tbi
.align 3
.globl imb
.ent imb
imb:
call_pal PAL_imb
ret ($26)
.end imb
.align 3
.globl rdmces
.ent rdmces
......
......@@ -85,7 +85,7 @@ bzdisk: vmlinux
@$(MAKEBOOT) BOOTIMAGE=bzImage zdisk
install: vmlinux
@$(MAKEBOOT) install
@$(MAKEBOOT) BOOTIMAGE=zImage install
archclean:
@$(MAKEBOOT) clean
......
......@@ -653,6 +653,8 @@ extern int cpu_idle(void * unused);
__initfunc(int start_secondary(void *unused))
{
smp_callin();
while (!smp_commenced)
barrier();
cpu_idle(NULL);
}
......
......@@ -240,8 +240,24 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
unlock_kernel();
}
void enable_NMI(void)
{
unsigned char reason;
unsigned long i;
reason = inb(0x61);
printk("NMI reason = %02x\n", reason);
reason |= 8;
outb(reason, 0x61);
i = 400000000;
while (--i) ;
reason &= ~8;
outb(reason, 0x61);
}
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
{
show_registers(regs);
#ifdef CONFIG_SMP_NMI_INVAL
smp_flush_tlb_rcv();
#else
......@@ -251,6 +267,7 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
printk("power saving mode enabled.\n");
#endif
#endif
enable_NMI();
}
asmlinkage void do_debug(struct pt_regs * regs, long error_code)
......
......@@ -5285,11 +5285,11 @@ static struct file_operations sbpcd_fops =
* bytes above).
*
*/
__initfunc(
#if (SBPCD_ISSUE-1)
static
__initfunc(static void sbpcd_setup(const char *s, int *p))
#else
__initfunc(void sbpcd_setup(const char *s, int *p))
#endif
void sbpcd_setup(const char *s, int *p))
{
setup_done++;
msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -503,7 +503,7 @@ const unsigned long bt485_cursor_source[64] __initdata = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
const unsigned int bt463_cursor_source[256] = __initdata {
const unsigned int bt463_cursor_source[256] __initdata = {
0xffff0000, 0x00000000, 0x00000000, 0x00000000,
0xffff0000, 0x00000000, 0x00000000, 0x00000000,
0xffff0000, 0x00000000, 0x00000000, 0x00000000,
......
......@@ -82,10 +82,13 @@ if [ "$CONFIG_PNP_PARPORT" != "n" ]; then
fi
dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
if [ "$CONFIG_PCI" = "y"]; then
dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
fi
dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_AM53C974" != "y"]; then
dep_tristate 'Tekram DC-390(T) (AMD PCscsi) SCSI support' CONFIG_SCSI_DC390T $CONFIG_SCSI
fi
dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then
......
......@@ -185,6 +185,14 @@ else
endif
endif
ifeq ($(CONFIG_SCSI_DC390T),y)
L_OBJS += tmscsim.o
else
ifeq ($(CONFIG_SCSI_DC390T),m)
M_OBJS += tmscsim.o
endif
endif
ifeq ($(CONFIG_SCSI_AM53C974),y)
L_OBJS += AM53C974.o
else
......
/***********************************************************************
* FILE NAME : DC390.H *
* BY : C.L. Huang *
* Description: Device Driver for Tekram DC-390(T) PCI SCSI *
* Bus Master Host Adapter *
***********************************************************************/
/* Kernel version autodetection */
#include <linux/version.h>
/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,50)
#define VERSION_ELF_1_2_13
#elseif LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,95)
#define VERSION_1_3_85
#else
#define VERSION_2_0_0
#endif
/*
* AMD 53C974 driver, header file
*/
#ifndef DC390_H
#define DC390_H
#if defined(HOSTS_C) || defined(MODULE)
#ifdef VERSION_2_0_0
#include <scsi/scsicam.h>
#else
#include <linux/scsicam.h>
#endif
extern int DC390_detect(Scsi_Host_Template *psht);
extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
extern int DC390_abort(Scsi_Cmnd *cmd);
#ifdef VERSION_2_0_0
extern int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags);
#else
extern int DC390_reset(Scsi_Cmnd *cmd);
#endif
#ifdef VERSION_ELF_1_2_13
extern int DC390_bios_param(Disk *disk, int devno, int geom[]);
#else
extern int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]);
#endif
#ifdef MODULE
static int DC390_release(struct Scsi_Host *);
#else
#define DC390_release NULL
#endif
#ifndef VERSION_ELF_1_2_13
extern struct proc_dir_entry proc_scsi_tmscsim;
extern int tmscsim_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
#endif
#ifdef VERSION_2_0_0
#define DC390_T { \
NULL, /* *next */ \
NULL, /* *usage_count */ \
&proc_scsi_tmscsim, /* *proc_dir */ \
tmscsim_proc_info, /* (*proc_info)() */ \
"Tekram DC390(T) V1.10 Dec-05-1996", /* *name */ \
DC390_detect, \
DC390_release, /* (*release)() */ \
NULL, /* *(*info)() */ \
NULL, /* (*command)() */ \
DC390_queue_command, \
DC390_abort, \
DC390_reset, \
NULL, /* slave attach */\
DC390_bios_param, \
10,/* can queue(-1) */ \
7, /* id(-1) */ \
SG_ALL, \
2, /* cmd per lun(2) */ \
0, /* present */ \
0, /* unchecked isa dma */ \
DISABLE_CLUSTERING \
}
#endif
#ifdef VERSION_1_3_85
#define DC390_T { \
NULL, /* *next */ \
NULL, /* *usage_count */ \
&proc_scsi_tmscsim, /* *proc_dir */ \
tmscsim_proc_info, /* (*proc_info)() */ \
"Tekram DC390(T) V1.10 Dec-05-1996", /* *name */ \
DC390_detect, \
DC390_release, /* (*release)() */ \
NULL, /* *(*info)() */ \
NULL, /* (*command)() */ \
DC390_queue_command, \
DC390_abort, \
DC390_reset, \
NULL, /* slave attach */\
DC390_bios_param, \
10,/* can queue(-1) */ \
7, /* id(-1) */ \
SG_ALL, \
2, /* cmd per lun(2) */ \
0, /* present */ \
0, /* unchecked isa dma */ \
DISABLE_CLUSTERING \
}
#endif
#ifdef VERSION_ELF_1_2_13
#define DC390_T { \
NULL, \
NULL, \
"Tekram DC390(T) V1.10 Dec-05-1996",\
DC390_detect, \
DC390_release, \
NULL, /* info */ \
NULL, /* command, deprecated */ \
DC390_queue_command, \
DC390_abort, \
DC390_reset, \
NULL, /* slave attach */\
DC390_bios_param, \
10,/* can queue(-1) */ \
7, /* id(-1) */ \
16,/* old (SG_ALL) */ \
2, /* cmd per lun(2) */ \
0, /* present */ \
0, /* unchecked isa dma */ \
DISABLE_CLUSTERING \
}
#endif
#endif /* defined(HOSTS_C) || defined(MODULE) */
#endif /* DC390_H */
......@@ -158,6 +158,10 @@
#include "NCR53c406a.h"
#endif
#ifdef CONFIG_SCSI_DC390T
#include "dc390.h"
#endif
#ifdef CONFIG_SCSI_AM53C974
#include "AM53C974.h"
#endif
......@@ -310,6 +314,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_EATA
EATA,
#endif
#ifdef CONFIG_SCSI_DC390T
DC390_T,
#endif
#ifdef CONFIG_SCSI_AM53C974
AM53C974,
#endif
......
/***********************************************************************
* FILE NAME : SCSIIOM.C *
* BY : C.L. Huang, ching@tekram.com.tw *
* Description: Device Driver for Tekram DC-390 (T) PCI SCSI *
* Bus Master Host Adapter *
***********************************************************************/
static USHORT
DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
{
USHORT ioport, rc;
UCHAR bval, bval1, i, cnt;
PUCHAR ptr;
ULONG wlval;
pSRB->TagNumber = 31;
ioport = pACB->IOPortBase;
bval = pDCB->UnitSCSIID;
outb(bval,ioport+Scsi_Dest_ID);
bval = pDCB->SyncPeriod;
outb(bval,ioport+Sync_Period);
bval = pDCB->SyncOffset;
outb(bval,ioport+Sync_Offset);
bval = pDCB->CtrlR1;
outb(bval,ioport+CtrlReg1);
bval = pDCB->CtrlR3;
outb(bval,ioport+CtrlReg3);
bval = pDCB->CtrlR4;
outb(bval,ioport+CtrlReg4);
bval = CLEAR_FIFO_CMD; /* Flush FIFO */
outb(bval,ioport+ScsiCmd);
pSRB->ScsiPhase = SCSI_NOP0;
bval = pDCB->IdentifyMsg;
if( !(pDCB->SyncMode & EN_ATN_STOP) )
{
if( (pSRB->CmdBlock[0] == INQUIRY) ||
(pSRB->CmdBlock[0] == REQUEST_SENSE) ||
(pSRB->SRBFlag & AUTO_REQSENSE) )
{
bval &= 0xBF; /* NO disconnection */
outb(bval,ioport+ScsiFifo);
bval1 = SELECT_W_ATN;
pSRB->SRBState = SRB_START_;
if( pDCB->SyncMode & SYNC_ENABLE )
{
if( !(pDCB->IdentifyMsg & 7) ||
(pSRB->CmdBlock[0] != INQUIRY) )
{
bval1 = SEL_W_ATN_STOP;
pSRB->SRBState = SRB_MSGOUT;
}
}
}
else
{
if(pDCB->SyncMode & EN_TAG_QUEUING)
{
outb(bval,ioport+ScsiFifo);
bval = MSG_SIMPLE_QTAG;
outb(bval,ioport+ScsiFifo);
wlval = 1;
bval = 0;
while( wlval & pDCB->TagMask )
{
wlval = wlval << 1;
bval++;
}
outb(bval,ioport+ScsiFifo);
pDCB->TagMask |= wlval;
pSRB->TagNumber = bval;
bval1 = SEL_W_ATN2;
pSRB->SRBState = SRB_START_;
}
else
{
outb(bval,ioport+ScsiFifo);
bval1 = SELECT_W_ATN;
pSRB->SRBState = SRB_START_;
}
}
if( pSRB->SRBFlag & AUTO_REQSENSE )
{
bval = REQUEST_SENSE;
outb(bval,ioport+ScsiFifo);
bval = pDCB->IdentifyMsg << 5;
outb(bval,ioport+ScsiFifo);
bval = 0;
outb(bval,ioport+ScsiFifo);
outb(bval,ioport+ScsiFifo);
bval = sizeof(pSRB->pcmd->sense_buffer);
outb(bval,ioport+ScsiFifo);
bval = 0;
outb(bval,ioport+ScsiFifo);
}
else
{
cnt = pSRB->ScsiCmdLen;
ptr = (PUCHAR) pSRB->CmdBlock;
for(i=0; i<cnt; i++)
{
bval = *ptr++;
outb(bval,ioport+ScsiFifo);
}
}
}
else /* ATN_STOP */
{
if( (pSRB->CmdBlock[0] == INQUIRY) ||
(pSRB->CmdBlock[0] == REQUEST_SENSE) ||
(pSRB->SRBFlag & AUTO_REQSENSE) )
{
bval &= 0xBF;
outb(bval,ioport+ScsiFifo);
bval1 = SELECT_W_ATN;
pSRB->SRBState = SRB_START_;
if( pDCB->SyncMode & SYNC_ENABLE )
{
if( !(pDCB->IdentifyMsg & 7) ||
(pSRB->CmdBlock[0] != INQUIRY) )
{
bval1 = SEL_W_ATN_STOP;
pSRB->SRBState = SRB_MSGOUT;
}
}
}
else
{
if(pDCB->SyncMode & EN_TAG_QUEUING)
{
outb(bval,ioport+ScsiFifo);
pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;
wlval = 1;
bval = 0;
while( wlval & pDCB->TagMask )
{
wlval = wlval << 1;
bval++;
}
pDCB->TagMask |= wlval;
pSRB->TagNumber = bval;
pSRB->MsgOutBuf[1] = bval;
pSRB->MsgCnt = 2;
bval1 = SEL_W_ATN_STOP;
pSRB->SRBState = SRB_START_;
}
else
{
outb(bval,ioport+ScsiFifo);
pSRB->MsgOutBuf[0] = MSG_NOP;
pSRB->MsgCnt = 1;
pSRB->SRBState = SRB_START_;
bval1 = SEL_W_ATN_STOP;
}
}
}
bval = inb( ioport+Scsi_Status );
if( bval & INTERRUPT )
{
pSRB->SRBState = SRB_READY;
pDCB->TagMask &= ~( 1 << pSRB->TagNumber );
rc = 1;
}
else
{
pSRB->ScsiPhase = SCSI_NOP1;
pACB->pActiveDCB = pDCB;
pDCB->pActiveSRB = pSRB;
rc = 0;
outb(bval1,ioport+ScsiCmd);
}
return( rc );
}
#ifndef VERSION_ELF_1_2_13
static void
DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
#else
static void
DC390_Interrupt( int irq, struct pt_regs *regs)
#endif
{
PACB pACB;
PDCB pDCB;
PSRB pSRB;
USHORT ioport = 0;
USHORT phase, i;
void (*stateV)( PACB, PSRB, PUCHAR );
UCHAR istate = 0;
UCHAR sstatus=0, istatus;
pACB = pACB_start;
if( pACB == NULL )
return;
for( i=0; i < adapterCnt; i++ )
{
if( pACB->IRQLevel == (UCHAR) irq )
{
ioport = pACB->IOPortBase;
sstatus = inb( ioport+Scsi_Status );
if( sstatus & INTERRUPT )
break;
else
pACB = pACB->pNextACB;
}
else
{
pACB = pACB->pNextACB;
}
}
#ifdef DC390_DEBUG1
printk("sstatus=%2x,",sstatus);
#endif
if( pACB == (PACB )-1 )
{
printk("DC390: Spurious interrupt detected!\n");
return;
}
istate = inb( ioport+Intern_State );
istatus = inb( ioport+INT_Status );
#ifdef DC390_DEBUG1
printk("Istatus=%2x,",istatus);
#endif
if(istatus & DISCONNECTED)
{
DC390_Disconnect( pACB );
return;
}
if(istatus & RESELECTED)
{
DC390_Reselect( pACB );
return;
}
if(istatus & INVALID_CMD)
{
DC390_InvalidCmd( pACB );
return;
}
if(istatus & SCSI_RESET)
{
DC390_ScsiRstDetect( pACB );
return;
}
if( istatus & (SUCCESSFUL_OP+SERVICE_REQUEST) )
{
pDCB = pACB->pActiveDCB;
pSRB = pDCB->pActiveSRB;
if( pDCB )
{
if( pDCB->DCBFlag & ABORT_DEV_ )
EnableMsgOut( pACB, pSRB );
}
phase = (USHORT) pSRB->ScsiPhase;
stateV = (void *) DC390_phase0[phase];
stateV( pACB, pSRB, &sstatus );
pSRB->ScsiPhase = sstatus & 7;
phase = (USHORT) sstatus & 7;
stateV = (void *) DC390_phase1[phase];
stateV( pACB, pSRB, &sstatus );
}
}
static void
DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR sstatus, bval;
USHORT ioport;
PSGL psgl;
ULONG ResidCnt, xferCnt;
ioport = pACB->IOPortBase;
sstatus = *psstatus;
if( !(pSRB->SRBState & SRB_XFERPAD) )
{
if( sstatus & PARITY_ERR )
pSRB->SRBStatus |= PARITY_ERROR;
if( sstatus & COUNT_2_ZERO )
{
bval = inb(ioport+DMA_Status);
while( !(bval & DMA_XFER_DONE) )
bval = inb(ioport+DMA_Status);
pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
pSRB->SGIndex++;
if( pSRB->SGIndex < pSRB->SGcount )
{
pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
#ifndef VERSION_ELF_1_2_13
pSRB->SGPhysAddr = virt_to_phys( psgl->address );
#else
pSRB->SGPhysAddr = (ULONG) psgl->address;
#endif
pSRB->SGToBeXferLen = (ULONG) psgl->length;
}
else
pSRB->SGToBeXferLen = 0;
}
else
{
bval = inb( ioport+Current_Fifo );
bval &= 0x1f;
ResidCnt = (ULONG) inb(ioport+CtcReg_High);
ResidCnt = ResidCnt << 8;
ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);
ResidCnt = ResidCnt << 8;
ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);
ResidCnt += (ULONG) bval;
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
pSRB->SGPhysAddr += xferCnt;
pSRB->TotalXferredLen += xferCnt;
pSRB->SGToBeXferLen = ResidCnt;
}
}
bval = WRITE_DIRECTION+DMA_IDLE_CMD;
outb( bval, ioport+DMA_Cmd);
}
static void
DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR sstatus, bval;
USHORT i, ioport, residual;
PSGL psgl;
ULONG ResidCnt, xferCnt;
PUCHAR ptr;
ioport = pACB->IOPortBase;
sstatus = *psstatus;
if( !(pSRB->SRBState & SRB_XFERPAD) )
{
if( sstatus & PARITY_ERR )
pSRB->SRBStatus |= PARITY_ERROR;
if( sstatus & COUNT_2_ZERO )
{
bval = inb(ioport+DMA_Status);
while( !(bval & DMA_XFER_DONE) )
bval = inb(ioport+DMA_Status);
bval = READ_DIRECTION+DMA_IDLE_CMD;
outb( bval, ioport+DMA_Cmd);
pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
pSRB->SGIndex++;
if( pSRB->SGIndex < pSRB->SGcount )
{
pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
#ifndef VERSION_ELF_1_2_13
pSRB->SGPhysAddr = virt_to_phys( psgl->address );
#else
pSRB->SGPhysAddr = (ULONG) psgl->address;
#endif
pSRB->SGToBeXferLen = (ULONG) psgl->length;
}
else
pSRB->SGToBeXferLen = 0;
}
else /* phase changed */
{
residual = 0;
bval = inb(ioport+Current_Fifo);
while( bval & 0x1f )
{
if( (bval & 0x1f) == 1 )
{
for(i=0; i< 0x100; i++)
{
bval = inb(ioport+Current_Fifo);
if( !(bval & 0x1f) )
goto din_1;
else if( i == 0x0ff )
{
residual = 1; /* ;1 residual byte */
goto din_1;
}
}
}
else
bval = inb(ioport+Current_Fifo);
}
din_1:
bval = READ_DIRECTION+DMA_BLAST_CMD;
outb(bval, ioport+DMA_Cmd);
for(i=0; i<0x8000; i++)
{
bval = inb(ioport+DMA_Status);
if(bval & BLAST_COMPLETE)
break;
}
bval = READ_DIRECTION+DMA_IDLE_CMD;
outb(bval, ioport+DMA_Cmd);
ResidCnt = (ULONG) inb(ioport+CtcReg_High);
ResidCnt = ResidCnt << 8;
ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);
ResidCnt = ResidCnt << 8;
ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
pSRB->SGPhysAddr += xferCnt;
pSRB->TotalXferredLen += xferCnt;
pSRB->SGToBeXferLen = ResidCnt;
if( residual )
{
bval = inb(ioport+ScsiFifo); /* get residual byte */
#ifndef VERSION_ELF_1_2_13
ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr );
#else
ptr = (PUCHAR) pSRB->SGPhysAddr;
#endif
*ptr = bval;
pSRB->SGPhysAddr++;
pSRB->TotalXferredLen++;
pSRB->SGToBeXferLen--;
}
}
}
}
static void
DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
}
static void
DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR bval;
USHORT ioport;
ioport = pACB->IOPortBase;
bval = inb(ioport+ScsiFifo);
pSRB->TargetStatus = bval;
bval++;
bval = inb(ioport+ScsiFifo); /* get message */
pSRB->EndMessage = bval;
*psstatus = SCSI_NOP0;
pSRB->SRBState = SRB_COMPLETED;
bval = MSG_ACCEPTED_CMD;
outb(bval, ioport+ScsiCmd);
}
static void
DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
*psstatus = SCSI_NOP0;
}
static void
DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR bval;
USHORT ioport, wval, wval1;
PDCB pDCB;
PSRB psrb;
ioport = pACB->IOPortBase;
pDCB = pACB->pActiveDCB;
bval = inb( ioport+ScsiFifo );
if( !(pSRB->SRBState & SRB_MSGIN_MULTI) )
{
if(bval == MSG_DISCONNECT)
{
pSRB->SRBState = SRB_DISCONNECT;
}
else if( bval == MSG_SAVE_PTR )
goto min6;
else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) &&
(bval <= MSG_ORDER_QTAG)) )
{
pSRB->SRBState |= SRB_MSGIN_MULTI;
pSRB->MsgInBuf[0] = bval;
pSRB->MsgCnt = 1;
pSRB->pMsgPtr = &pSRB->MsgInBuf[1];
}
else if(bval == MSG_REJECT_)
{
bval = RESET_ATN_CMD;
outb(bval, ioport+ScsiCmd);
if( pSRB->SRBState & DO_SYNC_NEGO)
goto set_async;
}
else if( bval == MSG_RESTORE_PTR)
goto min6;
else
goto min6;
}
else
{ /* minx: */
*pSRB->pMsgPtr = bval;
pSRB->MsgCnt++;
pSRB->pMsgPtr++;
if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) &&
(pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) )
{
if( pSRB->MsgCnt == 2)
{
pSRB->SRBState = 0;
bval = pSRB->MsgInBuf[1];
pSRB = pDCB->pGoingSRB;
psrb = pDCB->pGoingLast;
if( pSRB )
{
for( ;; )
{
if(pSRB->TagNumber != bval)
{
if( pSRB == psrb )
goto mingx0;
pSRB = pSRB->pNextSRB;
}
else
break;
}
if( pDCB->DCBFlag & ABORT_DEV_ )
{
pSRB->SRBState = SRB_ABORT_SENT;
EnableMsgOut( pACB, pSRB );
}
if( !(pSRB->SRBState & SRB_DISCONNECT) )
goto mingx0;
pDCB->pActiveSRB = pSRB;
pSRB->SRBState = SRB_DATA_XFER;
}
else
{
mingx0:
pSRB = pACB->pTmpSRB;
pSRB->SRBState = SRB_UNEXPECT_RESEL;
pDCB->pActiveSRB = pSRB;
pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
EnableMsgOut2( pACB, pSRB );
}
}
}
else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) )
{
pSRB->SRBState &= ~(SRB_MSGIN_MULTI+DO_SYNC_NEGO);
if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != 1) )
{ /* reject_msg: */
pSRB->MsgCnt = 1;
pSRB->MsgInBuf[0] = MSG_REJECT_;
bval = SET_ATN_CMD;
outb(bval, ioport+ScsiCmd);
}
else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) )
{
set_async:
pDCB = pSRB->pSRBDCB;
pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
pDCB->SyncPeriod = 0;
pDCB->SyncOffset = 0;
pDCB->CtrlR3 = FAST_CLK; /* ;non_fast */
pDCB->CtrlR4 &= 0x3f;
pDCB->CtrlR4 |= EATER_25NS; /* ; 25ns glitch eater */
goto re_prog;
}
else
{ /* set_sync: */
pDCB = pSRB->pSRBDCB;
pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
pDCB->SyncOffset &= 0x0f0;
pDCB->SyncOffset |= pSRB->MsgInBuf[4];
pDCB->NegoPeriod = pSRB->MsgInBuf[3];
wval = (USHORT) pSRB->MsgInBuf[3];
wval = wval << 2;
wval--;
wval1 = wval / 25;
if( (wval1 * 25) != wval)
wval1++;
bval = FAST_CLK+FAST_SCSI;
pDCB->CtrlR4 &= 0x3f;
if(wval1 >= 8)
{
wval1--;
bval = FAST_CLK; /* ;fast clock/normal scsi */
pDCB->CtrlR4 |= EATER_25NS; /* ;25 ns glitch eater */
}
pDCB->CtrlR3 = bval;
pDCB->SyncPeriod = (UCHAR)wval1;
re_prog:
bval = pDCB->SyncPeriod;
outb(bval, ioport+Sync_Period);
bval = pDCB->SyncOffset;
outb(bval, ioport+Sync_Offset);
bval = pDCB->CtrlR3;
outb(bval, ioport+CtrlReg3);
bval = pDCB->CtrlR4;
outb(bval, ioport+CtrlReg4);
SetXferRate( pACB, pDCB);
}
}
}
min6:
*psstatus = SCSI_NOP0;
bval = MSG_ACCEPTED_CMD;
outb(bval, ioport+ScsiCmd);
}
static void
DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
{
PSGL psgl;
UCHAR bval;
USHORT ioport;
ULONG lval;
ioport = pACB->IOPortBase;
if( pSRB->SGIndex < pSRB->SGcount )
{
bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */
outb( bval, ioport+DMA_Cmd);
if( !pSRB->SGToBeXferLen )
{
psgl = pSRB->pSegmentList;
#ifndef VERSION_ELF_1_2_13
pSRB->SGPhysAddr = virt_to_phys( psgl->address );
#else
pSRB->SGPhysAddr = (ULONG) psgl->address;
#endif
pSRB->SGToBeXferLen = (ULONG) psgl->length;
}
lval = pSRB->SGToBeXferLen;
bval = (UCHAR) lval;
outb(bval,ioport+CtcReg_Low);
lval = lval >> 8;
bval = (UCHAR) lval;
outb(bval,ioport+CtcReg_Mid);
lval = lval >> 8;
bval = (UCHAR) lval;
outb(bval,ioport+CtcReg_High);
lval = pSRB->SGToBeXferLen;
outl(lval, ioport+DMA_XferCnt);
lval = pSRB->SGPhysAddr;
outl( lval, ioport+DMA_XferAddr);
bval = DMA_COMMAND+INFO_XFER_CMD;
outb(bval, ioport+ScsiCmd);
pSRB->SRBState = SRB_DATA_XFER;
bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */
outb(bval, ioport+DMA_Cmd);
bval = DMA_START_CMD | ioDir; /* ;+EN_DMA_INT */
outb(bval, ioport+DMA_Cmd);
}
else /* xfer pad */
{
if( pSRB->SGcount )
{
pSRB->AdaptStatus = H_OVER_UNDER_RUN;
pSRB->SRBStatus |= OVER_RUN;
}
bval = 0;
outb(bval,ioport+CtcReg_Low);
outb(bval,ioport+CtcReg_Mid);
outb(bval,ioport+CtcReg_High);
pSRB->SRBState |= SRB_XFERPAD;
bval = DMA_COMMAND+XFER_PAD_BYTE;
outb(bval, ioport+ScsiCmd);
/*
bval = DMA_IDLE_CMD | ioDir; ;+EN_DMA_INT
outb(bval, ioport+DMA_Cmd);
bval = DMA_START_CMD | ioDir; ;+EN_DMA_INT
outb(bval, ioport+DMA_Cmd);
*/
}
}
static void
DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR ioDir;
ioDir = WRITE_DIRECTION;
DataIO_Comm( pACB, pSRB, ioDir);
}
static void
DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR ioDir;
ioDir = READ_DIRECTION;
DataIO_Comm( pACB, pSRB, ioDir);
}
static void
DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
PDCB pDCB;
UCHAR bval;
PUCHAR ptr;
USHORT ioport, i, cnt;
ioport = pACB->IOPortBase;
bval = RESET_ATN_CMD;
outb(bval, ioport+ScsiCmd);
bval = CLEAR_FIFO_CMD;
outb(bval, ioport+ScsiCmd);
if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
{
cnt = (USHORT) pSRB->ScsiCmdLen;
ptr = (PUCHAR) pSRB->CmdBlock;
for(i=0; i < cnt; i++)
{
outb(*ptr, ioport+ScsiFifo);
ptr++;
}
}
else
{
bval = REQUEST_SENSE;
outb(bval, ioport+ScsiFifo);
pDCB = pACB->pActiveDCB;
bval = pDCB->IdentifyMsg << 5;
outb(bval, ioport+ScsiFifo);
bval = 0;
outb(bval, ioport+ScsiFifo);
outb(bval, ioport+ScsiFifo);
bval = sizeof(pSRB->pcmd->sense_buffer);
outb(bval, ioport+ScsiFifo);
bval = 0;
outb(bval, ioport+ScsiFifo);
}
pSRB->SRBState = SRB_COMMAND;
bval = INFO_XFER_CMD;
outb(bval, ioport+ScsiCmd);
}
static void
DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR bval;
USHORT ioport;
ioport = pACB->IOPortBase;
bval = CLEAR_FIFO_CMD;
outb(bval, ioport+ScsiCmd);
pSRB->SRBState = SRB_STATUS;
bval = INITIATOR_CMD_CMPLTE;
outb(bval, ioport+ScsiCmd);
}
static void
DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR bval;
USHORT ioport, i, cnt;
PUCHAR ptr;
PDCB pDCB;
ioport = pACB->IOPortBase;
bval = CLEAR_FIFO_CMD;
outb(bval, ioport+ScsiCmd);
pDCB = pACB->pActiveDCB;
if( !(pSRB->SRBState & SRB_MSGOUT) )
{
cnt = pSRB->MsgCnt;
if( cnt )
{
ptr = (PUCHAR) pSRB->MsgOutBuf;
for(i=0; i < cnt; i++)
{
outb(*ptr, ioport+ScsiFifo);
ptr++;
}
pSRB->MsgCnt = 0;
if( (pDCB->DCBFlag & ABORT_DEV_) &&
(pSRB->MsgOutBuf[0] == MSG_ABORT) )
pSRB->SRBState = SRB_ABORT_SENT;
}
else
{
bval = MSG_ABORT; /* ??? MSG_NOP */
if( (pSRB->CmdBlock[0] == INQUIRY ) ||
(pSRB->CmdBlock[0] == REQUEST_SENSE) ||
(pSRB->SRBFlag & AUTO_REQSENSE) )
{
if( pDCB->SyncMode & SYNC_ENABLE )
goto mop1;
}
outb(bval, ioport+ScsiFifo);
}
bval = INFO_XFER_CMD;
outb( bval, ioport+ScsiCmd);
}
else
{
mop1:
bval = MSG_EXTENDED;
outb(bval, ioport+ScsiFifo);
bval = 3; /* ;length of extended msg */
outb(bval, ioport+ScsiFifo);
bval = 1; /* ; sync nego */
outb(bval, ioport+ScsiFifo);
bval = pDCB->NegoPeriod;
outb(bval, ioport+ScsiFifo);
bval = SYNC_NEGO_OFFSET;
outb(bval, ioport+ScsiFifo);
pSRB->SRBState |= DO_SYNC_NEGO;
bval = INFO_XFER_CMD;
outb(bval, ioport+ScsiCmd);
}
}
static void
DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
UCHAR bval;
USHORT ioport;
ioport = pACB->IOPortBase;
bval = CLEAR_FIFO_CMD;
outb(bval, ioport+ScsiCmd);
if( !(pSRB->SRBState & SRB_MSGIN) )
{
pSRB->SRBState &= SRB_DISCONNECT;
pSRB->SRBState |= SRB_MSGIN;
}
bval = INFO_XFER_CMD;
outb(bval, ioport+ScsiCmd);
}
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 )
{
UCHAR bval;
USHORT cnt, i;
PDCB ptr;
if( !(pDCB->IdentifyMsg & 0x07) )
{
if( pACB->scan_devices )
{
CurrSyncOffset = pDCB->SyncOffset;
}
else
{
ptr = pACB->pLinkDCB;
cnt = pACB->DeviceCnt;
bval = pDCB->UnitSCSIID;
for(i=0; i<cnt; i++)
{
if( ptr->UnitSCSIID == bval )
{
ptr->SyncPeriod = pDCB->SyncPeriod;
ptr->SyncOffset = pDCB->SyncOffset;
ptr->CtrlR3 = pDCB->CtrlR3;
ptr->CtrlR4 = pDCB->CtrlR4;
ptr->SyncMode = pDCB->SyncMode;
}
ptr = ptr->pNextDCB;
}
}
}
return;
}
static void
DC390_Disconnect( PACB pACB )
{
PDCB pDCB;
PSRB pSRB, psrb;
ULONG flags;
USHORT ioport, i, cnt;
UCHAR bval;
#ifdef DC390_DEBUG0
printk("DISC,");
#endif
save_flags(flags);
cli();
ioport = pACB->IOPortBase;
pDCB = pACB->pActiveDCB;
if (!pDCB)
{
#ifdef DC390_DEBUG0
printk("ACB:%08lx->ActiveDCB:%08lx !,",(ULONG)pACB,(ULONG)pDCB);
#endif
restore_flags(flags); return;
}
pSRB = pDCB->pActiveSRB;
pACB->pActiveDCB = 0;
pSRB->ScsiPhase = SCSI_NOP0;
bval = EN_SEL_RESEL;
outb(bval, ioport+ScsiCmd);
if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
{
pSRB->SRBState = 0;
DoWaitingSRB( pACB );
}
else if( pSRB->SRBState & SRB_ABORT_SENT )
{
pDCB->TagMask = 0;
pDCB->DCBFlag = 0;
cnt = pDCB->GoingSRBCnt;
pDCB->GoingSRBCnt = 0;
pSRB = pDCB->pGoingSRB;
for( i=0; i < cnt; i++)
{
psrb = pSRB->pNextSRB;
pSRB->pNextSRB = pACB->pFreeSRB;
pACB->pFreeSRB = pSRB;
pSRB = psrb;
}
pDCB->pGoingSRB = 0;
DoWaitingSRB( pACB );
}
else
{
if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
!(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
{ /* Selection time out */
if( !(pACB->scan_devices) )
{
pSRB->SRBState = SRB_READY;
RewaitSRB( pDCB, pSRB);
}
else
{
pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
goto disc1;
}
}
else if( pSRB->SRBState & SRB_DISCONNECT )
{
DoWaitingSRB( pACB );
}
else if( pSRB->SRBState & SRB_COMPLETED )
{
disc1:
if(pDCB->MaxCommand > 1)
{
bval = pSRB->TagNumber;
pDCB->TagMask &= (~(1 << bval)); /* free tag mask */
}
pDCB->pActiveSRB = 0;
pSRB->SRBState = SRB_FREE;
SRBdone( pACB, pDCB, pSRB);
}
}
restore_flags(flags);
return;
}
static void
DC390_Reselect( PACB pACB )
{
PDCB pDCB, pdcb;
PSRB pSRB;
USHORT ioport, wval;
UCHAR bval, bval1;
#ifdef DC390_DEBUG0
printk("RSEL,");
#endif
ioport = pACB->IOPortBase;
pDCB = pACB->pActiveDCB;
if( pDCB )
{ /* Arbitration lost but Reselection win */
pSRB = pDCB->pActiveSRB;
if( !( pACB->scan_devices ) )
{
pSRB->SRBState = SRB_READY;
RewaitSRB( pDCB, pSRB);
}
}
bval = inb(ioport+ScsiFifo); /* get ID */
bval = bval ^ pACB->HostID_Bit;
wval = 0;
bval1 = 1;
for(;;)
{
if( !(bval & bval1) )
{
bval1 = bval1 << 1;
wval++;
}
else
break;
}
wval |= ( (USHORT) inb(ioport+ScsiFifo) & 7) << 8; /* get LUN */
pDCB = pACB->pLinkDCB;
pdcb = pDCB;
while( wval != *((PUSHORT) &pDCB->UnitSCSIID) )
{
pDCB = pDCB->pNextDCB;
if( pDCB == pdcb )
return;
}
pACB->pActiveDCB = pDCB;
if( pDCB->SyncMode & EN_TAG_QUEUING )
{
pSRB = pACB->pTmpSRB;
pDCB->pActiveSRB = pSRB;
}
else
{
pSRB = pDCB->pActiveSRB;
if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
{
pSRB= pACB->pTmpSRB;
pSRB->SRBState = SRB_UNEXPECT_RESEL;
pDCB->pActiveSRB = pSRB;
EnableMsgOut( pACB, pSRB );
}
else
{
if( pDCB->DCBFlag & ABORT_DEV_ )
{
pSRB->SRBState = SRB_ABORT_SENT;
EnableMsgOut( pACB, pSRB );
}
else
pSRB->SRBState = SRB_DATA_XFER;
}
}
pSRB->ScsiPhase = SCSI_NOP0;
bval = pDCB->UnitSCSIID;
outb( bval, ioport+Scsi_Dest_ID);
bval = pDCB->SyncPeriod;
outb(bval, ioport+Sync_Period);
bval = pDCB->SyncOffset;
outb( bval, ioport+Sync_Offset);
bval = pDCB->CtrlR1;
outb(bval, ioport+CtrlReg1);
bval = pDCB->CtrlR3;
outb(bval, ioport+CtrlReg3);
bval = pDCB->CtrlR4; /* ; Glitch eater */
outb(bval, ioport+CtrlReg4);
bval = MSG_ACCEPTED_CMD; /* ;to rls the /ACK signal */
outb(bval, ioport+ScsiCmd);
}
static void
SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
{
PSRB psrb;
UCHAR bval, bval1, i, j, status;
PSCSICMD pcmd;
PSCSI_INQDATA ptr;
USHORT disable_tag;
ULONG flags;
PSGL ptr2;
ULONG swlval;
pcmd = pSRB->pcmd;
status = pSRB->TargetStatus;
if(pSRB->SRBFlag & AUTO_REQSENSE)
{
pSRB->SRBFlag &= ~AUTO_REQSENSE;
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
if(status == SCSI_STAT_CHECKCOND)
{
pcmd->result = DID_BAD_TARGET << 16;
goto ckc_e;
}
if(pSRB->RetryCnt == 0)
{
*((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
pSRB->TotalXferredLen = pSRB->Segment1[1];
if( (pSRB->TotalXferredLen) &&
(pSRB->TotalXferredLen >= pcmd->underflow) )
pcmd->result |= (DID_OK << 16);
else
pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
SCSI_STAT_CHECKCOND;
#ifdef DC390_DEBUG0
printk("Cmd=%2x,Result=%8x,XferL=%8x,",pSRB->CmdBlock[0],
(UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);
#endif
goto ckc_e;
}
else
{
pSRB->RetryCnt--;
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = 0;
*((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
*((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
{
pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
SCSI_STAT_CHECKCOND;
goto ckc_e;
}
pcmd->result |= (DRIVER_SENSE << 24);
pSRB->SGcount = (UCHAR) pSRB->Segment1[0];
pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8);
pSRB->SGIndex = 0;
pSRB->TotalXferredLen = 0;
pSRB->SGToBeXferLen = 0;
if( pcmd->use_sg )
pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
else if( pcmd->request_buffer )
{
pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
pSRB->Segmentx.length = pcmd->request_bufflen;
}
if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
RewaitSRB( pDCB, pSRB );
return;
}
}
if( status )
{
if( status == SCSI_STAT_CHECKCOND)
{
if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
{
bval = pSRB->SGcount;
swlval = 0;
ptr2 = pSRB->pSegmentList;
for( i=pSRB->SGIndex; i < bval; i++)
{
swlval += ptr2->length;
ptr2++;
}
#ifdef DC390_DEBUG0
printk("XferredLen=%8x,NotXferLen=%8x,",
(UINT) pSRB->TotalXferredLen, (UINT) swlval);
#endif
}
RequestSense( pACB, pDCB, pSRB );
return;
}
else if( status == SCSI_STAT_QUEUEFULL )
{
bval = (UCHAR) pDCB->GoingSRBCnt;
bval--;
pDCB->MaxCommand = bval;
RewaitSRB( pDCB, pSRB );
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = 0;
return;
}
else if(status == SCSI_STAT_SEL_TIMEOUT)
{
pSRB->AdaptStatus = H_SEL_TIMEOUT;
pSRB->TargetStatus = 0;
pcmd->result = DID_BAD_TARGET << 16;
}
else
{
pSRB->AdaptStatus = 0;
if( pSRB->RetryCnt )
{
pSRB->RetryCnt--;
pSRB->TargetStatus = 0;
pSRB->SGIndex = 0;
pSRB->TotalXferredLen = 0;
pSRB->SGToBeXferLen = 0;
if( pcmd->use_sg )
pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
else if( pcmd->request_buffer )
{
pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
pSRB->Segmentx.length = pcmd->request_bufflen;
}
if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
RewaitSRB( pDCB, pSRB );
return;
}
else
{
pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) |
(ULONG) status;
}
}
}
else
{
status = pSRB->AdaptStatus;
if(status & H_OVER_UNDER_RUN)
{
pSRB->TargetStatus = 0;
pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8);
}
else if( pSRB->SRBStatus & PARITY_ERROR)
{
pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8);
}
else /* No error */
{
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = 0;
pcmd->result |= (DID_OK << 16);
}
}
ckc_e:
if( pACB->scan_devices )
{
if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
{
if(pcmd->result != (DID_OK << 16))
{
if( pcmd->result & SCSI_STAT_CHECKCOND )
{
goto RTN_OK;
}
else
{
pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
pPrevDCB->pNextDCB = pACB->pLinkDCB;
if( (pcmd->target == pACB->max_id) &&
((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) )
{
pACB->scan_devices = 0;
}
}
}
else
{
RTN_OK:
pPrevDCB->pNextDCB = pDCB;
pDCB->pNextDCB = pACB->pLinkDCB;
if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) )
pACB->scan_devices = END_SCAN;
}
}
else if( pSRB->CmdBlock[0] == INQUIRY )
{
if( (pcmd->target == pACB->max_id) &&
(pcmd->lun == pACB->max_lun) )
{
pACB->scan_devices = 0;
}
ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
if( pcmd->use_sg )
ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
bval1 = ptr->DevType & SCSI_DEVTYPE;
if(bval1 == SCSI_NODEV)
{
pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
pPrevDCB->pNextDCB = pACB->pLinkDCB;
}
else
{
pACB->DeviceCnt++;
pPrevDCB = pDCB;
pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390_DCB ));
pDCB->DevType = bval1;
if(bval1 == TYPE_DISK || bval1 == TYPE_MOD)
{
if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) &&
(ptr->Flags & SCSI_INQ_CMDQUEUE) &&
(pDCB->DevMode & TAG_QUEUING_) &&
(pDCB->DevMode & EN_DISCONNECT_) )
{
disable_tag = 0;
for(i=0; i<BADDEVCNT; i++)
{
for(j=0; j<28; j++)
{
if( ((PUCHAR)ptr)[8+j] != baddevname1[i][j])
break;
}
if(j == 28)
{
disable_tag = 1;
break;
}
}
if( !disable_tag )
{
pDCB->MaxCommand = pACB->TagMaxNum;
pDCB->SyncMode |= EN_TAG_QUEUING;
pDCB->TagMask = 0;
}
else
{
pDCB->SyncMode |= EN_ATN_STOP;
}
}
}
}
}
}
save_flags( flags );
cli();
/* ReleaseSRB( pDCB, pSRB ); */
if(pSRB == pDCB->pGoingSRB )
{
pDCB->pGoingSRB = pSRB->pNextSRB;
}
else
{
psrb = pDCB->pGoingSRB;
while( psrb->pNextSRB != pSRB )
psrb = psrb->pNextSRB;
psrb->pNextSRB = pSRB->pNextSRB;
if( pSRB == pDCB->pGoingLast )
pDCB->pGoingLast = psrb;
}
pSRB->pNextSRB = pACB->pFreeSRB;
pACB->pFreeSRB = pSRB;
pDCB->GoingSRBCnt--;
DoWaitingSRB( pACB );
restore_flags(flags);
/* Notify cmd done */
pcmd->scsi_done( pcmd );
if( pDCB->QIORBCnt )
DoNextCmd( pACB, pDCB );
return;
}
static void
DoingSRB_Done( PACB pACB )
{
PDCB pDCB, pdcb;
PSRB psrb, psrb2;
USHORT cnt, i;
PSCSICMD pcmd;
pDCB = pACB->pLinkDCB;
pdcb = pDCB;
do
{
cnt = pdcb->GoingSRBCnt;
psrb = pdcb->pGoingSRB;
for( i=0; i<cnt; i++)
{
psrb2 = psrb->pNextSRB;
pcmd = psrb->pcmd;
pcmd->result = DID_RESET << 16;
/* ReleaseSRB( pDCB, pSRB ); */
psrb->pNextSRB = pACB->pFreeSRB;
pACB->pFreeSRB = psrb;
pcmd->scsi_done( pcmd );
psrb = psrb2;
}
pdcb->GoingSRBCnt = 0;;
pdcb->pGoingSRB = NULL;
pdcb->TagMask = 0;
pdcb = pdcb->pNextDCB;
}
while( pdcb != pDCB );
}
static void
DC390_ResetSCSIBus( PACB pACB )
{
USHORT ioport;
UCHAR bval;
ULONG flags;
save_flags(flags);
cli();
pACB->ACBFlag |= RESET_DEV;
ioport = pACB->IOPortBase;
bval = DMA_IDLE_CMD;
outb(bval,ioport+DMA_Cmd);
bval = RST_SCSI_BUS_CMD;
outb(bval,ioport+ScsiCmd);
restore_flags(flags);
return;
}
static void
DC390_ScsiRstDetect( PACB pACB )
{
ULONG wlval, flags;
USHORT ioport;
UCHAR bval;
#ifdef DC390_DEBUG0
printk("RST_DETEC");
#endif
save_flags(flags);
sti();
wlval = jiffies + HZ;
while( jiffies < wlval ); /* delay 1 sec */
cli();
ioport = pACB->IOPortBase;
bval = DMA_IDLE_CMD;
outb(bval,ioport+DMA_Cmd);
bval = CLEAR_FIFO_CMD;
outb(bval,ioport+ScsiCmd);
if( pACB->ACBFlag & RESET_DEV )
pACB->ACBFlag |= RESET_DONE;
else
{
pACB->ACBFlag |= RESET_DETECT;
ResetDevParam( pACB );
/* DoingSRB_Done( pACB ); ???? */
RecoverSRB( pACB );
pACB->pActiveDCB = NULL;
pACB->ACBFlag = 0;
DoWaitingSRB( pACB );
}
restore_flags(flags);
return;
}
static void
RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
{
PSCSICMD pcmd;
pSRB->SRBFlag |= AUTO_REQSENSE;
pSRB->Segment0[0] = *((PULONG) &(pSRB->CmdBlock[0]));
pSRB->Segment0[1] = *((PULONG) &(pSRB->CmdBlock[4]));
pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount);
pSRB->Segment1[1] = pSRB->TotalXferredLen;
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = 0;
pcmd = pSRB->pcmd;
pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
pSRB->pSegmentList = &pSRB->Segmentx;
pSRB->SGcount = 1;
pSRB->SGIndex = 0;
*((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003;
pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
*((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer);
pSRB->ScsiCmdLen = 6;
pSRB->TotalXferredLen = 0;
pSRB->SGToBeXferLen = 0;
if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
RewaitSRB( pDCB, pSRB );
}
static void
EnableMsgOut2( PACB pACB, PSRB pSRB )
{
USHORT ioport;
UCHAR bval;
ioport = pACB->IOPortBase;
pSRB->MsgCnt = 1;
bval = SET_ATN_CMD;
outb(bval, ioport+ScsiCmd);
}
static void
EnableMsgOut( PACB pACB, PSRB pSRB )
{
pSRB->MsgOutBuf[0] = MSG_ABORT;
EnableMsgOut2( pACB, pSRB );
}
static void
DC390_InvalidCmd( PACB pACB )
{
UCHAR bval;
USHORT ioport;
PSRB pSRB;
pSRB = pACB->pActiveDCB->pActiveSRB;
if( pSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
{
ioport = pACB->IOPortBase;
bval = CLEAR_FIFO_CMD;
outb(bval,(ioport+ScsiCmd));
}
}
/***********************************************************************
* FILE NAME : TMSCSIM.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. *
***********************************************************************/
/* Minor enhancements and bugfixes by *
* Kurt Garloff <K.Garloff@ping.de> *
***********************************************************************/
/* HISTORY: *
* *
* REV# DATE NAME DESCRIPTION *
* 1.00 04/24/96 CLH First release *
* 1.01 06/12/96 CLH Fixed bug of Media Change for Removable *
* Device, scan all LUN. Support Pre2.0.10 *
* 1.02 06/18/96 CLH Fixed bug of Command timeout ... *
* 1.03 09/25/96 KG Added tmscsim_proc_info() *
* 1.04 10/11/96 CLH Updating for support KV 2.0.x *
* 1.05 10/18/96 KG Fixed bug in DC390_abort(null ptr deref)*
* 1.06 10/25/96 KG Fixed module support *
* 1.07 11/09/96 KG Fixed tmscsim_proc_info() *
* 1.08 11/18/96 KG Fixed null ptr in DC390_Disconnect() *
* 1.09 11/30/96 KG Added register the allocated IO space *
* 1.10 12/05/96 CLH Modified tmscsim_proc_info(), and reset *
* pending interrupt in DC390_detect() *
***********************************************************************/
#define DC390_DEBUG
#define SCSI_MALLOC
#ifdef MODULE
#include <linux/module.h>
#endif
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/system.h>
#include <linux/delay.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/config.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < 66354 /* 1.3.50 */
#include "../block/blk.h"
#else
#include <linux/blk.h>
#endif
#include "scsi.h"
#include "hosts.h"
#include "tmscsim.h"
#include "constants.h"
#include "sd.h"
#include <linux/stat.h>
#include "dc390.h"
#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI
#ifndef VERSION_ELF_1_2_13
struct proc_dir_entry proc_scsi_tmscsim ={
PROC_SCSI_DC390T, 7 ,"tmscsim",
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
#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 );
int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index );
void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd );
#ifdef MODULE
static int DC390_release(struct Scsi_Host *host);
static int DC390_shutdown (struct Scsi_Host *host);
#endif
static PSHT pSHT_start = NULL;
static PSH pSH_start = NULL;
static PSH pSH_current = NULL;
static PACB pACB_start= NULL;
static PACB pACB_current = NULL;
static PDCB pPrevDCB = NULL;
static USHORT adapterCnt = 0;
static USHORT InitialTime = 0;
static USHORT CurrSyncOffset = 0;
static ULONG mech1addr;
static UCHAR mech2bus, mech2Agent, mech2CfgSPenR;
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,
};
UCHAR eepromBuf[MAX_ADAPTER_NUM][128];
UCHAR clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
UCHAR baddevname1[2][28] ={
"SEAGATE ST3390N 9546",
"HP C3323-300 4269"};
#define BADDEVCNT 2
/***********************************************************************
*
*
*
**********************************************************************/
static void
QLinkcmd( PSCSICMD cmd, PDCB pDCB )
{
ULONG flags;
PSCSICMD pcmd;
save_flags(flags);
cli();
if( !pDCB->QIORBCnt )
{
pDCB->pQIORBhead = cmd;
pDCB->pQIORBtail = cmd;
pDCB->QIORBCnt++;
cmd->next = NULL;
}
else
{
pcmd = pDCB->pQIORBtail;
pcmd->next = cmd;
pDCB->pQIORBtail = cmd;
pDCB->QIORBCnt++;
cmd->next = NULL;
}
restore_flags(flags);
}
static PSCSICMD
Getcmd( PDCB pDCB )
{
ULONG flags;
PSCSICMD pcmd;
save_flags(flags);
cli();
pcmd = pDCB->pQIORBhead;
pDCB->pQIORBhead = pcmd->next;
pcmd->next = NULL;
pDCB->QIORBCnt--;
restore_flags(flags);
return( pcmd );
}
static PSRB
GetSRB( PACB pACB )
{
ULONG flags;
PSRB pSRB;
save_flags(flags);
cli();
pSRB = pACB->pFreeSRB;
if( pSRB )
{
pACB->pFreeSRB = pSRB->pNextSRB;
pSRB->pNextSRB = NULL;
}
restore_flags(flags);
return( pSRB );
}
static void
RewaitSRB0( PDCB pDCB, PSRB pSRB )
{
PSRB psrb1;
ULONG flags;
save_flags(flags);
cli();
if( (psrb1 = pDCB->pWaitingSRB) )
{
pSRB->pNextSRB = psrb1;
pDCB->pWaitingSRB = pSRB;
}
else
{
pSRB->pNextSRB = NULL;
pDCB->pWaitingSRB = pSRB;
pDCB->pWaitLast = pSRB;
}
restore_flags(flags);
}
static void
RewaitSRB( PDCB pDCB, PSRB pSRB )
{
PSRB psrb1;
ULONG flags;
UCHAR bval;
save_flags(flags);
cli();
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 */
restore_flags(flags);
}
static void
DoWaitingSRB( PACB pACB )
{
ULONG flags;
PDCB ptr, ptr1;
PSRB pSRB;
save_flags(flags);
cli();
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;
}
}
}
restore_flags(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 )
{
ULONG flags;
PDCB pDCB;
save_flags(flags);
cli();
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:
restore_flags(flags);
return;
}
/***********************************************************************
* Function : static int DC390_queue_command (Scsi_Cmnd *cmd,
* void (*done)(Scsi_Cmnd *))
*
* Purpose : enqueues a SCSI command
*
* Inputs : cmd - SCSI command, done - function called on completion, with
* a pointer to the command descriptor.
*
* Returns : 0
*
***********************************************************************/
int
DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
{
USHORT ioport, i;
Scsi_Cmnd *pcmd;
struct Scsi_Host *psh;
PACB pACB;
PDCB pDCB;
PSRB pSRB;
ULONG flags;
PUCHAR ptr,ptr1;
psh = cmd->host;
pACB = (PACB ) psh->hostdata;
ioport = pACB->IOPortBase;
#ifdef DC390_DEBUG0
/* if(pACB->scan_devices) */
printk("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmnd[0],cmd->target,cmd->lun);
#endif
if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) )
{
pACB->scan_devices = 0;
pPrevDCB->pNextDCB = pACB->pLinkDCB;
}
else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) )
{
pACB->scan_devices = 0;
pPrevDCB->pNextDCB = pACB->pLinkDCB;
}
if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) )
{
/* printk("DC390: Ignore target %d lun %d\n",
cmd->target, cmd->lun); */
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
return( 0 );
}
if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
{
if( pACB->DeviceCnt < MAX_DEVICES )
{
pACB->DCBmap[cmd->target] |= (1 << cmd->lun);
pDCB = pACB->pDCB_free;
#ifdef DC390_DEBUG0
printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target);
#endif
DC390_initDCB( pACB, pDCB, cmd );
}
else /* ???? */
{
/* printk("DC390: Ignore target %d lun %d\n",
cmd->target, cmd->lun); */
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
return(0);
}
}
else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
{
/* printk("DC390: Ignore target %d lun %d\n",
cmd->target, cmd->lun); */
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
return(0);
}
else
{
pDCB = pACB->pLinkDCB;
while( (pDCB->UnitSCSIID != cmd->target) ||
(pDCB->UnitSCSILUN != cmd->lun) )
{
pDCB = pDCB->pNextDCB;
}
#ifdef DC390_DEBUG0
printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target);
#endif
}
cmd->scsi_done = done;
cmd->result = 0;
save_flags(flags);
cli();
if( pDCB->QIORBCnt )
{
QLinkcmd( cmd, pDCB );
pcmd = Getcmd( pDCB );
}
else
pcmd = cmd;
pSRB = GetSRB( pACB );
if( !pSRB )
{
QLinkcmd( pcmd, pDCB );
restore_flags(flags);
return(0);
}
/* BuildSRB(pSRB); */
pSRB->pSRBDCB = pDCB;
pSRB->pcmd = pcmd;
ptr = (PUCHAR) pSRB->CmdBlock;
ptr1 = (PUCHAR) pcmd->cmnd;
pSRB->ScsiCmdLen = pcmd->cmd_len;
for(i=0; i< pcmd->cmd_len; i++)
{
*ptr = *ptr1;
ptr++;
ptr1++;
}
if( pcmd->use_sg )
{
pSRB->SGcount = (UCHAR) pcmd->use_sg;
pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
}
else if( pcmd->request_buffer )
{
pSRB->SGcount = 1;
pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
pSRB->Segmentx.length = pcmd->request_bufflen;
}
else
pSRB->SGcount = 0;
pSRB->SGIndex = 0;
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = 0;
pSRB->MsgCnt = 0;
if( pDCB->DevType != TYPE_TAPE )
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;
SendSRB( pcmd, pACB, pSRB );
restore_flags(flags);
return(0);
}
static void
DoNextCmd( PACB pACB, PDCB pDCB )
{
Scsi_Cmnd *pcmd;
PSRB pSRB;
ULONG flags;
PUCHAR ptr,ptr1;
USHORT i;
if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )
return;
save_flags(flags);
cli();
pcmd = Getcmd( pDCB );
pSRB = GetSRB( pACB );
if( !pSRB )
{
QLinkcmd( pcmd, pDCB );
restore_flags(flags);
return;
}
pSRB->pSRBDCB = pDCB;
pSRB->pcmd = pcmd;
ptr = (PUCHAR) pSRB->CmdBlock;
ptr1 = (PUCHAR) pcmd->cmnd;
pSRB->ScsiCmdLen = pcmd->cmd_len;
for(i=0; i< pcmd->cmd_len; i++)
{
*ptr = *ptr1;
ptr++;
ptr1++;
}
if( pcmd->use_sg )
{
pSRB->SGcount = (UCHAR) pcmd->use_sg;
pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
}
else if( pcmd->request_buffer )
{
pSRB->SGcount = 1;
pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
pSRB->Segmentx.length = pcmd->request_bufflen;
}
else
pSRB->SGcount = 0;
pSRB->SGIndex = 0;
pSRB->AdaptStatus = 0;
pSRB->TargetStatus = 0;
pSRB->MsgCnt = 0;
if( pDCB->DevType != TYPE_TAPE )
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;
SendSRB( pcmd, pACB, pSRB );
restore_flags(flags);
return;
}
/***********************************************************************
* Function:
* DC390_bios_param
*
* Description:
* Return the disk geometry for the given SCSI device.
***********************************************************************/
#ifdef VERSION_ELF_1_2_13
int DC390_bios_param(Disk *disk, int devno, int geom[])
#else
int DC390_bios_param(Disk *disk, kdev_t devno, int geom[])
#endif
{
int heads, sectors, cylinders;
PACB pACB;
pACB = (PACB) disk->device->host->hostdata;
heads = 64;
sectors = 32;
cylinders = disk->capacity / (heads * sectors);
if ( cylinders > 1024)
{
heads = 255;
sectors = 63;
cylinders = disk->capacity / (255 * 63);
}
geom[0] = heads;
geom[1] = sectors;
geom[2] = cylinders;
return (0);
}
/***********************************************************************
* Function : int DC390_abort (Scsi_Cmnd *cmd)
*
* Purpose : Abort an errant SCSI command
*
* Inputs : cmd - command to abort
*
* Returns : 0 on success, -1 on failure.
***********************************************************************/
int
DC390_abort (Scsi_Cmnd *cmd)
{
ULONG flags;
PACB pACB;
PDCB pDCB, pdcb;
PSRB pSRB, psrb;
USHORT count, i;
PSCSICMD pcmd, pcmd1;
int status;
#ifdef DC390_DEBUG0
printk("DC390 : Abort Cmd.");
#endif
save_flags(flags);
cli();
pACB = (PACB) cmd->host->hostdata;
pDCB = pACB->pLinkDCB;
pdcb = pDCB;
while( (pDCB->UnitSCSIID != cmd->target) ||
(pDCB->UnitSCSILUN != cmd->lun) )
{
pDCB = pDCB->pNextDCB;
if( pDCB == pdcb )
goto NOT_RUN;
}
if( pDCB->QIORBCnt )
{
pcmd = pDCB->pQIORBhead;
if( pcmd == cmd )
{
pDCB->pQIORBhead = pcmd->next;
pcmd->next = NULL;
pDCB->QIORBCnt--;
status = SCSI_ABORT_SUCCESS;
goto ABO_X;
}
for( count = pDCB->QIORBCnt, i=0; i<count-1; i++)
{
if( pcmd->next == cmd )
{
pcmd1 = pcmd->next;
pcmd->next = pcmd1->next;
pcmd1->next = NULL;
pDCB->QIORBCnt--;
status = SCSI_ABORT_SUCCESS;
goto ABO_X;
}
else
{
pcmd = pcmd->next;
}
}
}
pSRB = pDCB->pWaitingSRB;
if( !pSRB )
goto ON_GOING;
if( pSRB->pcmd == cmd )
{
pDCB->pWaitingSRB = pSRB->pNextSRB;
goto IN_WAIT;
}
else
{
psrb = pSRB;
if( !(psrb->pNextSRB) )
goto ON_GOING;
while( psrb->pNextSRB->pcmd != cmd )
{
psrb = psrb->pNextSRB;
if( !(psrb->pNextSRB) )
goto ON_GOING;
}
pSRB = psrb->pNextSRB;
psrb->pNextSRB = pSRB->pNextSRB;
if( pSRB == pDCB->pWaitLast )
pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */
IN_WAIT:
pSRB->pNextSRB = pACB->pFreeSRB;
pACB->pFreeSRB = pSRB;
cmd->next = NULL;
status = SCSI_ABORT_SUCCESS;
goto ABO_X;
}
ON_GOING:
pSRB = pDCB->pGoingSRB;
for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
{
if( pSRB->pcmd != cmd )
pSRB = pSRB->pNextSRB;
else
{
if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
{
status = SCSI_ABORT_BUSY;
goto ABO_X;
}
else
{
status = SCSI_ABORT_SNOOZE;
goto ABO_X;
}
}
}
NOT_RUN:
status = SCSI_ABORT_NOT_RUNNING;
ABO_X:
cmd->result = DID_ABORT << 16;
cmd->scsi_done(cmd);
restore_flags(flags);
return( status );
}
static void
ResetDevParam( PACB pACB )
{
PDCB pDCB, pdcb;
pDCB = pACB->pLinkDCB;
if( pDCB == NULL )
return;
pdcb = pDCB;
do
{
pDCB->SyncMode &= ~SYNC_NEGO_DONE;
pDCB->SyncPeriod = 0;
pDCB->SyncOffset = 0;
pDCB->CtrlR3 = FAST_CLK;
pDCB->CtrlR4 &= NEGATE_REQACKDATA;
pDCB->CtrlR4 |= EATER_25NS;
pDCB = pDCB->pNextDCB;
}
while( pdcb != pDCB );
}
static void
RecoverSRB( PACB pACB )
{
PDCB pDCB, pdcb;
PSRB psrb, psrb2;
USHORT cnt, i;
pDCB = pACB->pLinkDCB;
if( pDCB == NULL )
return;
pdcb = pDCB;
do
{
cnt = pdcb->GoingSRBCnt;
psrb = pdcb->pGoingSRB;
for (i=0; i<cnt; i++)
{
psrb2 = psrb;
psrb = psrb->pNextSRB;
/* RewaitSRB( pDCB, psrb ); */
if( pdcb->pWaitingSRB )
{
psrb2->pNextSRB = pdcb->pWaitingSRB;
pdcb->pWaitingSRB = psrb2;
}
else
{
pdcb->pWaitingSRB = psrb2;
pdcb->pWaitLast = psrb2;
psrb2->pNextSRB = NULL;
}
}
pdcb->GoingSRBCnt = 0;
pdcb->pGoingSRB = NULL;
pdcb->TagMask = 0;
pdcb = pdcb->pNextDCB;
}
while( pdcb != pDCB );
}
/***********************************************************************
* Function : int DC390_reset (Scsi_Cmnd *cmd, ...)
*
* Purpose : perform a hard reset on the SCSI bus
*
* Inputs : cmd - command which caused the SCSI RESET
*
* Returns : 0 on success.
***********************************************************************/
#ifdef VERSION_2_0_0
int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags)
#else
int DC390_reset (Scsi_Cmnd *cmd)
#endif
{
USHORT ioport;
unsigned long flags;
PACB pACB;
UCHAR bval;
USHORT i;
#ifdef DC390_DEBUG1
printk("DC390: RESET,");
#endif
pACB = (PACB ) cmd->host->hostdata;
ioport = pACB->IOPortBase;
save_flags(flags);
cli();
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++ )
udelay(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 );
restore_flags(flags);
#ifdef DC390_DEBUG1
printk("DC390: RESET1,");
#endif
return( SCSI_RESET_SUCCESS );
}
#include "scsiiom.c"
/***********************************************************************
* Function : static void DC390_initDCB
*
* Purpose : initialize the internal structures for a given DCB
*
* Inputs : cmd - pointer to this scsi cmd request block structure
*
***********************************************************************/
void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd )
{
PEEprom prom;
UCHAR bval;
USHORT index;
if( pACB->DeviceCnt == 0 )
{
pACB->pLinkDCB = pDCB;
pACB->pDCBRunRobin = pDCB;
pDCB->pNextDCB = pDCB;
pPrevDCB = pDCB;
}
else
pPrevDCB->pNextDCB = pDCB;
pDCB->pDCBACB = pACB;
pDCB->QIORBCnt = 0;
pDCB->UnitSCSIID = cmd->target;
pDCB->UnitSCSILUN = cmd->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][cmd->target << 2];
pDCB->DevMode = prom->EE_MODE1;
pDCB->AdpMode = eepromBuf[index][EE_MODE2];
if( pDCB->DevMode & EN_DISCONNECT_ )
bval = 0xC0;
else
bval = 0x80;
bval |= cmd->lun;
pDCB->IdentifyMsg = bval;
pDCB->SyncMode = 0;
if( pDCB->DevMode & SYNC_NEGO_ )
{
if( !(cmd->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
*
***********************************************************************/
void DC390_initSRB( PSRB psrb )
{
#ifndef VERSION_ELF_1_2_13
#ifdef DC390_DEBUG0
printk("DC390 init: %08lx %08lx,",(ULONG)psrb,(ULONG)virt_to_bus(psrb));
#endif
psrb->PhysSRB = virt_to_bus( psrb );
#else
psrb->PhysSRB = (ULONG) psrb;
#endif
}
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
*
***********************************************************************/
void DC390_initACB( PSH psh, ULONG io_port, UCHAR Irq, USHORT index )
{
PACB pACB;
USHORT i;
psh->can_queue = MAX_CMD_QUEUE;
psh->cmd_per_lun = MAX_CMD_PER_LUN;
psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID];
psh->io_port = io_port;
psh->n_io_port = 0x80;
psh->irq = Irq;
pACB = (PACB) psh->hostdata;
#ifndef VERSION_ELF_1_2_13
psh->max_id = 8;
#ifdef CONFIG_SCSI_MULTI_LUN
if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
psh->max_lun = 8;
else
#endif
psh->max_lun = 1;
#endif
pACB->max_id = 7;
if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] )
pACB->max_id--;
#ifdef CONFIG_SCSI_MULTI_LUN
if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
pACB->max_lun = 7;
else
#endif
pACB->max_lun = 0;
pACB->pScsiHost = psh;
pACB->IOPortBase = (USHORT) io_port;
pACB->pLinkDCB = NULL;
pACB->pDCBRunRobin = NULL;
pACB->pActiveDCB = NULL;
pACB->pFreeSRB = pACB->SRB_array;
pACB->SRBCount = MAX_SRB_CNT;
pACB->AdapterIndex = index;
pACB->status = 0;
pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID];
pACB->HostID_Bit = (1 << pACB->AdaptSCSIID);
pACB->AdaptSCSILUN = 0;
pACB->DeviceCnt = 0;
pACB->IRQLevel = Irq;
pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2;
pACB->ACBFlag = 0;
pACB->scan_devices = 1;
pACB->Gmode2 = eepromBuf[index][EE_MODE2];
if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
pACB->LUNchk = 1;
pACB->pDCB_free = &pACB->DCB_array[0];
DC390_linkSRB( pACB );
pACB->pTmpSRB = &pACB->TmpSRB;
DC390_initSRB( pACB->pTmpSRB );
for(i=0; i<MAX_SCSI_ID; i++)
pACB->DCBmap[i] = 0;
}
/***********************************************************************
* Function : static int DC390_initAdapter
*
* Purpose : initialize the SCSI chip ctrl registers
*
* Inputs : psh - pointer to this host adapter's structure
*
***********************************************************************/
int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index )
{
USHORT ioport;
UCHAR bval;
PACB 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 )
{
#ifdef VERSION_ELF_1_2_13
if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim"))
#else
if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim", NULL))
#endif
{
printk("DC390: register IRQ error!\n");
return( -1 );
}
}
request_region(io_port,psh->n_io_port,"tmscsim");
ioport = (USHORT) io_port;
pACB = (PACB) psh->hostdata;
bval = SEL_TIMEOUT; /* 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);
}
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;
ULONG wval;
ULONG flags;
save_flags(flags);
cli();
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);
restore_flags(flags);
return(bval);
}
USHORT
DC390_inWord( USHORT mechnum, UCHAR regval )
{
USHORT wval;
ULONG flags;
save_flags(flags);
cli();
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);
restore_flags(flags);
return(wval);
}
ULONG
DC390_inDword(USHORT mechnum, UCHAR regval )
{
ULONG wlval;
ULONG flags;
USHORT wval;
save_flags(flags);
cli();
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);
restore_flags(flags);
return(wlval);
}
void
DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
{
USHORT wval;
ULONG flags;
save_flags(flags);
cli();
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);
restore_flags(flags);
}
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);
udelay(160);
}
void
DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
{
UCHAR bval;
bval = 0;
if(Carry)
{
bval = 0x40;
*regval = 0x80;
DC390_OutB(mechnum,*regval,bval);
}
udelay(160);
bval |= 0x80;
DC390_OutB(mechnum,*regval,bval);
udelay(160);
bval = 0;
DC390_OutB(mechnum,*regval,bval);
udelay(160);
}
UCHAR
DC390_EEpromInDO( USHORT mechnum )
{
UCHAR bval,regval;
regval = 0x80;
bval = 0x80;
DC390_OutB(mechnum,regval,bval);
udelay(160);
bval = 0x40;
DC390_OutB(mechnum,regval,bval);
udelay(160);
regval = 0x0;
bval = DC390_inByte(mechnum,regval);
if(bval == 0x22)
return(1);
else
return(0);
}
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);
}
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;
}
}
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, &regval);
DC390_Prepare(mechnum, &regval, cmd);
*ptr = EEpromGetData1(mechnum);
ptr++;
cmd++;
DC390_EnDisableCE(DISABLE_CE,mechnum,&regval);
}
}
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 = -1;
return( rc );
}
USHORT
DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum )
{
USHORT devnum;
devnum = BusDevFunNum;
if(Mechnum == 2)
{
if(devnum & 0x80)
return(-1);
mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */
mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */
mech2Agent |= 0xc0;
mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */
mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20;
}
else /* use mech #1 method */
{
mech1addr = 0x80000000 | ((ULONG)devnum << 8);
}
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 (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum)
{
PSH psh;
PACB pACB;
if( !DC390_CheckEEpromCheckSum( MechNum, index) )
{
psh = scsi_register( psht, sizeof(DC390_ACB) );
if( !psh )
return( -1 );
if( !pSH_start )
{
pSH_start = psh;
pSH_current = psh;
}
else
{
pSH_current->next = psh;
pSH_current = psh;
}
#ifdef DC390_DEBUG0
printk("DC390: pSH = %8x,", (UINT) psh);
printk("DC390: Index %02i,", index);
#endif
DC390_initACB( psh, io_port, Irq, index );
if( !DC390_initAdapter( psh, io_port, Irq, index ) )
{
pACB = (PACB) psh->hostdata;
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;
}
#ifdef DC390_DEBUG0
printk("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n",
(UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array);
printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",
sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );
#endif
}
else
{
pSH_start = NULL;
scsi_unregister( psh );
return( -1 );
}
return( 0 );
}
else
{
printk("DC390_init: EEPROM reading error!\n");
return( -1 );
}
}
/***********************************************************************
* Function : int DC390_detect(Scsi_Host_Template *psht)
*
* Purpose : detects and initializes AMD53C974 SCSI chips
* that were autoprobed, overridden on the LILO command line,
* or specified at compile time.
*
* Inputs : psht - template for this SCSI adapter
*
* Returns : number of host adapters detected
*
***********************************************************************/
int
DC390_detect(Scsi_Host_Template *psht)
{
#ifdef FOR_PCI_OK
UCHAR pci_bus, pci_device_fn;
int error = 0;
USHORT chipType = 0;
USHORT i;
#endif
UCHAR irq;
UCHAR istatus;
#ifndef VERSION_ELF_1_2_13
UINT io_port;
#else
ULONG io_port;
#endif
USHORT adaptCnt = 0; /* Number of boards detected */
USHORT pci_index = 0; /* Device index to PCI BIOS calls */
USHORT MechNum, BusDevFunNum;
ULONG wlval;
#ifndef VERSION_ELF_1_2_13
psht->proc_dir = &proc_scsi_tmscsim;
#endif
InitialTime = 1;
pSHT_start = psht;
pACB_start = NULL;
MechNum = 1;
for( ; (MechNum < 3) && (!adaptCnt); MechNum++)
{
BusDevFunNum = 0;
for (; adaptCnt < MAX_ADAPTER_NUM ;)
{
if( !DC390_ToMech( MechNum, BusDevFunNum) )
{
wlval = DC390_inDword( MechNum, PCI_VENDOR_ID);
if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+
PCI_VENDOR_ID_AMD) )
{
io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE;
irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE);
#ifdef DC390_DEBUG0
printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
#endif
if( !DC390_init(psht, io_port, irq, pci_index, MechNum) )
{
adaptCnt++;
pci_index++;
istatus = inb( (USHORT)io_port+INT_Status ); /* Reset Pending INT */
#ifdef DC390_DEBUG0
printk("DC390: Mech=%2x,\n",(UCHAR) MechNum);
#endif
}
}
}
if( BusDevFunNum != 0xfff8 )
BusDevFunNum += 8; /* next device # */
else
break;
}
}
#ifdef FOR_PCI_OK
if ( pcibios_present() )
{
for (i = 0; i < MAX_ADAPTER_NUM; ++i)
{
if( !pcibios_find_device( PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD53C974,
pci_index, &pci_bus, &pci_device_fn) )
{
chipType = PCI_DEVICE_ID_AMD53C974;
pci_index++;
}
if( chipType )
{
error = pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &io_port);
error |= pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_INTERRUPT_LINE, &irq);
if( error )
{
printk("DC390_detect: reading configuration registers error!\n");
InitialTime = 0;
return( 0 );
}
(USHORT) io_port = (USHORT) io_port & 0xFFFE;
#ifdef DC390_DEBUG0
printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
#endif
if( !DC390_init(psht, io_port, irq, i) )
adaptCnt++;
chipType = 0;
}
else
break;
}
}
#endif
InitialTime = 0;
adapterCnt = adaptCnt;
return( adaptCnt );
}
#ifndef VERSION_ELF_1_2_13
/********************************************************************
* Function: tmscsim_set_info()
*
* Purpose: Set adapter info (!)
*
* Not yet implemented
*
*******************************************************************/
int tmscsim_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
{
return(-ENOSYS); /* Currently this is a no-op */
}
/********************************************************************
* Function: tmscsim_proc_info(char* buffer, char **start,
* off_t offset, int length, int hostno, int inout)
*
* Purpose: return SCSI Adapter/Device Info
*
* Input: buffer: Pointer to a buffer where to write info
* start :
* offset:
* hostno: Host adapter index
* inout : Read (=0) or set(!=0) info
*
* Output: buffer: contains info
* length; length of info in buffer
*
* return value: length
*
********************************************************************/
/* KG: proc_info taken from driver aha152x.c */
#undef SPRINTF
#define SPRINTF(args...) pos += sprintf(pos, ## args)
#define YESNO(YN)\
if (YN) SPRINTF(" Yes ");\
else SPRINTF(" No ")
int tmscsim_proc_info(char *buffer, char **start,
off_t offset, int length, int hostno, int inout)
{
int dev, spd, spd1;
char *pos = buffer;
PSH shpnt;
PACB acbpnt;
PDCB dcbpnt;
unsigned long flags;
/* Scsi_Cmnd *ptr; */
acbpnt = pACB_start;
while(acbpnt != (PACB)-1)
{
shpnt = acbpnt->pScsiHost;
if (shpnt->host_no == hostno) break;
acbpnt = acbpnt->pNextACB;
}
if (acbpnt == (PACB)-1) return(-ESRCH);
if(!shpnt) return(-ESRCH);
if(inout) // Has data been written to the file ?
return(tmscsim_set_info(buffer, length, shpnt));
SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, ");
SPRINTF("Driver Version 1.10, 1996/12/05\n");
save_flags(flags);
cli();
SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
SPRINTF("DC390 Adapter Nr %i\n", acbpnt->AdapterIndex);
SPRINTF("IOPortBase 0x%04x, ", acbpnt->IOPortBase);
SPRINTF("IRQLevel 0x%02x\n", acbpnt->IRQLevel);
SPRINTF("MaxID %i, MaxLUN %i, ",acbpnt->max_id, acbpnt->max_lun);
SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN);
SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status);
SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt);
SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs\n");
dcbpnt = acbpnt->pLinkDCB;
for (dev = 0; dev < acbpnt->DeviceCnt; dev++)
{
SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN);
YESNO(dcbpnt->DevMode & PARITY_CHK_);
YESNO(dcbpnt->SyncMode & SYNC_NEGO_DONE);
YESNO(dcbpnt->DevMode & EN_DISCONNECT_);
YESNO(dcbpnt->DevMode & SEND_START_);
YESNO(dcbpnt->SyncMode & EN_TAG_QUEUING);
SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2);
if (dcbpnt->SyncOffset & 0x0f)
{
spd = 1000/(dcbpnt->NegoPeriod <<2);
spd1 = 1000%(dcbpnt->NegoPeriod <<2);
spd1 = (spd1 * 10)/(dcbpnt->NegoPeriod <<2);
SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (dcbpnt->SyncOffset & 0x0f));
}
else SPRINTF("\n");
/* Add more info ...*/
dcbpnt = dcbpnt->pNextDCB;
}
restore_flags(flags);
*start = buffer + offset;
if (pos - buffer < offset)
return 0;
else if (pos - buffer - offset < length)
return pos - buffer - offset;
else
return length;
}
#endif /* VERSION_ELF_1_2_13 */
#ifdef MODULE
/***********************************************************************
* Function : static int DC390_shutdown (struct Scsi_Host *host)
*
* Purpose : does a clean (we hope) shutdown of the SCSI chip.
* Use prior to dumping core, unloading the driver, etc.
*
* Returns : 0 on success
***********************************************************************/
static int
DC390_shutdown (struct Scsi_Host *host)
{
UCHAR bval;
USHORT ioport;
unsigned long flags;
PACB pACB = (PACB)(host->hostdata);
ioport = (unsigned int) pACB->IOPortBase;
save_flags (flags);
cli();
/* pACB->soft_reset(host); */
#ifdef DC390_DEBUG0
printk("DC390: shutdown,");
#endif
bval = inb(ioport+CtrlReg1);
bval |= DIS_INT_ON_SCSI_RST;
outb(bval,ioport+CtrlReg1); /* disable interrupt */
DC390_ResetSCSIBus( pACB );
restore_flags (flags);
return( 0 );
}
int DC390_release(struct Scsi_Host *host)
{
int irq_count;
struct Scsi_Host *tmp;
DC390_shutdown (host);
if (host->irq != IRQ_NONE)
{
for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next)
{
if ( tmp->irq == host->irq )
++irq_count;
}
if (irq_count == 1)
{
#ifdef DC390_DEBUG0
printk("DC390: Free IRQ %i.",host->irq);
#endif
#ifndef VERSION_ELF_1_2_13
free_irq(host->irq,NULL);
#else
free_irq(host->irq);
#endif
}
}
release_region(host->io_port,host->n_io_port);
return( 1 );
}
Scsi_Host_Template driver_template = DC390_T;
#include "scsi_module.c"
#endif /* def MODULE */
/***********************************************************************
;* File Name : TMSCSIM.H *
;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter *
;* Device Driver *
;***********************************************************************/
#ifndef TMSCSIM_H
#define TMSCSIM_H
#define IRQ_NONE 255
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef unsigned int UINT;
typedef UCHAR *PUCHAR;
typedef USHORT *PUSHORT;
typedef ULONG *PULONG;
typedef Scsi_Host_Template *PSHT;
typedef struct Scsi_Host *PSH;
typedef Scsi_Device *PSCSIDEV;
typedef Scsi_Cmnd *PSCSICMD;
typedef void *PVOID;
typedef struct scatterlist *PSGL, SGL;
/*;-----------------------------------------------------------------------*/
typedef struct _SyncMsg
{
UCHAR ExtendMsg;
UCHAR ExtMsgLen;
UCHAR SyncXferReq;
UCHAR Period;
UCHAR ReqOffset;
} SyncMsg;
/*;-----------------------------------------------------------------------*/
typedef struct _Capacity
{
ULONG BlockCount;
ULONG BlockLength;
} Capacity;
/*;-----------------------------------------------------------------------*/
typedef struct _SGentry
{
ULONG SGXferDataPtr;
ULONG SGXferDataLen;
} SGentry;
typedef struct _SGentry1
{
ULONG SGXLen;
ULONG SGXPtr;
} SGentry1, *PSGE;
#define MAX_ADAPTER_NUM 4
#define MAX_DEVICES 10
#define MAX_SG_LIST_BUF 16
#define MAX_CMD_QUEUE 20
#define MAX_CMD_PER_LUN 8
#define MAX_SCSI_ID 8
#define MAX_SRB_CNT MAX_CMD_QUEUE+4
#define END_SCAN 2
#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */
/*
;-----------------------------------------------------------------------
; SCSI Request Block
;-----------------------------------------------------------------------
*/
struct _SRB
{
UCHAR CmdBlock[12];
struct _SRB *pNextSRB;
struct _DCB *pSRBDCB;
PSCSICMD pcmd;
PSGL pSegmentList;
ULONG PhysSRB;
ULONG TotalXferredLen;
ULONG SGPhysAddr; /*;a segment starting address */
ULONG SGToBeXferLen; /*; to be xfer length */
SGL Segmentx; /* make a one entry of S/G list table */
PUCHAR pMsgPtr;
USHORT SRBState;
USHORT Revxx2; /* ??? */
UCHAR MsgInBuf[6];
UCHAR MsgOutBuf[6];
UCHAR AdaptStatus;
UCHAR TargetStatus;
UCHAR MsgCnt;
UCHAR EndMessage;
UCHAR TagNumber;
UCHAR SGcount;
UCHAR SGIndex;
UCHAR IORBFlag; /*;81h-Reset, 2-retry */
UCHAR SRBStatus;
UCHAR RetryCnt;
UCHAR SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */
/*; b4-settimeout,b5-Residual valid */
UCHAR ScsiCmdLen;
UCHAR ScsiPhase;
UCHAR Reserved3[3]; /*;for dword alignment */
ULONG Segment0[2];
ULONG Segment1[2];
};
typedef struct _SRB DC390_SRB, *PSRB;
/*
;-----------------------------------------------------------------------
; Device Control Block
;-----------------------------------------------------------------------
*/
struct _DCB
{
struct _DCB *pNextDCB;
struct _ACB *pDCBACB;
PSCSICMD pQIORBhead;
PSCSICMD pQIORBtail;
PSCSICMD AboIORBhead;
PSCSICMD AboIORBtail;
USHORT QIORBCnt;
USHORT AboIORBcnt;
PSRB pWaitingSRB;
PSRB pWaitLast;
PSRB pGoingSRB;
PSRB pGoingLast;
PSRB pActiveSRB;
USHORT GoingSRBCnt;
USHORT WaitSRBCnt; /* ??? */
ULONG TagMask;
USHORT MaxCommand;
USHORT AdaptIndex; /*; UnitInfo struc start */
USHORT UnitIndex; /*; nth Unit on this card */
UCHAR UnitSCSIID; /*; SCSI Target ID (SCSI Only) */
UCHAR UnitSCSILUN; /*; SCSI Log. Unit (SCSI Only) */
UCHAR IdentifyMsg;
UCHAR CtrlR1;
UCHAR CtrlR3;
UCHAR CtrlR4;
UCHAR InqDataBuf[8];
UCHAR CapacityBuf[8];
UCHAR DevMode;
UCHAR AdpMode;
UCHAR SyncMode; /*; 0:async mode */
UCHAR NegoPeriod; /*;for nego. */
UCHAR SyncPeriod; /*;for reg. */
UCHAR SyncOffset; /*;for reg. and nego.(low nibble) */
UCHAR UnitCtrlFlag;
UCHAR DCBFlag;
UCHAR DevType;
UCHAR Reserved2[3]; /*;for dword alignment */
};
typedef struct _DCB DC390_DCB, *PDCB;
/*
;-----------------------------------------------------------------------
; Adapter Control Block
;-----------------------------------------------------------------------
*/
struct _ACB
{
ULONG PhysACB;
PSH pScsiHost;
struct _ACB *pNextACB;
USHORT IOPortBase;
USHORT Revxx1; /* ??? */
PDCB pLinkDCB;
PDCB pDCBRunRobin;
PDCB pActiveDCB;
PDCB pDCB_free;
PSRB pFreeSRB;
PSRB pTmpSRB;
USHORT SRBCount;
USHORT AdapterIndex; /*; nth Adapter this driver */
USHORT max_id;
USHORT max_lun;
UCHAR msgin123[4];
UCHAR status;
UCHAR AdaptSCSIID; /*; Adapter SCSI Target ID */
UCHAR AdaptSCSILUN; /*; Adapter SCSI LUN */
UCHAR DeviceCnt;
UCHAR IRQLevel;
UCHAR TagMaxNum;
UCHAR ACBFlag;
UCHAR Gmode2;
UCHAR LUNchk;
UCHAR scan_devices;
UCHAR HostID_Bit;
UCHAR Reserved1[1]; /*;for dword alignment */
UCHAR DCBmap[MAX_SCSI_ID];
DC390_DCB DCB_array[MAX_DEVICES]; /* +74h, Len=3E8 */
DC390_SRB SRB_array[MAX_SRB_CNT]; /* +45Ch, Len= */
DC390_SRB TmpSRB;
};
typedef struct _ACB DC390_ACB, *PACB;
/*;-----------------------------------------------------------------------*/
#define BIT31 0x80000000
#define BIT30 0x40000000
#define BIT29 0x20000000
#define BIT28 0x10000000
#define BIT27 0x08000000
#define BIT26 0x04000000
#define BIT25 0x02000000
#define BIT24 0x01000000
#define BIT23 0x00800000
#define BIT22 0x00400000
#define BIT21 0x00200000
#define BIT20 0x00100000
#define BIT19 0x00080000
#define BIT18 0x00040000
#define BIT17 0x00020000
#define BIT16 0x00010000
#define BIT15 0x00008000
#define BIT14 0x00004000
#define BIT13 0x00002000
#define BIT12 0x00001000
#define BIT11 0x00000800
#define BIT10 0x00000400
#define BIT9 0x00000200
#define BIT8 0x00000100
#define BIT7 0x00000080
#define BIT6 0x00000040
#define BIT5 0x00000020
#define BIT4 0x00000010
#define BIT3 0x00000008
#define BIT2 0x00000004
#define BIT1 0x00000002
#define BIT0 0x00000001
/*;---UnitCtrlFlag */
#define UNIT_ALLOCATED BIT0
#define UNIT_INFO_CHANGED BIT1
#define FORMATING_MEDIA BIT2
#define UNIT_RETRY BIT3
/*;---UnitFlags */
#define DASD_SUPPORT BIT0
#define SCSI_SUPPORT BIT1
#define ASPI_SUPPORT BIT2
/*;----SRBState machine definition */
#define SRB_FREE 0
#define SRB_WAIT BIT0
#define SRB_READY BIT1
#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/
#define SRB_MSGIN BIT3
#define SRB_MSGIN_MULTI BIT4
#define SRB_COMMAND BIT5
#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/
#define SRB_DISCONNECT BIT7
#define SRB_DATA_XFER BIT8
#define SRB_XFERPAD BIT9
#define SRB_STATUS BIT10
#define SRB_COMPLETED BIT11
#define SRB_ABORT_SENT BIT12
#define DO_SYNC_NEGO BIT13
#define SRB_UNEXPECT_RESEL BIT14
/*;---ACBFlag */
#define RESET_DEV BIT0
#define RESET_DETECT BIT1
#define RESET_DONE BIT2
/*;---DCBFlag */
#define ABORT_DEV_ BIT0
/*;---SRBstatus */
#define SRB_OK BIT0
#define ABORTION BIT1
#define OVER_RUN BIT2
#define UNDER_RUN BIT3
#define PARITY_ERROR BIT4
#define SRB_ERROR BIT5
/*;---SRBFlag */
#define DATAOUT BIT7
#define DATAIN BIT6
#define RESIDUAL_VALID BIT5
#define ENABLE_TIMER BIT4
#define RESET_DEV0 BIT2
#define ABORT_DEV BIT1
#define AUTO_REQSENSE BIT0
/*;---Adapter status */
#define H_STATUS_GOOD 0
#define H_SEL_TIMEOUT 0x11
#define H_OVER_UNDER_RUN 0x12
#define H_UNEXP_BUS_FREE 0x13
#define H_TARGET_PHASE_F 0x14
#define H_INVALID_CCB_OP 0x16
#define H_LINK_CCB_BAD 0x17
#define H_BAD_TARGET_DIR 0x18
#define H_DUPLICATE_CCB 0x19
#define H_BAD_CCB_OR_SG 0x1A
#define H_ABORT 0x0FF
/*; SCSI Status byte codes*/
#define SCSI_STAT_GOOD 0x0 /*; Good status */
#define SCSI_STAT_CHECKCOND 0x02 /*; SCSI Check Condition */
#define SCSI_STAT_CONDMET 0x04 /*; Condition Met */
#define SCSI_STAT_BUSY 0x08 /*; Target busy status */
#define SCSI_STAT_INTER 0x10 /*; Intermediate status */
#define SCSI_STAT_INTERCONDMET 0x14 /*; Intermediate condition met */
#define SCSI_STAT_RESCONFLICT 0x18 /*; Reservation conflict */
#define SCSI_STAT_CMDTERM 0x22 /*; Command Terminated */
#define SCSI_STAT_QUEUEFULL 0x28 /*; Queue Full */
#define SCSI_STAT_UNEXP_BUS_F 0xFD /*; Unexpect Bus Free */
#define SCSI_STAT_BUS_RST_DETECT 0xFE /*; Scsi Bus Reset detected */
#define SCSI_STAT_SEL_TIMEOUT 0xFF /*; Selection Time out */
/*;---Sync_Mode */
#define SYNC_DISABLE 0
#define SYNC_ENABLE BIT0
#define SYNC_NEGO_DONE BIT1
#define WIDE_ENABLE BIT2
#define WIDE_NEGO_DONE BIT3
#define EN_TAG_QUEUING BIT4
#define EN_ATN_STOP BIT5
#define SYNC_NEGO_OFFSET 15
/*;---SCSI bus phase*/
#define SCSI_DATA_OUT 0
#define SCSI_DATA_IN 1
#define SCSI_COMMAND 2
#define SCSI_STATUS_ 3
#define SCSI_NOP0 4
#define SCSI_NOP1 5
#define SCSI_MSG_OUT 6
#define SCSI_MSG_IN 7
/*;----SCSI MSG BYTE*/
#define MSG_COMPLETE 0x00
#define MSG_EXTENDED 0x01
#define MSG_SAVE_PTR 0x02
#define MSG_RESTORE_PTR 0x03
#define MSG_DISCONNECT 0x04
#define MSG_INITIATOR_ERROR 0x05
#define MSG_ABORT 0x06
#define MSG_REJECT_ 0x07
#define MSG_NOP 0x08
#define MSG_PARITY_ERROR 0x09
#define MSG_LINK_CMD_COMPL 0x0A
#define MSG_LINK_CMD_COMPL_FLG 0x0B
#define MSG_BUS_RESET 0x0C
#define MSG_ABORT_TAG 0x0D
#define MSG_SIMPLE_QTAG 0x20
#define MSG_HEAD_QTAG 0x21
#define MSG_ORDER_QTAG 0x22
#define MSG_IDENTIFY 0x80
#define MSG_HOST_ID 0x0C0
/*;----SCSI STATUS BYTE*/
#define STATUS_GOOD 0x00
#define CHECK_CONDITION_ 0x02
#define STATUS_BUSY 0x08
#define STATUS_INTERMEDIATE 0x10
#define RESERVE_CONFLICT 0x18
/* cmd->result */
#define STATUS_MASK_ 0xFF
#define MSG_MASK 0xFF00
#define RETURN_MASK 0xFF0000
/*
** Inquiry Data format
*/
typedef struct _SCSIInqData { /* INQ */
UCHAR DevType; /* Periph Qualifier & Periph Dev Type*/
UCHAR RMB_TypeMod; /* rem media bit & Dev Type Modifier */
UCHAR Vers; /* ISO, ECMA, & ANSI versions */
UCHAR RDF; /* AEN, TRMIOP, & response data format*/
UCHAR AddLen; /* length of additional data */
UCHAR Res1; /* reserved */
UCHAR Res2; /* reserved */
UCHAR Flags; /* RelADr,Wbus32,Wbus16,Sync,etc. */
UCHAR VendorID[8]; /* Vendor Identification */
UCHAR ProductID[16]; /* Product Identification */
UCHAR ProductRev[4]; /* Product Revision */
} SCSI_INQDATA, *PSCSI_INQDATA;
/* Inquiry byte 0 masks */
#define SCSI_DEVTYPE 0x1F /* Peripheral Device Type */
#define SCSI_PERIPHQUAL 0xE0 /* Peripheral Qualifier */
/* Inquiry byte 1 mask */
#define SCSI_REMOVABLE_MEDIA 0x80 /* Removable Media bit (1=removable) */
/* Peripheral Device Type definitions */
#define SCSI_DASD 0x00 /* Direct-access Device */
#define SCSI_SEQACESS 0x01 /* Sequential-access device */
#define SCSI_PRINTER 0x02 /* Printer device */
#define SCSI_PROCESSOR 0x03 /* Processor device */
#define SCSI_WRITEONCE 0x04 /* Write-once device */
#define SCSI_CDROM 0x05 /* CD-ROM device */
#define SCSI_SCANNER 0x06 /* Scanner device */
#define SCSI_OPTICAL 0x07 /* Optical memory device */
#define SCSI_MEDCHGR 0x08 /* Medium changer device */
#define SCSI_COMM 0x09 /* Communications device */
#define SCSI_NODEV 0x1F /* Unknown or no device type */
/*
** Inquiry flag definitions (Inq data byte 7)
*/
#define SCSI_INQ_RELADR 0x80 /* device supports relative addressing*/
#define SCSI_INQ_WBUS32 0x40 /* device supports 32 bit data xfers */
#define SCSI_INQ_WBUS16 0x20 /* device supports 16 bit data xfers */
#define SCSI_INQ_SYNC 0x10 /* device supports synchronous xfer */
#define SCSI_INQ_LINKED 0x08 /* device supports linked commands */
#define SCSI_INQ_CMDQUEUE 0x02 /* device supports command queueing */
#define SCSI_INQ_SFTRE 0x01 /* device supports soft resets */
/*
;==========================================================
; EEPROM byte offset
;==========================================================
*/
typedef struct _EEprom
{
UCHAR EE_MODE1;
UCHAR EE_SPEED;
UCHAR xx1;
UCHAR xx2;
} EEprom, *PEEprom;
#define EE_ADAPT_SCSI_ID 64
#define EE_MODE2 65
#define EE_DELAY 66
#define EE_TAG_CMD_NUM 67
/*; EE_MODE1 bits definition*/
#define PARITY_CHK_ BIT0
#define SYNC_NEGO_ BIT1
#define EN_DISCONNECT_ BIT2
#define SEND_START_ BIT3
#define TAG_QUEUING_ BIT4
/*; EE_MODE2 bits definition*/
#define MORE2_DRV BIT0
#define GREATER_1G BIT1
#define RST_SCSI_BUS BIT2
#define ACTIVE_NEGATION BIT3
#define NO_SEEK BIT4
#define LUN_CHECK BIT5
#define ENABLE_CE 1
#define DISABLE_CE 0
#define EEPROM_READ 0x80
/*
;==========================================================
; AMD 53C974 Registers bit Definition
;==========================================================
*/
/*
;====================
; SCSI Register
;====================
*/
/*; Command Reg.(+0CH) */
#define DMA_COMMAND BIT7
#define NOP_CMD 0
#define CLEAR_FIFO_CMD 1
#define RST_DEVICE_CMD 2
#define RST_SCSI_BUS_CMD 3
#define INFO_XFER_CMD 0x10
#define INITIATOR_CMD_CMPLTE 0x11
#define MSG_ACCEPTED_CMD 0x12
#define XFER_PAD_BYTE 0x18
#define SET_ATN_CMD 0x1A
#define RESET_ATN_CMD 0x1B
#define SELECT_W_ATN 0x42
#define SEL_W_ATN_STOP 0x43
#define EN_SEL_RESEL 0x44
#define SEL_W_ATN2 0x46
#define DATA_XFER_CMD INFO_XFER_CMD
/*; SCSI Status Reg.(+10H) */
#define INTERRUPT BIT7
#define ILLEGAL_OP_ERR BIT6
#define PARITY_ERR BIT5
#define COUNT_2_ZERO BIT4
#define GROUP_CODE_VALID BIT3
#define SCSI_PHASE_MASK (BIT2+BIT1+BIT0)
/*; Interrupt Status Reg.(+14H) */
#define SCSI_RESET BIT7
#define INVALID_CMD BIT6
#define DISCONNECTED BIT5
#define SERVICE_REQUEST BIT4
#define SUCCESSFUL_OP BIT3
#define RESELECTED BIT2
#define SEL_ATTENTION BIT1
#define SELECTED BIT0
/*; Internal State Reg.(+18H) */
#define SYNC_OFFSET_FLAG BIT3
#define INTRN_STATE_MASK (BIT2+BIT1+BIT0)
/*; Clock Factor Reg.(+24H) */
#define CLK_FREQ_40MHZ 0
#define CLK_FREQ_35MHZ (BIT2+BIT1+BIT0)
#define CLK_FREQ_30MHZ (BIT2+BIT1)
#define CLK_FREQ_25MHZ (BIT2+BIT0)
#define CLK_FREQ_20MHZ BIT2
#define CLK_FREQ_15MHZ (BIT1+BIT0)
#define CLK_FREQ_10MHZ BIT1
/*; Control Reg. 1(+20H) */
#define EXTENDED_TIMING BIT7
#define DIS_INT_ON_SCSI_RST BIT6
#define PARITY_ERR_REPO BIT4
#define SCSI_ID_ON_BUS (BIT2+BIT1+BIT0)
/*; Control Reg. 2(+2CH) */
#define EN_FEATURE BIT6
#define EN_SCSI2_CMD BIT3
/*; Control Reg. 3(+30H) */
#define ID_MSG_CHECK BIT7
#define EN_QTAG_MSG BIT6
#define EN_GRP2_CMD BIT5
#define FAST_SCSI BIT4 /* ;10MB/SEC */
#define FAST_CLK BIT3 /* ;25 - 40 MHZ */
/*; Control Reg. 4(+34H) */
#define EATER_12NS 0
#define EATER_25NS BIT7
#define EATER_35NS BIT6
#define EATER_0NS (BIT7+BIT6)
#define NEGATE_REQACKDATA BIT2
#define NEGATE_REQACK BIT3
/*
;====================
; DMA Register
;====================
*/
/*; DMA Command Reg.(+40H) */
#define READ_DIRECTION BIT7
#define WRITE_DIRECTION 0
#define EN_DMA_INT BIT6
#define MAP_TO_MDL BIT5
#define DIAGNOSTIC BIT4
#define DMA_IDLE_CMD 0
#define DMA_BLAST_CMD BIT0
#define DMA_ABORT_CMD BIT1
#define DMA_START_CMD (BIT1+BIT0)
/*; DMA Status Reg.(+54H) */
#define PCI_MS_ABORT BIT6
#define BLAST_COMPLETE BIT5
#define SCSI_INTERRUPT BIT4
#define DMA_XFER_DONE BIT3
#define DMA_XFER_ABORT BIT2
#define DMA_XFER_ERROR BIT1
#define POWER_DOWN BIT0
/*
; DMA SCSI Bus and Ctrl.(+70H)
;EN_INT_ON_PCI_ABORT
*/
/*
;==========================================================
; SCSI Chip register address offset
;==========================================================
*/
#define CtcReg_Low 0x00
#define CtcReg_Mid 0x04
#define ScsiFifo 0x08
#define ScsiCmd 0x0C
#define Scsi_Status 0x10
#define INT_Status 0x14
#define Sync_Period 0x18
#define Sync_Offset 0x1C
#define CtrlReg1 0x20
#define Clk_Factor 0x24
#define CtrlReg2 0x2C
#define CtrlReg3 0x30
#define CtrlReg4 0x34
#define CtcReg_High 0x38
#define DMA_Cmd 0x40
#define DMA_XferCnt 0x44
#define DMA_XferAddr 0x48
#define DMA_Wk_ByteCntr 0x4C
#define DMA_Wk_AddrCntr 0x50
#define DMA_Status 0x54
#define DMA_MDL_Addr 0x58
#define DMA_Wk_MDL_Cntr 0x5C
#define DMA_ScsiBusCtrl 0x70
#define StcReg_Low CtcReg_Low
#define StcReg_Mid CtcReg_Mid
#define Scsi_Dest_ID Scsi_Status
#define Scsi_TimeOut INT_Status
#define Intern_State Sync_Period
#define Current_Fifo Sync_Offset
#define StcReg_High CtcReg_High
#define am_target Scsi_Status
#define am_timeout INT_Status
#define am_seq_step Sync_Period
#define am_fifo_count Sync_Offset
#define DC390_read8(address) \
inb(DC390_ioport + (address)))
#define DC390_read16(address) \
inw(DC390_ioport + (address)))
#define DC390_read32(address) \
inl(DC390_ioport + (address)))
#define DC390_write8(address,value) \
outb((value), DC390_ioport + (address)))
#define DC390_write16(address,value) \
outw((value), DC390_ioport + (address)))
#define DC390_write32(address,value) \
outl((value), DC390_ioport + (address)))
/* Configuration method #1 */
#define PCI_CFG1_ADDRESS_REG 0xcf8
#define PCI_CFG1_DATA_REG 0xcfc
#define PCI_CFG1_ENABLE 0x80000000
#define PCI_CFG1_TUPPLE(bus, device, function, register) \
(PCI_CFG1_ENABLE | (((bus) << 16) & 0xff0000) | \
(((device) << 11) & 0xf800) | (((function) << 8) & 0x700)| \
(((register) << 2) & 0xfc))
/* Configuration method #2 */
#define PCI_CFG2_ENABLE_REG 0xcf8
#define PCI_CFG2_FORWARD_REG 0xcfa
#define PCI_CFG2_ENABLE 0x0f0
#define PCI_CFG2_TUPPLE(function) \
(PCI_CFG2_ENABLE | (((function) << 1) & 0xe))
#endif /* TMSCSIM_H */
#
# Sound driver configuration
#
#--------
# There is another confic script which is compatible with rest of
# the kernel. It can be activated by running 'make mkscript' in this
# directory. Please note that this is an _experimental_ feature which
# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro, Maui).
#--------
#
$MAKE -C drivers/sound config || exit 1
bool 'ProAudioSpectrum 16 support' CONFIG_PAS
bool '_TRUE_ Sound Blaster (SB, SBPro, SB16/32/64, ESS, Jazz16) support' CONFIG_SB
bool 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB
bool 'Gravis Ultrasound support' CONFIG_GUS
bool 'MPU-401 support (NOT for SB16)' CONFIG_MPU401
bool 'PSS (ECHO-ADI2111) support' CONFIG_PSS
bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16
bool 'GUS MAX support' CONFIG_GUSMAX
bool 'Microsoft Sound System support' CONFIG_MSS
bool 'Ensoniq SoundScape support' CONFIG_SSCAPE
bool 'MediaTrix AudioTrix Pro support' CONFIG_TRIX
bool 'Support for MAD16 and/or Mozart based cards' CONFIG_MAD16
bool 'Support for Crystal CS4232 based (PnP) cards' CONFIG_CS4232
bool 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_MAUI
bool 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812
if [ "$CONFIG_AEDSP16" = "y" ]; then
hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220
fi
if [ "$CONFIG_SB" = "y" ]; then
hex 'I/O base for SB Check from manual of the card' SBC_BASE 220
fi
if [ "$CONFIG_SB" = "y" ]; then
int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7
fi
if [ "$CONFIG_SB" = "y" ]; then
int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1
fi
if [ "$CONFIG_SB" = "y" ]; then
int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5
fi
if [ "$CONFIG_SB" = "y" ]; then
hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330
fi
if [ "$CONFIG_SB" = "y" ]; then
comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.'
fi
if [ "$CONFIG_SB" = "y" ]; then
comment 'Enter -1 to the following question if you have something else such as SB16/32.'
fi
if [ "$CONFIG_SB" = "y" ]; then
int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1
fi
if [ "$CONFIG_PAS" = "y" ]; then
int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10
fi
if [ "$CONFIG_PAS" = "y" ]; then
int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3
fi
if [ "$CONFIG_GUS" = "y" ]; then
hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220
fi
if [ "$CONFIG_GUS" = "y" ]; then
int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15
fi
if [ "$CONFIG_GUS" = "y" ]; then
int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6
fi
if [ "$CONFIG_GUS" = "y" ]; then
int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1
fi
if [ "$CONFIG_GUS16" = "y" ]; then
hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530
fi
if [ "$CONFIG_GUS16" = "y" ]; then
int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7
fi
if [ "$CONFIG_GUS16" = "y" ]; then
int 'GUS DMA 0, 1 or 3' GUS16_DMA 3
fi
if [ "$CONFIG_MPU401" = "y" ]; then
hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330
fi
if [ "$CONFIG_MPU401" = "y" ]; then
int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9
fi
if [ "$CONFIG_MAUI" = "y" ]; then
comment 'ERROR! You have to use old sound configuration method with Maui.'
fi
if [ "$CONFIG_MAUI" = "y" ]; then
hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330
fi
if [ "$CONFIG_MAUI" = "y" ]; then
int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9
fi
if [ "$CONFIG_UART6850" = "y" ]; then
hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0
fi
if [ "$CONFIG_UART6850" = "y" ]; then
int 'UART6850 IRQ (Unknown)' U6850_IRQ -1
fi
if [ "$CONFIG_PSS" = "y" ]; then
comment 'ERROR! You have to use old sound configuration method with PSS cards.'
fi
if [ "$CONFIG_PSS" = "y" ]; then
hex 'PSS I/O base 220 or 240' PSS_BASE 220
fi
if [ "$CONFIG_PSS" = "y" ]; then
hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530
fi
if [ "$CONFIG_PSS" = "y" ]; then
int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11
fi
if [ "$CONFIG_PSS" = "y" ]; then
int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3
fi
if [ "$CONFIG_PSS" = "y" ]; then
hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330
fi
if [ "$CONFIG_PSS" = "y" ]; then
int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9
fi
if [ "$CONFIG_MSS" = "y" ]; then
hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530
fi
if [ "$CONFIG_MSS" = "y" ]; then
int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11
fi
if [ "$CONFIG_MSS" = "y" ]; then
int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3
fi
if [ "$CONFIG_MSS" = "y" ]; then
int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1
fi
if [ "$CONFIG_SSCAPE" = "y" ]; then
hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330
fi
if [ "$CONFIG_SSCAPE" = "y" ]; then
int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9
fi
if [ "$CONFIG_SSCAPE" = "y" ]; then
int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3
fi
if [ "$CONFIG_SSCAPE" = "y" ]; then
hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534
fi
if [ "$CONFIG_SSCAPE" = "y" ]; then
int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11
fi
if [ "$CONFIG_TRIX" = "y" ]; then
comment 'ERROR! You have to use old sound configuration method with AudioTrix.'
fi
if [ "$CONFIG_TRIX" = "y" ]; then
hex 'AudioTrix audio I/O base 530, 604, E80 or F40' TRIX_BASE 530
fi
if [ "$CONFIG_TRIX" = "y" ]; then
int 'AudioTrix audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11
fi
if [ "$CONFIG_TRIX" = "y" ]; then
int 'AudioTrix audio DMA 0, 1 or 3' TRIX_DMA 0
fi
if [ "$CONFIG_TRIX" = "y" ]; then
int 'AudioTrix second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3
fi
if [ "$CONFIG_TRIX" = "y" ]; then
hex 'AudioTrix MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330
fi
if [ "$CONFIG_TRIX" = "y" ]; then
int 'AudioTrix MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9
fi
if [ "$CONFIG_TRIX" = "y" ]; then
hex 'AudioTrix SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220
fi
if [ "$CONFIG_TRIX" = "y" ]; then
int 'AudioTrix SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7
fi
if [ "$CONFIG_TRIX" = "y" ]; then
int 'AudioTrix SB DMA 1 or 3' TRIX_SB_DMA 1
fi
if [ "$CONFIG_CS4232" = "y" ]; then
hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530
fi
if [ "$CONFIG_CS4232" = "y" ]; then
int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11
fi
if [ "$CONFIG_CS4232" = "y" ]; then
int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0
fi
if [ "$CONFIG_CS4232" = "y" ]; then
int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3
fi
if [ "$CONFIG_CS4232" = "y" ]; then
hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330
fi
if [ "$CONFIG_CS4232" = "y" ]; then
int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9
fi
if [ "$CONFIG_MAD16" = "y" ]; then
hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530
fi
if [ "$CONFIG_MAD16" = "y" ]; then
int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11
fi
if [ "$CONFIG_MAD16" = "y" ]; then
int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3
fi
if [ "$CONFIG_MAD16" = "y" ]; then
int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0
fi
if [ "$CONFIG_MAD16" = "y" ]; then
hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330
fi
if [ "$CONFIG_MAD16" = "y" ]; then
int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9
fi
#
$MAKE -C drivers/sound kernelconfig || exit 1
bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
......
......@@ -39,7 +39,7 @@ extern struct hae {
extern inline void set_hae(unsigned long new_hae)
{
unsigned long ipl;
swpipl(ipl,7);
ipl = swpipl(7);
hae.cache = new_hae;
*hae.reg = new_hae;
mb();
......
......@@ -15,7 +15,7 @@ typedef struct { int dummy; } spinlock_t;
#define spin_lock_irq(lock) setipl(7)
#define spin_unlock_irq(lock) setipl(0)
#define spin_lock_irqsave(lock, flags) swpipl(flags,7)
#define spin_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0)
#define spin_unlock_irqrestore(lock, flags) setipl(flags)
/*
......@@ -40,9 +40,9 @@ typedef struct { int dummy; } rwlock_t;
#define write_lock_irq(lock) cli()
#define write_unlock_irq(lock) sti()
#define read_lock_irqsave(lock, flags) swpipl(flags,7)
#define read_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0)
#define read_unlock_irqrestore(lock, flags) setipl(flags)
#define write_lock_irqsave(lock, flags) swpipl(flags,7)
#define write_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0)
#define write_unlock_irqrestore(lock, flags) setipl(flags)
#else
......@@ -117,7 +117,7 @@ static inline void spin_lock(spinlock_t * lock)
do { spin_unlock(lock); __sti(); } while (0)
#define spin_lock_irqsave(lock, flags) \
do { swpipl(flags,7); spin_lock(lock); } while (0)
do { flags = swpipl(7); spin_lock(lock); } while (0)
#define spin_unlock_irqrestore(lock, flags) \
do { spin_unlock(lock); setipl(flags); } while (0)
......
......@@ -62,57 +62,89 @@ extern void wrmces (unsigned long);
extern void alpha_switch_to(unsigned long pctxp);
extern void imb(void);
#define mb() \
__asm__ __volatile__("mb": : :"memory")
#define imb() \
__asm__ __volatile__ ("call_pal %0" : : "i" (PAL_imb) : "memory")
#define draina() \
__asm__ __volatile__ ("call_pal %0" : : "i" (PAL_draina) : "memory")
#define getipl(__old_ipl) \
__asm__ __volatile__( \
"call_pal 54\n\t" \
"bis $0,$0,%0" \
: "=r" (__old_ipl) \
: : "$0", "$1", "$16", "$22", "$23", "$24", "$25")
#define setipl(__new_ipl) \
__asm__ __volatile__( \
"bis %0,%0,$16\n\t" \
"call_pal 53" \
: : "r" (__new_ipl) \
: "$0", "$1", "$16", "$22", "$23", "$24", "$25", "memory")
#define swpipl(__old_ipl,__new_ipl) \
__asm__ __volatile__( \
"bis %1,%1,$16\n\t" \
"call_pal 53\n\t" \
"bis $0,$0,%0" \
: "=r" (__old_ipl) \
: "r" (__new_ipl) \
: "$0", "$1", "$16", "$22", "$23", "$24", "$25", "memory")
#define call_pal1(palno,arg) \
({ \
register unsigned long __r0 __asm__("$0"); \
register unsigned long __r16 __asm__("$16"); __r16 = arg; \
__asm__ __volatile__( \
"call_pal %3" \
:"=r" (__r0),"=r" (__r16) \
:"1" (__r16),"i" (palno) \
:"$1", "$22", "$23", "$24", "$25", "memory"); \
__r0; \
})
#define getipl() \
({ \
register unsigned long r0 __asm__("$0"); \
__asm__ __volatile__( \
"call_pal %1" \
:"=r" (r0) \
:"i" (PAL_rdps) \
:"$1", "$16", "$22", "$23", "$24", "$25", "memory"); \
r0; \
})
#define setipl(ipl) \
do { \
register unsigned long __r16 __asm__("$16") = (ipl); \
__asm__ __volatile__( \
"call_pal %2" \
:"=r" (__r16) \
:"0" (__r16),"i" (PAL_swpipl) \
:"$0", "$1", "$22", "$23", "$24", "$25", "memory"); \
} while (0)
#define swpipl(ipl) \
({ \
register unsigned long __r0 __asm__("$0"); \
register unsigned long __r16 __asm__("$16") = (ipl); \
__asm__ __volatile__( \
"call_pal %3" \
:"=r" (__r0),"=r" (__r16) \
:"1" (__r16),"i" (PAL_swpipl) \
:"$1", "$22", "$23", "$24", "$25", "memory"); \
__r0; \
})
#define __cli() setipl(7)
#define __sti() setipl(0)
#define __save_flags(flags) getipl(flags)
#define __save_flags(flags) do { (flags) = getipl(); } while (0)
#define __restore_flags(flags) setipl(flags)
#define cli() setipl(7)
#define sti() setipl(0)
#define save_flags(flags) getipl(flags)
#define save_flags(flags) do { (flags) = getipl(); } while (0)
#define restore_flags(flags) setipl(flags)
/*
* TB routines..
*/
extern void tbi(long type, ...);
#define __tbi(nr,arg,arg1...) do { \
register unsigned long __r16 __asm__("$16") = (nr); \
register unsigned long __r17 __asm__("$17"); arg; \
__asm__ __volatile__( \
"call_pal %3" \
:"=r" (__r16),"=r" (__r17) \
:"0" (__r16),"i" (PAL_tbi) ,##arg1 \
:"$0", "$1", "$22", "$23", "$24", "$25"); \
} while (0)
#define tbisi(x) tbi(1,(x))
#define tbisd(x) tbi(2,(x))
#define tbis(x) tbi(3,(x))
#define tbiap() tbi(-1)
#define tbia() tbi(-2)
#define tbi(x,y) __tbi(x,__r17=(y),"1" (__r17))
#define tbisi(x) __tbi(1,__r17=(x),"1" (__r17))
#define tbisd(x) __tbi(2,__r17=(x),"1" (__r17))
#define tbis(x) __tbi(3,__r17=(x),"1" (__r17))
#define tbiap() __tbi(-1, /* no second argument */)
#define tbia() __tbi(-2, /* no second argument */)
/*
* Give prototypes to shut up gcc.
......
......@@ -80,7 +80,7 @@ __asm__ __volatile__( \
"\n1:\t" \
"lock ; btsl $0,%0\n\t" \
"jc 2f\n" \
".section .text.lock\n" \
".section .text.lock,\"ax\"\n" \
"2:\t" \
"testb $1,%0\n\t" \
"jne 2b\n\t" \
......@@ -134,7 +134,7 @@ typedef struct {
asm volatile("\n1:\t" \
"lock ; incl %0\n\t" \
"js 2f\n" \
".section .text.lock\n" \
".section .text.lock,\"ax\"\n" \
"2:\tlock ; decl %0\n" \
"3:\tcmpl $0,%0\n\t" \
"js 3b\n\t" \
......@@ -153,7 +153,7 @@ typedef struct {
"testl $0x7fffffff,%0\n\t" \
"jne 4f\n" \
"2:\n" \
".section .text.lock\n" \
".section .text.lock,\"ax\"\n" \
"3:\ttestl $-1,%0\n\t" \
"js 3b\n\t" \
"lock ; btsl $31,%0\n\t" \
......
/*
/* $Revision: 1.7 $$Date: 1997/03/26 10:30:00 $
* linux/include/linux/cyclades.h
*
* This file is maintained by Marcio Saito <marcio@cyclades.com> and
......@@ -6,9 +6,18 @@
*
* This file contains the general definitions for the cyclades.c driver
*$Log: cyclades.h,v $
* Revision 1.5 1995/11/13 21:13:31 bentson
* changes suggested by Michael Chastain <mec@duracef.shout.net>
* to support use of this file in non-kernel applications
*Revision 1.7 1997/03/26 10:30:00 daniel
*new entries at the end of cyclades_port struct to reallocate
*variables illegally allocated within card memory.
*
*Revision 1.6 1996/09/09 18:35:30 bentson
*fold in changes for Cyclom-Z -- including structures for
*communicating with board as well modest changes to original
*structures to support new features.
*
*Revision 1.5 1995/11/13 21:13:31 bentson
*changes suggested by Michael Chastain <mec@duracef.shout.net>
*to support use of this file in non-kernel applications
*
*
*/
......@@ -35,14 +44,359 @@ struct cyclades_monitor {
#define CYGETDEFTIMEOUT 0x435908
#define CYSETDEFTIMEOUT 0x435909
/*************** CYCLOM-Z ADDITIONS ***************/
#define CZIOC ('M' << 8)
#define CZ_NBOARDS (CZIOC|0xfa)
#define CZ_BOOT_START (CZIOC|0xfb)
#define CZ_BOOT_DATA (CZIOC|0xfc)
#define CZ_BOOT_END (CZIOC|0xfd)
#define CZ_TEST (CZIOC|0xfe)
#define MAX_BOARD 4 /* Max number of boards */
#define MAX_PORT 128 /* Max number of ports per board */
#define MAX_DEV 256 /* Max number of ports total */
#define CYZ_BOOT_NWORDS 0x100
struct CYZ_BOOT_CTRL {
unsigned short nboard;
int status[MAX_BOARD];
int nchannel[MAX_BOARD];
int fw_rev[MAX_BOARD];
unsigned long offset;
unsigned long data[CYZ_BOOT_NWORDS];
};
#ifndef DP_WINDOW_SIZE
/* #include "cyclomz.h" */
/****************** ****************** *******************/
/*
* The data types defined below are used in all ZFIRM interface
* data structures. They accomodate differences between HW
* architectures and compilers.
*/
typedef unsigned long uclong; /* 32 bits, unsigned */
typedef unsigned short ucshort; /* 16 bits, unsigned */
typedef unsigned char ucchar; /* 8 bits, unsigned */
/*
* Memory Window Sizes
*/
#define DP_WINDOW_SIZE (0x00080000) /* window size 512 Kb */
#define CTRL_WINDOW_SIZE (0x00000100) /* runtime regs 256 bytes */
/*
* CUSTOM_REG - Cyclom-Z/PCI Custom Registers Set. The driver
* normally will access only interested on the fpga_id, fpga_version,
* start_cpu and stop_cpu.
*/
struct CUSTOM_REG {
uclong fpga_id; /* FPGA Identification Register */
uclong fpga_version; /* FPGA Version Number Register */
uclong cpu_start; /* CPU start Register (write) */
uclong cpu_stop; /* CPU stop Register (write) */
uclong misc_reg; /* Miscelaneous Register */
uclong idt_mode; /* IDT mode Register */
uclong uart_irq_status; /* UART IRQ status Register */
uclong clear_timer0_irq; /* Clear timer interrupt Register */
uclong clear_timer1_irq; /* Clear timer interrupt Register */
uclong clear_timer2_irq; /* Clear timer interrupt Register */
uclong test_register; /* Test Register */
uclong test_count; /* Test Count Register */
uclong timer_select; /* Timer select register */
uclong pr_uart_irq_status; /* Prioritized UART IRQ stat Reg */
uclong ram_wait_state; /* RAM wait-state Register */
uclong uart_wait_state; /* UART wait-state Register */
uclong timer_wait_state; /* timer wait-state Register */
uclong ack_wait_state; /* ACK wait State Register */
};
/*
* RUNTIME_9060 - PLX PCI9060ES local configuration and shared runtime
* registers. This structure can be used to access the 9060 registers
* (memory mapped).
*/
struct RUNTIME_9060 {
uclong loc_addr_range; /* 00h - Local Address Range */
uclong loc_addr_base; /* 04h - Local Address Base */
uclong loc_arbitr; /* 08h - Local Arbitration */
uclong endian_descr; /* 0Ch - Big/Little Endian Descriptor */
uclong loc_rom_range; /* 10h - Local ROM Range */
uclong loc_rom_base; /* 14h - Local ROM Base */
uclong loc_bus_descr; /* 18h - Local Bus descriptor */
uclong loc_range_mst; /* 1Ch - Local Range for Master to PCI */
uclong loc_base_mst; /* 20h - Local Base for Master PCI */
uclong loc_range_io; /* 24h - Local Range for Master IO */
uclong pci_base_mst; /* 28h - PCI Base for Master PCI */
uclong pci_conf_io; /* 2Ch - PCI configuration for Master IO */
uclong filler1; /* 30h */
uclong filler2; /* 34h */
uclong filler3; /* 38h */
uclong filler4; /* 3Ch */
uclong mail_box_0; /* 40h - Mail Box 0 */
uclong mail_box_1; /* 44h - Mail Box 1 */
uclong mail_box_2; /* 48h - Mail Box 2 */
uclong mail_box_3; /* 4Ch - Mail Box 3 */
uclong filler5; /* 50h */
uclong filler6; /* 54h */
uclong filler7; /* 58h */
uclong filler8; /* 5Ch */
uclong pci_doorbell; /* 60h - PCI to Local Doorbell */
uclong loc_doorbell; /* 64h - Local to PCI Doorbell */
uclong intr_ctrl_stat; /* 68h - Interrupt Control/Status */
uclong init_ctrl; /* 6Ch - EEPROM control, Init Control, etc */
};
/* Values for the Local Base Address re-map register */
#define WIN_RAM 0x00000001L /* set the sliding window to RAM */
#define WIN_CREG 0x14000001L /* set the window to custom Registers */
/* Values timer select registers */
#define TIMER_BY_1M 0x00 /* clock divided by 1M */
#define TIMER_BY_256K 0x01 /* clock divided by 256k */
#define TIMER_BY_128K 0x02 /* clock divided by 128k */
#define TIMER_BY_32K 0x03 /* clock divided by 32k */
/****************** ****************** *******************/
#endif
#ifndef ZFIRM_ID
/* #include "zfwint.h" */
/****************** ****************** *******************/
/*
* This file contains the definitions for interfacing with the
* Cyclom-Z ZFIRM Firmware.
*/
/* General Constant definitions */
#define MAX_CHAN 64 /* max number of channels per board */
/* firmware id structure (set after boot) */
#define ID_ADDRESS 0x00000180L /* signature/pointer address */
#define ZFIRM_ID 0x5557465AL /* ZFIRM/U signature */
struct FIRM_ID {
uclong signature; /* ZFIRM/U signature */
uclong zfwctrl_addr; /* pointer to ZFW_CTRL structure */
};
/* Op. System id */
#define C_OS_LINUX 0x00000030 /* generic Linux system */
/* channel op_mode */
#define C_CH_DISABLE 0x00000000 /* channel is disabled */
#define C_CH_TXENABLE 0x00000001 /* channel Tx enabled */
#define C_CH_RXENABLE 0x00000002 /* channel Rx enabled */
#define C_CH_ENABLE 0x00000003 /* channel Tx/Rx enabled */
#define C_CH_LOOPBACK 0x00000004 /* Loopback mode */
/* comm_parity - parity */
#define C_PR_NONE 0x00000000 /* None */
#define C_PR_ODD 0x00000001 /* Odd */
#define C_PR_EVEN 0x00000002 /* Even */
#define C_PR_MARK 0x00000004 /* Mark */
#define C_PR_SPACE 0x00000008 /* Space */
#define C_PR_PARITY 0x000000ff
#define C_PR_DISCARD 0x00000100 /* discard char with frame/par error */
#define C_PR_IGNORE 0x00000200 /* ignore frame/par error */
/* comm_data_l - data length and stop bits */
#define C_DL_CS5 0x00000001
#define C_DL_CS6 0x00000002
#define C_DL_CS7 0x00000004
#define C_DL_CS8 0x00000008
#define C_DL_CS 0x0000000f
#define C_DL_1STOP 0x00000010
#define C_DL_15STOP 0x00000020
#define C_DL_2STOP 0x00000040
#define C_DL_STOP 0x000000f0
/* interrupt enabling/status */
#define C_IN_DISABLE 0x00000000 /* zero, disable interrupts */
#define C_IN_TXBEMPTY 0x00000001 /* tx buffer empty */
#define C_IN_TXLOWWM 0x00000002 /* tx buffer below LWM */
#define C_IN_RXHIWM 0x00000010 /* rx buffer above HWM */
#define C_IN_RXNNDT 0x00000020 /* rx no new data timeout */
#define C_IN_MDCD 0x00000100 /* modem DCD change */
#define C_IN_MDSR 0x00000200 /* modem DSR change */
#define C_IN_MRI 0x00000400 /* modem RI change */
#define C_IN_MCTS 0x00000800 /* modem CTS change */
#define C_IN_RXBRK 0x00001000 /* Break received */
#define C_IN_PR_ERROR 0x00002000 /* parity error */
#define C_IN_FR_ERROR 0x00004000 /* frame error */
/* flow control */
#define C_FL_OXX 0x00000001 /* output Xon/Xoff flow control */
#define C_FL_IXX 0x00000002 /* output Xon/Xoff flow control */
#define C_FL_OIXANY 0x00000004 /* output Xon/Xoff (any xon) */
#define C_FL_SWFLOW 0x0000000f
/* flow status */
#define C_FS_TXIDLE 0x00000000 /* no Tx data in the buffer or UART */
#define C_FS_SENDING 0x00000001 /* UART is sending data */
#define C_FS_SWFLOW 0x00000002 /* Tx is stopped by received Xoff */
/* rs_control/rs_status RS-232 signals */
#define C_RS_DCD 0x00000100 /* CD */
#define C_RS_DSR 0x00000200 /* DSR */
#define C_RS_RI 0x00000400 /* RI */
#define C_RS_CTS 0x00000800 /* CTS */
#define C_RS_RTS 0x00000001 /* RTS */
#define C_RS_DTR 0x00000004 /* DTR */
/* commands Host <-> Board */
#define C_CM_RESET 0x01 /* reset/flush buffers */
#define C_CM_IOCTL 0x02 /* re-read CH_CTRL */
#define C_CM_IOCTLW 0x03 /* re-read CH_CTRL, intr when done */
#define C_CM_IOCTLM 0x04 /* RS-232 outputs change */
#define C_CM_SENDXOFF 0x10 /* send Xoff */
#define C_CM_SENDXON 0x11 /* send Xon */
#define C_CM_CLFLOW 0x12 /* Clear flow control (resume) */
#define C_CM_SENDBRK 0x41 /* send break */
#define C_CM_INTBACK 0x42 /* Interrupt back */
#define C_CM_SET_BREAK 0x43 /* Tx break on */
#define C_CM_CLR_BREAK 0x44 /* Tx break off */
#define C_CM_CMD_DONE 0x45 /* Previous command done */
#define C_CM_TINACT 0x51 /* set inactivity detection */
#define C_CM_IRQ_ENBL 0x52 /* enable generation of interrupts */
#define C_CM_IRQ_DSBL 0x53 /* disable generation of interrupts */
#define C_CM_ACK_ENBL 0x54 /* enable acknolowdged interrupt mode */
#define C_CM_ACK_DSBL 0x55 /* disable acknolowdged intr mode */
#define C_CM_FLUSH_RX 0x56 /* flushes Rx buffer */
#define C_CM_FLUSH_TX 0x57 /* flushes Tx buffer */
#define C_CM_TXBEMPTY 0x60 /* Tx buffer is empty */
#define C_CM_TXLOWWM 0x61 /* Tx buffer low water mark */
#define C_CM_RXHIWM 0x62 /* Rx buffer high water mark */
#define C_CM_RXNNDT 0x63 /* rx no new data timeout */
#define C_CM_MDCD 0x70 /* modem DCD change */
#define C_CM_MDSR 0x71 /* modem DSR change */
#define C_CM_MRI 0x72 /* modem RI change */
#define C_CM_MCTS 0x73 /* modem CTS change */
#define C_CM_RXBRK 0x84 /* Break received */
#define C_CM_PR_ERROR 0x85 /* Parity error */
#define C_CM_FR_ERROR 0x86 /* Frame error */
#define C_CM_CMDERROR 0x90 /* command error */
#define C_CM_FATAL 0x91 /* fatal error */
#define C_CM_HW_RESET 0x92 /* reset board */
/*
* CH_CTRL - This per port structure contains all parameters
* that control an specific port. It can be seen as the
* configuration registers of a "super-serial-controller".
*/
struct CH_CTRL {
uclong op_mode; /* operation mode */
uclong intr_enable; /* interrupt masking */
uclong sw_flow; /* SW flow control */
uclong flow_status; /* output flow status */
uclong comm_baud; /* baud rate - numerically specified */
uclong comm_parity; /* parity */
uclong comm_data_l; /* data length/stop */
uclong comm_flags; /* other flags */
uclong hw_flow; /* HW flow control */
uclong rs_control; /* RS-232 outputs */
uclong rs_status; /* RS-232 inputs */
uclong flow_xon; /* xon char */
uclong flow_xoff; /* xoff char */
uclong filler[3]; /* filler to align structures */
};
/*
* BUF_CTRL - This per channel structure contains
* all Tx and Rx buffer control for a given channel.
*/
struct BUF_CTRL {
uclong flag_dma; /* buffers are in Host memory */
uclong tx_bufaddr; /* address of the tx buffer */
uclong tx_bufsize; /* tx buffer size */
uclong tx_threshold; /* tx low water mark */
uclong tx_get; /* tail index tx buf */
uclong tx_put; /* head index tx buf */
uclong rx_bufaddr; /* address of the rx buffer */
uclong rx_bufsize; /* rx buffer size */
uclong rx_threshold; /* rx high water mark */
uclong rx_get; /* tail index rx buf */
uclong rx_put; /* head index rx buf */
uclong filler[5]; /* filler to align structures */
};
/*
* BOARD_CTRL - This per board structure contains all global
* control fields related to the board.
*/
struct BOARD_CTRL {
/* static info provided by the on-board CPU */
uclong n_channel; /* number of channels */
uclong fw_version; /* firmware version */
/* static info provided by the driver */
uclong op_system; /* op_system id */
uclong dr_version; /* driver version */
/* board control area */
uclong inactivity; /* inactivity control */
/* host to FW commands */
uclong hcmd_channel; /* channel number */
uclong *hcmd_param; /* pointer to parameters */
/* FW to Host commands */
uclong fwcmd_channel; /* channel number */
uclong *fwcmd_param; /* pointer to parameters */
/* filler so the structures are aligned */
uclong filler[7];
};
/*
* ZFW_CTRL - This is the data structure that includes all other
* data structures used by the Firmware.
*/
struct ZFW_CTRL {
struct BOARD_CTRL board_ctrl;
struct CH_CTRL ch_ctrl[MAX_CHAN];
struct BUF_CTRL buf_ctrl[MAX_CHAN];
};
/****************** ****************** *******************/
#endif
#ifdef __KERNEL__
/* Per card data structure */
struct cyclades_card {
int base_addr;
long base_addr;
long ctl_addr;
int irq;
int num_chips; /* 0 if card is absent */
int num_chips; /* 0 if card absent, 1 if Z/PCI, else Y */
int first_line; /* minor number of first channel on card */
int bus_index; /* address shift - 0 for ISA, 1 for PCI */
};
......@@ -72,6 +426,7 @@ struct cyclades_port {
int xmit_fifo_size;
int cor1,cor2,cor3,cor4,cor5;
int tbpr,tco,rbpr,rco;
int baud;
int ignore_status_mask;
int close_delay;
int IER; /* Interrupt Enable Register */
......@@ -95,6 +450,8 @@ struct cyclades_port {
struct wait_queue *open_wait;
struct wait_queue *close_wait;
struct cyclades_monitor mon;
unsigned long jiffies[3];
unsigned long rflush_count;
};
/*
......@@ -111,6 +468,10 @@ struct cyclades_port {
#define CyMaxChipsPerCard 8
#define CyPCI_Ywin 0x4000
#define CyPCI_Zctl 0x100
#define CyPCI_Zwin 0x80000
/**** CD1400 registers ****/
#define CyRegSize 0x0400
......@@ -282,3 +643,4 @@ struct cyclades_port {
#endif /* __KERNEL__ */
#endif /* _LINUX_CYCLADES_H */
......@@ -162,6 +162,7 @@ enum scsi_directory_inos {
PROC_SCSI_7000FASST,
PROC_SCSI_IBMMCA,
PROC_SCSI_EATA2X,
PROC_SCSI_DC390T,
PROC_SCSI_AM53C974,
PROC_SCSI_SSC,
PROC_SCSI_NCR53C406A,
......
......@@ -46,7 +46,8 @@ struct serial_struct {
#define PORT_16650 6
#define PORT_16650V2 7
#define PORT_16750 8
#define PORT_MAX 8
#define PORT_STARTECH 9
#define PORT_MAX 9
struct serial_uart_config {
char *name;
......
......@@ -3,8 +3,8 @@
#include <asm/socket.h> /* arch-dependent defines */
#include <linux/sockios.h> /* the SIOCxxx I/O controls */
#include <linux/uio.h> /* iovec support */
#include <linux/types.h> /* pid_t */
#include <linux/uio.h> /* iovec support */
typedef unsigned short sa_family_t;
......
......@@ -195,6 +195,9 @@ extern void atari_scsi_setup (char *str, int *ints);
extern void wd33c93_setup (char *str, int *ints);
extern void gvp11_setup (char *str, int *ints);
#ifdef CONFIG_CYCLADES
extern void cy_setup(char *str, int *ints);
#endif
#ifdef CONFIG_DIGI
extern void pcxx_setup(char *str, int *ints);
#endif
......@@ -482,6 +485,9 @@ struct {
#if defined(CONFIG_GVP11_SCSI)
{ "gvp11=", gvp11_setup },
#endif
#ifdef CONFIG_CYCLADES
{ "cyclades=", cy_setup },
#endif
#ifdef CONFIG_DIGI
{ "digi=", pcxx_setup },
#endif
......
......@@ -252,6 +252,135 @@ static inline int goodness(struct task_struct * p, struct task_struct * prev, in
return weight;
}
/*
* Event timer code
*/
#define TVN_BITS 6
#define TVR_BITS 8
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
#define SLOW_BUT_DEBUGGING_TIMERS 0
struct timer_vec {
int index;
struct timer_list *vec[TVN_SIZE];
};
struct timer_vec_root {
int index;
struct timer_list *vec[TVR_SIZE];
};
static struct timer_vec tv5 = { 0 };
static struct timer_vec tv4 = { 0 };
static struct timer_vec tv3 = { 0 };
static struct timer_vec tv2 = { 0 };
static struct timer_vec_root tv1 = { 0 };
static struct timer_vec * const tvecs[] = {
(struct timer_vec *)&tv1, &tv2, &tv3, &tv4, &tv5
};
#define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0]))
static unsigned long timer_jiffies = 0;
static inline void insert_timer(struct timer_list *timer,
struct timer_list **vec, int idx)
{
if ((timer->next = vec[idx]))
vec[idx]->prev = timer;
vec[idx] = timer;
timer->prev = (struct timer_list *)&vec[idx];
}
static inline void internal_add_timer(struct timer_list *timer)
{
/*
* must be cli-ed when calling this
*/
unsigned long expires = timer->expires;
unsigned long idx = expires - timer_jiffies;
if (idx < TVR_SIZE) {
int i = expires & TVR_MASK;
insert_timer(timer, tv1.vec, i);
} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
int i = (expires >> TVR_BITS) & TVN_MASK;
insert_timer(timer, tv2.vec, i);
} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
insert_timer(timer, tv3.vec, i);
} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
insert_timer(timer, tv4.vec, i);
} else if (expires < timer_jiffies) {
/* can happen if you add a timer with expires == jiffies,
* or you set a timer to go off in the past
*/
insert_timer(timer, tv1.vec, tv1.index);
} else if (idx < 0xffffffffUL) {
int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
insert_timer(timer, tv5.vec, i);
} else {
/* Can only get here on architectures with 64-bit jiffies */
timer->next = timer->prev = timer;
}
}
static spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
void add_timer(struct timer_list *timer)
{
unsigned long flags;
spin_lock_irqsave(&timerlist_lock, flags);
#if SLOW_BUT_DEBUGGING_TIMERS
if (timer->next || timer->prev) {
printk("add_timer() called with non-zero list from %p\n",
__builtin_return_address(0));
goto out;
}
#endif
internal_add_timer(timer);
#if SLOW_BUT_DEBUGGING_TIMERS
out:
#endif
spin_unlock_irqrestore(&timerlist_lock, flags);
}
static inline int detach_timer(struct timer_list *timer)
{
int ret = 0;
struct timer_list *next, *prev;
next = timer->next;
prev = timer->prev;
if (next) {
next->prev = prev;
}
if (prev) {
ret = 1;
prev->next = next;
}
return ret;
}
int del_timer(struct timer_list * timer)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&timerlist_lock, flags);
ret = detach_timer(timer);
timer->next = timer->prev = 0;
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
}
#ifdef __SMP__
#define idle_task (task[cpu_number_map[this_cpu]])
......@@ -284,10 +413,8 @@ asmlinkage void schedule(void)
need_resched = 0;
prev = current;
this_cpu = smp_processor_id();
if (local_irq_count[this_cpu]) {
printk("Scheduling in interrupt\n");
*(char *)0 = 0;
}
if (local_irq_count[this_cpu])
goto scheduling_in_interrupt;
release_kernel_lock(prev, this_cpu, lock_depth);
if (bh_active & bh_mask)
do_bottom_half();
......@@ -297,16 +424,8 @@ asmlinkage void schedule(void)
/* move an exhausted RR process to be last.. */
if (!prev->counter && prev->policy == SCHED_RR) {
if (prev->pid) {
prev->counter = prev->priority;
move_last_runqueue(prev);
} else {
static int count = 5;
if (count) {
count--;
printk("Moving pid 0 last\n");
}
}
}
timeout = 0;
switch (prev->state) {
......@@ -338,7 +457,9 @@ asmlinkage void schedule(void)
* the scheduler lock
*/
spin_unlock_irq(&runqueue_lock);
#ifdef __SMP__
prev->has_cpu = 0;
#endif
/*
* Note! there may appear new tasks on the run-queue during this, as
......@@ -369,8 +490,10 @@ asmlinkage void schedule(void)
}
}
#ifdef __SMP__
next->has_cpu = 1;
next->processor = this_cpu;
#endif
if (prev != next) {
struct timer_list timer;
......@@ -392,6 +515,11 @@ asmlinkage void schedule(void)
spin_unlock(&scheduler_lock);
reacquire_kernel_lock(prev, smp_processor_id(), lock_depth);
return;
scheduling_in_interrupt:
printk("Scheduling in interrupt\n");
*(int *)0 = 0;
}
#ifndef __alpha__
......@@ -613,133 +741,6 @@ void sleep_on(struct wait_queue **p)
__sleep_on(p,TASK_UNINTERRUPTIBLE);
}
#define TVN_BITS 6
#define TVR_BITS 8
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
#define SLOW_BUT_DEBUGGING_TIMERS 0
struct timer_vec {
int index;
struct timer_list *vec[TVN_SIZE];
};
struct timer_vec_root {
int index;
struct timer_list *vec[TVR_SIZE];
};
static struct timer_vec tv5 = { 0 };
static struct timer_vec tv4 = { 0 };
static struct timer_vec tv3 = { 0 };
static struct timer_vec tv2 = { 0 };
static struct timer_vec_root tv1 = { 0 };
static struct timer_vec * const tvecs[] = {
(struct timer_vec *)&tv1, &tv2, &tv3, &tv4, &tv5
};
#define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0]))
static unsigned long timer_jiffies = 0;
static inline void insert_timer(struct timer_list *timer,
struct timer_list **vec, int idx)
{
if ((timer->next = vec[idx]))
vec[idx]->prev = timer;
vec[idx] = timer;
timer->prev = (struct timer_list *)&vec[idx];
}
static inline void internal_add_timer(struct timer_list *timer)
{
/*
* must be cli-ed when calling this
*/
unsigned long expires = timer->expires;
unsigned long idx = expires - timer_jiffies;
if (idx < TVR_SIZE) {
int i = expires & TVR_MASK;
insert_timer(timer, tv1.vec, i);
} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
int i = (expires >> TVR_BITS) & TVN_MASK;
insert_timer(timer, tv2.vec, i);
} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
insert_timer(timer, tv3.vec, i);
} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
insert_timer(timer, tv4.vec, i);
} else if (expires < timer_jiffies) {
/* can happen if you add a timer with expires == jiffies,
* or you set a timer to go off in the past
*/
insert_timer(timer, tv1.vec, tv1.index);
} else if (idx < 0xffffffffUL) {
int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
insert_timer(timer, tv5.vec, i);
} else {
/* Can only get here on architectures with 64-bit jiffies */
timer->next = timer->prev = timer;
}
}
static spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
void add_timer(struct timer_list *timer)
{
unsigned long flags;
spin_lock_irqsave(&timerlist_lock, flags);
#if SLOW_BUT_DEBUGGING_TIMERS
if (timer->next || timer->prev) {
printk("add_timer() called with non-zero list from %p\n",
__builtin_return_address(0));
goto out;
}
#endif
internal_add_timer(timer);
#if SLOW_BUT_DEBUGGING_TIMERS
out:
#endif
spin_unlock_irqrestore(&timerlist_lock, flags);
}
static inline int detach_timer(struct timer_list *timer)
{
int ret = 0;
struct timer_list *next, *prev;
next = timer->next;
prev = timer->prev;
if (next) {
next->prev = prev;
}
if (prev) {
ret = 1;
prev->next = next;
}
return ret;
}
int del_timer(struct timer_list * timer)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&timerlist_lock, flags);
ret = detach_timer(timer);
timer->next = timer->prev = 0;
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
}
static inline void cascade_timers(struct timer_vec *tv)
{
/* cascade all the timers from tv up one level */
......@@ -831,17 +832,18 @@ unsigned long avenrun[3] = { 0,0,0 };
*/
static unsigned long count_active_tasks(void)
{
struct task_struct **p;
struct task_struct *p;
unsigned long nr = 0;
for(p = &LAST_TASK; p > &FIRST_TASK; --p)
if (*p && ((*p)->state == TASK_RUNNING ||
(*p)->state == TASK_UNINTERRUPTIBLE ||
(*p)->state == TASK_SWAPPING))
read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pid &&
(p->state == TASK_RUNNING ||
p->state == TASK_UNINTERRUPTIBLE ||
p->state == TASK_SWAPPING))
nr += FIXED_1;
#ifdef __SMP__
nr-=(smp_num_cpus-1)*FIXED_1;
#endif
}
read_unlock(&tasklist_lock);
return nr;
}
......
......@@ -6,6 +6,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
......
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