mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-08 17:18:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
85
drivers/scsi/aic7xxx/Kconfig.aic79xx
Normal file
85
drivers/scsi/aic7xxx/Kconfig.aic79xx
Normal file
|
@ -0,0 +1,85 @@
|
|||
#
|
||||
# AIC79XX 2.5.X Kernel configuration File.
|
||||
# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic79xx#4 $
|
||||
#
|
||||
config SCSI_AIC79XX
|
||||
tristate "Adaptec AIC79xx U320 support"
|
||||
depends on PCI && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
help
|
||||
This driver supports all of Adaptec's Ultra 320 PCI-X
|
||||
based SCSI controllers.
|
||||
|
||||
config AIC79XX_CMDS_PER_DEVICE
|
||||
int "Maximum number of TCQ commands per device"
|
||||
depends on SCSI_AIC79XX
|
||||
default "32"
|
||||
---help---
|
||||
Specify the number of commands you would like to allocate per SCSI
|
||||
device when Tagged Command Queueing (TCQ) is enabled on that device.
|
||||
|
||||
This is an upper bound value for the number of tagged transactions
|
||||
to be used for any device. The aic7xxx driver will automatically
|
||||
vary this number based on device behavior. For devices with a
|
||||
fixed maximum, the driver will eventually lock to this maximum
|
||||
and display a console message indicating this value.
|
||||
|
||||
Due to resource allocation issues in the Linux SCSI mid-layer, using
|
||||
a high number of commands per device may result in memory allocation
|
||||
failures when many devices are attached to the system. For this reason,
|
||||
the default is set to 32. Higher values may result in higher performance
|
||||
on some devices. The upper bound is 253. 0 disables tagged queueing.
|
||||
|
||||
Per device tag depth can be controlled via the kernel command line
|
||||
"tag_info" option. See Documentation/scsi/aic79xx.txt for details.
|
||||
|
||||
config AIC79XX_RESET_DELAY_MS
|
||||
int "Initial bus reset delay in milli-seconds"
|
||||
depends on SCSI_AIC79XX
|
||||
default "5000"
|
||||
---help---
|
||||
The number of milliseconds to delay after an initial bus reset.
|
||||
The bus settle delay following all error recovery actions is
|
||||
dictated by the SCSI layer and is not affected by this value.
|
||||
|
||||
Default: 5000 (5 seconds)
|
||||
|
||||
config AIC79XX_BUILD_FIRMWARE
|
||||
bool "Build Adapter Firmware with Kernel Build"
|
||||
depends on SCSI_AIC79XX && !PREVENT_FIRMWARE_BUILD
|
||||
help
|
||||
This option should only be enabled if you are modifying the firmware
|
||||
source to the aic79xx driver and wish to have the generated firmware
|
||||
include files updated during a normal kernel build. The assembler
|
||||
for the firmware requires lex and yacc or their equivalents, as well
|
||||
as the db v1 library. You may have to install additional packages
|
||||
or modify the assembler Makefile or the files it includes if your
|
||||
build environment is different than that of the author.
|
||||
|
||||
config AIC79XX_DEBUG_ENABLE
|
||||
bool "Compile in Debugging Code"
|
||||
depends on SCSI_AIC79XX
|
||||
default y
|
||||
help
|
||||
Compile in aic79xx debugging code that can be useful in diagnosing
|
||||
driver errors.
|
||||
|
||||
config AIC79XX_DEBUG_MASK
|
||||
int "Debug code enable mask (16383 for all debugging)"
|
||||
depends on SCSI_AIC79XX
|
||||
default "0"
|
||||
help
|
||||
Bit mask of debug options that is only valid if the
|
||||
CONFIG_AIC79XX_DEBUG_ENABLE option is enabled. The bits in this mask
|
||||
are defined in the drivers/scsi/aic7xxx/aic79xx.h - search for the
|
||||
variable ahd_debug in that file to find them.
|
||||
|
||||
config AIC79XX_REG_PRETTY_PRINT
|
||||
bool "Decode registers during diagnostics"
|
||||
depends on SCSI_AIC79XX
|
||||
default y
|
||||
help
|
||||
Compile in register value tables for the output of expanded register
|
||||
contents in diagnostics. This make it much easier to understand debug
|
||||
output without having to refer to a data book and/or the aic7xxx.reg
|
||||
file.
|
90
drivers/scsi/aic7xxx/Kconfig.aic7xxx
Normal file
90
drivers/scsi/aic7xxx/Kconfig.aic7xxx
Normal file
|
@ -0,0 +1,90 @@
|
|||
#
|
||||
# AIC7XXX and AIC79XX 2.5.X Kernel configuration File.
|
||||
# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#7 $
|
||||
#
|
||||
config SCSI_AIC7XXX
|
||||
tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
|
||||
depends on (PCI || EISA) && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
---help---
|
||||
This driver supports all of Adaptec's Fast through Ultra 160 PCI
|
||||
based SCSI controllers as well as the aic7770 based EISA and VLB
|
||||
SCSI controllers (the 274x and 284x series). For AAA and ARO based
|
||||
configurations, only SCSI functionality is provided.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called aic7xxx.
|
||||
|
||||
config AIC7XXX_CMDS_PER_DEVICE
|
||||
int "Maximum number of TCQ commands per device"
|
||||
depends on SCSI_AIC7XXX
|
||||
default "32"
|
||||
---help---
|
||||
Specify the number of commands you would like to allocate per SCSI
|
||||
device when Tagged Command Queueing (TCQ) is enabled on that device.
|
||||
|
||||
This is an upper bound value for the number of tagged transactions
|
||||
to be used for any device. The aic7xxx driver will automatically
|
||||
vary this number based on device behavior. For devices with a
|
||||
fixed maximum, the driver will eventually lock to this maximum
|
||||
and display a console message indicating this value.
|
||||
|
||||
Due to resource allocation issues in the Linux SCSI mid-layer, using
|
||||
a high number of commands per device may result in memory allocation
|
||||
failures when many devices are attached to the system. For this reason,
|
||||
the default is set to 32. Higher values may result in higher performance
|
||||
on some devices. The upper bound is 253. 0 disables tagged queueing.
|
||||
|
||||
Per device tag depth can be controlled via the kernel command line
|
||||
"tag_info" option. See Documentation/scsi/aic7xxx.txt for details.
|
||||
|
||||
config AIC7XXX_RESET_DELAY_MS
|
||||
int "Initial bus reset delay in milli-seconds"
|
||||
depends on SCSI_AIC7XXX
|
||||
default "5000"
|
||||
---help---
|
||||
The number of milliseconds to delay after an initial bus reset.
|
||||
The bus settle delay following all error recovery actions is
|
||||
dictated by the SCSI layer and is not affected by this value.
|
||||
|
||||
Default: 5000 (5 seconds)
|
||||
|
||||
config AIC7XXX_BUILD_FIRMWARE
|
||||
bool "Build Adapter Firmware with Kernel Build"
|
||||
depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
|
||||
help
|
||||
This option should only be enabled if you are modifying the firmware
|
||||
source to the aic7xxx driver and wish to have the generated firmware
|
||||
include files updated during a normal kernel build. The assembler
|
||||
for the firmware requires lex and yacc or their equivalents, as well
|
||||
as the db v1 library. You may have to install additional packages
|
||||
or modify the assembler Makefile or the files it includes if your
|
||||
build environment is different than that of the author.
|
||||
|
||||
config AIC7XXX_DEBUG_ENABLE
|
||||
bool "Compile in Debugging Code"
|
||||
depends on SCSI_AIC7XXX
|
||||
default y
|
||||
help
|
||||
Compile in aic7xxx debugging code that can be useful in diagnosing
|
||||
driver errors.
|
||||
|
||||
config AIC7XXX_DEBUG_MASK
|
||||
int "Debug code enable mask (2047 for all debugging)"
|
||||
depends on SCSI_AIC7XXX
|
||||
default "0"
|
||||
help
|
||||
Bit mask of debug options that is only valid if the
|
||||
CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled. The bits in this mask
|
||||
are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the
|
||||
variable ahc_debug in that file to find them.
|
||||
|
||||
config AIC7XXX_REG_PRETTY_PRINT
|
||||
bool "Decode registers during diagnostics"
|
||||
depends on SCSI_AIC7XXX
|
||||
default y
|
||||
help
|
||||
Compile in register value tables for the output of expanded register
|
||||
contents in diagnostics. This make it much easier to understand debug
|
||||
output without having to refer to a data book and/or the aic7xxx.reg
|
||||
file.
|
85
drivers/scsi/aic7xxx/Makefile
Normal file
85
drivers/scsi/aic7xxx/Makefile
Normal file
|
@ -0,0 +1,85 @@
|
|||
#
|
||||
# Makefile for the Linux aic7xxx SCSI driver.
|
||||
#
|
||||
# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#8 $
|
||||
#
|
||||
|
||||
# Let kbuild descend into aicasm when cleaning
|
||||
subdir- += aicasm
|
||||
|
||||
obj-$(CONFIG_SCSI_AIC7XXX) += aic7xxx.o
|
||||
obj-$(CONFIG_SCSI_AIC79XX) += aic79xx.o
|
||||
|
||||
# Core Fast -> U160 files
|
||||
aic7xxx-y += aic7xxx_core.o \
|
||||
aic7xxx_93cx6.o
|
||||
aic7xxx-$(CONFIG_EISA) += aic7770.o
|
||||
aic7xxx-$(CONFIG_PCI) += aic7xxx_pci.o
|
||||
aic7xxx-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) += aic7xxx_reg_print.o
|
||||
|
||||
# Platform Specific Fast -> U160 Files
|
||||
aic7xxx-y += aic7xxx_osm.o \
|
||||
aic7xxx_proc.o
|
||||
aic7xxx-$(CONFIG_EISA) += aic7770_osm.o
|
||||
aic7xxx-$(CONFIG_PCI) += aic7xxx_osm_pci.o
|
||||
|
||||
# Core U320 files
|
||||
aic79xx-y += aic79xx_core.o \
|
||||
aic79xx_pci.o
|
||||
aic79xx-$(CONFIG_AIC79XX_REG_PRETTY_PRINT) += aic79xx_reg_print.o
|
||||
|
||||
# Platform Specific U320 Files
|
||||
aic79xx-y += aic79xx_osm.o \
|
||||
aic79xx_proc.o \
|
||||
aic79xx_osm_pci.o
|
||||
|
||||
ccflags-y += -Idrivers/scsi
|
||||
ifdef WARNINGS_BECOME_ERRORS
|
||||
ccflags-y += -Werror
|
||||
endif
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := aic7xxx_seq.h aic7xxx_reg.h aic7xxx_reg_print.c
|
||||
clean-files += aic79xx_seq.h aic79xx_reg.h aic79xx_reg_print.c
|
||||
|
||||
# Dependencies for generated files need to be listed explicitly
|
||||
|
||||
$(addprefix $(obj)/,$(aic7xxx-y)): $(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h
|
||||
$(addprefix $(obj)/,$(aic79xx-y)): $(obj)/aic79xx_seq.h $(obj)/aic79xx_reg.h
|
||||
|
||||
aic7xxx-gen-$(CONFIG_AIC7XXX_BUILD_FIRMWARE) := $(obj)/aic7xxx_reg.h
|
||||
aic7xxx-gen-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) += $(obj)/aic7xxx_reg_print.c
|
||||
|
||||
aicasm-7xxx-opts-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) := \
|
||||
-p $(obj)/aic7xxx_reg_print.c -i aic7xxx_osm.h
|
||||
|
||||
ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
|
||||
$(obj)/aic7xxx_seq.h: $(src)/aic7xxx.seq $(src)/aic7xxx.reg $(obj)/aicasm/aicasm
|
||||
$(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
|
||||
$(aicasm-7xxx-opts-y) -o $(obj)/aic7xxx_seq.h \
|
||||
$(src)/aic7xxx.seq
|
||||
|
||||
$(aic7xxx-gen-y): $(obj)/aic7xxx_seq.h
|
||||
else
|
||||
$(obj)/aic7xxx_reg_print.c: $(src)/aic7xxx_reg_print.c_shipped
|
||||
endif
|
||||
|
||||
aic79xx-gen-$(CONFIG_AIC79XX_BUILD_FIRMWARE) := $(obj)/aic79xx_reg.h
|
||||
aic79xx-gen-$(CONFIG_AIC79XX_REG_PRETTY_PRINT) += $(obj)/aic79xx_reg_print.c
|
||||
|
||||
aicasm-79xx-opts-$(CONFIG_AIC79XX_REG_PRETTY_PRINT) := \
|
||||
-p $(obj)/aic79xx_reg_print.c -i aic79xx_osm.h
|
||||
|
||||
ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y)
|
||||
$(obj)/aic79xx_seq.h: $(src)/aic79xx.seq $(src)/aic79xx.reg $(obj)/aicasm/aicasm
|
||||
$(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \
|
||||
$(aicasm-79xx-opts-y) -o $(obj)/aic79xx_seq.h \
|
||||
$(src)/aic79xx.seq
|
||||
|
||||
$(aic79xx-gen-y): $(obj)/aic79xx_seq.h
|
||||
else
|
||||
$(obj)/aic79xx_reg_print.c: $(src)/aic79xx_reg_print.c_shipped
|
||||
endif
|
||||
|
||||
$(obj)/aicasm/aicasm: $(src)/aicasm/*.[chyl]
|
||||
$(MAKE) -C $(src)/aicasm
|
391
drivers/scsi/aic7xxx/aic7770.c
Normal file
391
drivers/scsi/aic7xxx/aic7770.c
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* 27/284X and aic7770 motherboard SCSI controllers
|
||||
*
|
||||
* Copyright (c) 1994-1998, 2000, 2001 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7770.c#32 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#include "aic7xxx_osm.h"
|
||||
#include "aic7xxx_inline.h"
|
||||
#include "aic7xxx_93cx6.h"
|
||||
#else
|
||||
#include <dev/aic7xxx/aic7xxx_osm.h>
|
||||
#include <dev/aic7xxx/aic7xxx_inline.h>
|
||||
#include <dev/aic7xxx/aic7xxx_93cx6.h>
|
||||
#endif
|
||||
|
||||
#define ID_AIC7770 0x04907770
|
||||
#define ID_AHA_274x 0x04907771
|
||||
#define ID_AHA_284xB 0x04907756 /* BIOS enabled */
|
||||
#define ID_AHA_284x 0x04907757 /* BIOS disabled*/
|
||||
#define ID_OLV_274x 0x04907782 /* Olivetti OEM */
|
||||
#define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */
|
||||
|
||||
static int aic7770_chip_init(struct ahc_softc *ahc);
|
||||
static int aha2840_load_seeprom(struct ahc_softc *ahc);
|
||||
static ahc_device_setup_t ahc_aic7770_VL_setup;
|
||||
static ahc_device_setup_t ahc_aic7770_EISA_setup;
|
||||
static ahc_device_setup_t ahc_aic7770_setup;
|
||||
|
||||
struct aic7770_identity aic7770_ident_table[] =
|
||||
{
|
||||
{
|
||||
ID_AHA_274x,
|
||||
0xFFFFFFFF,
|
||||
"Adaptec 274X SCSI adapter",
|
||||
ahc_aic7770_EISA_setup
|
||||
},
|
||||
{
|
||||
ID_AHA_284xB,
|
||||
0xFFFFFFFE,
|
||||
"Adaptec 284X SCSI adapter",
|
||||
ahc_aic7770_VL_setup
|
||||
},
|
||||
{
|
||||
ID_AHA_284x,
|
||||
0xFFFFFFFE,
|
||||
"Adaptec 284X SCSI adapter (BIOS Disabled)",
|
||||
ahc_aic7770_VL_setup
|
||||
},
|
||||
{
|
||||
ID_OLV_274x,
|
||||
0xFFFFFFFF,
|
||||
"Adaptec (Olivetti OEM) 274X SCSI adapter",
|
||||
ahc_aic7770_EISA_setup
|
||||
},
|
||||
{
|
||||
ID_OLV_274xD,
|
||||
0xFFFFFFFF,
|
||||
"Adaptec (Olivetti OEM) 274X Differential SCSI adapter",
|
||||
ahc_aic7770_EISA_setup
|
||||
},
|
||||
/* Generic chip probes for devices we don't know 'exactly' */
|
||||
{
|
||||
ID_AIC7770,
|
||||
0xFFFFFFFF,
|
||||
"Adaptec aic7770 SCSI adapter",
|
||||
ahc_aic7770_EISA_setup
|
||||
}
|
||||
};
|
||||
const int ahc_num_aic7770_devs = ARRAY_SIZE(aic7770_ident_table);
|
||||
|
||||
struct aic7770_identity *
|
||||
aic7770_find_device(uint32_t id)
|
||||
{
|
||||
struct aic7770_identity *entry;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ahc_num_aic7770_devs; i++) {
|
||||
entry = &aic7770_ident_table[i];
|
||||
if (entry->full_id == (id & entry->id_mask))
|
||||
return (entry);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
|
||||
{
|
||||
int error;
|
||||
int have_seeprom;
|
||||
u_int hostconf;
|
||||
u_int irq;
|
||||
u_int intdef;
|
||||
|
||||
error = entry->setup(ahc);
|
||||
have_seeprom = 0;
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = aic7770_map_registers(ahc, io);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Before we continue probing the card, ensure that
|
||||
* its interrupts are *disabled*. We don't want
|
||||
* a misstep to hang the machine in an interrupt
|
||||
* storm.
|
||||
*/
|
||||
ahc_intr_enable(ahc, FALSE);
|
||||
|
||||
ahc->description = entry->name;
|
||||
error = ahc_softc_init(ahc);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
ahc->bus_chip_init = aic7770_chip_init;
|
||||
|
||||
error = ahc_reset(ahc, /*reinit*/FALSE);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Make sure we have a valid interrupt vector */
|
||||
intdef = ahc_inb(ahc, INTDEF);
|
||||
irq = intdef & VECTOR;
|
||||
switch (irq) {
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 14:
|
||||
case 15:
|
||||
break;
|
||||
default:
|
||||
printk("aic7770_config: invalid irq setting %d\n", intdef);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((intdef & EDGE_TRIG) != 0)
|
||||
ahc->flags |= AHC_EDGE_INTERRUPT;
|
||||
|
||||
switch (ahc->chip & (AHC_EISA|AHC_VL)) {
|
||||
case AHC_EISA:
|
||||
{
|
||||
u_int biosctrl;
|
||||
u_int scsiconf;
|
||||
u_int scsiconf1;
|
||||
|
||||
biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL);
|
||||
scsiconf = ahc_inb(ahc, SCSICONF);
|
||||
scsiconf1 = ahc_inb(ahc, SCSICONF + 1);
|
||||
|
||||
/* Get the primary channel information */
|
||||
if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
|
||||
ahc->flags |= 1;
|
||||
|
||||
if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
|
||||
ahc->flags |= AHC_USEDEFAULTS;
|
||||
} else {
|
||||
if ((ahc->features & AHC_WIDE) != 0) {
|
||||
ahc->our_id = scsiconf1 & HWSCSIID;
|
||||
if (scsiconf & TERM_ENB)
|
||||
ahc->flags |= AHC_TERM_ENB_A;
|
||||
} else {
|
||||
ahc->our_id = scsiconf & HSCSIID;
|
||||
ahc->our_id_b = scsiconf1 & HSCSIID;
|
||||
if (scsiconf & TERM_ENB)
|
||||
ahc->flags |= AHC_TERM_ENB_A;
|
||||
if (scsiconf1 & TERM_ENB)
|
||||
ahc->flags |= AHC_TERM_ENB_B;
|
||||
}
|
||||
}
|
||||
if ((ahc_inb(ahc, HA_274_BIOSGLOBAL) & HA_274_EXTENDED_TRANS))
|
||||
ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B;
|
||||
break;
|
||||
}
|
||||
case AHC_VL:
|
||||
{
|
||||
have_seeprom = aha2840_load_seeprom(ahc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (have_seeprom == 0) {
|
||||
kfree(ahc->seep_config);
|
||||
ahc->seep_config = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure autoflush is enabled
|
||||
*/
|
||||
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS);
|
||||
|
||||
/* Setup the FIFO threshold and the bus off time */
|
||||
hostconf = ahc_inb(ahc, HOSTCONF);
|
||||
ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
|
||||
ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
|
||||
|
||||
ahc->bus_softc.aic7770_softc.busspd = hostconf & DFTHRSH;
|
||||
ahc->bus_softc.aic7770_softc.bustime = (hostconf << 2) & BOFF;
|
||||
|
||||
/*
|
||||
* Generic aic7xxx initialization.
|
||||
*/
|
||||
error = ahc_init(ahc);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = aic7770_map_int(ahc, irq);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
ahc->init_level++;
|
||||
|
||||
/*
|
||||
* Enable the board's BUS drivers
|
||||
*/
|
||||
ahc_outb(ahc, BCTL, ENABLE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aic7770_chip_init(struct ahc_softc *ahc)
|
||||
{
|
||||
ahc_outb(ahc, BUSSPD, ahc->bus_softc.aic7770_softc.busspd);
|
||||
ahc_outb(ahc, BUSTIME, ahc->bus_softc.aic7770_softc.bustime);
|
||||
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS);
|
||||
ahc_outb(ahc, BCTL, ENABLE);
|
||||
return (ahc_chip_init(ahc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the 284x SEEPROM.
|
||||
*/
|
||||
static int
|
||||
aha2840_load_seeprom(struct ahc_softc *ahc)
|
||||
{
|
||||
struct seeprom_descriptor sd;
|
||||
struct seeprom_config *sc;
|
||||
int have_seeprom;
|
||||
uint8_t scsi_conf;
|
||||
|
||||
sd.sd_ahc = ahc;
|
||||
sd.sd_control_offset = SEECTL_2840;
|
||||
sd.sd_status_offset = STATUS_2840;
|
||||
sd.sd_dataout_offset = STATUS_2840;
|
||||
sd.sd_chip = C46;
|
||||
sd.sd_MS = 0;
|
||||
sd.sd_RDY = EEPROM_TF;
|
||||
sd.sd_CS = CS_2840;
|
||||
sd.sd_CK = CK_2840;
|
||||
sd.sd_DO = DO_2840;
|
||||
sd.sd_DI = DI_2840;
|
||||
sc = ahc->seep_config;
|
||||
|
||||
if (bootverbose)
|
||||
printk("%s: Reading SEEPROM...", ahc_name(ahc));
|
||||
have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
|
||||
/*start_addr*/0, sizeof(*sc)/2);
|
||||
|
||||
if (have_seeprom) {
|
||||
|
||||
if (ahc_verify_cksum(sc) == 0) {
|
||||
if(bootverbose)
|
||||
printk ("checksum error\n");
|
||||
have_seeprom = 0;
|
||||
} else if (bootverbose) {
|
||||
printk("done.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_seeprom) {
|
||||
if (bootverbose)
|
||||
printk("%s: No SEEPROM available\n", ahc_name(ahc));
|
||||
ahc->flags |= AHC_USEDEFAULTS;
|
||||
} else {
|
||||
/*
|
||||
* Put the data we've collected down into SRAM
|
||||
* where ahc_init will find it.
|
||||
*/
|
||||
int i;
|
||||
int max_targ;
|
||||
uint16_t discenable;
|
||||
|
||||
max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8;
|
||||
discenable = 0;
|
||||
for (i = 0; i < max_targ; i++){
|
||||
uint8_t target_settings;
|
||||
|
||||
target_settings = (sc->device_flags[i] & CFXFER) << 4;
|
||||
if (sc->device_flags[i] & CFSYNCH)
|
||||
target_settings |= SOFS;
|
||||
if (sc->device_flags[i] & CFWIDEB)
|
||||
target_settings |= WIDEXFER;
|
||||
if (sc->device_flags[i] & CFDISC)
|
||||
discenable |= (0x01 << i);
|
||||
ahc_outb(ahc, TARG_SCSIRATE + i, target_settings);
|
||||
}
|
||||
ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
|
||||
ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
|
||||
|
||||
ahc->our_id = sc->brtime_id & CFSCSIID;
|
||||
|
||||
scsi_conf = (ahc->our_id & 0x7);
|
||||
if (sc->adapter_control & CFSPARITY)
|
||||
scsi_conf |= ENSPCHK;
|
||||
if (sc->adapter_control & CFRESETB)
|
||||
scsi_conf |= RESET_SCSI;
|
||||
|
||||
if (sc->bios_control & CF284XEXTEND)
|
||||
ahc->flags |= AHC_EXTENDED_TRANS_A;
|
||||
/* Set SCSICONF info */
|
||||
ahc_outb(ahc, SCSICONF, scsi_conf);
|
||||
|
||||
if (sc->adapter_control & CF284XSTERM)
|
||||
ahc->flags |= AHC_TERM_ENB_A;
|
||||
}
|
||||
return (have_seeprom);
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_aic7770_VL_setup(struct ahc_softc *ahc)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = ahc_aic7770_setup(ahc);
|
||||
ahc->chip |= AHC_VL;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_aic7770_EISA_setup(struct ahc_softc *ahc)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = ahc_aic7770_setup(ahc);
|
||||
ahc->chip |= AHC_EISA;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_aic7770_setup(struct ahc_softc *ahc)
|
||||
{
|
||||
ahc->channel = 'A';
|
||||
ahc->channel_b = 'B';
|
||||
ahc->chip = AHC_AIC7770;
|
||||
ahc->features = AHC_AIC7770_FE;
|
||||
ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
|
||||
ahc->flags |= AHC_PAGESCBS;
|
||||
ahc->instruction_ram_size = 448;
|
||||
return (0);
|
||||
}
|
155
drivers/scsi/aic7xxx/aic7770_osm.c
Normal file
155
drivers/scsi/aic7xxx/aic7770_osm.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Linux driver attachment glue for aic7770 based controllers.
|
||||
*
|
||||
* Copyright (c) 2000-2003 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#14 $
|
||||
*/
|
||||
|
||||
#include "aic7xxx_osm.h"
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/eisa.h>
|
||||
|
||||
int
|
||||
aic7770_map_registers(struct ahc_softc *ahc, u_int port)
|
||||
{
|
||||
/*
|
||||
* Lock out other contenders for our i/o space.
|
||||
*/
|
||||
if (!request_region(port, AHC_EISA_IOSIZE, "aic7xxx"))
|
||||
return (ENOMEM);
|
||||
ahc->tag = BUS_SPACE_PIO;
|
||||
ahc->bsh.ioport = port;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
aic7770_map_int(struct ahc_softc *ahc, u_int irq)
|
||||
{
|
||||
int error;
|
||||
int shared;
|
||||
|
||||
shared = 0;
|
||||
if ((ahc->flags & AHC_EDGE_INTERRUPT) == 0)
|
||||
shared = IRQF_SHARED;
|
||||
|
||||
error = request_irq(irq, ahc_linux_isr, shared, "aic7xxx", ahc);
|
||||
if (error == 0)
|
||||
ahc->platform_data->irq = irq;
|
||||
|
||||
return (-error);
|
||||
}
|
||||
|
||||
static int
|
||||
aic7770_probe(struct device *dev)
|
||||
{
|
||||
struct eisa_device *edev = to_eisa_device(dev);
|
||||
u_int eisaBase = edev->base_addr+AHC_EISA_SLOT_OFFSET;
|
||||
struct ahc_softc *ahc;
|
||||
char buf[80];
|
||||
char *name;
|
||||
int error;
|
||||
|
||||
sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
|
||||
name = kstrdup(buf, GFP_ATOMIC);
|
||||
if (name == NULL)
|
||||
return (ENOMEM);
|
||||
ahc = ahc_alloc(&aic7xxx_driver_template, name);
|
||||
if (ahc == NULL)
|
||||
return (ENOMEM);
|
||||
error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data,
|
||||
eisaBase);
|
||||
if (error != 0) {
|
||||
ahc->bsh.ioport = 0;
|
||||
ahc_free(ahc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, ahc);
|
||||
|
||||
error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
aic7770_remove(struct device *dev)
|
||||
{
|
||||
struct ahc_softc *ahc = dev_get_drvdata(dev);
|
||||
u_long s;
|
||||
|
||||
if (ahc->platform_data && ahc->platform_data->host)
|
||||
scsi_remove_host(ahc->platform_data->host);
|
||||
|
||||
ahc_lock(ahc, &s);
|
||||
ahc_intr_enable(ahc, FALSE);
|
||||
ahc_unlock(ahc, &s);
|
||||
|
||||
ahc_free(ahc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct eisa_device_id aic7770_ids[] = {
|
||||
{ "ADP7771", 0 }, /* AHA 274x */
|
||||
{ "ADP7756", 1 }, /* AHA 284x BIOS enabled */
|
||||
{ "ADP7757", 2 }, /* AHA 284x BIOS disabled */
|
||||
{ "ADP7782", 3 }, /* AHA 274x Olivetti OEM */
|
||||
{ "ADP7783", 4 }, /* AHA 274x Olivetti OEM (Differential) */
|
||||
{ "ADP7770", 5 }, /* AIC7770 generic */
|
||||
{ "" }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(eisa, aic7770_ids);
|
||||
|
||||
static struct eisa_driver aic7770_driver = {
|
||||
.id_table = aic7770_ids,
|
||||
.driver = {
|
||||
.name = "aic7xxx",
|
||||
.probe = aic7770_probe,
|
||||
.remove = aic7770_remove,
|
||||
}
|
||||
};
|
||||
|
||||
int
|
||||
ahc_linux_eisa_init(void)
|
||||
{
|
||||
return eisa_driver_register(&aic7770_driver);
|
||||
}
|
||||
|
||||
void
|
||||
ahc_linux_eisa_exit(void)
|
||||
{
|
||||
eisa_driver_unregister(&aic7770_driver);
|
||||
}
|
1478
drivers/scsi/aic7xxx/aic79xx.h
Normal file
1478
drivers/scsi/aic7xxx/aic79xx.h
Normal file
File diff suppressed because it is too large
Load diff
4281
drivers/scsi/aic7xxx/aic79xx.reg
Normal file
4281
drivers/scsi/aic7xxx/aic79xx.reg
Normal file
File diff suppressed because it is too large
Load diff
2290
drivers/scsi/aic7xxx/aic79xx.seq
Normal file
2290
drivers/scsi/aic7xxx/aic79xx.seq
Normal file
File diff suppressed because it is too large
Load diff
10823
drivers/scsi/aic7xxx/aic79xx_core.c
Normal file
10823
drivers/scsi/aic7xxx/aic79xx_core.c
Normal file
File diff suppressed because it is too large
Load diff
172
drivers/scsi/aic7xxx/aic79xx_inline.h
Normal file
172
drivers/scsi/aic7xxx/aic79xx_inline.h
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Inline routines shareable across OS platforms.
|
||||
*
|
||||
* Copyright (c) 1994-2001 Justin T. Gibbs.
|
||||
* Copyright (c) 2000-2003 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#59 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _AIC79XX_INLINE_H_
|
||||
#define _AIC79XX_INLINE_H_
|
||||
|
||||
/******************************** Debugging ***********************************/
|
||||
static inline char *ahd_name(struct ahd_softc *ahd);
|
||||
|
||||
static inline char *ahd_name(struct ahd_softc *ahd)
|
||||
{
|
||||
return (ahd->name);
|
||||
}
|
||||
|
||||
/************************ Sequencer Execution Control *************************/
|
||||
static inline void ahd_known_modes(struct ahd_softc *ahd,
|
||||
ahd_mode src, ahd_mode dst);
|
||||
static inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
|
||||
ahd_mode src,
|
||||
ahd_mode dst);
|
||||
static inline void ahd_extract_mode_state(struct ahd_softc *ahd,
|
||||
ahd_mode_state state,
|
||||
ahd_mode *src, ahd_mode *dst);
|
||||
|
||||
void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
|
||||
ahd_mode dst);
|
||||
ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
|
||||
void ahd_restore_modes(struct ahd_softc *ahd,
|
||||
ahd_mode_state state);
|
||||
int ahd_is_paused(struct ahd_softc *ahd);
|
||||
void ahd_pause(struct ahd_softc *ahd);
|
||||
void ahd_unpause(struct ahd_softc *ahd);
|
||||
|
||||
static inline void
|
||||
ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
|
||||
{
|
||||
ahd->src_mode = src;
|
||||
ahd->dst_mode = dst;
|
||||
ahd->saved_src_mode = src;
|
||||
ahd->saved_dst_mode = dst;
|
||||
}
|
||||
|
||||
static inline ahd_mode_state
|
||||
ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
|
||||
{
|
||||
return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
|
||||
ahd_mode *src, ahd_mode *dst)
|
||||
{
|
||||
*src = (state & SRC_MODE) >> SRC_MODE_SHIFT;
|
||||
*dst = (state & DST_MODE) >> DST_MODE_SHIFT;
|
||||
}
|
||||
|
||||
/*********************** Scatter Gather List Handling *************************/
|
||||
void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
|
||||
void *sgptr, dma_addr_t addr,
|
||||
bus_size_t len, int last);
|
||||
|
||||
/************************** Memory mapping routines ***************************/
|
||||
static inline size_t ahd_sg_size(struct ahd_softc *ahd);
|
||||
|
||||
void ahd_sync_sglist(struct ahd_softc *ahd,
|
||||
struct scb *scb, int op);
|
||||
|
||||
static inline size_t ahd_sg_size(struct ahd_softc *ahd)
|
||||
{
|
||||
if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
|
||||
return (sizeof(struct ahd_dma64_seg));
|
||||
return (sizeof(struct ahd_dma_seg));
|
||||
}
|
||||
|
||||
/*********************** Miscellaneous Support Functions ***********************/
|
||||
struct ahd_initiator_tinfo *
|
||||
ahd_fetch_transinfo(struct ahd_softc *ahd,
|
||||
char channel, u_int our_id,
|
||||
u_int remote_id,
|
||||
struct ahd_tmode_tstate **tstate);
|
||||
uint16_t
|
||||
ahd_inw(struct ahd_softc *ahd, u_int port);
|
||||
void ahd_outw(struct ahd_softc *ahd, u_int port,
|
||||
u_int value);
|
||||
uint32_t
|
||||
ahd_inl(struct ahd_softc *ahd, u_int port);
|
||||
void ahd_outl(struct ahd_softc *ahd, u_int port,
|
||||
uint32_t value);
|
||||
uint64_t
|
||||
ahd_inq(struct ahd_softc *ahd, u_int port);
|
||||
void ahd_outq(struct ahd_softc *ahd, u_int port,
|
||||
uint64_t value);
|
||||
u_int ahd_get_scbptr(struct ahd_softc *ahd);
|
||||
void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
|
||||
u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
|
||||
u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
|
||||
struct scb *
|
||||
ahd_lookup_scb(struct ahd_softc *ahd, u_int tag);
|
||||
void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
|
||||
|
||||
static inline uint8_t *ahd_get_sense_buf(struct ahd_softc *ahd,
|
||||
struct scb *scb);
|
||||
static inline uint32_t ahd_get_sense_bufaddr(struct ahd_softc *ahd,
|
||||
struct scb *scb);
|
||||
|
||||
#if 0 /* unused */
|
||||
|
||||
#define AHD_COPY_COL_IDX(dst, src) \
|
||||
do { \
|
||||
dst->hscb->scsiid = src->hscb->scsiid; \
|
||||
dst->hscb->lun = src->hscb->lun; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
static inline uint8_t *
|
||||
ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
|
||||
{
|
||||
return (scb->sense_data);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
|
||||
{
|
||||
return (scb->sense_busaddr);
|
||||
}
|
||||
|
||||
/************************** Interrupt Processing ******************************/
|
||||
int ahd_intr(struct ahd_softc *ahd);
|
||||
|
||||
#endif /* _AIC79XX_INLINE_H_ */
|
2898
drivers/scsi/aic7xxx/aic79xx_osm.c
Normal file
2898
drivers/scsi/aic7xxx/aic79xx_osm.c
Normal file
File diff suppressed because it is too large
Load diff
695
drivers/scsi/aic7xxx/aic79xx_osm.h
Normal file
695
drivers/scsi/aic7xxx/aic79xx_osm.h
Normal file
|
@ -0,0 +1,695 @@
|
|||
/*
|
||||
* Adaptec AIC79xx device driver for Linux.
|
||||
*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#166 $
|
||||
*
|
||||
*/
|
||||
#ifndef _AIC79XX_LINUX_H_
|
||||
#define _AIC79XX_LINUX_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_transport_spi.h>
|
||||
|
||||
/* Core SCSI definitions */
|
||||
#define AIC_LIB_PREFIX ahd
|
||||
|
||||
/* Name space conflict with BSD queue macros */
|
||||
#ifdef LIST_HEAD
|
||||
#undef LIST_HEAD
|
||||
#endif
|
||||
|
||||
#include "cam.h"
|
||||
#include "queue.h"
|
||||
#include "scsi_message.h"
|
||||
#include "scsi_iu.h"
|
||||
#include "aiclib.h"
|
||||
|
||||
/*********************************** Debugging ********************************/
|
||||
#ifdef CONFIG_AIC79XX_DEBUG_ENABLE
|
||||
#ifdef CONFIG_AIC79XX_DEBUG_MASK
|
||||
#define AHD_DEBUG 1
|
||||
#define AHD_DEBUG_OPTS CONFIG_AIC79XX_DEBUG_MASK
|
||||
#else
|
||||
/*
|
||||
* Compile in debugging code, but do not enable any printfs.
|
||||
*/
|
||||
#define AHD_DEBUG 1
|
||||
#define AHD_DEBUG_OPTS 0
|
||||
#endif
|
||||
/* No debugging code. */
|
||||
#endif
|
||||
|
||||
/********************************** Misc Macros *******************************/
|
||||
#define powerof2(x) ((((x)-1)&(x))==0)
|
||||
|
||||
/************************* Forward Declarations *******************************/
|
||||
struct ahd_softc;
|
||||
typedef struct pci_dev *ahd_dev_softc_t;
|
||||
typedef struct scsi_cmnd *ahd_io_ctx_t;
|
||||
|
||||
/******************************* Byte Order ***********************************/
|
||||
#define ahd_htobe16(x) cpu_to_be16(x)
|
||||
#define ahd_htobe32(x) cpu_to_be32(x)
|
||||
#define ahd_htobe64(x) cpu_to_be64(x)
|
||||
#define ahd_htole16(x) cpu_to_le16(x)
|
||||
#define ahd_htole32(x) cpu_to_le32(x)
|
||||
#define ahd_htole64(x) cpu_to_le64(x)
|
||||
|
||||
#define ahd_be16toh(x) be16_to_cpu(x)
|
||||
#define ahd_be32toh(x) be32_to_cpu(x)
|
||||
#define ahd_be64toh(x) be64_to_cpu(x)
|
||||
#define ahd_le16toh(x) le16_to_cpu(x)
|
||||
#define ahd_le32toh(x) le32_to_cpu(x)
|
||||
#define ahd_le64toh(x) le64_to_cpu(x)
|
||||
|
||||
/************************* Configuration Data *********************************/
|
||||
extern uint32_t aic79xx_allow_memio;
|
||||
extern struct scsi_host_template aic79xx_driver_template;
|
||||
|
||||
/***************************** Bus Space/DMA **********************************/
|
||||
|
||||
typedef uint32_t bus_size_t;
|
||||
|
||||
typedef enum {
|
||||
BUS_SPACE_MEMIO,
|
||||
BUS_SPACE_PIO
|
||||
} bus_space_tag_t;
|
||||
|
||||
typedef union {
|
||||
u_long ioport;
|
||||
volatile uint8_t __iomem *maddr;
|
||||
} bus_space_handle_t;
|
||||
|
||||
typedef struct bus_dma_segment
|
||||
{
|
||||
dma_addr_t ds_addr;
|
||||
bus_size_t ds_len;
|
||||
} bus_dma_segment_t;
|
||||
|
||||
struct ahd_linux_dma_tag
|
||||
{
|
||||
bus_size_t alignment;
|
||||
bus_size_t boundary;
|
||||
bus_size_t maxsize;
|
||||
};
|
||||
typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
|
||||
|
||||
typedef dma_addr_t bus_dmamap_t;
|
||||
|
||||
typedef int bus_dma_filter_t(void*, dma_addr_t);
|
||||
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
|
||||
|
||||
#define BUS_DMA_WAITOK 0x0
|
||||
#define BUS_DMA_NOWAIT 0x1
|
||||
#define BUS_DMA_ALLOCNOW 0x2
|
||||
#define BUS_DMA_LOAD_SEGS 0x4 /*
|
||||
* Argument is an S/G list not
|
||||
* a single buffer.
|
||||
*/
|
||||
|
||||
#define BUS_SPACE_MAXADDR 0xFFFFFFFF
|
||||
#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
|
||||
#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
|
||||
|
||||
int ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/,
|
||||
bus_size_t /*alignment*/, bus_size_t /*boundary*/,
|
||||
dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/,
|
||||
bus_dma_filter_t*/*filter*/, void */*filterarg*/,
|
||||
bus_size_t /*maxsize*/, int /*nsegments*/,
|
||||
bus_size_t /*maxsegsz*/, int /*flags*/,
|
||||
bus_dma_tag_t */*dma_tagp*/);
|
||||
|
||||
void ahd_dma_tag_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/);
|
||||
|
||||
int ahd_dmamem_alloc(struct ahd_softc *, bus_dma_tag_t /*dmat*/,
|
||||
void** /*vaddr*/, int /*flags*/,
|
||||
bus_dmamap_t* /*mapp*/);
|
||||
|
||||
void ahd_dmamem_free(struct ahd_softc *, bus_dma_tag_t /*dmat*/,
|
||||
void* /*vaddr*/, bus_dmamap_t /*map*/);
|
||||
|
||||
void ahd_dmamap_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/,
|
||||
bus_dmamap_t /*map*/);
|
||||
|
||||
int ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t /*dmat*/,
|
||||
bus_dmamap_t /*map*/, void * /*buf*/,
|
||||
bus_size_t /*buflen*/, bus_dmamap_callback_t *,
|
||||
void */*callback_arg*/, int /*flags*/);
|
||||
|
||||
int ahd_dmamap_unload(struct ahd_softc *, bus_dma_tag_t, bus_dmamap_t);
|
||||
|
||||
/*
|
||||
* Operations performed by ahd_dmamap_sync().
|
||||
*/
|
||||
#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
|
||||
#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
|
||||
#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
|
||||
#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* ahd_dmamap_sync is only used on buffers allocated with
|
||||
* the pci_alloc_consistent() API. Although I'm not sure how
|
||||
* this works on architectures with a write buffer, Linux does
|
||||
* not have an API to sync "coherent" memory. Perhaps we need
|
||||
* to do an mb()?
|
||||
*/
|
||||
#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op)
|
||||
|
||||
/************************** Timer DataStructures ******************************/
|
||||
typedef struct timer_list ahd_timer_t;
|
||||
|
||||
/********************************** Includes **********************************/
|
||||
#ifdef CONFIG_AIC79XX_REG_PRETTY_PRINT
|
||||
#define AIC_DEBUG_REGISTERS 1
|
||||
#else
|
||||
#define AIC_DEBUG_REGISTERS 0
|
||||
#endif
|
||||
#include "aic79xx.h"
|
||||
|
||||
/***************************** Timer Facilities *******************************/
|
||||
#define ahd_timer_init init_timer
|
||||
#define ahd_timer_stop del_timer_sync
|
||||
|
||||
/***************************** SMP support ************************************/
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define AIC79XX_DRIVER_VERSION "3.0"
|
||||
|
||||
/*************************** Device Data Structures ***************************/
|
||||
/*
|
||||
* A per probed device structure used to deal with some error recovery
|
||||
* scenarios that the Linux mid-layer code just doesn't know how to
|
||||
* handle. The structure allocated for a device only becomes persistent
|
||||
* after a successfully completed inquiry command to the target when
|
||||
* that inquiry data indicates a lun is present.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
|
||||
AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
|
||||
AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
|
||||
AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
|
||||
} ahd_linux_dev_flags;
|
||||
|
||||
struct ahd_linux_device {
|
||||
TAILQ_ENTRY(ahd_linux_device) links;
|
||||
|
||||
/*
|
||||
* The number of transactions currently
|
||||
* queued to the device.
|
||||
*/
|
||||
int active;
|
||||
|
||||
/*
|
||||
* The currently allowed number of
|
||||
* transactions that can be queued to
|
||||
* the device. Must be signed for
|
||||
* conversion from tagged to untagged
|
||||
* mode where the device may have more
|
||||
* than one outstanding active transaction.
|
||||
*/
|
||||
int openings;
|
||||
|
||||
/*
|
||||
* A positive count indicates that this
|
||||
* device's queue is halted.
|
||||
*/
|
||||
u_int qfrozen;
|
||||
|
||||
/*
|
||||
* Cumulative command counter.
|
||||
*/
|
||||
u_long commands_issued;
|
||||
|
||||
/*
|
||||
* The number of tagged transactions when
|
||||
* running at our current opening level
|
||||
* that have been successfully received by
|
||||
* this device since the last QUEUE FULL.
|
||||
*/
|
||||
u_int tag_success_count;
|
||||
#define AHD_TAG_SUCCESS_INTERVAL 50
|
||||
|
||||
ahd_linux_dev_flags flags;
|
||||
|
||||
/*
|
||||
* Per device timer.
|
||||
*/
|
||||
struct timer_list timer;
|
||||
|
||||
/*
|
||||
* The high limit for the tags variable.
|
||||
*/
|
||||
u_int maxtags;
|
||||
|
||||
/*
|
||||
* The computed number of tags outstanding
|
||||
* at the time of the last QUEUE FULL event.
|
||||
*/
|
||||
u_int tags_on_last_queuefull;
|
||||
|
||||
/*
|
||||
* How many times we have seen a queue full
|
||||
* with the same number of tags. This is used
|
||||
* to stop our adaptive queue depth algorithm
|
||||
* on devices with a fixed number of tags.
|
||||
*/
|
||||
u_int last_queuefull_same_count;
|
||||
#define AHD_LOCK_TAGS_COUNT 50
|
||||
|
||||
/*
|
||||
* How many transactions have been queued
|
||||
* without the device going idle. We use
|
||||
* this statistic to determine when to issue
|
||||
* an ordered tag to prevent transaction
|
||||
* starvation. This statistic is only updated
|
||||
* if the AHD_DEV_PERIODIC_OTAG flag is set
|
||||
* on this device.
|
||||
*/
|
||||
u_int commands_since_idle_or_otag;
|
||||
#define AHD_OTAG_THRESH 500
|
||||
};
|
||||
|
||||
/********************* Definitions Required by the Core ***********************/
|
||||
/*
|
||||
* Number of SG segments we require. So long as the S/G segments for
|
||||
* a particular transaction are allocated in a physically contiguous
|
||||
* manner and are allocated below 4GB, the number of S/G segments is
|
||||
* unrestricted.
|
||||
*/
|
||||
#define AHD_NSEG 128
|
||||
|
||||
/*
|
||||
* Per-SCB OSM storage.
|
||||
*/
|
||||
struct scb_platform_data {
|
||||
struct ahd_linux_device *dev;
|
||||
dma_addr_t buf_busaddr;
|
||||
uint32_t xfer_len;
|
||||
uint32_t sense_resid; /* Auto-Sense residual */
|
||||
};
|
||||
|
||||
/*
|
||||
* Define a structure used for each host adapter. All members are
|
||||
* aligned on a boundary >= the size of the member to honor the
|
||||
* alignment restrictions of the various platforms supported by
|
||||
* this driver.
|
||||
*/
|
||||
struct ahd_platform_data {
|
||||
/*
|
||||
* Fields accessed from interrupt context.
|
||||
*/
|
||||
struct scsi_target *starget[AHD_NUM_TARGETS];
|
||||
|
||||
spinlock_t spin_lock;
|
||||
struct completion *eh_done;
|
||||
struct Scsi_Host *host; /* pointer to scsi host */
|
||||
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
|
||||
uint32_t irq; /* IRQ for this adapter */
|
||||
uint32_t bios_address;
|
||||
resource_size_t mem_busaddr; /* Mem Base Addr */
|
||||
};
|
||||
|
||||
void ahd_delay(long);
|
||||
|
||||
/***************************** Low Level I/O **********************************/
|
||||
uint8_t ahd_inb(struct ahd_softc * ahd, long port);
|
||||
void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
|
||||
void ahd_outw_atomic(struct ahd_softc * ahd,
|
||||
long port, uint16_t val);
|
||||
void ahd_outsb(struct ahd_softc * ahd, long port,
|
||||
uint8_t *, int count);
|
||||
void ahd_insb(struct ahd_softc * ahd, long port,
|
||||
uint8_t *, int count);
|
||||
|
||||
/**************************** Initialization **********************************/
|
||||
int ahd_linux_register_host(struct ahd_softc *,
|
||||
struct scsi_host_template *);
|
||||
|
||||
/******************************** Locking *************************************/
|
||||
static inline void
|
||||
ahd_lockinit(struct ahd_softc *ahd)
|
||||
{
|
||||
spin_lock_init(&ahd->platform_data->spin_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahd_lock(struct ahd_softc *ahd, unsigned long *flags)
|
||||
{
|
||||
spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
|
||||
}
|
||||
|
||||
/******************************* PCI Definitions ******************************/
|
||||
/*
|
||||
* PCIM_xxx: mask to locate subfield in register
|
||||
* PCIR_xxx: config register offset
|
||||
* PCIC_xxx: device class
|
||||
* PCIS_xxx: device subclass
|
||||
* PCIP_xxx: device programming interface
|
||||
* PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
|
||||
* PCID_xxx: device ID
|
||||
*/
|
||||
#define PCIR_DEVVENDOR 0x00
|
||||
#define PCIR_VENDOR 0x00
|
||||
#define PCIR_DEVICE 0x02
|
||||
#define PCIR_COMMAND 0x04
|
||||
#define PCIM_CMD_PORTEN 0x0001
|
||||
#define PCIM_CMD_MEMEN 0x0002
|
||||
#define PCIM_CMD_BUSMASTEREN 0x0004
|
||||
#define PCIM_CMD_MWRICEN 0x0010
|
||||
#define PCIM_CMD_PERRESPEN 0x0040
|
||||
#define PCIM_CMD_SERRESPEN 0x0100
|
||||
#define PCIR_STATUS 0x06
|
||||
#define PCIR_REVID 0x08
|
||||
#define PCIR_PROGIF 0x09
|
||||
#define PCIR_SUBCLASS 0x0a
|
||||
#define PCIR_CLASS 0x0b
|
||||
#define PCIR_CACHELNSZ 0x0c
|
||||
#define PCIR_LATTIMER 0x0d
|
||||
#define PCIR_HEADERTYPE 0x0e
|
||||
#define PCIM_MFDEV 0x80
|
||||
#define PCIR_BIST 0x0f
|
||||
#define PCIR_CAP_PTR 0x34
|
||||
|
||||
/* config registers for header type 0 devices */
|
||||
#define PCIR_MAPS 0x10
|
||||
#define PCIR_SUBVEND_0 0x2c
|
||||
#define PCIR_SUBDEV_0 0x2e
|
||||
|
||||
/****************************** PCI-X definitions *****************************/
|
||||
#define PCIXR_COMMAND 0x96
|
||||
#define PCIXR_DEVADDR 0x98
|
||||
#define PCIXM_DEVADDR_FNUM 0x0003 /* Function Number */
|
||||
#define PCIXM_DEVADDR_DNUM 0x00F8 /* Device Number */
|
||||
#define PCIXM_DEVADDR_BNUM 0xFF00 /* Bus Number */
|
||||
#define PCIXR_STATUS 0x9A
|
||||
#define PCIXM_STATUS_64BIT 0x0001 /* Active 64bit connection to device. */
|
||||
#define PCIXM_STATUS_133CAP 0x0002 /* Device is 133MHz capable */
|
||||
#define PCIXM_STATUS_SCDISC 0x0004 /* Split Completion Discarded */
|
||||
#define PCIXM_STATUS_UNEXPSC 0x0008 /* Unexpected Split Completion */
|
||||
#define PCIXM_STATUS_CMPLEXDEV 0x0010 /* Device Complexity (set == bridge) */
|
||||
#define PCIXM_STATUS_MAXMRDBC 0x0060 /* Maximum Burst Read Count */
|
||||
#define PCIXM_STATUS_MAXSPLITS 0x0380 /* Maximum Split Transactions */
|
||||
#define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */
|
||||
#define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AHD_POWER_STATE_D0,
|
||||
AHD_POWER_STATE_D1,
|
||||
AHD_POWER_STATE_D2,
|
||||
AHD_POWER_STATE_D3
|
||||
} ahd_power_state;
|
||||
|
||||
void ahd_power_state_change(struct ahd_softc *ahd,
|
||||
ahd_power_state new_state);
|
||||
|
||||
/******************************* PCI Routines *********************************/
|
||||
int ahd_linux_pci_init(void);
|
||||
void ahd_linux_pci_exit(void);
|
||||
int ahd_pci_map_registers(struct ahd_softc *ahd);
|
||||
int ahd_pci_map_int(struct ahd_softc *ahd);
|
||||
|
||||
uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
|
||||
int reg, int width);
|
||||
void ahd_pci_write_config(ahd_dev_softc_t pci,
|
||||
int reg, uint32_t value,
|
||||
int width);
|
||||
|
||||
static inline int ahd_get_pci_function(ahd_dev_softc_t);
|
||||
static inline int
|
||||
ahd_get_pci_function(ahd_dev_softc_t pci)
|
||||
{
|
||||
return (PCI_FUNC(pci->devfn));
|
||||
}
|
||||
|
||||
static inline int ahd_get_pci_slot(ahd_dev_softc_t);
|
||||
static inline int
|
||||
ahd_get_pci_slot(ahd_dev_softc_t pci)
|
||||
{
|
||||
return (PCI_SLOT(pci->devfn));
|
||||
}
|
||||
|
||||
static inline int ahd_get_pci_bus(ahd_dev_softc_t);
|
||||
static inline int
|
||||
ahd_get_pci_bus(ahd_dev_softc_t pci)
|
||||
{
|
||||
return (pci->bus->number);
|
||||
}
|
||||
|
||||
static inline void ahd_flush_device_writes(struct ahd_softc *);
|
||||
static inline void
|
||||
ahd_flush_device_writes(struct ahd_softc *ahd)
|
||||
{
|
||||
/* XXX Is this sufficient for all architectures??? */
|
||||
ahd_inb(ahd, INTSTAT);
|
||||
}
|
||||
|
||||
/**************************** Proc FS Support *********************************/
|
||||
int ahd_proc_write_seeprom(struct Scsi_Host *, char *, int);
|
||||
int ahd_linux_show_info(struct seq_file *,struct Scsi_Host *);
|
||||
|
||||
/*********************** Transaction Access Wrappers **************************/
|
||||
static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
|
||||
static inline void ahd_set_transaction_status(struct scb *, uint32_t);
|
||||
static inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
|
||||
static inline void ahd_set_scsi_status(struct scb *, uint32_t);
|
||||
static inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
|
||||
static inline uint32_t ahd_get_transaction_status(struct scb *);
|
||||
static inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
|
||||
static inline uint32_t ahd_get_scsi_status(struct scb *);
|
||||
static inline void ahd_set_transaction_tag(struct scb *, int, u_int);
|
||||
static inline u_long ahd_get_transfer_length(struct scb *);
|
||||
static inline int ahd_get_transfer_dir(struct scb *);
|
||||
static inline void ahd_set_residual(struct scb *, u_long);
|
||||
static inline void ahd_set_sense_residual(struct scb *scb, u_long resid);
|
||||
static inline u_long ahd_get_residual(struct scb *);
|
||||
static inline u_long ahd_get_sense_residual(struct scb *);
|
||||
static inline int ahd_perform_autosense(struct scb *);
|
||||
static inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *,
|
||||
struct scb *);
|
||||
static inline void ahd_notify_xfer_settings_change(struct ahd_softc *,
|
||||
struct ahd_devinfo *);
|
||||
static inline void ahd_platform_scb_free(struct ahd_softc *ahd,
|
||||
struct scb *scb);
|
||||
static inline void ahd_freeze_scb(struct scb *scb);
|
||||
|
||||
static inline
|
||||
void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
|
||||
{
|
||||
cmd->result &= ~(CAM_STATUS_MASK << 16);
|
||||
cmd->result |= status << 16;
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahd_set_transaction_status(struct scb *scb, uint32_t status)
|
||||
{
|
||||
ahd_cmd_set_transaction_status(scb->io_ctx,status);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
|
||||
{
|
||||
cmd->result &= ~0xFFFF;
|
||||
cmd->result |= status;
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahd_set_scsi_status(struct scb *scb, uint32_t status)
|
||||
{
|
||||
ahd_cmd_set_scsi_status(scb->io_ctx, status);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return ((cmd->result >> 16) & CAM_STATUS_MASK);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahd_get_transaction_status(struct scb *scb)
|
||||
{
|
||||
return (ahd_cmd_get_transaction_status(scb->io_ctx));
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return (cmd->result & 0xFFFF);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahd_get_scsi_status(struct scb *scb)
|
||||
{
|
||||
return (ahd_cmd_get_scsi_status(scb->io_ctx));
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
|
||||
{
|
||||
/*
|
||||
* Nothing to do for linux as the incoming transaction
|
||||
* has no concept of tag/non tagged, etc.
|
||||
*/
|
||||
}
|
||||
|
||||
static inline
|
||||
u_long ahd_get_transfer_length(struct scb *scb)
|
||||
{
|
||||
return (scb->platform_data->xfer_len);
|
||||
}
|
||||
|
||||
static inline
|
||||
int ahd_get_transfer_dir(struct scb *scb)
|
||||
{
|
||||
return (scb->io_ctx->sc_data_direction);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahd_set_residual(struct scb *scb, u_long resid)
|
||||
{
|
||||
scsi_set_resid(scb->io_ctx, resid);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahd_set_sense_residual(struct scb *scb, u_long resid)
|
||||
{
|
||||
scb->platform_data->sense_resid = resid;
|
||||
}
|
||||
|
||||
static inline
|
||||
u_long ahd_get_residual(struct scb *scb)
|
||||
{
|
||||
return scsi_get_resid(scb->io_ctx);
|
||||
}
|
||||
|
||||
static inline
|
||||
u_long ahd_get_sense_residual(struct scb *scb)
|
||||
{
|
||||
return (scb->platform_data->sense_resid);
|
||||
}
|
||||
|
||||
static inline
|
||||
int ahd_perform_autosense(struct scb *scb)
|
||||
{
|
||||
/*
|
||||
* We always perform autosense in Linux.
|
||||
* On other platforms this is set on a
|
||||
* per-transaction basis.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb)
|
||||
{
|
||||
return (sizeof(struct scsi_sense_data));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahd_notify_xfer_settings_change(struct ahd_softc *ahd,
|
||||
struct ahd_devinfo *devinfo)
|
||||
{
|
||||
/* Nothing to do here for linux */
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
|
||||
{
|
||||
ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
|
||||
}
|
||||
|
||||
int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg);
|
||||
void ahd_platform_free(struct ahd_softc *ahd);
|
||||
void ahd_platform_init(struct ahd_softc *ahd);
|
||||
void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
|
||||
|
||||
static inline void
|
||||
ahd_freeze_scb(struct scb *scb)
|
||||
{
|
||||
if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
|
||||
scb->io_ctx->result |= CAM_DEV_QFRZN << 16;
|
||||
scb->platform_data->dev->qfrozen++;
|
||||
}
|
||||
}
|
||||
|
||||
void ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
|
||||
struct ahd_devinfo *devinfo, ahd_queue_alg);
|
||||
int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
|
||||
char channel, int lun, u_int tag,
|
||||
role_t role, uint32_t status);
|
||||
irqreturn_t
|
||||
ahd_linux_isr(int irq, void *dev_id);
|
||||
void ahd_done(struct ahd_softc*, struct scb*);
|
||||
void ahd_send_async(struct ahd_softc *, char channel,
|
||||
u_int target, u_int lun, ac_code);
|
||||
void ahd_print_path(struct ahd_softc *, struct scb *);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#define AHD_PCI_CONFIG 1
|
||||
#else
|
||||
#define AHD_PCI_CONFIG 0
|
||||
#endif
|
||||
#define bootverbose aic79xx_verbose
|
||||
extern uint32_t aic79xx_verbose;
|
||||
|
||||
#endif /* _AIC79XX_LINUX_H_ */
|
397
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
Normal file
397
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
Normal file
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
* Linux driver attachment glue for PCI based U320 controllers.
|
||||
*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#25 $
|
||||
*/
|
||||
|
||||
#include "aic79xx_osm.h"
|
||||
#include "aic79xx_inline.h"
|
||||
#include "aic79xx_pci.h"
|
||||
|
||||
/* Define the macro locally since it's different for different class of chips.
|
||||
*/
|
||||
#define ID(x) \
|
||||
ID2C(x), \
|
||||
ID2C(IDIROC(x))
|
||||
|
||||
static const struct pci_device_id ahd_linux_pci_id_table[] = {
|
||||
/* aic7901 based controllers */
|
||||
ID(ID_AHA_29320A),
|
||||
ID(ID_AHA_29320ALP),
|
||||
ID(ID_AHA_29320LPE),
|
||||
/* aic7902 based controllers */
|
||||
ID(ID_AHA_29320),
|
||||
ID(ID_AHA_29320B),
|
||||
ID(ID_AHA_29320LP),
|
||||
ID(ID_AHA_39320),
|
||||
ID(ID_AHA_39320_B),
|
||||
ID(ID_AHA_39320A),
|
||||
ID(ID_AHA_39320D),
|
||||
ID(ID_AHA_39320D_HP),
|
||||
ID(ID_AHA_39320D_B),
|
||||
ID(ID_AHA_39320D_B_HP),
|
||||
/* Generic chip probes for devices we don't know exactly. */
|
||||
ID16(ID_AIC7901 & ID_9005_GENERIC_MASK),
|
||||
ID(ID_AIC7901A & ID_DEV_VENDOR_MASK),
|
||||
ID16(ID_AIC7902 & ID_9005_GENERIC_MASK),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int
|
||||
ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||
{
|
||||
struct ahd_softc *ahd = pci_get_drvdata(pdev);
|
||||
int rc;
|
||||
|
||||
if ((rc = ahd_suspend(ahd)))
|
||||
return rc;
|
||||
|
||||
ahd_pci_suspend(ahd);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
||||
if (mesg.event & PM_EVENT_SLEEP)
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ahd_linux_pci_dev_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct ahd_softc *ahd = pci_get_drvdata(pdev);
|
||||
int rc;
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
if ((rc = pci_enable_device(pdev))) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"failed to enable device after resume (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ahd_pci_resume(ahd);
|
||||
|
||||
ahd_resume(ahd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ahd_softc *ahd = pci_get_drvdata(pdev);
|
||||
u_long s;
|
||||
|
||||
if (ahd->platform_data && ahd->platform_data->host)
|
||||
scsi_remove_host(ahd->platform_data->host);
|
||||
|
||||
ahd_lock(ahd, &s);
|
||||
ahd_intr_enable(ahd, FALSE);
|
||||
ahd_unlock(ahd, &s);
|
||||
ahd_free(ahd);
|
||||
}
|
||||
|
||||
static void
|
||||
ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
|
||||
{
|
||||
struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
|
||||
unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
|
||||
|
||||
master_pdev = pci_get_slot(pdev->bus, master_devfn);
|
||||
if (master_pdev) {
|
||||
struct ahd_softc *master = pci_get_drvdata(master_pdev);
|
||||
if (master) {
|
||||
ahd->flags &= ~AHD_BIOS_ENABLED;
|
||||
ahd->flags |= master->flags & AHD_BIOS_ENABLED;
|
||||
} else
|
||||
printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
|
||||
pci_dev_put(master_pdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
char buf[80];
|
||||
struct ahd_softc *ahd;
|
||||
ahd_dev_softc_t pci;
|
||||
const struct ahd_pci_identity *entry;
|
||||
char *name;
|
||||
int error;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
pci = pdev;
|
||||
entry = ahd_find_pci_device(pci);
|
||||
if (entry == NULL)
|
||||
return (-ENODEV);
|
||||
|
||||
/*
|
||||
* Allocate a softc for this card and
|
||||
* set it up for attachment by our
|
||||
* common detect routine.
|
||||
*/
|
||||
sprintf(buf, "ahd_pci:%d:%d:%d",
|
||||
ahd_get_pci_bus(pci),
|
||||
ahd_get_pci_slot(pci),
|
||||
ahd_get_pci_function(pci));
|
||||
name = kstrdup(buf, GFP_ATOMIC);
|
||||
if (name == NULL)
|
||||
return (-ENOMEM);
|
||||
ahd = ahd_alloc(NULL, name);
|
||||
if (ahd == NULL)
|
||||
return (-ENOMEM);
|
||||
if (pci_enable_device(pdev)) {
|
||||
ahd_free(ahd);
|
||||
return (-ENODEV);
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
if (sizeof(dma_addr_t) > 4) {
|
||||
const u64 required_mask = dma_get_required_mask(dev);
|
||||
|
||||
if (required_mask > DMA_BIT_MASK(39) &&
|
||||
dma_set_mask(dev, DMA_BIT_MASK(64)) == 0)
|
||||
ahd->flags |= AHD_64BIT_ADDRESSING;
|
||||
else if (required_mask > DMA_BIT_MASK(32) &&
|
||||
dma_set_mask(dev, DMA_BIT_MASK(39)) == 0)
|
||||
ahd->flags |= AHD_39BIT_ADDRESSING;
|
||||
else
|
||||
dma_set_mask(dev, DMA_BIT_MASK(32));
|
||||
} else {
|
||||
dma_set_mask(dev, DMA_BIT_MASK(32));
|
||||
}
|
||||
ahd->dev_softc = pci;
|
||||
error = ahd_pci_config(ahd, entry);
|
||||
if (error != 0) {
|
||||
ahd_free(ahd);
|
||||
return (-error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second Function PCI devices need to inherit some
|
||||
* * settings from function 0.
|
||||
*/
|
||||
if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
|
||||
ahd_linux_pci_inherit_flags(ahd);
|
||||
|
||||
pci_set_drvdata(pdev, ahd);
|
||||
|
||||
ahd_linux_register_host(ahd, &aic79xx_driver_template);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct pci_driver aic79xx_pci_driver = {
|
||||
.name = "aic79xx",
|
||||
.probe = ahd_linux_pci_dev_probe,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ahd_linux_pci_dev_suspend,
|
||||
.resume = ahd_linux_pci_dev_resume,
|
||||
#endif
|
||||
.remove = ahd_linux_pci_dev_remove,
|
||||
.id_table = ahd_linux_pci_id_table
|
||||
};
|
||||
|
||||
int
|
||||
ahd_linux_pci_init(void)
|
||||
{
|
||||
return pci_register_driver(&aic79xx_pci_driver);
|
||||
}
|
||||
|
||||
void
|
||||
ahd_linux_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&aic79xx_pci_driver);
|
||||
}
|
||||
|
||||
static int
|
||||
ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, resource_size_t *base,
|
||||
resource_size_t *base2)
|
||||
{
|
||||
*base = pci_resource_start(ahd->dev_softc, 0);
|
||||
/*
|
||||
* This is really the 3rd bar and should be at index 2,
|
||||
* but the Linux PCI code doesn't know how to "count" 64bit
|
||||
* bars.
|
||||
*/
|
||||
*base2 = pci_resource_start(ahd->dev_softc, 3);
|
||||
if (*base == 0 || *base2 == 0)
|
||||
return (ENOMEM);
|
||||
if (!request_region(*base, 256, "aic79xx"))
|
||||
return (ENOMEM);
|
||||
if (!request_region(*base2, 256, "aic79xx")) {
|
||||
release_region(*base, 256);
|
||||
return (ENOMEM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
|
||||
resource_size_t *bus_addr,
|
||||
uint8_t __iomem **maddr)
|
||||
{
|
||||
resource_size_t start;
|
||||
resource_size_t base_page;
|
||||
u_long base_offset;
|
||||
int error = 0;
|
||||
|
||||
if (aic79xx_allow_memio == 0)
|
||||
return (ENOMEM);
|
||||
|
||||
if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0)
|
||||
return (ENOMEM);
|
||||
|
||||
start = pci_resource_start(ahd->dev_softc, 1);
|
||||
base_page = start & PAGE_MASK;
|
||||
base_offset = start - base_page;
|
||||
if (start != 0) {
|
||||
*bus_addr = start;
|
||||
if (!request_mem_region(start, 0x1000, "aic79xx"))
|
||||
error = ENOMEM;
|
||||
if (!error) {
|
||||
*maddr = ioremap_nocache(base_page, base_offset + 512);
|
||||
if (*maddr == NULL) {
|
||||
error = ENOMEM;
|
||||
release_mem_region(start, 0x1000);
|
||||
} else
|
||||
*maddr += base_offset;
|
||||
}
|
||||
} else
|
||||
error = ENOMEM;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ahd_pci_map_registers(struct ahd_softc *ahd)
|
||||
{
|
||||
uint32_t command;
|
||||
resource_size_t base;
|
||||
uint8_t __iomem *maddr;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* If its allowed, we prefer memory mapped access.
|
||||
*/
|
||||
command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4);
|
||||
command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
|
||||
base = 0;
|
||||
maddr = NULL;
|
||||
error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr);
|
||||
if (error == 0) {
|
||||
ahd->platform_data->mem_busaddr = base;
|
||||
ahd->tags[0] = BUS_SPACE_MEMIO;
|
||||
ahd->bshs[0].maddr = maddr;
|
||||
ahd->tags[1] = BUS_SPACE_MEMIO;
|
||||
ahd->bshs[1].maddr = maddr + 0x100;
|
||||
ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
|
||||
command | PCIM_CMD_MEMEN, 4);
|
||||
|
||||
if (ahd_pci_test_register_access(ahd) != 0) {
|
||||
|
||||
printk("aic79xx: PCI Device %d:%d:%d "
|
||||
"failed memory mapped test. Using PIO.\n",
|
||||
ahd_get_pci_bus(ahd->dev_softc),
|
||||
ahd_get_pci_slot(ahd->dev_softc),
|
||||
ahd_get_pci_function(ahd->dev_softc));
|
||||
iounmap(maddr);
|
||||
release_mem_region(ahd->platform_data->mem_busaddr,
|
||||
0x1000);
|
||||
ahd->bshs[0].maddr = NULL;
|
||||
maddr = NULL;
|
||||
} else
|
||||
command |= PCIM_CMD_MEMEN;
|
||||
} else if (bootverbose) {
|
||||
printk("aic79xx: PCI%d:%d:%d MEM region 0x%llx "
|
||||
"unavailable. Cannot memory map device.\n",
|
||||
ahd_get_pci_bus(ahd->dev_softc),
|
||||
ahd_get_pci_slot(ahd->dev_softc),
|
||||
ahd_get_pci_function(ahd->dev_softc),
|
||||
(unsigned long long)base);
|
||||
}
|
||||
|
||||
if (maddr == NULL) {
|
||||
resource_size_t base2;
|
||||
|
||||
error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2);
|
||||
if (error == 0) {
|
||||
ahd->tags[0] = BUS_SPACE_PIO;
|
||||
ahd->tags[1] = BUS_SPACE_PIO;
|
||||
ahd->bshs[0].ioport = (u_long)base;
|
||||
ahd->bshs[1].ioport = (u_long)base2;
|
||||
command |= PCIM_CMD_PORTEN;
|
||||
} else {
|
||||
printk("aic79xx: PCI%d:%d:%d IO regions 0x%llx and "
|
||||
"0x%llx unavailable. Cannot map device.\n",
|
||||
ahd_get_pci_bus(ahd->dev_softc),
|
||||
ahd_get_pci_slot(ahd->dev_softc),
|
||||
ahd_get_pci_function(ahd->dev_softc),
|
||||
(unsigned long long)base,
|
||||
(unsigned long long)base2);
|
||||
}
|
||||
}
|
||||
ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ahd_pci_map_int(struct ahd_softc *ahd)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = request_irq(ahd->dev_softc->irq, ahd_linux_isr,
|
||||
IRQF_SHARED, "aic79xx", ahd);
|
||||
if (!error)
|
||||
ahd->platform_data->irq = ahd->dev_softc->irq;
|
||||
|
||||
return (-error);
|
||||
}
|
||||
|
||||
void
|
||||
ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state)
|
||||
{
|
||||
pci_set_power_state(ahd->dev_softc, new_state);
|
||||
}
|
1014
drivers/scsi/aic7xxx/aic79xx_pci.c
Normal file
1014
drivers/scsi/aic7xxx/aic79xx_pci.c
Normal file
File diff suppressed because it is too large
Load diff
72
drivers/scsi/aic7xxx/aic79xx_pci.h
Normal file
72
drivers/scsi/aic7xxx/aic79xx_pci.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Adaptec AIC79xx device driver for Linux.
|
||||
*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#ifndef _AIC79XX_PCI_H_
|
||||
#define _AIC79XX_PCI_H_
|
||||
|
||||
#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
|
||||
#define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull
|
||||
#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
|
||||
#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
|
||||
#define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull
|
||||
|
||||
#define ID_AIC7901 0x800F9005FFFF9005ull
|
||||
#define ID_AHA_29320A 0x8000900500609005ull
|
||||
#define ID_AHA_29320ALP 0x8017900500449005ull
|
||||
#define ID_AHA_29320LPE 0x8017900500459005ull
|
||||
|
||||
#define ID_AIC7901A 0x801E9005FFFF9005ull
|
||||
#define ID_AHA_29320LP 0x8014900500449005ull
|
||||
|
||||
#define ID_AIC7902 0x801F9005FFFF9005ull
|
||||
#define ID_AIC7902_B 0x801D9005FFFF9005ull
|
||||
#define ID_AHA_39320 0x8010900500409005ull
|
||||
#define ID_AHA_29320 0x8012900500429005ull
|
||||
#define ID_AHA_29320B 0x8013900500439005ull
|
||||
#define ID_AHA_39320_B 0x8015900500409005ull
|
||||
#define ID_AHA_39320_B_DELL 0x8015900501681028ull
|
||||
#define ID_AHA_39320A 0x8016900500409005ull
|
||||
#define ID_AHA_39320D 0x8011900500419005ull
|
||||
#define ID_AHA_39320D_B 0x801C900500419005ull
|
||||
#define ID_AHA_39320D_HP 0x8011900500AC0E11ull
|
||||
#define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull
|
||||
|
||||
#endif /* _AIC79XX_PCI_H_ */
|
317
drivers/scsi/aic7xxx/aic79xx_proc.c
Normal file
317
drivers/scsi/aic7xxx/aic79xx_proc.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
|
||||
* sym driver.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#19 $
|
||||
*/
|
||||
#include "aic79xx_osm.h"
|
||||
#include "aic79xx_inline.h"
|
||||
|
||||
static void ahd_dump_target_state(struct ahd_softc *ahd,
|
||||
struct seq_file *m,
|
||||
u_int our_id, char channel,
|
||||
u_int target_id);
|
||||
static void ahd_dump_device_state(struct seq_file *m,
|
||||
struct scsi_device *sdev);
|
||||
|
||||
/*
|
||||
* Table of syncrates that don't follow the "divisible by 4"
|
||||
* rule. This table will be expanded in future SCSI specs.
|
||||
*/
|
||||
static const struct {
|
||||
u_int period_factor;
|
||||
u_int period; /* in 100ths of ns */
|
||||
} scsi_syncrates[] = {
|
||||
{ 0x08, 625 }, /* FAST-160 */
|
||||
{ 0x09, 1250 }, /* FAST-80 */
|
||||
{ 0x0a, 2500 }, /* FAST-40 40MHz */
|
||||
{ 0x0b, 3030 }, /* FAST-40 33MHz */
|
||||
{ 0x0c, 5000 } /* FAST-20 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the frequency in kHz corresponding to the given
|
||||
* sync period factor.
|
||||
*/
|
||||
static u_int
|
||||
ahd_calc_syncsrate(u_int period_factor)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* See if the period is in the "exception" table */
|
||||
for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) {
|
||||
|
||||
if (period_factor == scsi_syncrates[i].period_factor) {
|
||||
/* Period in kHz */
|
||||
return (100000000 / scsi_syncrates[i].period);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wasn't in the table, so use the standard
|
||||
* 4 times conversion.
|
||||
*/
|
||||
return (10000000 / (period_factor * 4 * 10));
|
||||
}
|
||||
|
||||
static void
|
||||
ahd_format_transinfo(struct seq_file *m, struct ahd_transinfo *tinfo)
|
||||
{
|
||||
u_int speed;
|
||||
u_int freq;
|
||||
u_int mb;
|
||||
|
||||
if (tinfo->period == AHD_PERIOD_UNKNOWN) {
|
||||
seq_printf(m, "Renegotiation Pending\n");
|
||||
return;
|
||||
}
|
||||
speed = 3300;
|
||||
freq = 0;
|
||||
if (tinfo->offset != 0) {
|
||||
freq = ahd_calc_syncsrate(tinfo->period);
|
||||
speed = freq;
|
||||
}
|
||||
speed *= (0x01 << tinfo->width);
|
||||
mb = speed / 1000;
|
||||
if (mb > 0)
|
||||
seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
|
||||
else
|
||||
seq_printf(m, "%dKB/s transfers", speed);
|
||||
|
||||
if (freq != 0) {
|
||||
int printed_options;
|
||||
|
||||
printed_options = 0;
|
||||
seq_printf(m, " (%d.%03dMHz", freq / 1000, freq % 1000);
|
||||
if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
|
||||
seq_printf(m, " RDSTRM");
|
||||
printed_options++;
|
||||
}
|
||||
if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
|
||||
seq_printf(m, "%s", printed_options ? "|DT" : " DT");
|
||||
printed_options++;
|
||||
}
|
||||
if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
|
||||
seq_printf(m, "%s", printed_options ? "|IU" : " IU");
|
||||
printed_options++;
|
||||
}
|
||||
if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) {
|
||||
seq_printf(m, "%s",
|
||||
printed_options ? "|RTI" : " RTI");
|
||||
printed_options++;
|
||||
}
|
||||
if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
|
||||
seq_printf(m, "%s",
|
||||
printed_options ? "|QAS" : " QAS");
|
||||
printed_options++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tinfo->width > 0) {
|
||||
if (freq != 0) {
|
||||
seq_printf(m, ", ");
|
||||
} else {
|
||||
seq_printf(m, " (");
|
||||
}
|
||||
seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
|
||||
} else if (freq != 0) {
|
||||
seq_printf(m, ")");
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
ahd_dump_target_state(struct ahd_softc *ahd, struct seq_file *m,
|
||||
u_int our_id, char channel, u_int target_id)
|
||||
{
|
||||
struct scsi_target *starget;
|
||||
struct ahd_initiator_tinfo *tinfo;
|
||||
struct ahd_tmode_tstate *tstate;
|
||||
int lun;
|
||||
|
||||
tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
|
||||
target_id, &tstate);
|
||||
seq_printf(m, "Target %d Negotiation Settings\n", target_id);
|
||||
seq_printf(m, "\tUser: ");
|
||||
ahd_format_transinfo(m, &tinfo->user);
|
||||
starget = ahd->platform_data->starget[target_id];
|
||||
if (starget == NULL)
|
||||
return;
|
||||
|
||||
seq_printf(m, "\tGoal: ");
|
||||
ahd_format_transinfo(m, &tinfo->goal);
|
||||
seq_printf(m, "\tCurr: ");
|
||||
ahd_format_transinfo(m, &tinfo->curr);
|
||||
|
||||
for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
|
||||
struct scsi_device *dev;
|
||||
|
||||
dev = scsi_device_lookup_by_target(starget, lun);
|
||||
|
||||
if (dev == NULL)
|
||||
continue;
|
||||
|
||||
ahd_dump_device_state(m, dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
|
||||
{
|
||||
struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
|
||||
|
||||
seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
|
||||
sdev->sdev_target->channel + 'A',
|
||||
sdev->sdev_target->id, (u8)sdev->lun);
|
||||
|
||||
seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
|
||||
seq_printf(m, "\t\tCommands Active %d\n", dev->active);
|
||||
seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
|
||||
seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
|
||||
seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
|
||||
}
|
||||
|
||||
int
|
||||
ahd_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
|
||||
{
|
||||
struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
|
||||
ahd_mode_state saved_modes;
|
||||
int have_seeprom;
|
||||
u_long s;
|
||||
int paused;
|
||||
int written;
|
||||
|
||||
/* Default to failure. */
|
||||
written = -EINVAL;
|
||||
ahd_lock(ahd, &s);
|
||||
paused = ahd_is_paused(ahd);
|
||||
if (!paused)
|
||||
ahd_pause(ahd);
|
||||
|
||||
saved_modes = ahd_save_modes(ahd);
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
if (length != sizeof(struct seeprom_config)) {
|
||||
printk("ahd_proc_write_seeprom: incorrect buffer size\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
have_seeprom = ahd_verify_cksum((struct seeprom_config*)buffer);
|
||||
if (have_seeprom == 0) {
|
||||
printk("ahd_proc_write_seeprom: cksum verification failed\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
have_seeprom = ahd_acquire_seeprom(ahd);
|
||||
if (!have_seeprom) {
|
||||
printk("ahd_proc_write_seeprom: No Serial EEPROM\n");
|
||||
goto done;
|
||||
} else {
|
||||
u_int start_addr;
|
||||
|
||||
if (ahd->seep_config == NULL) {
|
||||
ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC);
|
||||
if (ahd->seep_config == NULL) {
|
||||
printk("aic79xx: Unable to allocate serial "
|
||||
"eeprom buffer. Write failing\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
printk("aic79xx: Writing Serial EEPROM\n");
|
||||
start_addr = 32 * (ahd->channel - 'A');
|
||||
ahd_write_seeprom(ahd, (u_int16_t *)buffer, start_addr,
|
||||
sizeof(struct seeprom_config)/2);
|
||||
ahd_read_seeprom(ahd, (uint16_t *)ahd->seep_config,
|
||||
start_addr, sizeof(struct seeprom_config)/2,
|
||||
/*ByteStream*/FALSE);
|
||||
ahd_release_seeprom(ahd);
|
||||
written = length;
|
||||
}
|
||||
|
||||
done:
|
||||
ahd_restore_modes(ahd, saved_modes);
|
||||
if (!paused)
|
||||
ahd_unpause(ahd);
|
||||
ahd_unlock(ahd, &s);
|
||||
return (written);
|
||||
}
|
||||
/*
|
||||
* Return information to handle /proc support for the driver.
|
||||
*/
|
||||
int
|
||||
ahd_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
|
||||
{
|
||||
struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
|
||||
char ahd_info[256];
|
||||
u_int max_targ;
|
||||
u_int i;
|
||||
|
||||
seq_printf(m, "Adaptec AIC79xx driver version: %s\n",
|
||||
AIC79XX_DRIVER_VERSION);
|
||||
seq_printf(m, "%s\n", ahd->description);
|
||||
ahd_controller_info(ahd, ahd_info);
|
||||
seq_printf(m, "%s\n", ahd_info);
|
||||
seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
|
||||
ahd->scb_data.numscbs, AHD_NSEG);
|
||||
|
||||
max_targ = 16;
|
||||
|
||||
if (ahd->seep_config == NULL)
|
||||
seq_printf(m, "No Serial EEPROM\n");
|
||||
else {
|
||||
seq_printf(m, "Serial EEPROM:\n");
|
||||
for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) {
|
||||
if (((i % 8) == 0) && (i != 0)) {
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
seq_printf(m, "0x%.4x ",
|
||||
((uint16_t*)ahd->seep_config)[i]);
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
|
||||
if ((ahd->features & AHD_WIDE) == 0)
|
||||
max_targ = 8;
|
||||
|
||||
for (i = 0; i < max_targ; i++) {
|
||||
|
||||
ahd_dump_target_state(ahd, m, ahd->our_id, 'A',
|
||||
/*target_id*/i);
|
||||
}
|
||||
return 0;
|
||||
}
|
2685
drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
Normal file
2685
drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
Normal file
File diff suppressed because it is too large
Load diff
745
drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
Normal file
745
drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
Normal file
|
@ -0,0 +1,745 @@
|
|||
/*
|
||||
* DO NOT EDIT - This file is automatically generated
|
||||
* from the following source files:
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
|
||||
*/
|
||||
|
||||
#include "aic79xx_osm.h"
|
||||
|
||||
static const ahd_reg_parse_entry_t INTSTAT_parse_table[] = {
|
||||
{ "SPLTINT", 0x01, 0x01 },
|
||||
{ "CMDCMPLT", 0x02, 0x02 },
|
||||
{ "SEQINT", 0x04, 0x04 },
|
||||
{ "SCSIINT", 0x08, 0x08 },
|
||||
{ "PCIINT", 0x10, 0x10 },
|
||||
{ "SWTMINT", 0x20, 0x20 },
|
||||
{ "BRKADRINT", 0x40, 0x40 },
|
||||
{ "HWERRINT", 0x80, 0x80 },
|
||||
{ "INT_PEND", 0xff, 0xff }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(INTSTAT_parse_table, 9, "INTSTAT",
|
||||
0x01, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
|
||||
{ "ENINT_COALESCE", 0x40, 0x40 },
|
||||
{ "HOST_TQINPOS", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(HS_MAILBOX_parse_table, 2, "HS_MAILBOX",
|
||||
0x0b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
|
||||
{ "SEQ_SPLTINT", 0x01, 0x01 },
|
||||
{ "SEQ_PCIINT", 0x02, 0x02 },
|
||||
{ "SEQ_SCSIINT", 0x04, 0x04 },
|
||||
{ "SEQ_SEQINT", 0x08, 0x08 },
|
||||
{ "SEQ_SWTMRTO", 0x10, 0x10 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQINTSTAT_parse_table, 5, "SEQINTSTAT",
|
||||
0x0c, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t INTCTL_parse_table[] = {
|
||||
{ "SPLTINTEN", 0x01, 0x01 },
|
||||
{ "SEQINTEN", 0x02, 0x02 },
|
||||
{ "SCSIINTEN", 0x04, 0x04 },
|
||||
{ "PCIINTEN", 0x08, 0x08 },
|
||||
{ "AUTOCLRCMDINT", 0x10, 0x10 },
|
||||
{ "SWTIMER_START", 0x20, 0x20 },
|
||||
{ "SWTMINTEN", 0x40, 0x40 },
|
||||
{ "SWTMINTMASK", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_intctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(INTCTL_parse_table, 8, "INTCTL",
|
||||
0x18, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t DFCNTRL_parse_table[] = {
|
||||
{ "DIRECTIONEN", 0x01, 0x01 },
|
||||
{ "FIFOFLUSH", 0x02, 0x02 },
|
||||
{ "FIFOFLUSHACK", 0x02, 0x02 },
|
||||
{ "DIRECTION", 0x04, 0x04 },
|
||||
{ "DIRECTIONACK", 0x04, 0x04 },
|
||||
{ "HDMAEN", 0x08, 0x08 },
|
||||
{ "HDMAENACK", 0x08, 0x08 },
|
||||
{ "SCSIEN", 0x20, 0x20 },
|
||||
{ "SCSIENACK", 0x20, 0x20 },
|
||||
{ "SCSIENWRDIS", 0x40, 0x40 },
|
||||
{ "PRELOADEN", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(DFCNTRL_parse_table, 11, "DFCNTRL",
|
||||
0x19, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t DFSTATUS_parse_table[] = {
|
||||
{ "FIFOEMP", 0x01, 0x01 },
|
||||
{ "FIFOFULL", 0x02, 0x02 },
|
||||
{ "DFTHRESH", 0x04, 0x04 },
|
||||
{ "HDONE", 0x08, 0x08 },
|
||||
{ "MREQPEND", 0x10, 0x10 },
|
||||
{ "PKT_PRELOAD_AVAIL", 0x40, 0x40 },
|
||||
{ "PRELOAD_AVAIL", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_dfstatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(DFSTATUS_parse_table, 7, "DFSTATUS",
|
||||
0x1a, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
|
||||
{ "LAST_SEG_DONE", 0x01, 0x01 },
|
||||
{ "LAST_SEG", 0x02, 0x02 },
|
||||
{ "ODD_SEG", 0x04, 0x04 },
|
||||
{ "SG_ADDR_MASK", 0xf8, 0xf8 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SG_CACHE_SHADOW_parse_table, 4, "SG_CACHE_SHADOW",
|
||||
0x1b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SCSISEQ0_parse_table[] = {
|
||||
{ "SCSIRSTO", 0x01, 0x01 },
|
||||
{ "FORCEBUSFREE", 0x10, 0x10 },
|
||||
{ "ENARBO", 0x20, 0x20 },
|
||||
{ "ENSELO", 0x40, 0x40 },
|
||||
{ "TEMODEO", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_scsiseq0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SCSISEQ0_parse_table, 5, "SCSISEQ0",
|
||||
0x3a, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SCSISEQ1_parse_table[] = {
|
||||
{ "ALTSTIM", 0x01, 0x01 },
|
||||
{ "ENAUTOATNP", 0x02, 0x02 },
|
||||
{ "MANUALP", 0x0c, 0x0c },
|
||||
{ "ENRSELI", 0x10, 0x10 },
|
||||
{ "ENSELI", 0x20, 0x20 },
|
||||
{ "MANUALCTL", 0x40, 0x40 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_scsiseq1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SCSISEQ1_parse_table, 6, "SCSISEQ1",
|
||||
0x3b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t DFFSTAT_parse_table[] = {
|
||||
{ "CURRFIFO_0", 0x00, 0x03 },
|
||||
{ "CURRFIFO_1", 0x01, 0x03 },
|
||||
{ "CURRFIFO_NONE", 0x03, 0x03 },
|
||||
{ "FIFO0FREE", 0x10, 0x10 },
|
||||
{ "FIFO1FREE", 0x20, 0x20 },
|
||||
{ "CURRFIFO", 0x03, 0x03 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_dffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(DFFSTAT_parse_table, 6, "DFFSTAT",
|
||||
0x3f, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SCSISIGI_parse_table[] = {
|
||||
{ "P_DATAOUT", 0x00, 0xe0 },
|
||||
{ "P_DATAOUT_DT", 0x20, 0xe0 },
|
||||
{ "P_DATAIN", 0x40, 0xe0 },
|
||||
{ "P_DATAIN_DT", 0x60, 0xe0 },
|
||||
{ "P_COMMAND", 0x80, 0xe0 },
|
||||
{ "P_MESGOUT", 0xa0, 0xe0 },
|
||||
{ "P_STATUS", 0xc0, 0xe0 },
|
||||
{ "P_MESGIN", 0xe0, 0xe0 },
|
||||
{ "ACKI", 0x01, 0x01 },
|
||||
{ "REQI", 0x02, 0x02 },
|
||||
{ "BSYI", 0x04, 0x04 },
|
||||
{ "SELI", 0x08, 0x08 },
|
||||
{ "ATNI", 0x10, 0x10 },
|
||||
{ "MSGI", 0x20, 0x20 },
|
||||
{ "IOI", 0x40, 0x40 },
|
||||
{ "CDI", 0x80, 0x80 },
|
||||
{ "PHASE_MASK", 0xe0, 0xe0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SCSISIGI_parse_table, 17, "SCSISIGI",
|
||||
0x41, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SCSIPHASE_parse_table[] = {
|
||||
{ "DATA_OUT_PHASE", 0x01, 0x03 },
|
||||
{ "DATA_IN_PHASE", 0x02, 0x03 },
|
||||
{ "DATA_PHASE_MASK", 0x03, 0x03 },
|
||||
{ "MSG_OUT_PHASE", 0x04, 0x04 },
|
||||
{ "MSG_IN_PHASE", 0x08, 0x08 },
|
||||
{ "COMMAND_PHASE", 0x10, 0x10 },
|
||||
{ "STATUS_PHASE", 0x20, 0x20 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SCSIPHASE_parse_table, 7, "SCSIPHASE",
|
||||
0x42, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_scsibus_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "SCSIBUS",
|
||||
0x46, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SELID_parse_table[] = {
|
||||
{ "ONEBIT", 0x08, 0x08 },
|
||||
{ "SELID_MASK", 0xf0, 0xf0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SELID_parse_table, 2, "SELID",
|
||||
0x49, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
|
||||
{ "ARBDO", 0x01, 0x01 },
|
||||
{ "SPIORDY", 0x02, 0x02 },
|
||||
{ "OVERRUN", 0x04, 0x04 },
|
||||
{ "IOERR", 0x08, 0x08 },
|
||||
{ "SELINGO", 0x10, 0x10 },
|
||||
{ "SELDI", 0x20, 0x20 },
|
||||
{ "SELDO", 0x40, 0x40 },
|
||||
{ "TARGET", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
|
||||
0x4b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
|
||||
{ "ENARBDO", 0x01, 0x01 },
|
||||
{ "ENSPIORDY", 0x02, 0x02 },
|
||||
{ "ENOVERRUN", 0x04, 0x04 },
|
||||
{ "ENIOERR", 0x08, 0x08 },
|
||||
{ "ENSELINGO", 0x10, 0x10 },
|
||||
{ "ENSELDI", 0x20, 0x20 },
|
||||
{ "ENSELDO", 0x40, 0x40 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SIMODE0_parse_table, 7, "SIMODE0",
|
||||
0x4b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SSTAT1_parse_table[] = {
|
||||
{ "REQINIT", 0x01, 0x01 },
|
||||
{ "STRB2FAST", 0x02, 0x02 },
|
||||
{ "SCSIPERR", 0x04, 0x04 },
|
||||
{ "BUSFREE", 0x08, 0x08 },
|
||||
{ "PHASEMIS", 0x10, 0x10 },
|
||||
{ "SCSIRSTI", 0x20, 0x20 },
|
||||
{ "ATNTARG", 0x40, 0x40 },
|
||||
{ "SELTO", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SSTAT1_parse_table, 8, "SSTAT1",
|
||||
0x4c, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SSTAT2_parse_table[] = {
|
||||
{ "BUSFREE_LQO", 0x40, 0xc0 },
|
||||
{ "BUSFREE_DFF0", 0x80, 0xc0 },
|
||||
{ "BUSFREE_DFF1", 0xc0, 0xc0 },
|
||||
{ "DMADONE", 0x01, 0x01 },
|
||||
{ "SDONE", 0x02, 0x02 },
|
||||
{ "WIDE_RES", 0x04, 0x04 },
|
||||
{ "BSYX", 0x08, 0x08 },
|
||||
{ "EXP_ACTIVE", 0x10, 0x10 },
|
||||
{ "NONPACKREQ", 0x20, 0x20 },
|
||||
{ "BUSFREETIME", 0xc0, 0xc0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SSTAT2_parse_table, 10, "SSTAT2",
|
||||
0x4d, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
|
||||
{ "DTERR", 0x01, 0x01 },
|
||||
{ "DGFORMERR", 0x02, 0x02 },
|
||||
{ "CRCERR", 0x04, 0x04 },
|
||||
{ "AIPERR", 0x08, 0x08 },
|
||||
{ "PARITYERR", 0x10, 0x10 },
|
||||
{ "PREVPHASE", 0x20, 0x20 },
|
||||
{ "HIPERR", 0x40, 0x40 },
|
||||
{ "HIZERO", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_perrdiag_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(PERRDIAG_parse_table, 8, "PERRDIAG",
|
||||
0x4e, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_soffcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "SOFFCNT",
|
||||
0x4f, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LQISTAT0_parse_table[] = {
|
||||
{ "LQIATNCMD", 0x01, 0x01 },
|
||||
{ "LQIATNLQ", 0x02, 0x02 },
|
||||
{ "LQIBADLQT", 0x04, 0x04 },
|
||||
{ "LQICRCT2", 0x08, 0x08 },
|
||||
{ "LQICRCT1", 0x10, 0x10 },
|
||||
{ "LQIATNQAS", 0x20, 0x20 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lqistat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LQISTAT0_parse_table, 6, "LQISTAT0",
|
||||
0x50, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LQISTAT1_parse_table[] = {
|
||||
{ "LQIOVERI_NLQ", 0x01, 0x01 },
|
||||
{ "LQIOVERI_LQ", 0x02, 0x02 },
|
||||
{ "LQIBADLQI", 0x04, 0x04 },
|
||||
{ "LQICRCI_NLQ", 0x08, 0x08 },
|
||||
{ "LQICRCI_LQ", 0x10, 0x10 },
|
||||
{ "LQIABORT", 0x20, 0x20 },
|
||||
{ "LQIPHASE_NLQ", 0x40, 0x40 },
|
||||
{ "LQIPHASE_LQ", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lqistat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LQISTAT1_parse_table, 8, "LQISTAT1",
|
||||
0x51, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LQISTAT2_parse_table[] = {
|
||||
{ "LQIGSAVAIL", 0x01, 0x01 },
|
||||
{ "LQISTOPCMD", 0x02, 0x02 },
|
||||
{ "LQISTOPLQ", 0x04, 0x04 },
|
||||
{ "LQISTOPPKT", 0x08, 0x08 },
|
||||
{ "LQIWAITFIFO", 0x10, 0x10 },
|
||||
{ "LQIWORKONLQ", 0x20, 0x20 },
|
||||
{ "LQIPHASE_OUTPKT", 0x40, 0x40 },
|
||||
{ "PACKETIZED", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lqistat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LQISTAT2_parse_table, 8, "LQISTAT2",
|
||||
0x52, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SSTAT3_parse_table[] = {
|
||||
{ "OSRAMPERR", 0x01, 0x01 },
|
||||
{ "NTRAMPERR", 0x02, 0x02 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SSTAT3_parse_table, 2, "SSTAT3",
|
||||
0x53, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
|
||||
{ "LQOTCRC", 0x01, 0x01 },
|
||||
{ "LQOATNPKT", 0x02, 0x02 },
|
||||
{ "LQOATNLQ", 0x04, 0x04 },
|
||||
{ "LQOSTOPT2", 0x08, 0x08 },
|
||||
{ "LQOTARGSCBPERR", 0x10, 0x10 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lqostat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LQOSTAT0_parse_table, 5, "LQOSTAT0",
|
||||
0x54, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
|
||||
{ "LQOPHACHGINPKT", 0x01, 0x01 },
|
||||
{ "LQOBUSFREE", 0x02, 0x02 },
|
||||
{ "LQOBADQAS", 0x04, 0x04 },
|
||||
{ "LQOSTOPI2", 0x08, 0x08 },
|
||||
{ "LQOINITSCBPERR", 0x10, 0x10 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lqostat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LQOSTAT1_parse_table, 5, "LQOSTAT1",
|
||||
0x55, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
|
||||
{ "LQOSTOP0", 0x01, 0x01 },
|
||||
{ "LQOPHACHGOUTPKT", 0x02, 0x02 },
|
||||
{ "LQOWAITFIFO", 0x10, 0x10 },
|
||||
{ "LQOPKT", 0xe0, 0xe0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lqostat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LQOSTAT2_parse_table, 4, "LQOSTAT2",
|
||||
0x56, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SIMODE1_parse_table[] = {
|
||||
{ "ENREQINIT", 0x01, 0x01 },
|
||||
{ "ENSTRB2FAST", 0x02, 0x02 },
|
||||
{ "ENSCSIPERR", 0x04, 0x04 },
|
||||
{ "ENBUSFREE", 0x08, 0x08 },
|
||||
{ "ENPHASEMIS", 0x10, 0x10 },
|
||||
{ "ENSCSIRST", 0x20, 0x20 },
|
||||
{ "ENATNTARG", 0x40, 0x40 },
|
||||
{ "ENSELTIMO", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_simode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SIMODE1_parse_table, 8, "SIMODE1",
|
||||
0x57, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t DFFSXFRCTL_parse_table[] = {
|
||||
{ "RSTCHN", 0x01, 0x01 },
|
||||
{ "CLRCHN", 0x02, 0x02 },
|
||||
{ "CLRSHCNT", 0x04, 0x04 },
|
||||
{ "DFFBITBUCKET", 0x08, 0x08 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_dffsxfrctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(DFFSXFRCTL_parse_table, 4, "DFFSXFRCTL",
|
||||
0x5a, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQINTSRC_parse_table[] = {
|
||||
{ "CFG4TCMD", 0x01, 0x01 },
|
||||
{ "CFG4ICMD", 0x02, 0x02 },
|
||||
{ "CFG4TSTAT", 0x04, 0x04 },
|
||||
{ "CFG4ISTAT", 0x08, 0x08 },
|
||||
{ "CFG4DATA", 0x10, 0x10 },
|
||||
{ "SAVEPTRS", 0x20, 0x20 },
|
||||
{ "CTXTDONE", 0x40, 0x40 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seqintsrc_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQINTSRC_parse_table, 7, "SEQINTSRC",
|
||||
0x5b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQIMODE_parse_table[] = {
|
||||
{ "ENCFG4TCMD", 0x01, 0x01 },
|
||||
{ "ENCFG4ICMD", 0x02, 0x02 },
|
||||
{ "ENCFG4TSTAT", 0x04, 0x04 },
|
||||
{ "ENCFG4ISTAT", 0x08, 0x08 },
|
||||
{ "ENCFG4DATA", 0x10, 0x10 },
|
||||
{ "ENSAVEPTRS", 0x20, 0x20 },
|
||||
{ "ENCTXTDONE", 0x40, 0x40 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seqimode_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQIMODE_parse_table, 7, "SEQIMODE",
|
||||
0x5c, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t MDFFSTAT_parse_table[] = {
|
||||
{ "FIFOFREE", 0x01, 0x01 },
|
||||
{ "DATAINFIFO", 0x02, 0x02 },
|
||||
{ "DLZERO", 0x04, 0x04 },
|
||||
{ "SHVALID", 0x08, 0x08 },
|
||||
{ "LASTSDONE", 0x10, 0x10 },
|
||||
{ "SHCNTMINUS1", 0x20, 0x20 },
|
||||
{ "SHCNTNEGATIVE", 0x40, 0x40 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_mdffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(MDFFSTAT_parse_table, 7, "MDFFSTAT",
|
||||
0x5d, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_seloid_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "SELOID",
|
||||
0x6b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SG_STATE_parse_table[] = {
|
||||
{ "SEGS_AVAIL", 0x01, 0x01 },
|
||||
{ "LOADING_NEEDED", 0x02, 0x02 },
|
||||
{ "FETCH_INPROG", 0x04, 0x04 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_sg_state_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SG_STATE_parse_table, 3, "SG_STATE",
|
||||
0xa6, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
|
||||
{ "CCSCBRESET", 0x01, 0x01 },
|
||||
{ "CCSCBDIR", 0x04, 0x04 },
|
||||
{ "CCSCBEN", 0x08, 0x08 },
|
||||
{ "CCARREN", 0x10, 0x10 },
|
||||
{ "ARRDONE", 0x40, 0x40 },
|
||||
{ "CCSCBDONE", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(CCSCBCTL_parse_table, 6, "CCSCBCTL",
|
||||
0xad, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
|
||||
{ "CCSGRESET", 0x01, 0x01 },
|
||||
{ "SG_FETCH_REQ", 0x02, 0x02 },
|
||||
{ "CCSGENACK", 0x08, 0x08 },
|
||||
{ "SG_CACHE_AVAIL", 0x10, 0x10 },
|
||||
{ "CCSGDONE", 0x80, 0x80 },
|
||||
{ "CCSGEN", 0x0c, 0x0c }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
|
||||
0xad, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQCTL0_parse_table[] = {
|
||||
{ "LOADRAM", 0x01, 0x01 },
|
||||
{ "SEQRESET", 0x02, 0x02 },
|
||||
{ "STEP", 0x04, 0x04 },
|
||||
{ "BRKADRINTEN", 0x08, 0x08 },
|
||||
{ "FASTMODE", 0x10, 0x10 },
|
||||
{ "FAILDIS", 0x20, 0x20 },
|
||||
{ "PAUSEDIS", 0x40, 0x40 },
|
||||
{ "PERRORDIS", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seqctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQCTL0_parse_table, 8, "SEQCTL0",
|
||||
0xd6, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQINTCTL_parse_table[] = {
|
||||
{ "IRET", 0x01, 0x01 },
|
||||
{ "INTMASK1", 0x02, 0x02 },
|
||||
{ "INTMASK2", 0x04, 0x04 },
|
||||
{ "SCS_SEQ_INT1M0", 0x08, 0x08 },
|
||||
{ "SCS_SEQ_INT1M1", 0x10, 0x10 },
|
||||
{ "INT1_CONTEXT", 0x20, 0x20 },
|
||||
{ "INTVEC1DSL", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seqintctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQINTCTL_parse_table, 7, "SEQINTCTL",
|
||||
0xd9, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "SRAM_BASE",
|
||||
0x100, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "QFREEZE_COUNT",
|
||||
0x132, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT",
|
||||
0x134, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "SAVED_MODE",
|
||||
0x136, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
|
||||
{ "NO_DISCONNECT", 0x01, 0x01 },
|
||||
{ "SPHASE_PENDING", 0x02, 0x02 },
|
||||
{ "DPHASE_PENDING", 0x04, 0x04 },
|
||||
{ "CMDPHASE_PENDING", 0x08, 0x08 },
|
||||
{ "TARG_CMD_PENDING", 0x10, 0x10 },
|
||||
{ "DPHASE", 0x20, 0x20 },
|
||||
{ "NO_CDB_SENT", 0x40, 0x40 },
|
||||
{ "TARGET_CMD_IS_TAGGED",0x40, 0x40 },
|
||||
{ "NOT_IDENTIFIED", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS",
|
||||
0x139, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
|
||||
{ "P_DATAOUT", 0x00, 0xe0 },
|
||||
{ "P_DATAOUT_DT", 0x20, 0xe0 },
|
||||
{ "P_DATAIN", 0x40, 0xe0 },
|
||||
{ "P_DATAIN_DT", 0x60, 0xe0 },
|
||||
{ "P_COMMAND", 0x80, 0xe0 },
|
||||
{ "P_MESGOUT", 0xa0, 0xe0 },
|
||||
{ "P_STATUS", 0xc0, 0xe0 },
|
||||
{ "P_MESGIN", 0xe0, 0xe0 },
|
||||
{ "P_BUSFREE", 0x01, 0x01 },
|
||||
{ "MSGI", 0x20, 0x20 },
|
||||
{ "IOI", 0x40, 0x40 },
|
||||
{ "CDI", 0x80, 0x80 },
|
||||
{ "PHASE_MASK", 0xe0, 0xe0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE",
|
||||
0x13c, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
|
||||
{ "PENDING_MK_MESSAGE", 0x01, 0x01 },
|
||||
{ "TARGET_MSG_PENDING", 0x02, 0x02 },
|
||||
{ "SELECTOUT_QFROZEN", 0x04, 0x04 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SEQ_FLAGS2_parse_table, 3, "SEQ_FLAGS2",
|
||||
0x14d, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_mk_message_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCB",
|
||||
0x160, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID",
|
||||
0x162, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(NULL, 0, "SCB_BASE",
|
||||
0x180, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
|
||||
{ "SCB_TAG_TYPE", 0x03, 0x03 },
|
||||
{ "DISCONNECTED", 0x04, 0x04 },
|
||||
{ "STATUS_RCVD", 0x08, 0x08 },
|
||||
{ "MK_MESSAGE", 0x10, 0x10 },
|
||||
{ "TAG_ENB", 0x20, 0x20 },
|
||||
{ "DISCENB", 0x40, 0x40 },
|
||||
{ "TARGET_SCB", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SCB_CONTROL_parse_table, 7, "SCB_CONTROL",
|
||||
0x192, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahd_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
|
||||
{ "OID", 0x0f, 0x0f },
|
||||
{ "TID", 0xf0, 0xf0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahd_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahd_print_register(SCB_SCSIID_parse_table, 2, "SCB_SCSIID",
|
||||
0x193, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
1190
drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
Normal file
1190
drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
Normal file
File diff suppressed because it is too large
Load diff
1284
drivers/scsi/aic7xxx/aic7xxx.h
Normal file
1284
drivers/scsi/aic7xxx/aic7xxx.h
Normal file
File diff suppressed because it is too large
Load diff
1761
drivers/scsi/aic7xxx/aic7xxx.reg
Normal file
1761
drivers/scsi/aic7xxx/aic7xxx.reg
Normal file
File diff suppressed because it is too large
Load diff
2399
drivers/scsi/aic7xxx/aic7xxx.seq
Normal file
2399
drivers/scsi/aic7xxx/aic7xxx.seq
Normal file
File diff suppressed because it is too large
Load diff
324
drivers/scsi/aic7xxx/aic7xxx_93cx6.c
Normal file
324
drivers/scsi/aic7xxx/aic7xxx_93cx6.c
Normal file
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* Interface for the 93C66/56/46/26/06 serial eeprom parts.
|
||||
*
|
||||
* Copyright (c) 1995, 1996 Daniel M. Eischen
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL").
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
|
||||
*/
|
||||
|
||||
/*
|
||||
* The instruction set of the 93C66/56/46/26/06 chips are as follows:
|
||||
*
|
||||
* Start OP *
|
||||
* Function Bit Code Address** Data Description
|
||||
* -------------------------------------------------------------------
|
||||
* READ 1 10 A5 - A0 Reads data stored in memory,
|
||||
* starting at specified address
|
||||
* EWEN 1 00 11XXXX Write enable must precede
|
||||
* all programming modes
|
||||
* ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0
|
||||
* WRITE 1 01 A5 - A0 D15 - D0 Writes register
|
||||
* ERAL 1 00 10XXXX Erase all registers
|
||||
* WRAL 1 00 01XXXX D15 - D0 Writes to all registers
|
||||
* EWDS 1 00 00XXXX Disables all programming
|
||||
* instructions
|
||||
* *Note: A value of X for address is a don't care condition.
|
||||
* **Note: There are 8 address bits for the 93C56/66 chips unlike
|
||||
* the 93C46/26/06 chips which have 6 address bits.
|
||||
*
|
||||
* The 93C46 has a four wire interface: clock, chip select, data in, and
|
||||
* data out. In order to perform one of the above functions, you need
|
||||
* to enable the chip select for a clock period (typically a minimum of
|
||||
* 1 usec, with the clock high and low a minimum of 750 and 250 nsec
|
||||
* respectively). While the chip select remains high, you can clock in
|
||||
* the instructions (above) starting with the start bit, followed by the
|
||||
* OP code, Address, and Data (if needed). For the READ instruction, the
|
||||
* requested 16-bit register contents is read from the data out line but
|
||||
* is preceded by an initial zero (leading 0, followed by 16-bits, MSB
|
||||
* first). The clock cycling from low to high initiates the next data
|
||||
* bit to be sent from the chip.
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#include "aic7xxx_osm.h"
|
||||
#include "aic7xxx_inline.h"
|
||||
#include "aic7xxx_93cx6.h"
|
||||
#else
|
||||
#include <dev/aic7xxx/aic7xxx_osm.h>
|
||||
#include <dev/aic7xxx/aic7xxx_inline.h>
|
||||
#include <dev/aic7xxx/aic7xxx_93cx6.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Right now, we only have to read the SEEPROM. But we make it easier to
|
||||
* add other 93Cx6 functions.
|
||||
*/
|
||||
struct seeprom_cmd {
|
||||
uint8_t len;
|
||||
uint8_t bits[11];
|
||||
};
|
||||
|
||||
/* Short opcodes for the c46 */
|
||||
static const struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
|
||||
static const struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
|
||||
/* Long opcodes for the C56/C66 */
|
||||
static const struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
|
||||
static const struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
|
||||
/* Common opcodes */
|
||||
static const struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
|
||||
static const struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
|
||||
|
||||
/*
|
||||
* Wait for the SEERDY to go high; about 800 ns.
|
||||
*/
|
||||
#define CLOCK_PULSE(sd, rdy) \
|
||||
while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \
|
||||
; /* Do nothing */ \
|
||||
} \
|
||||
(void)SEEPROM_INB(sd); /* Clear clock */
|
||||
|
||||
/*
|
||||
* Send a START condition and the given command
|
||||
*/
|
||||
static void
|
||||
send_seeprom_cmd(struct seeprom_descriptor *sd, const struct seeprom_cmd *cmd)
|
||||
{
|
||||
uint8_t temp;
|
||||
int i = 0;
|
||||
|
||||
/* Send chip select for one clock cycle. */
|
||||
temp = sd->sd_MS ^ sd->sd_CS;
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
|
||||
for (i = 0; i < cmd->len; i++) {
|
||||
if (cmd->bits[i] != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
if (cmd->bits[i] != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear CS put the chip in the reset state, where it can wait for new commands.
|
||||
*/
|
||||
static void
|
||||
reset_seeprom(struct seeprom_descriptor *sd)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
temp = sd->sd_MS;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the serial EEPROM and returns 1 if successful and 0 if
|
||||
* not successful.
|
||||
*/
|
||||
int
|
||||
ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
|
||||
u_int start_addr, u_int count)
|
||||
{
|
||||
int i = 0;
|
||||
u_int k = 0;
|
||||
uint16_t v;
|
||||
uint8_t temp;
|
||||
|
||||
/*
|
||||
* Read the requested registers of the seeprom. The loop
|
||||
* will range from 0 to count-1.
|
||||
*/
|
||||
for (k = start_addr; k < count + start_addr; k++) {
|
||||
/*
|
||||
* Now we're ready to send the read command followed by the
|
||||
* address of the 16-bit register we want to read.
|
||||
*/
|
||||
send_seeprom_cmd(sd, &seeprom_read);
|
||||
|
||||
/* Send the 6 or 8 bit address (MSB first, LSB last). */
|
||||
temp = sd->sd_MS ^ sd->sd_CS;
|
||||
for (i = (sd->sd_chip - 1); i >= 0; i--) {
|
||||
if ((k & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
if ((k & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now read the 16 bit register. An initial 0 precedes the
|
||||
* register contents which begins with bit 15 (MSB) and ends
|
||||
* with bit 0 (LSB). The initial 0 will be shifted off the
|
||||
* top of our word as we let the loop run from 0 to 16.
|
||||
*/
|
||||
v = 0;
|
||||
for (i = 16; i >= 0; i--) {
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
v <<= 1;
|
||||
if (SEEPROM_DATA_INB(sd) & sd->sd_DI)
|
||||
v |= 1;
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
}
|
||||
|
||||
buf[k - start_addr] = v;
|
||||
|
||||
/* Reset the chip select for the next command cycle. */
|
||||
reset_seeprom(sd);
|
||||
}
|
||||
#ifdef AHC_DUMP_EEPROM
|
||||
printk("\nSerial EEPROM:\n\t");
|
||||
for (k = 0; k < count; k = k + 1) {
|
||||
if (((k % 8) == 0) && (k != 0)) {
|
||||
printk(KERN_CONT "\n\t");
|
||||
}
|
||||
printk(KERN_CONT " 0x%x", buf[k]);
|
||||
}
|
||||
printk(KERN_CONT "\n");
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the serial EEPROM and return 1 if successful and 0 if
|
||||
* not successful.
|
||||
*/
|
||||
int
|
||||
ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
|
||||
u_int start_addr, u_int count)
|
||||
{
|
||||
const struct seeprom_cmd *ewen, *ewds;
|
||||
uint16_t v;
|
||||
uint8_t temp;
|
||||
int i, k;
|
||||
|
||||
/* Place the chip into write-enable mode */
|
||||
if (sd->sd_chip == C46) {
|
||||
ewen = &seeprom_ewen;
|
||||
ewds = &seeprom_ewds;
|
||||
} else if (sd->sd_chip == C56_66) {
|
||||
ewen = &seeprom_long_ewen;
|
||||
ewds = &seeprom_long_ewds;
|
||||
} else {
|
||||
printk("ahc_write_seeprom: unsupported seeprom type %d\n",
|
||||
sd->sd_chip);
|
||||
return (0);
|
||||
}
|
||||
|
||||
send_seeprom_cmd(sd, ewen);
|
||||
reset_seeprom(sd);
|
||||
|
||||
/* Write all requested data out to the seeprom. */
|
||||
temp = sd->sd_MS ^ sd->sd_CS;
|
||||
for (k = start_addr; k < count + start_addr; k++) {
|
||||
/* Send the write command */
|
||||
send_seeprom_cmd(sd, &seeprom_write);
|
||||
|
||||
/* Send the 6 or 8 bit address (MSB first). */
|
||||
for (i = (sd->sd_chip - 1); i >= 0; i--) {
|
||||
if ((k & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
if ((k & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
}
|
||||
|
||||
/* Write the 16 bit value, MSB first */
|
||||
v = buf[k - start_addr];
|
||||
for (i = 15; i >= 0; i--) {
|
||||
if ((v & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
if ((v & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
}
|
||||
|
||||
/* Wait for the chip to complete the write */
|
||||
temp = sd->sd_MS;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
temp = sd->sd_MS ^ sd->sd_CS;
|
||||
do {
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
|
||||
CLOCK_PULSE(sd, sd->sd_RDY);
|
||||
} while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0);
|
||||
|
||||
reset_seeprom(sd);
|
||||
}
|
||||
|
||||
/* Put the chip back into write-protect mode */
|
||||
send_seeprom_cmd(sd, ewds);
|
||||
reset_seeprom(sd);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
ahc_verify_cksum(struct seeprom_config *sc)
|
||||
{
|
||||
int i;
|
||||
int maxaddr;
|
||||
uint32_t checksum;
|
||||
uint16_t *scarray;
|
||||
|
||||
maxaddr = (sizeof(*sc)/2) - 1;
|
||||
checksum = 0;
|
||||
scarray = (uint16_t *)sc;
|
||||
|
||||
for (i = 0; i < maxaddr; i++)
|
||||
checksum = checksum + scarray[i];
|
||||
if (checksum == 0
|
||||
|| (checksum & 0xFFFF) != sc->checksum) {
|
||||
return (0);
|
||||
} else {
|
||||
return(1);
|
||||
}
|
||||
}
|
102
drivers/scsi/aic7xxx/aic7xxx_93cx6.h
Normal file
102
drivers/scsi/aic7xxx/aic7xxx_93cx6.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Interface to the 93C46/56 serial EEPROM that is used to store BIOS
|
||||
* settings for the aic7xxx based adaptec SCSI controllers. It can
|
||||
* also be used for 93C26 and 93C06 serial EEPROMS.
|
||||
*
|
||||
* Copyright (c) 1994, 1995, 2000 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.h#12 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#ifndef _AIC7XXX_93CX6_H_
|
||||
#define _AIC7XXX_93CX6_H_
|
||||
|
||||
typedef enum {
|
||||
C46 = 6,
|
||||
C56_66 = 8
|
||||
} seeprom_chip_t;
|
||||
|
||||
struct seeprom_descriptor {
|
||||
struct ahc_softc *sd_ahc;
|
||||
u_int sd_control_offset;
|
||||
u_int sd_status_offset;
|
||||
u_int sd_dataout_offset;
|
||||
seeprom_chip_t sd_chip;
|
||||
uint16_t sd_MS;
|
||||
uint16_t sd_RDY;
|
||||
uint16_t sd_CS;
|
||||
uint16_t sd_CK;
|
||||
uint16_t sd_DO;
|
||||
uint16_t sd_DI;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function will read count 16-bit words from the serial EEPROM and
|
||||
* return their value in buf. The port address of the aic7xxx serial EEPROM
|
||||
* control register is passed in as offset. The following parameters are
|
||||
* also passed in:
|
||||
*
|
||||
* CS - Chip select
|
||||
* CK - Clock
|
||||
* DO - Data out
|
||||
* DI - Data in
|
||||
* RDY - SEEPROM ready
|
||||
* MS - Memory port mode select
|
||||
*
|
||||
* A failed read attempt returns 0, and a successful read returns 1.
|
||||
*/
|
||||
|
||||
#define SEEPROM_INB(sd) \
|
||||
ahc_inb(sd->sd_ahc, sd->sd_control_offset)
|
||||
#define SEEPROM_OUTB(sd, value) \
|
||||
do { \
|
||||
ahc_outb(sd->sd_ahc, sd->sd_control_offset, value); \
|
||||
ahc_flush_device_writes(sd->sd_ahc); \
|
||||
} while(0)
|
||||
|
||||
#define SEEPROM_STATUS_INB(sd) \
|
||||
ahc_inb(sd->sd_ahc, sd->sd_status_offset)
|
||||
#define SEEPROM_DATA_INB(sd) \
|
||||
ahc_inb(sd->sd_ahc, sd->sd_dataout_offset)
|
||||
|
||||
int ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
|
||||
u_int start_addr, u_int count);
|
||||
int ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
|
||||
u_int start_addr, u_int count);
|
||||
int ahc_verify_cksum(struct seeprom_config *sc);
|
||||
|
||||
#endif /* _AIC7XXX_93CX6_H_ */
|
7973
drivers/scsi/aic7xxx/aic7xxx_core.c
Normal file
7973
drivers/scsi/aic7xxx/aic7xxx_core.c
Normal file
File diff suppressed because it is too large
Load diff
97
drivers/scsi/aic7xxx/aic7xxx_inline.h
Normal file
97
drivers/scsi/aic7xxx/aic7xxx_inline.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Inline routines shareable across OS platforms.
|
||||
*
|
||||
* Copyright (c) 1994-2001 Justin T. Gibbs.
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#43 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _AIC7XXX_INLINE_H_
|
||||
#define _AIC7XXX_INLINE_H_
|
||||
|
||||
/************************* Sequencer Execution Control ************************/
|
||||
int ahc_is_paused(struct ahc_softc *ahc);
|
||||
void ahc_pause(struct ahc_softc *ahc);
|
||||
void ahc_unpause(struct ahc_softc *ahc);
|
||||
|
||||
/************************** Memory mapping routines ***************************/
|
||||
void ahc_sync_sglist(struct ahc_softc *ahc,
|
||||
struct scb *scb, int op);
|
||||
|
||||
/******************************** Debugging ***********************************/
|
||||
static inline char *ahc_name(struct ahc_softc *ahc);
|
||||
|
||||
static inline char *ahc_name(struct ahc_softc *ahc)
|
||||
{
|
||||
return (ahc->name);
|
||||
}
|
||||
|
||||
/*********************** Miscellaneous Support Functions ***********************/
|
||||
|
||||
struct ahc_initiator_tinfo *
|
||||
ahc_fetch_transinfo(struct ahc_softc *ahc,
|
||||
char channel, u_int our_id,
|
||||
u_int remote_id,
|
||||
struct ahc_tmode_tstate **tstate);
|
||||
uint16_t
|
||||
ahc_inw(struct ahc_softc *ahc, u_int port);
|
||||
void ahc_outw(struct ahc_softc *ahc, u_int port,
|
||||
u_int value);
|
||||
uint32_t
|
||||
ahc_inl(struct ahc_softc *ahc, u_int port);
|
||||
void ahc_outl(struct ahc_softc *ahc, u_int port,
|
||||
uint32_t value);
|
||||
uint64_t
|
||||
ahc_inq(struct ahc_softc *ahc, u_int port);
|
||||
void ahc_outq(struct ahc_softc *ahc, u_int port,
|
||||
uint64_t value);
|
||||
struct scb*
|
||||
ahc_get_scb(struct ahc_softc *ahc);
|
||||
void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
|
||||
struct scb *
|
||||
ahc_lookup_scb(struct ahc_softc *ahc, u_int tag);
|
||||
void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
|
||||
struct scsi_sense_data *
|
||||
ahc_get_sense_buf(struct ahc_softc *ahc,
|
||||
struct scb *scb);
|
||||
|
||||
/************************** Interrupt Processing ******************************/
|
||||
int ahc_intr(struct ahc_softc *ahc);
|
||||
|
||||
#endif /* _AIC7XXX_INLINE_H_ */
|
2610
drivers/scsi/aic7xxx/aic7xxx_osm.c
Normal file
2610
drivers/scsi/aic7xxx/aic7xxx_osm.c
Normal file
File diff suppressed because it is too large
Load diff
705
drivers/scsi/aic7xxx/aic7xxx_osm.h
Normal file
705
drivers/scsi/aic7xxx/aic7xxx_osm.h
Normal file
|
@ -0,0 +1,705 @@
|
|||
/*
|
||||
* Adaptec AIC7xxx device driver for Linux.
|
||||
*
|
||||
* Copyright (c) 1994 John Aycock
|
||||
* The University of Calgary Department of Computer Science.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Copyright (c) 2000-2003 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#151 $
|
||||
*
|
||||
*/
|
||||
#ifndef _AIC7XXX_LINUX_H_
|
||||
#define _AIC7XXX_LINUX_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_transport_spi.h>
|
||||
|
||||
/* Core SCSI definitions */
|
||||
#define AIC_LIB_PREFIX ahc
|
||||
|
||||
/* Name space conflict with BSD queue macros */
|
||||
#ifdef LIST_HEAD
|
||||
#undef LIST_HEAD
|
||||
#endif
|
||||
|
||||
#include "cam.h"
|
||||
#include "queue.h"
|
||||
#include "scsi_message.h"
|
||||
#include "aiclib.h"
|
||||
|
||||
/*********************************** Debugging ********************************/
|
||||
#ifdef CONFIG_AIC7XXX_DEBUG_ENABLE
|
||||
#ifdef CONFIG_AIC7XXX_DEBUG_MASK
|
||||
#define AHC_DEBUG 1
|
||||
#define AHC_DEBUG_OPTS CONFIG_AIC7XXX_DEBUG_MASK
|
||||
#else
|
||||
/*
|
||||
* Compile in debugging code, but do not enable any printfs.
|
||||
*/
|
||||
#define AHC_DEBUG 1
|
||||
#endif
|
||||
/* No debugging code. */
|
||||
#endif
|
||||
|
||||
/************************* Forward Declarations *******************************/
|
||||
struct ahc_softc;
|
||||
typedef struct pci_dev *ahc_dev_softc_t;
|
||||
typedef struct scsi_cmnd *ahc_io_ctx_t;
|
||||
|
||||
/******************************* Byte Order ***********************************/
|
||||
#define ahc_htobe16(x) cpu_to_be16(x)
|
||||
#define ahc_htobe32(x) cpu_to_be32(x)
|
||||
#define ahc_htobe64(x) cpu_to_be64(x)
|
||||
#define ahc_htole16(x) cpu_to_le16(x)
|
||||
#define ahc_htole32(x) cpu_to_le32(x)
|
||||
#define ahc_htole64(x) cpu_to_le64(x)
|
||||
|
||||
#define ahc_be16toh(x) be16_to_cpu(x)
|
||||
#define ahc_be32toh(x) be32_to_cpu(x)
|
||||
#define ahc_be64toh(x) be64_to_cpu(x)
|
||||
#define ahc_le16toh(x) le16_to_cpu(x)
|
||||
#define ahc_le32toh(x) le32_to_cpu(x)
|
||||
#define ahc_le64toh(x) le64_to_cpu(x)
|
||||
|
||||
/************************* Configuration Data *********************************/
|
||||
extern u_int aic7xxx_no_probe;
|
||||
extern u_int aic7xxx_allow_memio;
|
||||
extern struct scsi_host_template aic7xxx_driver_template;
|
||||
|
||||
/***************************** Bus Space/DMA **********************************/
|
||||
|
||||
typedef uint32_t bus_size_t;
|
||||
|
||||
typedef enum {
|
||||
BUS_SPACE_MEMIO,
|
||||
BUS_SPACE_PIO
|
||||
} bus_space_tag_t;
|
||||
|
||||
typedef union {
|
||||
u_long ioport;
|
||||
volatile uint8_t __iomem *maddr;
|
||||
} bus_space_handle_t;
|
||||
|
||||
typedef struct bus_dma_segment
|
||||
{
|
||||
dma_addr_t ds_addr;
|
||||
bus_size_t ds_len;
|
||||
} bus_dma_segment_t;
|
||||
|
||||
struct ahc_linux_dma_tag
|
||||
{
|
||||
bus_size_t alignment;
|
||||
bus_size_t boundary;
|
||||
bus_size_t maxsize;
|
||||
};
|
||||
typedef struct ahc_linux_dma_tag* bus_dma_tag_t;
|
||||
|
||||
typedef dma_addr_t bus_dmamap_t;
|
||||
|
||||
typedef int bus_dma_filter_t(void*, dma_addr_t);
|
||||
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
|
||||
|
||||
#define BUS_DMA_WAITOK 0x0
|
||||
#define BUS_DMA_NOWAIT 0x1
|
||||
#define BUS_DMA_ALLOCNOW 0x2
|
||||
#define BUS_DMA_LOAD_SEGS 0x4 /*
|
||||
* Argument is an S/G list not
|
||||
* a single buffer.
|
||||
*/
|
||||
|
||||
#define BUS_SPACE_MAXADDR 0xFFFFFFFF
|
||||
#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
|
||||
#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
|
||||
|
||||
int ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/,
|
||||
bus_size_t /*alignment*/, bus_size_t /*boundary*/,
|
||||
dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/,
|
||||
bus_dma_filter_t*/*filter*/, void */*filterarg*/,
|
||||
bus_size_t /*maxsize*/, int /*nsegments*/,
|
||||
bus_size_t /*maxsegsz*/, int /*flags*/,
|
||||
bus_dma_tag_t */*dma_tagp*/);
|
||||
|
||||
void ahc_dma_tag_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/);
|
||||
|
||||
int ahc_dmamem_alloc(struct ahc_softc *, bus_dma_tag_t /*dmat*/,
|
||||
void** /*vaddr*/, int /*flags*/,
|
||||
bus_dmamap_t* /*mapp*/);
|
||||
|
||||
void ahc_dmamem_free(struct ahc_softc *, bus_dma_tag_t /*dmat*/,
|
||||
void* /*vaddr*/, bus_dmamap_t /*map*/);
|
||||
|
||||
void ahc_dmamap_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/,
|
||||
bus_dmamap_t /*map*/);
|
||||
|
||||
int ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t /*dmat*/,
|
||||
bus_dmamap_t /*map*/, void * /*buf*/,
|
||||
bus_size_t /*buflen*/, bus_dmamap_callback_t *,
|
||||
void */*callback_arg*/, int /*flags*/);
|
||||
|
||||
int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
|
||||
|
||||
/*
|
||||
* Operations performed by ahc_dmamap_sync().
|
||||
*/
|
||||
#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
|
||||
#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
|
||||
#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
|
||||
#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* ahc_dmamap_sync is only used on buffers allocated with
|
||||
* the pci_alloc_consistent() API. Although I'm not sure how
|
||||
* this works on architectures with a write buffer, Linux does
|
||||
* not have an API to sync "coherent" memory. Perhaps we need
|
||||
* to do an mb()?
|
||||
*/
|
||||
#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op)
|
||||
|
||||
/********************************** Includes **********************************/
|
||||
#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
|
||||
#define AIC_DEBUG_REGISTERS 1
|
||||
#else
|
||||
#define AIC_DEBUG_REGISTERS 0
|
||||
#endif
|
||||
#include "aic7xxx.h"
|
||||
|
||||
/***************************** Timer Facilities *******************************/
|
||||
static inline void
|
||||
ahc_scb_timer_reset(struct scb *scb, u_int usec)
|
||||
{
|
||||
}
|
||||
|
||||
/***************************** SMP support ************************************/
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define AIC7XXX_DRIVER_VERSION "7.0"
|
||||
|
||||
/*************************** Device Data Structures ***************************/
|
||||
/*
|
||||
* A per probed device structure used to deal with some error recovery
|
||||
* scenarios that the Linux mid-layer code just doesn't know how to
|
||||
* handle. The structure allocated for a device only becomes persistent
|
||||
* after a successfully completed inquiry command to the target when
|
||||
* that inquiry data indicates a lun is present.
|
||||
*/
|
||||
typedef enum {
|
||||
AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
|
||||
AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
|
||||
AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
|
||||
AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
|
||||
} ahc_linux_dev_flags;
|
||||
|
||||
struct ahc_linux_device {
|
||||
/*
|
||||
* The number of transactions currently
|
||||
* queued to the device.
|
||||
*/
|
||||
int active;
|
||||
|
||||
/*
|
||||
* The currently allowed number of
|
||||
* transactions that can be queued to
|
||||
* the device. Must be signed for
|
||||
* conversion from tagged to untagged
|
||||
* mode where the device may have more
|
||||
* than one outstanding active transaction.
|
||||
*/
|
||||
int openings;
|
||||
|
||||
/*
|
||||
* A positive count indicates that this
|
||||
* device's queue is halted.
|
||||
*/
|
||||
u_int qfrozen;
|
||||
|
||||
/*
|
||||
* Cumulative command counter.
|
||||
*/
|
||||
u_long commands_issued;
|
||||
|
||||
/*
|
||||
* The number of tagged transactions when
|
||||
* running at our current opening level
|
||||
* that have been successfully received by
|
||||
* this device since the last QUEUE FULL.
|
||||
*/
|
||||
u_int tag_success_count;
|
||||
#define AHC_TAG_SUCCESS_INTERVAL 50
|
||||
|
||||
ahc_linux_dev_flags flags;
|
||||
|
||||
/*
|
||||
* The high limit for the tags variable.
|
||||
*/
|
||||
u_int maxtags;
|
||||
|
||||
/*
|
||||
* The computed number of tags outstanding
|
||||
* at the time of the last QUEUE FULL event.
|
||||
*/
|
||||
u_int tags_on_last_queuefull;
|
||||
|
||||
/*
|
||||
* How many times we have seen a queue full
|
||||
* with the same number of tags. This is used
|
||||
* to stop our adaptive queue depth algorithm
|
||||
* on devices with a fixed number of tags.
|
||||
*/
|
||||
u_int last_queuefull_same_count;
|
||||
#define AHC_LOCK_TAGS_COUNT 50
|
||||
|
||||
/*
|
||||
* How many transactions have been queued
|
||||
* without the device going idle. We use
|
||||
* this statistic to determine when to issue
|
||||
* an ordered tag to prevent transaction
|
||||
* starvation. This statistic is only updated
|
||||
* if the AHC_DEV_PERIODIC_OTAG flag is set
|
||||
* on this device.
|
||||
*/
|
||||
u_int commands_since_idle_or_otag;
|
||||
#define AHC_OTAG_THRESH 500
|
||||
};
|
||||
|
||||
/********************* Definitions Required by the Core ***********************/
|
||||
/*
|
||||
* Number of SG segments we require. So long as the S/G segments for
|
||||
* a particular transaction are allocated in a physically contiguous
|
||||
* manner and are allocated below 4GB, the number of S/G segments is
|
||||
* unrestricted.
|
||||
*/
|
||||
#define AHC_NSEG 128
|
||||
|
||||
/*
|
||||
* Per-SCB OSM storage.
|
||||
*/
|
||||
struct scb_platform_data {
|
||||
struct ahc_linux_device *dev;
|
||||
dma_addr_t buf_busaddr;
|
||||
uint32_t xfer_len;
|
||||
uint32_t sense_resid; /* Auto-Sense residual */
|
||||
};
|
||||
|
||||
/*
|
||||
* Define a structure used for each host adapter. All members are
|
||||
* aligned on a boundary >= the size of the member to honor the
|
||||
* alignment restrictions of the various platforms supported by
|
||||
* this driver.
|
||||
*/
|
||||
struct ahc_platform_data {
|
||||
/*
|
||||
* Fields accessed from interrupt context.
|
||||
*/
|
||||
struct scsi_target *starget[AHC_NUM_TARGETS];
|
||||
|
||||
spinlock_t spin_lock;
|
||||
u_int qfrozen;
|
||||
struct completion *eh_done;
|
||||
struct Scsi_Host *host; /* pointer to scsi host */
|
||||
#define AHC_LINUX_NOIRQ ((uint32_t)~0)
|
||||
uint32_t irq; /* IRQ for this adapter */
|
||||
uint32_t bios_address;
|
||||
resource_size_t mem_busaddr; /* Mem Base Addr */
|
||||
};
|
||||
|
||||
void ahc_delay(long);
|
||||
|
||||
|
||||
/***************************** Low Level I/O **********************************/
|
||||
uint8_t ahc_inb(struct ahc_softc * ahc, long port);
|
||||
void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
|
||||
void ahc_outsb(struct ahc_softc * ahc, long port,
|
||||
uint8_t *, int count);
|
||||
void ahc_insb(struct ahc_softc * ahc, long port,
|
||||
uint8_t *, int count);
|
||||
|
||||
/**************************** Initialization **********************************/
|
||||
int ahc_linux_register_host(struct ahc_softc *,
|
||||
struct scsi_host_template *);
|
||||
|
||||
/******************************** Locking *************************************/
|
||||
/* Lock protecting internal data structures */
|
||||
|
||||
static inline void
|
||||
ahc_lockinit(struct ahc_softc *ahc)
|
||||
{
|
||||
spin_lock_init(&ahc->platform_data->spin_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
|
||||
{
|
||||
spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags);
|
||||
}
|
||||
|
||||
/******************************* PCI Definitions ******************************/
|
||||
/*
|
||||
* PCIM_xxx: mask to locate subfield in register
|
||||
* PCIR_xxx: config register offset
|
||||
* PCIC_xxx: device class
|
||||
* PCIS_xxx: device subclass
|
||||
* PCIP_xxx: device programming interface
|
||||
* PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
|
||||
* PCID_xxx: device ID
|
||||
*/
|
||||
#define PCIR_DEVVENDOR 0x00
|
||||
#define PCIR_VENDOR 0x00
|
||||
#define PCIR_DEVICE 0x02
|
||||
#define PCIR_COMMAND 0x04
|
||||
#define PCIM_CMD_PORTEN 0x0001
|
||||
#define PCIM_CMD_MEMEN 0x0002
|
||||
#define PCIM_CMD_BUSMASTEREN 0x0004
|
||||
#define PCIM_CMD_MWRICEN 0x0010
|
||||
#define PCIM_CMD_PERRESPEN 0x0040
|
||||
#define PCIM_CMD_SERRESPEN 0x0100
|
||||
#define PCIR_STATUS 0x06
|
||||
#define PCIR_REVID 0x08
|
||||
#define PCIR_PROGIF 0x09
|
||||
#define PCIR_SUBCLASS 0x0a
|
||||
#define PCIR_CLASS 0x0b
|
||||
#define PCIR_CACHELNSZ 0x0c
|
||||
#define PCIR_LATTIMER 0x0d
|
||||
#define PCIR_HEADERTYPE 0x0e
|
||||
#define PCIM_MFDEV 0x80
|
||||
#define PCIR_BIST 0x0f
|
||||
#define PCIR_CAP_PTR 0x34
|
||||
|
||||
/* config registers for header type 0 devices */
|
||||
#define PCIR_MAPS 0x10
|
||||
#define PCIR_SUBVEND_0 0x2c
|
||||
#define PCIR_SUBDEV_0 0x2e
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AHC_POWER_STATE_D0,
|
||||
AHC_POWER_STATE_D1,
|
||||
AHC_POWER_STATE_D2,
|
||||
AHC_POWER_STATE_D3
|
||||
} ahc_power_state;
|
||||
|
||||
/**************************** VL/EISA Routines ********************************/
|
||||
#ifdef CONFIG_EISA
|
||||
int ahc_linux_eisa_init(void);
|
||||
void ahc_linux_eisa_exit(void);
|
||||
int aic7770_map_registers(struct ahc_softc *ahc,
|
||||
u_int port);
|
||||
int aic7770_map_int(struct ahc_softc *ahc, u_int irq);
|
||||
#else
|
||||
static inline int ahc_linux_eisa_init(void) {
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline void ahc_linux_eisa_exit(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************* PCI Routines *********************************/
|
||||
#ifdef CONFIG_PCI
|
||||
int ahc_linux_pci_init(void);
|
||||
void ahc_linux_pci_exit(void);
|
||||
int ahc_pci_map_registers(struct ahc_softc *ahc);
|
||||
int ahc_pci_map_int(struct ahc_softc *ahc);
|
||||
|
||||
uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
|
||||
int reg, int width);
|
||||
|
||||
void ahc_pci_write_config(ahc_dev_softc_t pci,
|
||||
int reg, uint32_t value,
|
||||
int width);
|
||||
|
||||
static inline int ahc_get_pci_function(ahc_dev_softc_t);
|
||||
static inline int
|
||||
ahc_get_pci_function(ahc_dev_softc_t pci)
|
||||
{
|
||||
return (PCI_FUNC(pci->devfn));
|
||||
}
|
||||
|
||||
static inline int ahc_get_pci_slot(ahc_dev_softc_t);
|
||||
static inline int
|
||||
ahc_get_pci_slot(ahc_dev_softc_t pci)
|
||||
{
|
||||
return (PCI_SLOT(pci->devfn));
|
||||
}
|
||||
|
||||
static inline int ahc_get_pci_bus(ahc_dev_softc_t);
|
||||
static inline int
|
||||
ahc_get_pci_bus(ahc_dev_softc_t pci)
|
||||
{
|
||||
return (pci->bus->number);
|
||||
}
|
||||
#else
|
||||
static inline int ahc_linux_pci_init(void) {
|
||||
return 0;
|
||||
}
|
||||
static inline void ahc_linux_pci_exit(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void ahc_flush_device_writes(struct ahc_softc *);
|
||||
static inline void
|
||||
ahc_flush_device_writes(struct ahc_softc *ahc)
|
||||
{
|
||||
/* XXX Is this sufficient for all architectures??? */
|
||||
ahc_inb(ahc, INTSTAT);
|
||||
}
|
||||
|
||||
/**************************** Proc FS Support *********************************/
|
||||
int ahc_proc_write_seeprom(struct Scsi_Host *, char *, int);
|
||||
int ahc_linux_show_info(struct seq_file *, struct Scsi_Host *);
|
||||
|
||||
/*************************** Domain Validation ********************************/
|
||||
/*********************** Transaction Access Wrappers *************************/
|
||||
static inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
|
||||
static inline void ahc_set_transaction_status(struct scb *, uint32_t);
|
||||
static inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
|
||||
static inline void ahc_set_scsi_status(struct scb *, uint32_t);
|
||||
static inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd);
|
||||
static inline uint32_t ahc_get_transaction_status(struct scb *);
|
||||
static inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd);
|
||||
static inline uint32_t ahc_get_scsi_status(struct scb *);
|
||||
static inline void ahc_set_transaction_tag(struct scb *, int, u_int);
|
||||
static inline u_long ahc_get_transfer_length(struct scb *);
|
||||
static inline int ahc_get_transfer_dir(struct scb *);
|
||||
static inline void ahc_set_residual(struct scb *, u_long);
|
||||
static inline void ahc_set_sense_residual(struct scb *scb, u_long resid);
|
||||
static inline u_long ahc_get_residual(struct scb *);
|
||||
static inline u_long ahc_get_sense_residual(struct scb *);
|
||||
static inline int ahc_perform_autosense(struct scb *);
|
||||
static inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *,
|
||||
struct scb *);
|
||||
static inline void ahc_notify_xfer_settings_change(struct ahc_softc *,
|
||||
struct ahc_devinfo *);
|
||||
static inline void ahc_platform_scb_free(struct ahc_softc *ahc,
|
||||
struct scb *scb);
|
||||
static inline void ahc_freeze_scb(struct scb *scb);
|
||||
|
||||
static inline
|
||||
void ahc_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
|
||||
{
|
||||
cmd->result &= ~(CAM_STATUS_MASK << 16);
|
||||
cmd->result |= status << 16;
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahc_set_transaction_status(struct scb *scb, uint32_t status)
|
||||
{
|
||||
ahc_cmd_set_transaction_status(scb->io_ctx,status);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahc_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
|
||||
{
|
||||
cmd->result &= ~0xFFFF;
|
||||
cmd->result |= status;
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahc_set_scsi_status(struct scb *scb, uint32_t status)
|
||||
{
|
||||
ahc_cmd_set_scsi_status(scb->io_ctx, status);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return ((cmd->result >> 16) & CAM_STATUS_MASK);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahc_get_transaction_status(struct scb *scb)
|
||||
{
|
||||
return (ahc_cmd_get_transaction_status(scb->io_ctx));
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return (cmd->result & 0xFFFF);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t ahc_get_scsi_status(struct scb *scb)
|
||||
{
|
||||
return (ahc_cmd_get_scsi_status(scb->io_ctx));
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
|
||||
{
|
||||
/*
|
||||
* Nothing to do for linux as the incoming transaction
|
||||
* has no concept of tag/non tagged, etc.
|
||||
*/
|
||||
}
|
||||
|
||||
static inline
|
||||
u_long ahc_get_transfer_length(struct scb *scb)
|
||||
{
|
||||
return (scb->platform_data->xfer_len);
|
||||
}
|
||||
|
||||
static inline
|
||||
int ahc_get_transfer_dir(struct scb *scb)
|
||||
{
|
||||
return (scb->io_ctx->sc_data_direction);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahc_set_residual(struct scb *scb, u_long resid)
|
||||
{
|
||||
scsi_set_resid(scb->io_ctx, resid);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ahc_set_sense_residual(struct scb *scb, u_long resid)
|
||||
{
|
||||
scb->platform_data->sense_resid = resid;
|
||||
}
|
||||
|
||||
static inline
|
||||
u_long ahc_get_residual(struct scb *scb)
|
||||
{
|
||||
return scsi_get_resid(scb->io_ctx);
|
||||
}
|
||||
|
||||
static inline
|
||||
u_long ahc_get_sense_residual(struct scb *scb)
|
||||
{
|
||||
return (scb->platform_data->sense_resid);
|
||||
}
|
||||
|
||||
static inline
|
||||
int ahc_perform_autosense(struct scb *scb)
|
||||
{
|
||||
/*
|
||||
* We always perform autosense in Linux.
|
||||
* On other platforms this is set on a
|
||||
* per-transaction basis.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb)
|
||||
{
|
||||
return (sizeof(struct scsi_sense_data));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahc_notify_xfer_settings_change(struct ahc_softc *ahc,
|
||||
struct ahc_devinfo *devinfo)
|
||||
{
|
||||
/* Nothing to do here for linux */
|
||||
}
|
||||
|
||||
static inline void
|
||||
ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
|
||||
{
|
||||
}
|
||||
|
||||
int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
|
||||
void ahc_platform_free(struct ahc_softc *ahc);
|
||||
void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
|
||||
|
||||
static inline void
|
||||
ahc_freeze_scb(struct scb *scb)
|
||||
{
|
||||
if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
|
||||
scb->io_ctx->result |= CAM_DEV_QFRZN << 16;
|
||||
scb->platform_data->dev->qfrozen++;
|
||||
}
|
||||
}
|
||||
|
||||
void ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
|
||||
struct ahc_devinfo *devinfo, ahc_queue_alg);
|
||||
int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
|
||||
char channel, int lun, u_int tag,
|
||||
role_t role, uint32_t status);
|
||||
irqreturn_t
|
||||
ahc_linux_isr(int irq, void *dev_id);
|
||||
void ahc_platform_flushwork(struct ahc_softc *ahc);
|
||||
void ahc_done(struct ahc_softc*, struct scb*);
|
||||
void ahc_send_async(struct ahc_softc *, char channel,
|
||||
u_int target, u_int lun, ac_code);
|
||||
void ahc_print_path(struct ahc_softc *, struct scb *);
|
||||
void ahc_platform_dump_card_state(struct ahc_softc *ahc);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#define AHC_PCI_CONFIG 1
|
||||
#else
|
||||
#define AHC_PCI_CONFIG 0
|
||||
#endif
|
||||
#define bootverbose aic7xxx_verbose
|
||||
extern u_int aic7xxx_verbose;
|
||||
#endif /* _AIC7XXX_LINUX_H_ */
|
470
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
Normal file
470
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
Normal file
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* Linux driver attachment glue for PCI based controllers.
|
||||
*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#47 $
|
||||
*/
|
||||
|
||||
#include "aic7xxx_osm.h"
|
||||
#include "aic7xxx_pci.h"
|
||||
|
||||
/* Define the macro locally since it's different for different class of chips.
|
||||
*/
|
||||
#define ID(x) ID_C(x, PCI_CLASS_STORAGE_SCSI)
|
||||
|
||||
static const struct pci_device_id ahc_linux_pci_id_table[] = {
|
||||
/* aic7850 based controllers */
|
||||
ID(ID_AHA_2902_04_10_15_20C_30C),
|
||||
/* aic7860 based controllers */
|
||||
ID(ID_AHA_2930CU),
|
||||
ID(ID_AHA_1480A & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK),
|
||||
/* aic7870 based controllers */
|
||||
ID(ID_AHA_2940),
|
||||
ID(ID_AHA_3940),
|
||||
ID(ID_AHA_398X),
|
||||
ID(ID_AHA_2944),
|
||||
ID(ID_AHA_3944),
|
||||
ID(ID_AHA_4944),
|
||||
/* aic7880 based controllers */
|
||||
ID(ID_AHA_2940U & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_3940U & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2944U & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_3944U & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_398XU & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_4944U & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2930U & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK),
|
||||
/* aic7890 based controllers */
|
||||
ID(ID_AHA_2930U2),
|
||||
ID(ID_AHA_2940U2B),
|
||||
ID(ID_AHA_2940U2_OEM),
|
||||
ID(ID_AHA_2940U2),
|
||||
ID(ID_AHA_2950U2B),
|
||||
ID16(ID_AIC7890_ARO & ID_AIC7895_ARO_MASK),
|
||||
ID(ID_AAA_131U2),
|
||||
/* aic7890 based controllers */
|
||||
ID(ID_AHA_29160),
|
||||
ID(ID_AHA_29160_CPQ),
|
||||
ID(ID_AHA_29160N),
|
||||
ID(ID_AHA_29160C),
|
||||
ID(ID_AHA_29160B),
|
||||
ID(ID_AHA_19160B),
|
||||
ID(ID_AIC7892_ARO),
|
||||
/* aic7892 based controllers */
|
||||
ID(ID_AHA_2940U_DUAL),
|
||||
ID(ID_AHA_3940AU),
|
||||
ID(ID_AHA_3944AU),
|
||||
ID(ID_AIC7895_ARO),
|
||||
ID(ID_AHA_3950U2B_0),
|
||||
ID(ID_AHA_3950U2B_1),
|
||||
ID(ID_AHA_3950U2D_0),
|
||||
ID(ID_AHA_3950U2D_1),
|
||||
ID(ID_AIC7896_ARO),
|
||||
/* aic7899 based controllers */
|
||||
ID(ID_AHA_3960D),
|
||||
ID(ID_AHA_3960D_CPQ),
|
||||
ID(ID_AIC7899_ARO),
|
||||
/* Generic chip probes for devices we don't know exactly. */
|
||||
ID(ID_AIC7850 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AIC7855 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AIC7859 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AIC7860 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AIC7870 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AIC7880 & ID_DEV_VENDOR_MASK),
|
||||
ID16(ID_AIC7890 & ID_9005_GENERIC_MASK),
|
||||
ID16(ID_AIC7892 & ID_9005_GENERIC_MASK),
|
||||
ID(ID_AIC7895 & ID_DEV_VENDOR_MASK),
|
||||
ID16(ID_AIC7896 & ID_9005_GENERIC_MASK),
|
||||
ID16(ID_AIC7899 & ID_9005_GENERIC_MASK),
|
||||
ID(ID_AIC7810 & ID_DEV_VENDOR_MASK),
|
||||
ID(ID_AIC7815 & ID_DEV_VENDOR_MASK),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int
|
||||
ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||
{
|
||||
struct ahc_softc *ahc = pci_get_drvdata(pdev);
|
||||
int rc;
|
||||
|
||||
if ((rc = ahc_suspend(ahc)))
|
||||
return rc;
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
||||
if (mesg.event & PM_EVENT_SLEEP)
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_linux_pci_dev_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct ahc_softc *ahc = pci_get_drvdata(pdev);
|
||||
int rc;
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
if ((rc = pci_enable_device(pdev))) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"failed to enable device after resume (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ahc_pci_resume(ahc);
|
||||
|
||||
return (ahc_resume(ahc));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ahc_softc *ahc = pci_get_drvdata(pdev);
|
||||
u_long s;
|
||||
|
||||
if (ahc->platform_data && ahc->platform_data->host)
|
||||
scsi_remove_host(ahc->platform_data->host);
|
||||
|
||||
ahc_lock(ahc, &s);
|
||||
ahc_intr_enable(ahc, FALSE);
|
||||
ahc_unlock(ahc, &s);
|
||||
ahc_free(ahc);
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
|
||||
{
|
||||
struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
|
||||
unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
|
||||
|
||||
master_pdev = pci_get_slot(pdev->bus, master_devfn);
|
||||
if (master_pdev) {
|
||||
struct ahc_softc *master = pci_get_drvdata(master_pdev);
|
||||
if (master) {
|
||||
ahc->flags &= ~AHC_BIOS_ENABLED;
|
||||
ahc->flags |= master->flags & AHC_BIOS_ENABLED;
|
||||
|
||||
ahc->flags &= ~AHC_PRIMARY_CHANNEL;
|
||||
ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
|
||||
} else
|
||||
printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
|
||||
pci_dev_put(master_pdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
char buf[80];
|
||||
const uint64_t mask_39bit = 0x7FFFFFFFFFULL;
|
||||
struct ahc_softc *ahc;
|
||||
ahc_dev_softc_t pci;
|
||||
const struct ahc_pci_identity *entry;
|
||||
char *name;
|
||||
int error;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
pci = pdev;
|
||||
entry = ahc_find_pci_device(pci);
|
||||
if (entry == NULL)
|
||||
return (-ENODEV);
|
||||
|
||||
/*
|
||||
* Allocate a softc for this card and
|
||||
* set it up for attachment by our
|
||||
* common detect routine.
|
||||
*/
|
||||
sprintf(buf, "ahc_pci:%d:%d:%d",
|
||||
ahc_get_pci_bus(pci),
|
||||
ahc_get_pci_slot(pci),
|
||||
ahc_get_pci_function(pci));
|
||||
name = kstrdup(buf, GFP_ATOMIC);
|
||||
if (name == NULL)
|
||||
return (-ENOMEM);
|
||||
ahc = ahc_alloc(NULL, name);
|
||||
if (ahc == NULL)
|
||||
return (-ENOMEM);
|
||||
if (pci_enable_device(pdev)) {
|
||||
ahc_free(ahc);
|
||||
return (-ENODEV);
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
if (sizeof(dma_addr_t) > 4
|
||||
&& ahc->features & AHC_LARGE_SCBS
|
||||
&& dma_set_mask(dev, mask_39bit) == 0
|
||||
&& dma_get_required_mask(dev) > DMA_BIT_MASK(32)) {
|
||||
ahc->flags |= AHC_39BIT_ADDRESSING;
|
||||
} else {
|
||||
if (dma_set_mask(dev, DMA_BIT_MASK(32))) {
|
||||
ahc_free(ahc);
|
||||
printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
|
||||
return (-ENODEV);
|
||||
}
|
||||
}
|
||||
ahc->dev_softc = pci;
|
||||
error = ahc_pci_config(ahc, entry);
|
||||
if (error != 0) {
|
||||
ahc_free(ahc);
|
||||
return (-error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second Function PCI devices need to inherit some
|
||||
* settings from function 0.
|
||||
*/
|
||||
if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
|
||||
ahc_linux_pci_inherit_flags(ahc);
|
||||
|
||||
pci_set_drvdata(pdev, ahc);
|
||||
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************* PCI Routines *********************************/
|
||||
uint32_t
|
||||
ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
|
||||
{
|
||||
switch (width) {
|
||||
case 1:
|
||||
{
|
||||
uint8_t retval;
|
||||
|
||||
pci_read_config_byte(pci, reg, &retval);
|
||||
return (retval);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
uint16_t retval;
|
||||
pci_read_config_word(pci, reg, &retval);
|
||||
return (retval);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
uint32_t retval;
|
||||
pci_read_config_dword(pci, reg, &retval);
|
||||
return (retval);
|
||||
}
|
||||
default:
|
||||
panic("ahc_pci_read_config: Read size too big");
|
||||
/* NOTREACHED */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
|
||||
{
|
||||
switch (width) {
|
||||
case 1:
|
||||
pci_write_config_byte(pci, reg, value);
|
||||
break;
|
||||
case 2:
|
||||
pci_write_config_word(pci, reg, value);
|
||||
break;
|
||||
case 4:
|
||||
pci_write_config_dword(pci, reg, value);
|
||||
break;
|
||||
default:
|
||||
panic("ahc_pci_write_config: Write size too big");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct pci_driver aic7xxx_pci_driver = {
|
||||
.name = "aic7xxx",
|
||||
.probe = ahc_linux_pci_dev_probe,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ahc_linux_pci_dev_suspend,
|
||||
.resume = ahc_linux_pci_dev_resume,
|
||||
#endif
|
||||
.remove = ahc_linux_pci_dev_remove,
|
||||
.id_table = ahc_linux_pci_id_table
|
||||
};
|
||||
|
||||
int
|
||||
ahc_linux_pci_init(void)
|
||||
{
|
||||
return pci_register_driver(&aic7xxx_pci_driver);
|
||||
}
|
||||
|
||||
void
|
||||
ahc_linux_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&aic7xxx_pci_driver);
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, resource_size_t *base)
|
||||
{
|
||||
if (aic7xxx_allow_memio == 0)
|
||||
return (ENOMEM);
|
||||
|
||||
*base = pci_resource_start(ahc->dev_softc, 0);
|
||||
if (*base == 0)
|
||||
return (ENOMEM);
|
||||
if (!request_region(*base, 256, "aic7xxx"))
|
||||
return (ENOMEM);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
|
||||
resource_size_t *bus_addr,
|
||||
uint8_t __iomem **maddr)
|
||||
{
|
||||
resource_size_t start;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
start = pci_resource_start(ahc->dev_softc, 1);
|
||||
if (start != 0) {
|
||||
*bus_addr = start;
|
||||
if (!request_mem_region(start, 0x1000, "aic7xxx"))
|
||||
error = ENOMEM;
|
||||
if (error == 0) {
|
||||
*maddr = ioremap_nocache(start, 256);
|
||||
if (*maddr == NULL) {
|
||||
error = ENOMEM;
|
||||
release_mem_region(start, 0x1000);
|
||||
}
|
||||
}
|
||||
} else
|
||||
error = ENOMEM;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ahc_pci_map_registers(struct ahc_softc *ahc)
|
||||
{
|
||||
uint32_t command;
|
||||
resource_size_t base;
|
||||
uint8_t __iomem *maddr;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* If its allowed, we prefer memory mapped access.
|
||||
*/
|
||||
command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4);
|
||||
command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
|
||||
base = 0;
|
||||
maddr = NULL;
|
||||
error = ahc_linux_pci_reserve_mem_region(ahc, &base, &maddr);
|
||||
if (error == 0) {
|
||||
ahc->platform_data->mem_busaddr = base;
|
||||
ahc->tag = BUS_SPACE_MEMIO;
|
||||
ahc->bsh.maddr = maddr;
|
||||
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
|
||||
command | PCIM_CMD_MEMEN, 4);
|
||||
|
||||
/*
|
||||
* Do a quick test to see if memory mapped
|
||||
* I/O is functioning correctly.
|
||||
*/
|
||||
if (ahc_pci_test_register_access(ahc) != 0) {
|
||||
|
||||
printk("aic7xxx: PCI Device %d:%d:%d "
|
||||
"failed memory mapped test. Using PIO.\n",
|
||||
ahc_get_pci_bus(ahc->dev_softc),
|
||||
ahc_get_pci_slot(ahc->dev_softc),
|
||||
ahc_get_pci_function(ahc->dev_softc));
|
||||
iounmap(maddr);
|
||||
release_mem_region(ahc->platform_data->mem_busaddr,
|
||||
0x1000);
|
||||
ahc->bsh.maddr = NULL;
|
||||
maddr = NULL;
|
||||
} else
|
||||
command |= PCIM_CMD_MEMEN;
|
||||
} else {
|
||||
printk("aic7xxx: PCI%d:%d:%d MEM region 0x%llx "
|
||||
"unavailable. Cannot memory map device.\n",
|
||||
ahc_get_pci_bus(ahc->dev_softc),
|
||||
ahc_get_pci_slot(ahc->dev_softc),
|
||||
ahc_get_pci_function(ahc->dev_softc),
|
||||
(unsigned long long)base);
|
||||
}
|
||||
|
||||
/*
|
||||
* We always prefer memory mapped access.
|
||||
*/
|
||||
if (maddr == NULL) {
|
||||
|
||||
error = ahc_linux_pci_reserve_io_region(ahc, &base);
|
||||
if (error == 0) {
|
||||
ahc->tag = BUS_SPACE_PIO;
|
||||
ahc->bsh.ioport = (u_long)base;
|
||||
command |= PCIM_CMD_PORTEN;
|
||||
} else {
|
||||
printk("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] "
|
||||
"unavailable. Cannot map device.\n",
|
||||
ahc_get_pci_bus(ahc->dev_softc),
|
||||
ahc_get_pci_slot(ahc->dev_softc),
|
||||
ahc_get_pci_function(ahc->dev_softc),
|
||||
(unsigned long long)base);
|
||||
}
|
||||
}
|
||||
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ahc_pci_map_int(struct ahc_softc *ahc)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = request_irq(ahc->dev_softc->irq, ahc_linux_isr,
|
||||
IRQF_SHARED, "aic7xxx", ahc);
|
||||
if (error == 0)
|
||||
ahc->platform_data->irq = ahc->dev_softc->irq;
|
||||
|
||||
return (-error);
|
||||
}
|
||||
|
2469
drivers/scsi/aic7xxx/aic7xxx_pci.c
Normal file
2469
drivers/scsi/aic7xxx/aic7xxx_pci.c
Normal file
File diff suppressed because it is too large
Load diff
125
drivers/scsi/aic7xxx/aic7xxx_pci.h
Normal file
125
drivers/scsi/aic7xxx/aic7xxx_pci.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Adaptec AIC7xxx device driver for Linux.
|
||||
*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
#ifndef _AIC7XXX_PCI_H_
|
||||
#define _AIC7XXX_PCI_H_
|
||||
|
||||
#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
|
||||
#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
|
||||
#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
|
||||
#define ID_9005_SISL_MASK 0x000FFFFF00000000ull
|
||||
#define ID_9005_SISL_ID 0x0005900500000000ull
|
||||
#define ID_AIC7850 0x5078900400000000ull
|
||||
#define ID_AHA_2902_04_10_15_20C_30C 0x5078900478509004ull
|
||||
#define ID_AIC7855 0x5578900400000000ull
|
||||
#define ID_AIC7859 0x3860900400000000ull
|
||||
#define ID_AHA_2930CU 0x3860900438699004ull
|
||||
#define ID_AIC7860 0x6078900400000000ull
|
||||
#define ID_AIC7860C 0x6078900478609004ull
|
||||
#define ID_AHA_1480A 0x6075900400000000ull
|
||||
#define ID_AHA_2940AU_0 0x6178900400000000ull
|
||||
#define ID_AHA_2940AU_1 0x6178900478619004ull
|
||||
#define ID_AHA_2940AU_CN 0x2178900478219004ull
|
||||
#define ID_AHA_2930C_VAR 0x6038900438689004ull
|
||||
|
||||
#define ID_AIC7870 0x7078900400000000ull
|
||||
#define ID_AHA_2940 0x7178900400000000ull
|
||||
#define ID_AHA_3940 0x7278900400000000ull
|
||||
#define ID_AHA_398X 0x7378900400000000ull
|
||||
#define ID_AHA_2944 0x7478900400000000ull
|
||||
#define ID_AHA_3944 0x7578900400000000ull
|
||||
#define ID_AHA_4944 0x7678900400000000ull
|
||||
|
||||
#define ID_AIC7880 0x8078900400000000ull
|
||||
#define ID_AIC7880_B 0x8078900478809004ull
|
||||
#define ID_AHA_2940U 0x8178900400000000ull
|
||||
#define ID_AHA_3940U 0x8278900400000000ull
|
||||
#define ID_AHA_2944U 0x8478900400000000ull
|
||||
#define ID_AHA_3944U 0x8578900400000000ull
|
||||
#define ID_AHA_398XU 0x8378900400000000ull
|
||||
#define ID_AHA_4944U 0x8678900400000000ull
|
||||
#define ID_AHA_2940UB 0x8178900478819004ull
|
||||
#define ID_AHA_2930U 0x8878900478889004ull
|
||||
#define ID_AHA_2940U_PRO 0x8778900478879004ull
|
||||
#define ID_AHA_2940U_CN 0x0078900478009004ull
|
||||
|
||||
#define ID_AIC7895 0x7895900478959004ull
|
||||
#define ID_AIC7895_ARO 0x7890900478939004ull
|
||||
#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull
|
||||
#define ID_AHA_2940U_DUAL 0x7895900478919004ull
|
||||
#define ID_AHA_3940AU 0x7895900478929004ull
|
||||
#define ID_AHA_3944AU 0x7895900478949004ull
|
||||
|
||||
#define ID_AIC7890 0x001F9005000F9005ull
|
||||
#define ID_AIC7890_ARO 0x00139005000F9005ull
|
||||
#define ID_AAA_131U2 0x0013900500039005ull
|
||||
#define ID_AHA_2930U2 0x0011900501819005ull
|
||||
#define ID_AHA_2940U2B 0x00109005A1009005ull
|
||||
#define ID_AHA_2940U2_OEM 0x0010900521809005ull
|
||||
#define ID_AHA_2940U2 0x00109005A1809005ull
|
||||
#define ID_AHA_2950U2B 0x00109005E1009005ull
|
||||
|
||||
#define ID_AIC7892 0x008F9005FFFF9005ull
|
||||
#define ID_AIC7892_ARO 0x00839005FFFF9005ull
|
||||
#define ID_AHA_29160 0x00809005E2A09005ull
|
||||
#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull
|
||||
#define ID_AHA_29160N 0x0080900562A09005ull
|
||||
#define ID_AHA_29160C 0x0080900562209005ull
|
||||
#define ID_AHA_29160B 0x00809005E2209005ull
|
||||
#define ID_AHA_19160B 0x0081900562A19005ull
|
||||
#define ID_AHA_2915_30LP 0x0082900502109005ull
|
||||
|
||||
#define ID_AIC7896 0x005F9005FFFF9005ull
|
||||
#define ID_AIC7896_ARO 0x00539005FFFF9005ull
|
||||
#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull
|
||||
#define ID_AHA_3950U2B_1 0x00509005F5009005ull
|
||||
#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull
|
||||
#define ID_AHA_3950U2D_1 0x00519005B5009005ull
|
||||
|
||||
#define ID_AIC7899 0x00CF9005FFFF9005ull
|
||||
#define ID_AIC7899_ARO 0x00C39005FFFF9005ull
|
||||
#define ID_AHA_3960D 0x00C09005F6209005ull
|
||||
#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull
|
||||
|
||||
#define ID_AIC7810 0x1078900400000000ull
|
||||
#define ID_AIC7815 0x7815900400000000ull
|
||||
|
||||
#endif /* _AIC7XXX_PCI_H_ */
|
342
drivers/scsi/aic7xxx/aic7xxx_proc.c
Normal file
342
drivers/scsi/aic7xxx/aic7xxx_proc.c
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
|
||||
* sym driver.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#29 $
|
||||
*/
|
||||
#include "aic7xxx_osm.h"
|
||||
#include "aic7xxx_inline.h"
|
||||
#include "aic7xxx_93cx6.h"
|
||||
|
||||
static void ahc_dump_target_state(struct ahc_softc *ahc,
|
||||
struct seq_file *m,
|
||||
u_int our_id, char channel,
|
||||
u_int target_id, u_int target_offset);
|
||||
static void ahc_dump_device_state(struct seq_file *m,
|
||||
struct scsi_device *dev);
|
||||
|
||||
/*
|
||||
* Table of syncrates that don't follow the "divisible by 4"
|
||||
* rule. This table will be expanded in future SCSI specs.
|
||||
*/
|
||||
static const struct {
|
||||
u_int period_factor;
|
||||
u_int period; /* in 100ths of ns */
|
||||
} scsi_syncrates[] = {
|
||||
{ 0x08, 625 }, /* FAST-160 */
|
||||
{ 0x09, 1250 }, /* FAST-80 */
|
||||
{ 0x0a, 2500 }, /* FAST-40 40MHz */
|
||||
{ 0x0b, 3030 }, /* FAST-40 33MHz */
|
||||
{ 0x0c, 5000 } /* FAST-20 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the frequency in kHz corresponding to the given
|
||||
* sync period factor.
|
||||
*/
|
||||
static u_int
|
||||
ahc_calc_syncsrate(u_int period_factor)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* See if the period is in the "exception" table */
|
||||
for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) {
|
||||
|
||||
if (period_factor == scsi_syncrates[i].period_factor) {
|
||||
/* Period in kHz */
|
||||
return (100000000 / scsi_syncrates[i].period);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wasn't in the table, so use the standard
|
||||
* 4 times conversion.
|
||||
*/
|
||||
return (10000000 / (period_factor * 4 * 10));
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_format_transinfo(struct seq_file *m, struct ahc_transinfo *tinfo)
|
||||
{
|
||||
u_int speed;
|
||||
u_int freq;
|
||||
u_int mb;
|
||||
|
||||
speed = 3300;
|
||||
freq = 0;
|
||||
if (tinfo->offset != 0) {
|
||||
freq = ahc_calc_syncsrate(tinfo->period);
|
||||
speed = freq;
|
||||
}
|
||||
speed *= (0x01 << tinfo->width);
|
||||
mb = speed / 1000;
|
||||
if (mb > 0)
|
||||
seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
|
||||
else
|
||||
seq_printf(m, "%dKB/s transfers", speed);
|
||||
|
||||
if (freq != 0) {
|
||||
seq_printf(m, " (%d.%03dMHz%s, offset %d",
|
||||
freq / 1000, freq % 1000,
|
||||
(tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
|
||||
? " DT" : "", tinfo->offset);
|
||||
}
|
||||
|
||||
if (tinfo->width > 0) {
|
||||
if (freq != 0) {
|
||||
seq_printf(m, ", ");
|
||||
} else {
|
||||
seq_printf(m, " (");
|
||||
}
|
||||
seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
|
||||
} else if (freq != 0) {
|
||||
seq_printf(m, ")");
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_dump_target_state(struct ahc_softc *ahc, struct seq_file *m,
|
||||
u_int our_id, char channel, u_int target_id,
|
||||
u_int target_offset)
|
||||
{
|
||||
struct scsi_target *starget;
|
||||
struct ahc_initiator_tinfo *tinfo;
|
||||
struct ahc_tmode_tstate *tstate;
|
||||
int lun;
|
||||
|
||||
tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
|
||||
target_id, &tstate);
|
||||
if ((ahc->features & AHC_TWIN) != 0)
|
||||
seq_printf(m, "Channel %c ", channel);
|
||||
seq_printf(m, "Target %d Negotiation Settings\n", target_id);
|
||||
seq_printf(m, "\tUser: ");
|
||||
ahc_format_transinfo(m, &tinfo->user);
|
||||
starget = ahc->platform_data->starget[target_offset];
|
||||
if (!starget)
|
||||
return;
|
||||
|
||||
seq_printf(m, "\tGoal: ");
|
||||
ahc_format_transinfo(m, &tinfo->goal);
|
||||
seq_printf(m, "\tCurr: ");
|
||||
ahc_format_transinfo(m, &tinfo->curr);
|
||||
|
||||
for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
|
||||
struct scsi_device *sdev;
|
||||
|
||||
sdev = scsi_device_lookup_by_target(starget, lun);
|
||||
|
||||
if (sdev == NULL)
|
||||
continue;
|
||||
|
||||
ahc_dump_device_state(m, sdev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
|
||||
{
|
||||
struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
|
||||
|
||||
seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
|
||||
sdev->sdev_target->channel + 'A',
|
||||
sdev->sdev_target->id, (u8)sdev->lun);
|
||||
|
||||
seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
|
||||
seq_printf(m, "\t\tCommands Active %d\n", dev->active);
|
||||
seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
|
||||
seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
|
||||
seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
|
||||
}
|
||||
|
||||
int
|
||||
ahc_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
|
||||
{
|
||||
struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
|
||||
struct seeprom_descriptor sd;
|
||||
int have_seeprom;
|
||||
u_long s;
|
||||
int paused;
|
||||
int written;
|
||||
|
||||
/* Default to failure. */
|
||||
written = -EINVAL;
|
||||
ahc_lock(ahc, &s);
|
||||
paused = ahc_is_paused(ahc);
|
||||
if (!paused)
|
||||
ahc_pause(ahc);
|
||||
|
||||
if (length != sizeof(struct seeprom_config)) {
|
||||
printk("ahc_proc_write_seeprom: incorrect buffer size\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
have_seeprom = ahc_verify_cksum((struct seeprom_config*)buffer);
|
||||
if (have_seeprom == 0) {
|
||||
printk("ahc_proc_write_seeprom: cksum verification failed\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
sd.sd_ahc = ahc;
|
||||
#if AHC_PCI_CONFIG > 0
|
||||
if ((ahc->chip & AHC_PCI) != 0) {
|
||||
sd.sd_control_offset = SEECTL;
|
||||
sd.sd_status_offset = SEECTL;
|
||||
sd.sd_dataout_offset = SEECTL;
|
||||
if (ahc->flags & AHC_LARGE_SEEPROM)
|
||||
sd.sd_chip = C56_66;
|
||||
else
|
||||
sd.sd_chip = C46;
|
||||
sd.sd_MS = SEEMS;
|
||||
sd.sd_RDY = SEERDY;
|
||||
sd.sd_CS = SEECS;
|
||||
sd.sd_CK = SEECK;
|
||||
sd.sd_DO = SEEDO;
|
||||
sd.sd_DI = SEEDI;
|
||||
have_seeprom = ahc_acquire_seeprom(ahc, &sd);
|
||||
} else
|
||||
#endif
|
||||
if ((ahc->chip & AHC_VL) != 0) {
|
||||
sd.sd_control_offset = SEECTL_2840;
|
||||
sd.sd_status_offset = STATUS_2840;
|
||||
sd.sd_dataout_offset = STATUS_2840;
|
||||
sd.sd_chip = C46;
|
||||
sd.sd_MS = 0;
|
||||
sd.sd_RDY = EEPROM_TF;
|
||||
sd.sd_CS = CS_2840;
|
||||
sd.sd_CK = CK_2840;
|
||||
sd.sd_DO = DO_2840;
|
||||
sd.sd_DI = DI_2840;
|
||||
have_seeprom = TRUE;
|
||||
} else {
|
||||
printk("ahc_proc_write_seeprom: unsupported adapter type\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!have_seeprom) {
|
||||
printk("ahc_proc_write_seeprom: No Serial EEPROM\n");
|
||||
goto done;
|
||||
} else {
|
||||
u_int start_addr;
|
||||
|
||||
if (ahc->seep_config == NULL) {
|
||||
ahc->seep_config = kmalloc(sizeof(*ahc->seep_config), GFP_ATOMIC);
|
||||
if (ahc->seep_config == NULL) {
|
||||
printk("aic7xxx: Unable to allocate serial "
|
||||
"eeprom buffer. Write failing\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
printk("aic7xxx: Writing Serial EEPROM\n");
|
||||
start_addr = 32 * (ahc->channel - 'A');
|
||||
ahc_write_seeprom(&sd, (u_int16_t *)buffer, start_addr,
|
||||
sizeof(struct seeprom_config)/2);
|
||||
ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config,
|
||||
start_addr, sizeof(struct seeprom_config)/2);
|
||||
#if AHC_PCI_CONFIG > 0
|
||||
if ((ahc->chip & AHC_VL) == 0)
|
||||
ahc_release_seeprom(&sd);
|
||||
#endif
|
||||
written = length;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!paused)
|
||||
ahc_unpause(ahc);
|
||||
ahc_unlock(ahc, &s);
|
||||
return (written);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return information to handle /proc support for the driver.
|
||||
*/
|
||||
int
|
||||
ahc_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
|
||||
{
|
||||
struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
|
||||
char ahc_info[256];
|
||||
u_int max_targ;
|
||||
u_int i;
|
||||
|
||||
seq_printf(m, "Adaptec AIC7xxx driver version: %s\n",
|
||||
AIC7XXX_DRIVER_VERSION);
|
||||
seq_printf(m, "%s\n", ahc->description);
|
||||
ahc_controller_info(ahc, ahc_info);
|
||||
seq_printf(m, "%s\n", ahc_info);
|
||||
seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
|
||||
ahc->scb_data->numscbs, AHC_NSEG);
|
||||
|
||||
|
||||
if (ahc->seep_config == NULL)
|
||||
seq_printf(m, "No Serial EEPROM\n");
|
||||
else {
|
||||
seq_printf(m, "Serial EEPROM:\n");
|
||||
for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) {
|
||||
if (((i % 8) == 0) && (i != 0)) {
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
seq_printf(m, "0x%.4x ",
|
||||
((uint16_t*)ahc->seep_config)[i]);
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
|
||||
max_targ = 16;
|
||||
if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
|
||||
max_targ = 8;
|
||||
|
||||
for (i = 0; i < max_targ; i++) {
|
||||
u_int our_id;
|
||||
u_int target_id;
|
||||
char channel;
|
||||
|
||||
channel = 'A';
|
||||
our_id = ahc->our_id;
|
||||
target_id = i;
|
||||
if (i > 7 && (ahc->features & AHC_TWIN) != 0) {
|
||||
channel = 'B';
|
||||
our_id = ahc->our_id_b;
|
||||
target_id = i % 8;
|
||||
}
|
||||
|
||||
ahc_dump_target_state(ahc, m, our_id,
|
||||
channel, target_id, i);
|
||||
}
|
||||
return 0;
|
||||
}
|
912
drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
Normal file
912
drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
Normal file
|
@ -0,0 +1,912 @@
|
|||
/*
|
||||
* DO NOT EDIT - This file is automatically generated
|
||||
* from the following source files:
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
|
||||
*/
|
||||
typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
|
||||
typedef struct ahc_reg_parse_entry {
|
||||
char *name;
|
||||
uint8_t value;
|
||||
uint8_t mask;
|
||||
} ahc_reg_parse_entry_t;
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scsiseq_print;
|
||||
#else
|
||||
#define ahc_scsiseq_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCSISEQ", 0x00, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sxfrctl0_print;
|
||||
#else
|
||||
#define ahc_sxfrctl0_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SXFRCTL0", 0x01, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scsisigi_print;
|
||||
#else
|
||||
#define ahc_scsisigi_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCSISIGI", 0x03, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scsirate_print;
|
||||
#else
|
||||
#define ahc_scsirate_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCSIRATE", 0x04, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sstat0_print;
|
||||
#else
|
||||
#define ahc_sstat0_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SSTAT0", 0x0b, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sstat1_print;
|
||||
#else
|
||||
#define ahc_sstat1_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SSTAT1", 0x0c, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sstat2_print;
|
||||
#else
|
||||
#define ahc_sstat2_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SSTAT2", 0x0d, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sstat3_print;
|
||||
#else
|
||||
#define ahc_sstat3_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SSTAT3", 0x0e, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_simode0_print;
|
||||
#else
|
||||
#define ahc_simode0_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SIMODE0", 0x10, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_simode1_print;
|
||||
#else
|
||||
#define ahc_simode1_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SIMODE1", 0x11, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scsibusl_print;
|
||||
#else
|
||||
#define ahc_scsibusl_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCSIBUSL", 0x12, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sblkctl_print;
|
||||
#else
|
||||
#define ahc_sblkctl_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SBLKCTL", 0x1f, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_seq_flags_print;
|
||||
#else
|
||||
#define ahc_seq_flags_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SEQ_FLAGS", 0x3c, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_lastphase_print;
|
||||
#else
|
||||
#define ahc_lastphase_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "LASTPHASE", 0x3f, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_seqctl_print;
|
||||
#else
|
||||
#define ahc_seqctl_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SEQCTL", 0x60, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_sram_base_print;
|
||||
#else
|
||||
#define ahc_sram_base_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SRAM_BASE", 0x70, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_error_print;
|
||||
#else
|
||||
#define ahc_error_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "ERROR", 0x92, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_dfcntrl_print;
|
||||
#else
|
||||
#define ahc_dfcntrl_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "DFCNTRL", 0x93, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_dfstatus_print;
|
||||
#else
|
||||
#define ahc_dfstatus_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "DFSTATUS", 0x94, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scsiphase_print;
|
||||
#else
|
||||
#define ahc_scsiphase_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCSIPHASE", 0x9e, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scb_base_print;
|
||||
#else
|
||||
#define ahc_scb_base_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCB_BASE", 0xa0, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scb_control_print;
|
||||
#else
|
||||
#define ahc_scb_control_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCB_CONTROL", 0xb8, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scb_scsiid_print;
|
||||
#else
|
||||
#define ahc_scb_scsiid_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCB_SCSIID", 0xb9, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scb_lun_print;
|
||||
#else
|
||||
#define ahc_scb_lun_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCB_LUN", 0xba, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
#if AIC_DEBUG_REGISTERS
|
||||
ahc_reg_print_t ahc_scb_tag_print;
|
||||
#else
|
||||
#define ahc_scb_tag_print(regvalue, cur_col, wrap) \
|
||||
ahc_print_register(NULL, 0, "SCB_TAG", 0xbb, regvalue, cur_col, wrap)
|
||||
#endif
|
||||
|
||||
|
||||
#define SCSISEQ 0x00
|
||||
#define TEMODE 0x80
|
||||
#define SCSIRSTO 0x01
|
||||
|
||||
#define SXFRCTL0 0x01
|
||||
#define DFON 0x80
|
||||
#define DFPEXP 0x40
|
||||
#define FAST20 0x20
|
||||
#define CLRSTCNT 0x10
|
||||
#define SPIOEN 0x08
|
||||
#define SCAMEN 0x04
|
||||
#define CLRCHN 0x02
|
||||
|
||||
#define SXFRCTL1 0x02
|
||||
#define STIMESEL 0x18
|
||||
#define BITBUCKET 0x80
|
||||
#define SWRAPEN 0x40
|
||||
#define ENSTIMER 0x04
|
||||
#define ACTNEGEN 0x02
|
||||
#define STPWEN 0x01
|
||||
|
||||
#define SCSISIGO 0x03
|
||||
#define CDO 0x80
|
||||
#define IOO 0x40
|
||||
#define MSGO 0x20
|
||||
#define ATNO 0x10
|
||||
#define SELO 0x08
|
||||
#define BSYO 0x04
|
||||
#define REQO 0x02
|
||||
#define ACKO 0x01
|
||||
|
||||
#define SCSISIGI 0x03
|
||||
#define P_DATAIN_DT 0x60
|
||||
#define P_DATAOUT_DT 0x20
|
||||
#define ATNI 0x10
|
||||
#define SELI 0x08
|
||||
#define BSYI 0x04
|
||||
#define REQI 0x02
|
||||
#define ACKI 0x01
|
||||
|
||||
#define SCSIRATE 0x04
|
||||
#define SXFR 0x70
|
||||
#define SOFS 0x0f
|
||||
#define SXFR_ULTRA2 0x0f
|
||||
#define WIDEXFER 0x80
|
||||
#define ENABLE_CRC 0x40
|
||||
#define SINGLE_EDGE 0x10
|
||||
|
||||
#define SCSIID 0x05
|
||||
#define SCSIOFFSET 0x05
|
||||
#define SOFS_ULTRA2 0x7f
|
||||
|
||||
#define SCSIDATL 0x06
|
||||
|
||||
#define SCSIDATH 0x07
|
||||
|
||||
#define STCNT 0x08
|
||||
|
||||
#define OPTIONMODE 0x08
|
||||
#define OPTIONMODE_DEFAULTS 0x03
|
||||
#define AUTORATEEN 0x80
|
||||
#define AUTOACKEN 0x40
|
||||
#define ATNMGMNTEN 0x20
|
||||
#define BUSFREEREV 0x10
|
||||
#define EXPPHASEDIS 0x08
|
||||
#define SCSIDATL_IMGEN 0x04
|
||||
#define AUTO_MSGOUT_DE 0x02
|
||||
#define DIS_MSGIN_DUALEDGE 0x01
|
||||
|
||||
#define TARGCRCCNT 0x0a
|
||||
|
||||
#define CLRSINT0 0x0b
|
||||
#define CLRSELDO 0x40
|
||||
#define CLRSELDI 0x20
|
||||
#define CLRSELINGO 0x10
|
||||
#define CLRIOERR 0x08
|
||||
#define CLRSWRAP 0x08
|
||||
#define CLRSPIORDY 0x02
|
||||
|
||||
#define SSTAT0 0x0b
|
||||
#define TARGET 0x80
|
||||
#define SELDO 0x40
|
||||
#define SELDI 0x20
|
||||
#define SELINGO 0x10
|
||||
#define SWRAP 0x08
|
||||
#define IOERR 0x08
|
||||
#define SDONE 0x04
|
||||
#define SPIORDY 0x02
|
||||
#define DMADONE 0x01
|
||||
|
||||
#define CLRSINT1 0x0c
|
||||
#define CLRSELTIMEO 0x80
|
||||
#define CLRATNO 0x40
|
||||
#define CLRSCSIRSTI 0x20
|
||||
#define CLRBUSFREE 0x08
|
||||
#define CLRSCSIPERR 0x04
|
||||
#define CLRPHASECHG 0x02
|
||||
#define CLRREQINIT 0x01
|
||||
|
||||
#define SSTAT1 0x0c
|
||||
#define SELTO 0x80
|
||||
#define ATNTARG 0x40
|
||||
#define SCSIRSTI 0x20
|
||||
#define PHASEMIS 0x10
|
||||
#define BUSFREE 0x08
|
||||
#define SCSIPERR 0x04
|
||||
#define PHASECHG 0x02
|
||||
#define REQINIT 0x01
|
||||
|
||||
#define SSTAT2 0x0d
|
||||
#define SFCNT 0x1f
|
||||
#define OVERRUN 0x80
|
||||
#define SHVALID 0x40
|
||||
#define EXP_ACTIVE 0x10
|
||||
#define CRCVALERR 0x08
|
||||
#define CRCENDERR 0x04
|
||||
#define CRCREQERR 0x02
|
||||
#define DUAL_EDGE_ERR 0x01
|
||||
|
||||
#define SSTAT3 0x0e
|
||||
#define SCSICNT 0xf0
|
||||
#define U2OFFCNT 0x7f
|
||||
#define OFFCNT 0x0f
|
||||
|
||||
#define SCSIID_ULTRA2 0x0f
|
||||
|
||||
#define SIMODE0 0x10
|
||||
#define ENSELDO 0x40
|
||||
#define ENSELDI 0x20
|
||||
#define ENSELINGO 0x10
|
||||
#define ENIOERR 0x08
|
||||
#define ENSWRAP 0x08
|
||||
#define ENSDONE 0x04
|
||||
#define ENSPIORDY 0x02
|
||||
#define ENDMADONE 0x01
|
||||
|
||||
#define SIMODE1 0x11
|
||||
#define ENSELTIMO 0x80
|
||||
#define ENATNTARG 0x40
|
||||
#define ENSCSIRST 0x20
|
||||
#define ENPHASEMIS 0x10
|
||||
#define ENBUSFREE 0x08
|
||||
#define ENSCSIPERR 0x04
|
||||
#define ENPHASECHG 0x02
|
||||
#define ENREQINIT 0x01
|
||||
|
||||
#define SCSIBUSL 0x12
|
||||
|
||||
#define SCSIBUSH 0x13
|
||||
|
||||
#define SXFRCTL2 0x13
|
||||
#define ASYNC_SETUP 0x07
|
||||
#define AUTORSTDIS 0x10
|
||||
#define CMDDMAEN 0x08
|
||||
|
||||
#define SHADDR 0x14
|
||||
|
||||
#define SELTIMER 0x18
|
||||
#define TARGIDIN 0x18
|
||||
#define STAGE6 0x20
|
||||
#define STAGE5 0x10
|
||||
#define STAGE4 0x08
|
||||
#define STAGE3 0x04
|
||||
#define STAGE2 0x02
|
||||
#define STAGE1 0x01
|
||||
|
||||
#define SELID 0x19
|
||||
#define SELID_MASK 0xf0
|
||||
#define ONEBIT 0x08
|
||||
|
||||
#define SCAMCTL 0x1a
|
||||
#define SCAMLVL 0x03
|
||||
#define ENSCAMSELO 0x80
|
||||
#define CLRSCAMSELID 0x40
|
||||
#define ALTSTIM 0x20
|
||||
#define DFLTTID 0x10
|
||||
|
||||
#define TARGID 0x1b
|
||||
|
||||
#define SPIOCAP 0x1b
|
||||
#define SOFT1 0x80
|
||||
#define SOFT0 0x40
|
||||
#define SOFTCMDEN 0x20
|
||||
#define EXT_BRDCTL 0x10
|
||||
#define SEEPROM 0x08
|
||||
#define EEPROM 0x04
|
||||
#define ROM 0x02
|
||||
#define SSPIOCPS 0x01
|
||||
|
||||
#define BRDCTL 0x1d
|
||||
#define BRDDAT7 0x80
|
||||
#define BRDDAT6 0x40
|
||||
#define BRDDAT5 0x20
|
||||
#define BRDDAT4 0x10
|
||||
#define BRDSTB 0x10
|
||||
#define BRDDAT3 0x08
|
||||
#define BRDCS 0x08
|
||||
#define BRDDAT2 0x04
|
||||
#define BRDRW 0x04
|
||||
#define BRDRW_ULTRA2 0x02
|
||||
#define BRDCTL1 0x02
|
||||
#define BRDCTL0 0x01
|
||||
#define BRDSTB_ULTRA2 0x01
|
||||
|
||||
#define SEECTL 0x1e
|
||||
#define EXTARBACK 0x80
|
||||
#define EXTARBREQ 0x40
|
||||
#define SEEMS 0x20
|
||||
#define SEERDY 0x10
|
||||
#define SEECS 0x08
|
||||
#define SEECK 0x04
|
||||
#define SEEDO 0x02
|
||||
#define SEEDI 0x01
|
||||
|
||||
#define SBLKCTL 0x1f
|
||||
#define DIAGLEDEN 0x80
|
||||
#define DIAGLEDON 0x40
|
||||
#define AUTOFLUSHDIS 0x20
|
||||
#define ENAB40 0x08
|
||||
#define SELBUSB 0x08
|
||||
#define ENAB20 0x04
|
||||
#define SELWIDE 0x02
|
||||
#define XCVR 0x01
|
||||
|
||||
#define BUSY_TARGETS 0x20
|
||||
#define TARG_SCSIRATE 0x20
|
||||
|
||||
#define ULTRA_ENB 0x30
|
||||
#define CMDSIZE_TABLE 0x30
|
||||
|
||||
#define DISC_DSB 0x32
|
||||
|
||||
#define CMDSIZE_TABLE_TAIL 0x34
|
||||
|
||||
#define MWI_RESIDUAL 0x38
|
||||
|
||||
#define NEXT_QUEUED_SCB 0x39
|
||||
|
||||
#define MSG_OUT 0x3a
|
||||
|
||||
#define DMAPARAMS 0x3b
|
||||
#define PRELOADEN 0x80
|
||||
#define WIDEODD 0x40
|
||||
#define SCSIEN 0x20
|
||||
#define SDMAEN 0x10
|
||||
#define SDMAENACK 0x10
|
||||
#define HDMAEN 0x08
|
||||
#define HDMAENACK 0x08
|
||||
#define DIRECTION 0x04
|
||||
#define FIFOFLUSH 0x02
|
||||
#define FIFORESET 0x01
|
||||
|
||||
#define SEQ_FLAGS 0x3c
|
||||
#define NOT_IDENTIFIED 0x80
|
||||
#define NO_CDB_SENT 0x40
|
||||
#define TARGET_CMD_IS_TAGGED 0x40
|
||||
#define DPHASE 0x20
|
||||
#define TARG_CMD_PENDING 0x10
|
||||
#define CMDPHASE_PENDING 0x08
|
||||
#define DPHASE_PENDING 0x04
|
||||
#define SPHASE_PENDING 0x02
|
||||
#define NO_DISCONNECT 0x01
|
||||
|
||||
#define SAVED_SCSIID 0x3d
|
||||
|
||||
#define SAVED_LUN 0x3e
|
||||
|
||||
#define LASTPHASE 0x3f
|
||||
#define P_MESGIN 0xe0
|
||||
#define PHASE_MASK 0xe0
|
||||
#define P_STATUS 0xc0
|
||||
#define P_MESGOUT 0xa0
|
||||
#define P_COMMAND 0x80
|
||||
#define P_DATAIN 0x40
|
||||
#define P_BUSFREE 0x01
|
||||
#define P_DATAOUT 0x00
|
||||
#define CDI 0x80
|
||||
#define IOI 0x40
|
||||
#define MSGI 0x20
|
||||
|
||||
#define WAITING_SCBH 0x40
|
||||
|
||||
#define DISCONNECTED_SCBH 0x41
|
||||
|
||||
#define FREE_SCBH 0x42
|
||||
|
||||
#define COMPLETE_SCBH 0x43
|
||||
|
||||
#define HSCB_ADDR 0x44
|
||||
|
||||
#define SHARED_DATA_ADDR 0x48
|
||||
|
||||
#define KERNEL_QINPOS 0x4c
|
||||
|
||||
#define QINPOS 0x4d
|
||||
|
||||
#define QOUTPOS 0x4e
|
||||
|
||||
#define KERNEL_TQINPOS 0x4f
|
||||
|
||||
#define TQINPOS 0x50
|
||||
|
||||
#define ARG_1 0x51
|
||||
#define RETURN_1 0x51
|
||||
#define SEND_MSG 0x80
|
||||
#define SEND_SENSE 0x40
|
||||
#define SEND_REJ 0x20
|
||||
#define MSGOUT_PHASEMIS 0x10
|
||||
#define EXIT_MSG_LOOP 0x08
|
||||
#define CONT_MSG_LOOP 0x04
|
||||
#define CONT_TARG_SESSION 0x02
|
||||
|
||||
#define ARG_2 0x52
|
||||
#define RETURN_2 0x52
|
||||
|
||||
#define LAST_MSG 0x53
|
||||
#define TARG_IMMEDIATE_SCB 0x53
|
||||
|
||||
#define SCSISEQ_TEMPLATE 0x54
|
||||
#define ENSELO 0x40
|
||||
#define ENSELI 0x20
|
||||
#define ENRSELI 0x10
|
||||
#define ENAUTOATNO 0x08
|
||||
#define ENAUTOATNI 0x04
|
||||
#define ENAUTOATNP 0x02
|
||||
|
||||
#define HA_274_BIOSGLOBAL 0x56
|
||||
#define INITIATOR_TAG 0x56
|
||||
#define HA_274_EXTENDED_TRANS 0x01
|
||||
|
||||
#define SEQ_FLAGS2 0x57
|
||||
#define TARGET_MSG_PENDING 0x02
|
||||
#define SCB_DMA 0x01
|
||||
|
||||
#define SCSICONF 0x5a
|
||||
#define HWSCSIID 0x0f
|
||||
#define HSCSIID 0x07
|
||||
#define TERM_ENB 0x80
|
||||
#define RESET_SCSI 0x40
|
||||
#define ENSPCHK 0x20
|
||||
|
||||
#define INTDEF 0x5c
|
||||
#define VECTOR 0x0f
|
||||
#define EDGE_TRIG 0x80
|
||||
|
||||
#define HOSTCONF 0x5d
|
||||
|
||||
#define HA_274_BIOSCTRL 0x5f
|
||||
#define BIOSDISABLED 0x30
|
||||
#define BIOSMODE 0x30
|
||||
#define CHANNEL_B_PRIMARY 0x08
|
||||
|
||||
#define SEQCTL 0x60
|
||||
#define PERRORDIS 0x80
|
||||
#define PAUSEDIS 0x40
|
||||
#define FAILDIS 0x20
|
||||
#define FASTMODE 0x10
|
||||
#define BRKADRINTEN 0x08
|
||||
#define STEP 0x04
|
||||
#define SEQRESET 0x02
|
||||
#define LOADRAM 0x01
|
||||
|
||||
#define SEQRAM 0x61
|
||||
|
||||
#define SEQADDR0 0x62
|
||||
|
||||
#define SEQADDR1 0x63
|
||||
#define SEQADDR1_MASK 0x01
|
||||
|
||||
#define ACCUM 0x64
|
||||
|
||||
#define SINDEX 0x65
|
||||
|
||||
#define DINDEX 0x66
|
||||
|
||||
#define ALLONES 0x69
|
||||
|
||||
#define ALLZEROS 0x6a
|
||||
|
||||
#define NONE 0x6a
|
||||
|
||||
#define FLAGS 0x6b
|
||||
#define ZERO 0x02
|
||||
#define CARRY 0x01
|
||||
|
||||
#define SINDIR 0x6c
|
||||
|
||||
#define DINDIR 0x6d
|
||||
|
||||
#define FUNCTION1 0x6e
|
||||
|
||||
#define STACK 0x6f
|
||||
|
||||
#define TARG_OFFSET 0x70
|
||||
|
||||
#define SRAM_BASE 0x70
|
||||
|
||||
#define BCTL 0x84
|
||||
#define ACE 0x08
|
||||
#define ENABLE 0x01
|
||||
|
||||
#define DSCOMMAND0 0x84
|
||||
#define CACHETHEN 0x80
|
||||
#define DPARCKEN 0x40
|
||||
#define MPARCKEN 0x20
|
||||
#define EXTREQLCK 0x10
|
||||
#define INTSCBRAMSEL 0x08
|
||||
#define RAMPS 0x04
|
||||
#define USCBSIZE32 0x02
|
||||
#define CIOPARCKEN 0x01
|
||||
|
||||
#define BUSTIME 0x85
|
||||
#define BOFF 0xf0
|
||||
#define BON 0x0f
|
||||
|
||||
#define DSCOMMAND1 0x85
|
||||
#define DSLATT 0xfc
|
||||
#define HADDLDSEL1 0x02
|
||||
#define HADDLDSEL0 0x01
|
||||
|
||||
#define BUSSPD 0x86
|
||||
#define DFTHRSH 0xc0
|
||||
#define DFTHRSH_75 0x80
|
||||
#define STBOFF 0x38
|
||||
#define STBON 0x07
|
||||
|
||||
#define HS_MAILBOX 0x86
|
||||
#define HOST_MAILBOX 0xf0
|
||||
#define HOST_TQINPOS 0x80
|
||||
#define SEQ_MAILBOX 0x0f
|
||||
|
||||
#define DSPCISTATUS 0x86
|
||||
#define DFTHRSH_100 0xc0
|
||||
|
||||
#define HCNTRL 0x87
|
||||
#define POWRDN 0x40
|
||||
#define SWINT 0x10
|
||||
#define IRQMS 0x08
|
||||
#define PAUSE 0x04
|
||||
#define INTEN 0x02
|
||||
#define CHIPRST 0x01
|
||||
#define CHIPRSTACK 0x01
|
||||
|
||||
#define HADDR 0x88
|
||||
|
||||
#define HCNT 0x8c
|
||||
|
||||
#define SCBPTR 0x90
|
||||
|
||||
#define INTSTAT 0x91
|
||||
#define SEQINT_MASK 0xf1
|
||||
#define OUT_OF_RANGE 0xe1
|
||||
#define NO_FREE_SCB 0xd1
|
||||
#define SCB_MISMATCH 0xc1
|
||||
#define MISSED_BUSFREE 0xb1
|
||||
#define MKMSG_FAILED 0xa1
|
||||
#define DATA_OVERRUN 0x91
|
||||
#define PERR_DETECTED 0x81
|
||||
#define BAD_STATUS 0x71
|
||||
#define HOST_MSG_LOOP 0x61
|
||||
#define PDATA_REINIT 0x51
|
||||
#define IGN_WIDE_RES 0x41
|
||||
#define NO_MATCH 0x31
|
||||
#define PROTO_VIOLATION 0x21
|
||||
#define SEND_REJECT 0x11
|
||||
#define INT_PEND 0x0f
|
||||
#define BAD_PHASE 0x01
|
||||
#define BRKADRINT 0x08
|
||||
#define SCSIINT 0x04
|
||||
#define CMDCMPLT 0x02
|
||||
#define SEQINT 0x01
|
||||
|
||||
#define CLRINT 0x92
|
||||
#define CLRPARERR 0x10
|
||||
#define CLRBRKADRINT 0x08
|
||||
#define CLRSCSIINT 0x04
|
||||
#define CLRCMDINT 0x02
|
||||
#define CLRSEQINT 0x01
|
||||
|
||||
#define ERROR 0x92
|
||||
#define CIOPARERR 0x80
|
||||
#define PCIERRSTAT 0x40
|
||||
#define MPARERR 0x20
|
||||
#define DPARERR 0x10
|
||||
#define SQPARERR 0x08
|
||||
#define ILLOPCODE 0x04
|
||||
#define ILLSADDR 0x02
|
||||
#define ILLHADDR 0x01
|
||||
|
||||
#define DFCNTRL 0x93
|
||||
|
||||
#define DFSTATUS 0x94
|
||||
#define PRELOAD_AVAIL 0x80
|
||||
#define DFCACHETH 0x40
|
||||
#define FIFOQWDEMP 0x20
|
||||
#define MREQPEND 0x10
|
||||
#define HDONE 0x08
|
||||
#define DFTHRESH 0x04
|
||||
#define FIFOFULL 0x02
|
||||
#define FIFOEMP 0x01
|
||||
|
||||
#define DFWADDR 0x95
|
||||
|
||||
#define DFRADDR 0x97
|
||||
|
||||
#define DFDAT 0x99
|
||||
|
||||
#define SCBCNT 0x9a
|
||||
#define SCBCNT_MASK 0x1f
|
||||
#define SCBAUTO 0x80
|
||||
|
||||
#define QINFIFO 0x9b
|
||||
|
||||
#define QINCNT 0x9c
|
||||
|
||||
#define QOUTFIFO 0x9d
|
||||
|
||||
#define CRCCONTROL1 0x9d
|
||||
#define CRCONSEEN 0x80
|
||||
#define CRCVALCHKEN 0x40
|
||||
#define CRCENDCHKEN 0x20
|
||||
#define CRCREQCHKEN 0x10
|
||||
#define TARGCRCENDEN 0x08
|
||||
#define TARGCRCCNTEN 0x04
|
||||
|
||||
#define QOUTCNT 0x9e
|
||||
|
||||
#define SCSIPHASE 0x9e
|
||||
#define DATA_PHASE_MASK 0x03
|
||||
#define STATUS_PHASE 0x20
|
||||
#define COMMAND_PHASE 0x10
|
||||
#define MSG_IN_PHASE 0x08
|
||||
#define MSG_OUT_PHASE 0x04
|
||||
#define DATA_IN_PHASE 0x02
|
||||
#define DATA_OUT_PHASE 0x01
|
||||
|
||||
#define SFUNCT 0x9f
|
||||
#define ALT_MODE 0x80
|
||||
|
||||
#define SCB_BASE 0xa0
|
||||
|
||||
#define SCB_CDB_PTR 0xa0
|
||||
#define SCB_RESIDUAL_DATACNT 0xa0
|
||||
#define SCB_CDB_STORE 0xa0
|
||||
|
||||
#define SCB_RESIDUAL_SGPTR 0xa4
|
||||
|
||||
#define SCB_SCSI_STATUS 0xa8
|
||||
|
||||
#define SCB_TARGET_PHASES 0xa9
|
||||
|
||||
#define SCB_TARGET_DATA_DIR 0xaa
|
||||
|
||||
#define SCB_TARGET_ITAG 0xab
|
||||
|
||||
#define SCB_DATAPTR 0xac
|
||||
|
||||
#define SCB_DATACNT 0xb0
|
||||
#define SG_HIGH_ADDR_BITS 0x7f
|
||||
#define SG_LAST_SEG 0x80
|
||||
|
||||
#define SCB_SGPTR 0xb4
|
||||
#define SG_RESID_VALID 0x04
|
||||
#define SG_FULL_RESID 0x02
|
||||
#define SG_LIST_NULL 0x01
|
||||
|
||||
#define SCB_CONTROL 0xb8
|
||||
#define SCB_TAG_TYPE 0x03
|
||||
#define STATUS_RCVD 0x80
|
||||
#define TARGET_SCB 0x80
|
||||
#define DISCENB 0x40
|
||||
#define TAG_ENB 0x20
|
||||
#define MK_MESSAGE 0x10
|
||||
#define ULTRAENB 0x08
|
||||
#define DISCONNECTED 0x04
|
||||
|
||||
#define SCB_SCSIID 0xb9
|
||||
#define TID 0xf0
|
||||
#define TWIN_TID 0x70
|
||||
#define OID 0x0f
|
||||
#define TWIN_CHNLB 0x80
|
||||
|
||||
#define SCB_LUN 0xba
|
||||
#define LID 0x3f
|
||||
#define SCB_XFERLEN_ODD 0x80
|
||||
|
||||
#define SCB_TAG 0xbb
|
||||
|
||||
#define SCB_CDB_LEN 0xbc
|
||||
|
||||
#define SCB_SCSIRATE 0xbd
|
||||
|
||||
#define SCB_SCSIOFFSET 0xbe
|
||||
|
||||
#define SCB_NEXT 0xbf
|
||||
|
||||
#define SCB_64_SPARE 0xc0
|
||||
|
||||
#define SEECTL_2840 0xc0
|
||||
#define CS_2840 0x04
|
||||
#define CK_2840 0x02
|
||||
#define DO_2840 0x01
|
||||
|
||||
#define STATUS_2840 0xc1
|
||||
#define BIOS_SEL 0x60
|
||||
#define ADSEL 0x1e
|
||||
#define EEPROM_TF 0x80
|
||||
#define DI_2840 0x01
|
||||
|
||||
#define SCB_64_BTT 0xd0
|
||||
|
||||
#define CCHADDR 0xe0
|
||||
|
||||
#define CCHCNT 0xe8
|
||||
|
||||
#define CCSGRAM 0xe9
|
||||
|
||||
#define CCSGADDR 0xea
|
||||
|
||||
#define CCSGCTL 0xeb
|
||||
#define CCSGDONE 0x80
|
||||
#define CCSGEN 0x08
|
||||
#define SG_FETCH_NEEDED 0x02
|
||||
#define CCSGRESET 0x01
|
||||
|
||||
#define CCSCBRAM 0xec
|
||||
|
||||
#define CCSCBADDR 0xed
|
||||
|
||||
#define CCSCBCTL 0xee
|
||||
#define CCSCBDONE 0x80
|
||||
#define ARRDONE 0x40
|
||||
#define CCARREN 0x10
|
||||
#define CCSCBEN 0x08
|
||||
#define CCSCBDIR 0x04
|
||||
#define CCSCBRESET 0x01
|
||||
|
||||
#define CCSCBCNT 0xef
|
||||
|
||||
#define SCBBADDR 0xf0
|
||||
|
||||
#define CCSCBPTR 0xf1
|
||||
|
||||
#define HNSCB_QOFF 0xf4
|
||||
|
||||
#define SNSCB_QOFF 0xf6
|
||||
|
||||
#define SDSCB_QOFF 0xf8
|
||||
|
||||
#define QOFF_CTLSTA 0xfa
|
||||
#define SCB_QSIZE 0x07
|
||||
#define SCB_QSIZE_256 0x06
|
||||
#define SCB_AVAIL 0x40
|
||||
#define SNSCB_ROLLOVER 0x20
|
||||
#define SDSCB_ROLLOVER 0x10
|
||||
|
||||
#define DFF_THRSH 0xfb
|
||||
#define WR_DFTHRSH 0x70
|
||||
#define WR_DFTHRSH_MAX 0x70
|
||||
#define WR_DFTHRSH_90 0x60
|
||||
#define WR_DFTHRSH_85 0x50
|
||||
#define WR_DFTHRSH_75 0x40
|
||||
#define WR_DFTHRSH_63 0x30
|
||||
#define WR_DFTHRSH_50 0x20
|
||||
#define WR_DFTHRSH_25 0x10
|
||||
#define RD_DFTHRSH 0x07
|
||||
#define RD_DFTHRSH_MAX 0x07
|
||||
#define RD_DFTHRSH_90 0x06
|
||||
#define RD_DFTHRSH_85 0x05
|
||||
#define RD_DFTHRSH_75 0x04
|
||||
#define RD_DFTHRSH_63 0x03
|
||||
#define RD_DFTHRSH_50 0x02
|
||||
#define RD_DFTHRSH_25 0x01
|
||||
#define RD_DFTHRSH_MIN 0x00
|
||||
#define WR_DFTHRSH_MIN 0x00
|
||||
|
||||
#define SG_CACHE_SHADOW 0xfc
|
||||
#define SG_ADDR_MASK 0xf8
|
||||
#define LAST_SEG 0x02
|
||||
#define LAST_SEG_DONE 0x01
|
||||
|
||||
#define SG_CACHE_PRE 0xfc
|
||||
|
||||
|
||||
#define MAX_OFFSET_ULTRA2 0x7f
|
||||
#define MAX_OFFSET_16BIT 0x08
|
||||
#define BUS_8_BIT 0x00
|
||||
#define TARGET_CMD_CMPLT 0xfe
|
||||
#define STATUS_QUEUE_FULL 0x28
|
||||
#define STATUS_BUSY 0x08
|
||||
#define MAX_OFFSET_8BIT 0x0f
|
||||
#define BUS_32_BIT 0x02
|
||||
#define CCSGADDR_MAX 0x80
|
||||
#define TID_SHIFT 0x04
|
||||
#define SCB_DOWNLOAD_SIZE_64 0x30
|
||||
#define HOST_MAILBOX_SHIFT 0x04
|
||||
#define CMD_GROUP_CODE_SHIFT 0x05
|
||||
#define CCSGRAM_MAXSEGS 0x10
|
||||
#define SCB_LIST_NULL 0xff
|
||||
#define SG_SIZEOF 0x08
|
||||
#define SCB_DOWNLOAD_SIZE 0x20
|
||||
#define SEQ_MAILBOX_SHIFT 0x00
|
||||
#define TARGET_DATA_IN 0x01
|
||||
#define HOST_MSG 0xff
|
||||
#define MAX_OFFSET 0x7f
|
||||
#define BUS_16_BIT 0x01
|
||||
#define SCB_UPLOAD_SIZE 0x20
|
||||
#define STACK_SIZE 0x04
|
||||
|
||||
|
||||
/* Downloaded Constant Definitions */
|
||||
#define INVERTED_CACHESIZE_MASK 0x03
|
||||
#define SG_PREFETCH_ADDR_MASK 0x06
|
||||
#define SG_PREFETCH_ALIGN_MASK 0x05
|
||||
#define QOUTFIFO_OFFSET 0x00
|
||||
#define SG_PREFETCH_CNT 0x04
|
||||
#define CACHESIZE_MASK 0x02
|
||||
#define QINFIFO_OFFSET 0x01
|
||||
#define DOWNLOAD_CONST_COUNT 0x07
|
||||
|
||||
|
||||
/* Exported Labels */
|
413
drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
Normal file
413
drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
Normal file
|
@ -0,0 +1,413 @@
|
|||
/*
|
||||
* DO NOT EDIT - This file is automatically generated
|
||||
* from the following source files:
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
|
||||
*/
|
||||
|
||||
#include "aic7xxx_osm.h"
|
||||
|
||||
static const ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
|
||||
{ "SCSIRSTO", 0x01, 0x01 },
|
||||
{ "ENAUTOATNP", 0x02, 0x02 },
|
||||
{ "ENAUTOATNI", 0x04, 0x04 },
|
||||
{ "ENAUTOATNO", 0x08, 0x08 },
|
||||
{ "ENRSELI", 0x10, 0x10 },
|
||||
{ "ENSELI", 0x20, 0x20 },
|
||||
{ "ENSELO", 0x40, 0x40 },
|
||||
{ "TEMODE", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scsiseq_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCSISEQ_parse_table, 8, "SCSISEQ",
|
||||
0x00, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
|
||||
{ "CLRCHN", 0x02, 0x02 },
|
||||
{ "SCAMEN", 0x04, 0x04 },
|
||||
{ "SPIOEN", 0x08, 0x08 },
|
||||
{ "CLRSTCNT", 0x10, 0x10 },
|
||||
{ "FAST20", 0x20, 0x20 },
|
||||
{ "DFPEXP", 0x40, 0x40 },
|
||||
{ "DFON", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SXFRCTL0_parse_table, 7, "SXFRCTL0",
|
||||
0x01, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
|
||||
{ "ACKI", 0x01, 0x01 },
|
||||
{ "REQI", 0x02, 0x02 },
|
||||
{ "BSYI", 0x04, 0x04 },
|
||||
{ "SELI", 0x08, 0x08 },
|
||||
{ "ATNI", 0x10, 0x10 },
|
||||
{ "MSGI", 0x20, 0x20 },
|
||||
{ "IOI", 0x40, 0x40 },
|
||||
{ "CDI", 0x80, 0x80 },
|
||||
{ "P_DATAOUT", 0x00, 0x00 },
|
||||
{ "P_DATAOUT_DT", 0x20, 0x20 },
|
||||
{ "P_DATAIN", 0x40, 0x40 },
|
||||
{ "P_DATAIN_DT", 0x60, 0x60 },
|
||||
{ "P_COMMAND", 0x80, 0x80 },
|
||||
{ "P_MESGOUT", 0xa0, 0xa0 },
|
||||
{ "P_STATUS", 0xc0, 0xc0 },
|
||||
{ "PHASE_MASK", 0xe0, 0xe0 },
|
||||
{ "P_MESGIN", 0xe0, 0xe0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCSISIGI_parse_table, 17, "SCSISIGI",
|
||||
0x03, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
|
||||
{ "SINGLE_EDGE", 0x10, 0x10 },
|
||||
{ "ENABLE_CRC", 0x40, 0x40 },
|
||||
{ "WIDEXFER", 0x80, 0x80 },
|
||||
{ "SXFR_ULTRA2", 0x0f, 0x0f },
|
||||
{ "SOFS", 0x0f, 0x0f },
|
||||
{ "SXFR", 0x70, 0x70 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scsirate_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCSIRATE_parse_table, 6, "SCSIRATE",
|
||||
0x04, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
|
||||
{ "DMADONE", 0x01, 0x01 },
|
||||
{ "SPIORDY", 0x02, 0x02 },
|
||||
{ "SDONE", 0x04, 0x04 },
|
||||
{ "SWRAP", 0x08, 0x08 },
|
||||
{ "IOERR", 0x08, 0x08 },
|
||||
{ "SELINGO", 0x10, 0x10 },
|
||||
{ "SELDI", 0x20, 0x20 },
|
||||
{ "SELDO", 0x40, 0x40 },
|
||||
{ "TARGET", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SSTAT0_parse_table, 9, "SSTAT0",
|
||||
0x0b, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
|
||||
{ "REQINIT", 0x01, 0x01 },
|
||||
{ "PHASECHG", 0x02, 0x02 },
|
||||
{ "SCSIPERR", 0x04, 0x04 },
|
||||
{ "BUSFREE", 0x08, 0x08 },
|
||||
{ "PHASEMIS", 0x10, 0x10 },
|
||||
{ "SCSIRSTI", 0x20, 0x20 },
|
||||
{ "ATNTARG", 0x40, 0x40 },
|
||||
{ "SELTO", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SSTAT1_parse_table, 8, "SSTAT1",
|
||||
0x0c, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
|
||||
{ "DUAL_EDGE_ERR", 0x01, 0x01 },
|
||||
{ "CRCREQERR", 0x02, 0x02 },
|
||||
{ "CRCENDERR", 0x04, 0x04 },
|
||||
{ "CRCVALERR", 0x08, 0x08 },
|
||||
{ "EXP_ACTIVE", 0x10, 0x10 },
|
||||
{ "SHVALID", 0x40, 0x40 },
|
||||
{ "OVERRUN", 0x80, 0x80 },
|
||||
{ "SFCNT", 0x1f, 0x1f }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SSTAT2_parse_table, 8, "SSTAT2",
|
||||
0x0d, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
|
||||
{ "OFFCNT", 0x0f, 0x0f },
|
||||
{ "U2OFFCNT", 0x7f, 0x7f },
|
||||
{ "SCSICNT", 0xf0, 0xf0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SSTAT3_parse_table, 3, "SSTAT3",
|
||||
0x0e, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
|
||||
{ "ENDMADONE", 0x01, 0x01 },
|
||||
{ "ENSPIORDY", 0x02, 0x02 },
|
||||
{ "ENSDONE", 0x04, 0x04 },
|
||||
{ "ENSWRAP", 0x08, 0x08 },
|
||||
{ "ENIOERR", 0x08, 0x08 },
|
||||
{ "ENSELINGO", 0x10, 0x10 },
|
||||
{ "ENSELDI", 0x20, 0x20 },
|
||||
{ "ENSELDO", 0x40, 0x40 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SIMODE0_parse_table, 8, "SIMODE0",
|
||||
0x10, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
|
||||
{ "ENREQINIT", 0x01, 0x01 },
|
||||
{ "ENPHASECHG", 0x02, 0x02 },
|
||||
{ "ENSCSIPERR", 0x04, 0x04 },
|
||||
{ "ENBUSFREE", 0x08, 0x08 },
|
||||
{ "ENPHASEMIS", 0x10, 0x10 },
|
||||
{ "ENSCSIRST", 0x20, 0x20 },
|
||||
{ "ENATNTARG", 0x40, 0x40 },
|
||||
{ "ENSELTIMO", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_simode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SIMODE1_parse_table, 8, "SIMODE1",
|
||||
0x11, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahc_scsibusl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(NULL, 0, "SCSIBUSL",
|
||||
0x12, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
|
||||
{ "XCVR", 0x01, 0x01 },
|
||||
{ "SELWIDE", 0x02, 0x02 },
|
||||
{ "ENAB20", 0x04, 0x04 },
|
||||
{ "SELBUSB", 0x08, 0x08 },
|
||||
{ "ENAB40", 0x08, 0x08 },
|
||||
{ "AUTOFLUSHDIS", 0x20, 0x20 },
|
||||
{ "DIAGLEDON", 0x40, 0x40 },
|
||||
{ "DIAGLEDEN", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SBLKCTL_parse_table, 8, "SBLKCTL",
|
||||
0x1f, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
|
||||
{ "NO_DISCONNECT", 0x01, 0x01 },
|
||||
{ "SPHASE_PENDING", 0x02, 0x02 },
|
||||
{ "DPHASE_PENDING", 0x04, 0x04 },
|
||||
{ "CMDPHASE_PENDING", 0x08, 0x08 },
|
||||
{ "TARG_CMD_PENDING", 0x10, 0x10 },
|
||||
{ "DPHASE", 0x20, 0x20 },
|
||||
{ "NO_CDB_SENT", 0x40, 0x40 },
|
||||
{ "TARGET_CMD_IS_TAGGED",0x40, 0x40 },
|
||||
{ "NOT_IDENTIFIED", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS",
|
||||
0x3c, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
|
||||
{ "MSGI", 0x20, 0x20 },
|
||||
{ "IOI", 0x40, 0x40 },
|
||||
{ "CDI", 0x80, 0x80 },
|
||||
{ "P_DATAOUT", 0x00, 0x00 },
|
||||
{ "P_BUSFREE", 0x01, 0x01 },
|
||||
{ "P_DATAIN", 0x40, 0x40 },
|
||||
{ "P_COMMAND", 0x80, 0x80 },
|
||||
{ "P_MESGOUT", 0xa0, 0xa0 },
|
||||
{ "P_STATUS", 0xc0, 0xc0 },
|
||||
{ "PHASE_MASK", 0xe0, 0xe0 },
|
||||
{ "P_MESGIN", 0xe0, 0xe0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(LASTPHASE_parse_table, 11, "LASTPHASE",
|
||||
0x3f, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
|
||||
{ "LOADRAM", 0x01, 0x01 },
|
||||
{ "SEQRESET", 0x02, 0x02 },
|
||||
{ "STEP", 0x04, 0x04 },
|
||||
{ "BRKADRINTEN", 0x08, 0x08 },
|
||||
{ "FASTMODE", 0x10, 0x10 },
|
||||
{ "FAILDIS", 0x20, 0x20 },
|
||||
{ "PAUSEDIS", 0x40, 0x40 },
|
||||
{ "PERRORDIS", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_seqctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SEQCTL_parse_table, 8, "SEQCTL",
|
||||
0x60, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahc_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(NULL, 0, "SRAM_BASE",
|
||||
0x70, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t ERROR_parse_table[] = {
|
||||
{ "ILLHADDR", 0x01, 0x01 },
|
||||
{ "ILLSADDR", 0x02, 0x02 },
|
||||
{ "ILLOPCODE", 0x04, 0x04 },
|
||||
{ "SQPARERR", 0x08, 0x08 },
|
||||
{ "DPARERR", 0x10, 0x10 },
|
||||
{ "MPARERR", 0x20, 0x20 },
|
||||
{ "PCIERRSTAT", 0x40, 0x40 },
|
||||
{ "CIOPARERR", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(ERROR_parse_table, 8, "ERROR",
|
||||
0x92, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
|
||||
{ "FIFORESET", 0x01, 0x01 },
|
||||
{ "FIFOFLUSH", 0x02, 0x02 },
|
||||
{ "DIRECTION", 0x04, 0x04 },
|
||||
{ "HDMAEN", 0x08, 0x08 },
|
||||
{ "HDMAENACK", 0x08, 0x08 },
|
||||
{ "SDMAEN", 0x10, 0x10 },
|
||||
{ "SDMAENACK", 0x10, 0x10 },
|
||||
{ "SCSIEN", 0x20, 0x20 },
|
||||
{ "WIDEODD", 0x40, 0x40 },
|
||||
{ "PRELOADEN", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(DFCNTRL_parse_table, 10, "DFCNTRL",
|
||||
0x93, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
|
||||
{ "FIFOEMP", 0x01, 0x01 },
|
||||
{ "FIFOFULL", 0x02, 0x02 },
|
||||
{ "DFTHRESH", 0x04, 0x04 },
|
||||
{ "HDONE", 0x08, 0x08 },
|
||||
{ "MREQPEND", 0x10, 0x10 },
|
||||
{ "FIFOQWDEMP", 0x20, 0x20 },
|
||||
{ "DFCACHETH", 0x40, 0x40 },
|
||||
{ "PRELOAD_AVAIL", 0x80, 0x80 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_dfstatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(DFSTATUS_parse_table, 8, "DFSTATUS",
|
||||
0x94, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
|
||||
{ "DATA_OUT_PHASE", 0x01, 0x01 },
|
||||
{ "DATA_IN_PHASE", 0x02, 0x02 },
|
||||
{ "MSG_OUT_PHASE", 0x04, 0x04 },
|
||||
{ "MSG_IN_PHASE", 0x08, 0x08 },
|
||||
{ "COMMAND_PHASE", 0x10, 0x10 },
|
||||
{ "STATUS_PHASE", 0x20, 0x20 },
|
||||
{ "DATA_PHASE_MASK", 0x03, 0x03 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCSIPHASE_parse_table, 7, "SCSIPHASE",
|
||||
0x9e, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahc_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(NULL, 0, "SCB_BASE",
|
||||
0xa0, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
|
||||
{ "DISCONNECTED", 0x04, 0x04 },
|
||||
{ "ULTRAENB", 0x08, 0x08 },
|
||||
{ "MK_MESSAGE", 0x10, 0x10 },
|
||||
{ "TAG_ENB", 0x20, 0x20 },
|
||||
{ "DISCENB", 0x40, 0x40 },
|
||||
{ "TARGET_SCB", 0x80, 0x80 },
|
||||
{ "STATUS_RCVD", 0x80, 0x80 },
|
||||
{ "SCB_TAG_TYPE", 0x03, 0x03 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCB_CONTROL_parse_table, 8, "SCB_CONTROL",
|
||||
0xb8, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
|
||||
{ "TWIN_CHNLB", 0x80, 0x80 },
|
||||
{ "OID", 0x0f, 0x0f },
|
||||
{ "TWIN_TID", 0x70, 0x70 },
|
||||
{ "TID", 0xf0, 0xf0 }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCB_SCSIID_parse_table, 4, "SCB_SCSIID",
|
||||
0xb9, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
static const ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
|
||||
{ "SCB_XFERLEN_ODD", 0x80, 0x80 },
|
||||
{ "LID", 0x3f, 0x3f }
|
||||
};
|
||||
|
||||
int
|
||||
ahc_scb_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(SCB_LUN_parse_table, 2, "SCB_LUN",
|
||||
0xba, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
||||
int
|
||||
ahc_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
|
||||
{
|
||||
return (ahc_print_register(NULL, 0, "SCB_TAG",
|
||||
0xbb, regvalue, cur_col, wrap));
|
||||
}
|
||||
|
1308
drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
Normal file
1308
drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
Normal file
File diff suppressed because it is too large
Load diff
80
drivers/scsi/aic7xxx/aicasm/Makefile
Normal file
80
drivers/scsi/aic7xxx/aicasm/Makefile
Normal file
|
@ -0,0 +1,80 @@
|
|||
PROG= aicasm
|
||||
|
||||
.SUFFIXES= .l .y .c .h
|
||||
|
||||
CSRCS= aicasm.c aicasm_symbol.c
|
||||
YSRCS= aicasm_gram.y aicasm_macro_gram.y
|
||||
LSRCS= aicasm_scan.l aicasm_macro_scan.l
|
||||
|
||||
GENHDRS= aicdb.h $(YSRCS:.y=.h)
|
||||
GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c)
|
||||
|
||||
SRCS= ${CSRCS} ${GENSRCS}
|
||||
LIBS= -ldb
|
||||
clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG)
|
||||
# Override default kernel CFLAGS. This is a userland app.
|
||||
AICASM_CFLAGS:= -I/usr/include -I.
|
||||
LEX= flex
|
||||
YACC= bison
|
||||
YFLAGS= -d
|
||||
|
||||
NOMAN= noman
|
||||
|
||||
ifneq ($(HOSTCC),)
|
||||
AICASM_CC= $(HOSTCC)
|
||||
else
|
||||
AICASM_CC= $(CC)
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS+= -DDEBUG -g
|
||||
YFLAGS+= -t -v
|
||||
LFLAGS= -d
|
||||
endif
|
||||
|
||||
$(PROG): ${GENHDRS} $(SRCS)
|
||||
$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
|
||||
|
||||
aicdb.h:
|
||||
@if [ -e "/usr/include/db4/db_185.h" ]; then \
|
||||
echo "#include <db4/db_185.h>" > aicdb.h; \
|
||||
elif [ -e "/usr/include/db3/db_185.h" ]; then \
|
||||
echo "#include <db3/db_185.h>" > aicdb.h; \
|
||||
elif [ -e "/usr/include/db2/db_185.h" ]; then \
|
||||
echo "#include <db2/db_185.h>" > aicdb.h; \
|
||||
elif [ -e "/usr/include/db1/db_185.h" ]; then \
|
||||
echo "#include <db1/db_185.h>" > aicdb.h; \
|
||||
elif [ -e "/usr/include/db/db_185.h" ]; then \
|
||||
echo "#include <db/db_185.h>" > aicdb.h; \
|
||||
elif [ -e "/usr/include/db_185.h" ]; then \
|
||||
echo "#include <db_185.h>" > aicdb.h; \
|
||||
else \
|
||||
echo "*** Install db development libraries"; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -f $(clean-files)
|
||||
|
||||
# Create a dependency chain in generated files
|
||||
# to avoid concurrent invocations of the single
|
||||
# rule that builds them all.
|
||||
aicasm_gram.c: aicasm_gram.h
|
||||
aicasm_gram.c aicasm_gram.h: aicasm_gram.y
|
||||
$(YACC) $(YFLAGS) -b $(<:.y=) $<
|
||||
mv $(<:.y=).tab.c $(<:.y=.c)
|
||||
mv $(<:.y=).tab.h $(<:.y=.h)
|
||||
|
||||
# Create a dependency chain in generated files
|
||||
# to avoid concurrent invocations of the single
|
||||
# rule that builds them all.
|
||||
aicasm_macro_gram.c: aicasm_macro_gram.h
|
||||
aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y
|
||||
$(YACC) $(YFLAGS) -b $(<:.y=) -p mm $<
|
||||
mv $(<:.y=).tab.c $(<:.y=.c)
|
||||
mv $(<:.y=).tab.h $(<:.y=.h)
|
||||
|
||||
aicasm_scan.c: aicasm_scan.l
|
||||
$(LEX) $(LFLAGS) -o$@ $<
|
||||
|
||||
aicasm_macro_scan.c: aicasm_macro_scan.l
|
||||
$(LEX) $(LFLAGS) -Pmm -o$@ $<
|
844
drivers/scsi/aic7xxx/aicasm/aicasm.c
Normal file
844
drivers/scsi/aic7xxx/aicasm/aicasm.c
Normal file
|
@ -0,0 +1,844 @@
|
|||
/*
|
||||
* Aic7xxx SCSI host adapter firmware assembler
|
||||
*
|
||||
* Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs.
|
||||
* Copyright (c) 2001, 2002 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if linux
|
||||
#include <endian.h>
|
||||
#else
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
|
||||
#include "aicasm.h"
|
||||
#include "aicasm_symbol.h"
|
||||
#include "aicasm_insformat.h"
|
||||
|
||||
typedef struct patch {
|
||||
STAILQ_ENTRY(patch) links;
|
||||
int patch_func;
|
||||
u_int begin;
|
||||
u_int skip_instr;
|
||||
u_int skip_patch;
|
||||
} patch_t;
|
||||
|
||||
STAILQ_HEAD(patch_list, patch) patches;
|
||||
|
||||
static void usage(void);
|
||||
static void back_patch(void);
|
||||
static void output_code(void);
|
||||
static void output_listing(char *ifilename);
|
||||
static void dump_scope(scope_t *scope);
|
||||
static void emit_patch(scope_t *scope, int patch);
|
||||
static int check_patch(patch_t **start_patch, int start_instr,
|
||||
int *skip_addr, int *func_vals);
|
||||
|
||||
struct path_list search_path;
|
||||
int includes_search_curdir;
|
||||
char *appname;
|
||||
char *stock_include_file;
|
||||
FILE *ofile;
|
||||
char *ofilename;
|
||||
char *regfilename;
|
||||
FILE *regfile;
|
||||
char *listfilename;
|
||||
FILE *listfile;
|
||||
char *regdiagfilename;
|
||||
FILE *regdiagfile;
|
||||
int src_mode;
|
||||
int dst_mode;
|
||||
|
||||
static STAILQ_HEAD(,instruction) seq_program;
|
||||
struct cs_tailq cs_tailq;
|
||||
struct scope_list scope_stack;
|
||||
symlist_t patch_functions;
|
||||
|
||||
#if DEBUG
|
||||
extern int yy_flex_debug;
|
||||
extern int mm_flex_debug;
|
||||
extern int yydebug;
|
||||
extern int mmdebug;
|
||||
#endif
|
||||
extern FILE *yyin;
|
||||
extern int yyparse(void);
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int ch;
|
||||
int retval;
|
||||
char *inputfilename;
|
||||
scope_t *sentinal;
|
||||
|
||||
STAILQ_INIT(&patches);
|
||||
SLIST_INIT(&search_path);
|
||||
STAILQ_INIT(&seq_program);
|
||||
TAILQ_INIT(&cs_tailq);
|
||||
SLIST_INIT(&scope_stack);
|
||||
|
||||
/* Set Sentinal scope node */
|
||||
sentinal = scope_alloc();
|
||||
sentinal->type = SCOPE_ROOT;
|
||||
|
||||
includes_search_curdir = 1;
|
||||
appname = *argv;
|
||||
regfile = NULL;
|
||||
listfile = NULL;
|
||||
#if DEBUG
|
||||
yy_flex_debug = 0;
|
||||
mm_flex_debug = 0;
|
||||
yydebug = 0;
|
||||
mmdebug = 0;
|
||||
#endif
|
||||
while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:")) != -1) {
|
||||
switch(ch) {
|
||||
case 'd':
|
||||
#if DEBUG
|
||||
if (strcmp(optarg, "s") == 0) {
|
||||
yy_flex_debug = 1;
|
||||
mm_flex_debug = 1;
|
||||
} else if (strcmp(optarg, "p") == 0) {
|
||||
yydebug = 1;
|
||||
mmdebug = 1;
|
||||
} else {
|
||||
fprintf(stderr, "%s: -d Requires either an "
|
||||
"'s' or 'p' argument\n", appname);
|
||||
usage();
|
||||
}
|
||||
#else
|
||||
stop("-d: Assembler not built with debugging "
|
||||
"information", EX_SOFTWARE);
|
||||
#endif
|
||||
break;
|
||||
case 'i':
|
||||
stock_include_file = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
/* Create a program listing */
|
||||
if ((listfile = fopen(optarg, "w")) == NULL) {
|
||||
perror(optarg);
|
||||
stop(NULL, EX_CANTCREAT);
|
||||
}
|
||||
listfilename = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
/* Don't complain about the -nostdinc directrive */
|
||||
if (strcmp(optarg, "ostdinc")) {
|
||||
fprintf(stderr, "%s: Unknown option -%c%s\n",
|
||||
appname, ch, optarg);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if ((ofile = fopen(optarg, "w")) == NULL) {
|
||||
perror(optarg);
|
||||
stop(NULL, EX_CANTCREAT);
|
||||
}
|
||||
ofilename = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
/* Create Register Diagnostic "printing" Functions */
|
||||
if ((regdiagfile = fopen(optarg, "w")) == NULL) {
|
||||
perror(optarg);
|
||||
stop(NULL, EX_CANTCREAT);
|
||||
}
|
||||
regdiagfilename = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
if ((regfile = fopen(optarg, "w")) == NULL) {
|
||||
perror(optarg);
|
||||
stop(NULL, EX_CANTCREAT);
|
||||
}
|
||||
regfilename = optarg;
|
||||
break;
|
||||
case 'I':
|
||||
{
|
||||
path_entry_t include_dir;
|
||||
|
||||
if (strcmp(optarg, "-") == 0) {
|
||||
if (includes_search_curdir == 0) {
|
||||
fprintf(stderr, "%s: Warning - '-I-' "
|
||||
"specified multiple "
|
||||
"times\n", appname);
|
||||
}
|
||||
includes_search_curdir = 0;
|
||||
for (include_dir = SLIST_FIRST(&search_path);
|
||||
include_dir != NULL;
|
||||
include_dir = SLIST_NEXT(include_dir,
|
||||
links))
|
||||
/*
|
||||
* All entries before a '-I-' only
|
||||
* apply to includes specified with
|
||||
* quotes instead of "<>".
|
||||
*/
|
||||
include_dir->quoted_includes_only = 1;
|
||||
} else {
|
||||
include_dir =
|
||||
(path_entry_t)malloc(sizeof(*include_dir));
|
||||
if (include_dir == NULL) {
|
||||
perror(optarg);
|
||||
stop(NULL, EX_OSERR);
|
||||
}
|
||||
include_dir->directory = strdup(optarg);
|
||||
if (include_dir->directory == NULL) {
|
||||
perror(optarg);
|
||||
stop(NULL, EX_OSERR);
|
||||
}
|
||||
include_dir->quoted_includes_only = 0;
|
||||
SLIST_INSERT_HEAD(&search_path, include_dir,
|
||||
links);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "%s: No input file specifiled\n", appname);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (regdiagfile != NULL
|
||||
&& (regfile == NULL || stock_include_file == NULL)) {
|
||||
fprintf(stderr,
|
||||
"%s: The -p option requires the -r and -i options.\n",
|
||||
appname);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
symtable_open();
|
||||
inputfilename = *argv;
|
||||
include_file(*argv, SOURCE_FILE);
|
||||
retval = yyparse();
|
||||
if (retval == 0) {
|
||||
if (SLIST_FIRST(&scope_stack) == NULL
|
||||
|| SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
|
||||
stop("Unterminated conditional expression", EX_DATAERR);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* Process outmost scope */
|
||||
process_scope(SLIST_FIRST(&scope_stack));
|
||||
/*
|
||||
* Decend the tree of scopes and insert/emit
|
||||
* patches as appropriate. We perform a depth first
|
||||
* tranversal, recursively handling each scope.
|
||||
*/
|
||||
/* start at the root scope */
|
||||
dump_scope(SLIST_FIRST(&scope_stack));
|
||||
|
||||
/* Patch up forward jump addresses */
|
||||
back_patch();
|
||||
|
||||
if (ofile != NULL)
|
||||
output_code();
|
||||
if (regfile != NULL)
|
||||
symtable_dump(regfile, regdiagfile);
|
||||
if (listfile != NULL)
|
||||
output_listing(inputfilename);
|
||||
}
|
||||
|
||||
stop(NULL, 0);
|
||||
/* NOTREACHED */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]\n"
|
||||
" [-r register_output_file [-p register_diag_file -i includefile]]\n"
|
||||
" [-l program_list_file]\n"
|
||||
" input_file\n", appname);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
static void
|
||||
back_patch()
|
||||
{
|
||||
struct instruction *cur_instr;
|
||||
|
||||
for (cur_instr = STAILQ_FIRST(&seq_program);
|
||||
cur_instr != NULL;
|
||||
cur_instr = STAILQ_NEXT(cur_instr, links)) {
|
||||
if (cur_instr->patch_label != NULL) {
|
||||
struct ins_format3 *f3_instr;
|
||||
u_int address;
|
||||
|
||||
if (cur_instr->patch_label->type != LABEL) {
|
||||
char buf[255];
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"Undefined label %s",
|
||||
cur_instr->patch_label->name);
|
||||
stop(buf, EX_DATAERR);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
f3_instr = &cur_instr->format.format3;
|
||||
address = f3_instr->address;
|
||||
address += cur_instr->patch_label->info.linfo->address;
|
||||
f3_instr->address = address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
output_code()
|
||||
{
|
||||
struct instruction *cur_instr;
|
||||
patch_t *cur_patch;
|
||||
critical_section_t *cs;
|
||||
symbol_node_t *cur_node;
|
||||
int instrcount;
|
||||
|
||||
instrcount = 0;
|
||||
fprintf(ofile,
|
||||
"/*\n"
|
||||
" * DO NOT EDIT - This file is automatically generated\n"
|
||||
" * from the following source files:\n"
|
||||
" *\n"
|
||||
"%s */\n", versions);
|
||||
|
||||
fprintf(ofile, "static const uint8_t seqprog[] = {\n");
|
||||
for (cur_instr = STAILQ_FIRST(&seq_program);
|
||||
cur_instr != NULL;
|
||||
cur_instr = STAILQ_NEXT(cur_instr, links)) {
|
||||
|
||||
fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
|
||||
cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
cur_instr->format.bytes[0],
|
||||
cur_instr->format.bytes[1],
|
||||
cur_instr->format.bytes[2],
|
||||
cur_instr->format.bytes[3]);
|
||||
#else
|
||||
cur_instr->format.bytes[3],
|
||||
cur_instr->format.bytes[2],
|
||||
cur_instr->format.bytes[1],
|
||||
cur_instr->format.bytes[0]);
|
||||
#endif
|
||||
instrcount++;
|
||||
}
|
||||
fprintf(ofile, "\n};\n\n");
|
||||
|
||||
if (patch_arg_list == NULL)
|
||||
stop("Patch argument list not defined",
|
||||
EX_DATAERR);
|
||||
|
||||
/*
|
||||
* Output patch information. Patch functions first.
|
||||
*/
|
||||
fprintf(ofile,
|
||||
"typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list);
|
||||
|
||||
for (cur_node = SLIST_FIRST(&patch_functions);
|
||||
cur_node != NULL;
|
||||
cur_node = SLIST_NEXT(cur_node,links)) {
|
||||
fprintf(ofile,
|
||||
"static %spatch_func_t %spatch%d_func;\n"
|
||||
"\n"
|
||||
"static int\n"
|
||||
"%spatch%d_func(%s)\n"
|
||||
"{\n"
|
||||
" return (%s);\n"
|
||||
"}\n\n",
|
||||
prefix,
|
||||
prefix,
|
||||
cur_node->symbol->info.condinfo->func_num,
|
||||
prefix,
|
||||
cur_node->symbol->info.condinfo->func_num,
|
||||
patch_arg_list,
|
||||
cur_node->symbol->name);
|
||||
}
|
||||
|
||||
fprintf(ofile,
|
||||
"static const struct patch {\n"
|
||||
" %spatch_func_t *patch_func;\n"
|
||||
" uint32_t begin :10,\n"
|
||||
" skip_instr :10,\n"
|
||||
" skip_patch :12;\n"
|
||||
"} patches[] = {\n", prefix);
|
||||
|
||||
for (cur_patch = STAILQ_FIRST(&patches);
|
||||
cur_patch != NULL;
|
||||
cur_patch = STAILQ_NEXT(cur_patch,links)) {
|
||||
fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }",
|
||||
cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
|
||||
prefix,
|
||||
cur_patch->patch_func, cur_patch->begin,
|
||||
cur_patch->skip_instr, cur_patch->skip_patch);
|
||||
}
|
||||
|
||||
fprintf(ofile, "\n};\n\n");
|
||||
|
||||
fprintf(ofile,
|
||||
"static const struct cs {\n"
|
||||
" uint16_t begin;\n"
|
||||
" uint16_t end;\n"
|
||||
"} critical_sections[] = {\n");
|
||||
|
||||
for (cs = TAILQ_FIRST(&cs_tailq);
|
||||
cs != NULL;
|
||||
cs = TAILQ_NEXT(cs, links)) {
|
||||
fprintf(ofile, "%s\t{ %d, %d }",
|
||||
cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
|
||||
cs->begin_addr, cs->end_addr);
|
||||
}
|
||||
|
||||
fprintf(ofile, "\n};\n\n");
|
||||
|
||||
fprintf(ofile,
|
||||
"static const int num_critical_sections = sizeof(critical_sections)\n"
|
||||
" / sizeof(*critical_sections);\n");
|
||||
|
||||
fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_scope(scope_t *scope)
|
||||
{
|
||||
scope_t *cur_scope;
|
||||
|
||||
/*
|
||||
* Emit the first patch for this scope
|
||||
*/
|
||||
emit_patch(scope, 0);
|
||||
|
||||
/*
|
||||
* Dump each scope within this one.
|
||||
*/
|
||||
cur_scope = TAILQ_FIRST(&scope->inner_scope);
|
||||
|
||||
while (cur_scope != NULL) {
|
||||
|
||||
dump_scope(cur_scope);
|
||||
|
||||
cur_scope = TAILQ_NEXT(cur_scope, scope_links);
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit the second, closing, patch for this scope
|
||||
*/
|
||||
emit_patch(scope, 1);
|
||||
}
|
||||
|
||||
void
|
||||
emit_patch(scope_t *scope, int patch)
|
||||
{
|
||||
patch_info_t *pinfo;
|
||||
patch_t *new_patch;
|
||||
|
||||
pinfo = &scope->patches[patch];
|
||||
|
||||
if (pinfo->skip_instr == 0)
|
||||
/* No-Op patch */
|
||||
return;
|
||||
|
||||
new_patch = (patch_t *)malloc(sizeof(*new_patch));
|
||||
|
||||
if (new_patch == NULL)
|
||||
stop("Could not malloc patch structure", EX_OSERR);
|
||||
|
||||
memset(new_patch, 0, sizeof(*new_patch));
|
||||
|
||||
if (patch == 0) {
|
||||
new_patch->patch_func = scope->func_num;
|
||||
new_patch->begin = scope->begin_addr;
|
||||
} else {
|
||||
new_patch->patch_func = 0;
|
||||
new_patch->begin = scope->end_addr;
|
||||
}
|
||||
new_patch->skip_instr = pinfo->skip_instr;
|
||||
new_patch->skip_patch = pinfo->skip_patch;
|
||||
STAILQ_INSERT_TAIL(&patches, new_patch, links);
|
||||
}
|
||||
|
||||
void
|
||||
output_listing(char *ifilename)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *ifile;
|
||||
struct instruction *cur_instr;
|
||||
patch_t *cur_patch;
|
||||
symbol_node_t *cur_func;
|
||||
int *func_values;
|
||||
int instrcount;
|
||||
int instrptr;
|
||||
int line;
|
||||
int func_count;
|
||||
int skip_addr;
|
||||
|
||||
instrcount = 0;
|
||||
instrptr = 0;
|
||||
line = 1;
|
||||
skip_addr = 0;
|
||||
if ((ifile = fopen(ifilename, "r")) == NULL) {
|
||||
perror(ifilename);
|
||||
stop(NULL, EX_DATAERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which options to apply to this listing.
|
||||
*/
|
||||
for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
|
||||
cur_func != NULL;
|
||||
cur_func = SLIST_NEXT(cur_func, links))
|
||||
func_count++;
|
||||
|
||||
func_values = NULL;
|
||||
if (func_count != 0) {
|
||||
func_values = (int *)malloc(func_count * sizeof(int));
|
||||
|
||||
if (func_values == NULL)
|
||||
stop("Could not malloc", EX_OSERR);
|
||||
|
||||
func_values[0] = 0; /* FALSE func */
|
||||
func_count--;
|
||||
|
||||
/*
|
||||
* Ask the user to fill in the return values for
|
||||
* the rest of the functions.
|
||||
*/
|
||||
|
||||
|
||||
for (cur_func = SLIST_FIRST(&patch_functions);
|
||||
cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
|
||||
cur_func = SLIST_NEXT(cur_func, links), func_count--) {
|
||||
int input;
|
||||
|
||||
fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
|
||||
fprintf(stdout,
|
||||
"Enter the return value for "
|
||||
"this expression[T/F]:");
|
||||
|
||||
while (1) {
|
||||
|
||||
input = getchar();
|
||||
input = toupper(input);
|
||||
|
||||
if (input == 'T') {
|
||||
func_values[func_count] = 1;
|
||||
break;
|
||||
} else if (input == 'F') {
|
||||
func_values[func_count] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isatty(fileno(stdin)) == 0)
|
||||
putchar(input);
|
||||
}
|
||||
fprintf(stdout, "\nThanks!\n");
|
||||
}
|
||||
|
||||
/* Now output the listing */
|
||||
cur_patch = STAILQ_FIRST(&patches);
|
||||
for (cur_instr = STAILQ_FIRST(&seq_program);
|
||||
cur_instr != NULL;
|
||||
cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
|
||||
|
||||
if (check_patch(&cur_patch, instrcount,
|
||||
&skip_addr, func_values) == 0) {
|
||||
/* Don't count this instruction as it is in a patch
|
||||
* that was removed.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
while (line < cur_instr->srcline) {
|
||||
fgets(buf, sizeof(buf), ifile);
|
||||
fprintf(listfile, " \t%s", buf);
|
||||
line++;
|
||||
}
|
||||
fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
cur_instr->format.bytes[0],
|
||||
cur_instr->format.bytes[1],
|
||||
cur_instr->format.bytes[2],
|
||||
cur_instr->format.bytes[3]);
|
||||
#else
|
||||
cur_instr->format.bytes[3],
|
||||
cur_instr->format.bytes[2],
|
||||
cur_instr->format.bytes[1],
|
||||
cur_instr->format.bytes[0]);
|
||||
#endif
|
||||
/*
|
||||
* Macro expansions can cause several instructions
|
||||
* to be output for a single source line. Only
|
||||
* advance the line once in these cases.
|
||||
*/
|
||||
if (line == cur_instr->srcline) {
|
||||
fgets(buf, sizeof(buf), ifile);
|
||||
fprintf(listfile, "\t%s", buf);
|
||||
line++;
|
||||
} else {
|
||||
fprintf(listfile, "\n");
|
||||
}
|
||||
instrptr++;
|
||||
}
|
||||
/* Dump the remainder of the file */
|
||||
while(fgets(buf, sizeof(buf), ifile) != NULL)
|
||||
fprintf(listfile, " %s", buf);
|
||||
|
||||
fclose(ifile);
|
||||
}
|
||||
|
||||
static int
|
||||
check_patch(patch_t **start_patch, int start_instr,
|
||||
int *skip_addr, int *func_vals)
|
||||
{
|
||||
patch_t *cur_patch;
|
||||
|
||||
cur_patch = *start_patch;
|
||||
|
||||
while (cur_patch != NULL && start_instr == cur_patch->begin) {
|
||||
if (func_vals[cur_patch->patch_func] == 0) {
|
||||
int skip;
|
||||
|
||||
/* Start rejecting code */
|
||||
*skip_addr = start_instr + cur_patch->skip_instr;
|
||||
for (skip = cur_patch->skip_patch;
|
||||
skip > 0 && cur_patch != NULL;
|
||||
skip--)
|
||||
cur_patch = STAILQ_NEXT(cur_patch, links);
|
||||
} else {
|
||||
/* Accepted this patch. Advance to the next
|
||||
* one and wait for our intruction pointer to
|
||||
* hit this point.
|
||||
*/
|
||||
cur_patch = STAILQ_NEXT(cur_patch, links);
|
||||
}
|
||||
}
|
||||
|
||||
*start_patch = cur_patch;
|
||||
if (start_instr < *skip_addr)
|
||||
/* Still skipping */
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out error information if appropriate, and clean up before
|
||||
* terminating the program.
|
||||
*/
|
||||
void
|
||||
stop(const char *string, int err_code)
|
||||
{
|
||||
if (string != NULL) {
|
||||
fprintf(stderr, "%s: ", appname);
|
||||
if (yyfilename != NULL) {
|
||||
fprintf(stderr, "Stopped at file %s, line %d - ",
|
||||
yyfilename, yylineno);
|
||||
}
|
||||
fprintf(stderr, "%s\n", string);
|
||||
}
|
||||
|
||||
if (ofile != NULL) {
|
||||
fclose(ofile);
|
||||
if (err_code != 0) {
|
||||
fprintf(stderr, "%s: Removing %s due to error\n",
|
||||
appname, ofilename);
|
||||
unlink(ofilename);
|
||||
}
|
||||
}
|
||||
|
||||
if (regfile != NULL) {
|
||||
fclose(regfile);
|
||||
if (err_code != 0) {
|
||||
fprintf(stderr, "%s: Removing %s due to error\n",
|
||||
appname, regfilename);
|
||||
unlink(regfilename);
|
||||
}
|
||||
}
|
||||
|
||||
if (listfile != NULL) {
|
||||
fclose(listfile);
|
||||
if (err_code != 0) {
|
||||
fprintf(stderr, "%s: Removing %s due to error\n",
|
||||
appname, listfilename);
|
||||
unlink(listfilename);
|
||||
}
|
||||
}
|
||||
|
||||
symlist_free(&patch_functions);
|
||||
symtable_close();
|
||||
|
||||
exit(err_code);
|
||||
}
|
||||
|
||||
struct instruction *
|
||||
seq_alloc()
|
||||
{
|
||||
struct instruction *new_instr;
|
||||
|
||||
new_instr = (struct instruction *)malloc(sizeof(struct instruction));
|
||||
if (new_instr == NULL)
|
||||
stop("Unable to malloc instruction object", EX_SOFTWARE);
|
||||
memset(new_instr, 0, sizeof(*new_instr));
|
||||
STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
|
||||
new_instr->srcline = yylineno;
|
||||
return new_instr;
|
||||
}
|
||||
|
||||
critical_section_t *
|
||||
cs_alloc()
|
||||
{
|
||||
critical_section_t *new_cs;
|
||||
|
||||
new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
|
||||
if (new_cs == NULL)
|
||||
stop("Unable to malloc critical_section object", EX_SOFTWARE);
|
||||
memset(new_cs, 0, sizeof(*new_cs));
|
||||
|
||||
TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
|
||||
return new_cs;
|
||||
}
|
||||
|
||||
scope_t *
|
||||
scope_alloc()
|
||||
{
|
||||
scope_t *new_scope;
|
||||
|
||||
new_scope = (scope_t *)malloc(sizeof(scope_t));
|
||||
if (new_scope == NULL)
|
||||
stop("Unable to malloc scope object", EX_SOFTWARE);
|
||||
memset(new_scope, 0, sizeof(*new_scope));
|
||||
TAILQ_INIT(&new_scope->inner_scope);
|
||||
|
||||
if (SLIST_FIRST(&scope_stack) != NULL) {
|
||||
TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
|
||||
new_scope, scope_links);
|
||||
}
|
||||
/* This patch is now the current scope */
|
||||
SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
|
||||
return new_scope;
|
||||
}
|
||||
|
||||
void
|
||||
process_scope(scope_t *scope)
|
||||
{
|
||||
/*
|
||||
* We are "leaving" this scope. We should now have
|
||||
* enough information to process the lists of scopes
|
||||
* we encapsulate.
|
||||
*/
|
||||
scope_t *cur_scope;
|
||||
u_int skip_patch_count;
|
||||
u_int skip_instr_count;
|
||||
|
||||
cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
|
||||
skip_patch_count = 0;
|
||||
skip_instr_count = 0;
|
||||
while (cur_scope != NULL) {
|
||||
u_int patch0_patch_skip;
|
||||
|
||||
patch0_patch_skip = 0;
|
||||
switch (cur_scope->type) {
|
||||
case SCOPE_IF:
|
||||
case SCOPE_ELSE_IF:
|
||||
if (skip_instr_count != 0) {
|
||||
/* Create a tail patch */
|
||||
patch0_patch_skip++;
|
||||
cur_scope->patches[1].skip_patch =
|
||||
skip_patch_count + 1;
|
||||
cur_scope->patches[1].skip_instr =
|
||||
skip_instr_count;
|
||||
}
|
||||
|
||||
/* Count Head patch */
|
||||
patch0_patch_skip++;
|
||||
|
||||
/* Count any patches contained in our inner scope */
|
||||
patch0_patch_skip += cur_scope->inner_scope_patches;
|
||||
|
||||
cur_scope->patches[0].skip_patch = patch0_patch_skip;
|
||||
cur_scope->patches[0].skip_instr =
|
||||
cur_scope->end_addr - cur_scope->begin_addr;
|
||||
|
||||
skip_instr_count += cur_scope->patches[0].skip_instr;
|
||||
|
||||
skip_patch_count += patch0_patch_skip;
|
||||
if (cur_scope->type == SCOPE_IF) {
|
||||
scope->inner_scope_patches += skip_patch_count;
|
||||
skip_patch_count = 0;
|
||||
skip_instr_count = 0;
|
||||
}
|
||||
break;
|
||||
case SCOPE_ELSE:
|
||||
/* Count any patches contained in our innter scope */
|
||||
skip_patch_count += cur_scope->inner_scope_patches;
|
||||
|
||||
skip_instr_count += cur_scope->end_addr
|
||||
- cur_scope->begin_addr;
|
||||
break;
|
||||
case SCOPE_ROOT:
|
||||
stop("Unexpected scope type encountered", EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
|
||||
}
|
||||
}
|
95
drivers/scsi/aic7xxx/aicasm/aicasm.h
Normal file
95
drivers/scsi/aic7xxx/aicasm/aicasm.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Assembler for the sequencer program downloaded to Aic7xxx SCSI host adapters
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* Copyright (c) 2001, 2002 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.h#14 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#include "../queue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
typedef struct path_entry {
|
||||
char *directory;
|
||||
int quoted_includes_only;
|
||||
SLIST_ENTRY(path_entry) links;
|
||||
} *path_entry_t;
|
||||
|
||||
typedef enum {
|
||||
QUOTED_INCLUDE,
|
||||
BRACKETED_INCLUDE,
|
||||
SOURCE_FILE
|
||||
} include_type;
|
||||
|
||||
SLIST_HEAD(path_list, path_entry);
|
||||
|
||||
extern struct path_list search_path;
|
||||
extern struct cs_tailq cs_tailq;
|
||||
extern struct scope_list scope_stack;
|
||||
extern struct symlist patch_functions;
|
||||
extern int includes_search_curdir; /* False if we've seen -I- */
|
||||
extern char *appname;
|
||||
extern char *stock_include_file;
|
||||
extern int yylineno;
|
||||
extern char *yyfilename;
|
||||
extern char *prefix;
|
||||
extern char *patch_arg_list;
|
||||
extern char *versions;
|
||||
extern int src_mode;
|
||||
extern int dst_mode;
|
||||
struct symbol;
|
||||
|
||||
void stop(const char *errstring, int err_code);
|
||||
void include_file(char *file_name, include_type type);
|
||||
void expand_macro(struct symbol *macro_symbol);
|
||||
struct instruction *seq_alloc(void);
|
||||
struct critical_section *cs_alloc(void);
|
||||
struct scope *scope_alloc(void);
|
||||
void process_scope(struct scope *);
|
2004
drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
Normal file
2004
drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
Normal file
File diff suppressed because it is too large
Load diff
218
drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
Normal file
218
drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Instruction formats for the sequencer program downloaded to
|
||||
* Aic7xxx SCSI host adapters
|
||||
*
|
||||
* Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#12 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
/* 8bit ALU logic operations */
|
||||
struct ins_format1 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
uint32_t immediate : 8,
|
||||
source : 9,
|
||||
destination : 9,
|
||||
ret : 1,
|
||||
opcode : 4,
|
||||
parity : 1;
|
||||
#else
|
||||
uint32_t parity : 1,
|
||||
opcode : 4,
|
||||
ret : 1,
|
||||
destination : 9,
|
||||
source : 9,
|
||||
immediate : 8;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 8bit ALU shift/rotate operations */
|
||||
struct ins_format2 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
uint32_t shift_control : 8,
|
||||
source : 9,
|
||||
destination : 9,
|
||||
ret : 1,
|
||||
opcode : 4,
|
||||
parity : 1;
|
||||
#else
|
||||
uint32_t parity : 1,
|
||||
opcode : 4,
|
||||
ret : 1,
|
||||
destination : 9,
|
||||
source : 9,
|
||||
shift_control : 8;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 8bit branch control operations */
|
||||
struct ins_format3 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
uint32_t immediate : 8,
|
||||
source : 9,
|
||||
address : 10,
|
||||
opcode : 4,
|
||||
parity : 1;
|
||||
#else
|
||||
uint32_t parity : 1,
|
||||
opcode : 4,
|
||||
address : 10,
|
||||
source : 9,
|
||||
immediate : 8;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 16bit ALU logic operations */
|
||||
struct ins_format4 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
uint32_t opcode_ext : 8,
|
||||
source : 9,
|
||||
destination : 9,
|
||||
ret : 1,
|
||||
opcode : 4,
|
||||
parity : 1;
|
||||
#else
|
||||
uint32_t parity : 1,
|
||||
opcode : 4,
|
||||
ret : 1,
|
||||
destination : 9,
|
||||
source : 9,
|
||||
opcode_ext : 8;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 16bit branch control operations */
|
||||
struct ins_format5 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
uint32_t opcode_ext : 8,
|
||||
source : 9,
|
||||
address : 10,
|
||||
opcode : 4,
|
||||
parity : 1;
|
||||
#else
|
||||
uint32_t parity : 1,
|
||||
opcode : 4,
|
||||
address : 10,
|
||||
source : 9,
|
||||
opcode_ext : 8;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Far branch operations */
|
||||
struct ins_format6 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
uint32_t page : 3,
|
||||
opcode_ext : 5,
|
||||
source : 9,
|
||||
address : 10,
|
||||
opcode : 4,
|
||||
parity : 1;
|
||||
#else
|
||||
uint32_t parity : 1,
|
||||
opcode : 4,
|
||||
address : 10,
|
||||
source : 9,
|
||||
opcode_ext : 5,
|
||||
page : 3;
|
||||
#endif
|
||||
};
|
||||
|
||||
union ins_formats {
|
||||
struct ins_format1 format1;
|
||||
struct ins_format2 format2;
|
||||
struct ins_format3 format3;
|
||||
struct ins_format4 format4;
|
||||
struct ins_format5 format5;
|
||||
struct ins_format6 format6;
|
||||
uint8_t bytes[4];
|
||||
uint32_t integer;
|
||||
};
|
||||
struct instruction {
|
||||
union ins_formats format;
|
||||
u_int srcline;
|
||||
struct symbol *patch_label;
|
||||
STAILQ_ENTRY(instruction) links;
|
||||
};
|
||||
|
||||
#define AIC_OP_OR 0x0
|
||||
#define AIC_OP_AND 0x1
|
||||
#define AIC_OP_XOR 0x2
|
||||
#define AIC_OP_ADD 0x3
|
||||
#define AIC_OP_ADC 0x4
|
||||
#define AIC_OP_ROL 0x5
|
||||
#define AIC_OP_BMOV 0x6
|
||||
|
||||
#define AIC_OP_MVI16 0x7
|
||||
|
||||
#define AIC_OP_JMP 0x8
|
||||
#define AIC_OP_JC 0x9
|
||||
#define AIC_OP_JNC 0xa
|
||||
#define AIC_OP_CALL 0xb
|
||||
#define AIC_OP_JNE 0xc
|
||||
#define AIC_OP_JNZ 0xd
|
||||
#define AIC_OP_JE 0xe
|
||||
#define AIC_OP_JZ 0xf
|
||||
|
||||
/* Pseudo Ops */
|
||||
#define AIC_OP_SHL 0x10
|
||||
#define AIC_OP_SHR 0x20
|
||||
#define AIC_OP_ROR 0x30
|
||||
|
||||
/* 16bit Ops. Low byte main opcode. High byte extended opcode. */
|
||||
#define AIC_OP_OR16 0x8005
|
||||
#define AIC_OP_AND16 0x8105
|
||||
#define AIC_OP_XOR16 0x8205
|
||||
#define AIC_OP_ADD16 0x8305
|
||||
#define AIC_OP_ADC16 0x8405
|
||||
#define AIC_OP_JNE16 0x8805
|
||||
#define AIC_OP_JNZ16 0x8905
|
||||
#define AIC_OP_JE16 0x8C05
|
||||
#define AIC_OP_JZ16 0x8B05
|
||||
#define AIC_OP_JMP16 0x9005
|
||||
#define AIC_OP_JC16 0x9105
|
||||
#define AIC_OP_JNC16 0x9205
|
||||
#define AIC_OP_CALL16 0x9305
|
||||
|
||||
/* Page extension is low three bits of second opcode byte. */
|
||||
#define AIC_OP_JMPF 0xA005
|
||||
#define AIC_OP_CALLF 0xB005
|
||||
#define AIC_OP_JCF 0xC005
|
||||
#define AIC_OP_JNCF 0xD005
|
||||
#define AIC_OP_CMPXCHG 0xE005
|
165
drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
Normal file
165
drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
Normal file
|
@ -0,0 +1,165 @@
|
|||
%{
|
||||
/*
|
||||
* Sub-parser for macro invocation in the Aic7xxx SCSI
|
||||
* Host adapter sequencer assembler.
|
||||
*
|
||||
* Copyright (c) 2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_gram.y#5 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include "../queue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
#include "aicasm.h"
|
||||
#include "aicasm_symbol.h"
|
||||
#include "aicasm_insformat.h"
|
||||
|
||||
static symbol_t *macro_symbol;
|
||||
|
||||
static void add_macro_arg(const char *argtext, int position);
|
||||
void mmerror(const char *string);
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
int value;
|
||||
char *str;
|
||||
symbol_t *sym;
|
||||
}
|
||||
|
||||
|
||||
%token <str> T_ARG
|
||||
|
||||
%token <sym> T_SYMBOL
|
||||
|
||||
%type <value> macro_arglist
|
||||
|
||||
%%
|
||||
|
||||
macrocall:
|
||||
T_SYMBOL '('
|
||||
{
|
||||
macro_symbol = $1;
|
||||
}
|
||||
macro_arglist ')'
|
||||
{
|
||||
if (macro_symbol->info.macroinfo->narg != $4) {
|
||||
printf("Narg == %d", macro_symbol->info.macroinfo->narg);
|
||||
stop("Too few arguments for macro invocation",
|
||||
EX_DATAERR);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
macro_symbol = NULL;
|
||||
YYACCEPT;
|
||||
}
|
||||
;
|
||||
|
||||
macro_arglist:
|
||||
{
|
||||
/* Macros can take 0 arguments */
|
||||
$$ = 0;
|
||||
}
|
||||
| T_ARG
|
||||
{
|
||||
$$ = 1;
|
||||
add_macro_arg($1, 1);
|
||||
}
|
||||
| macro_arglist ',' T_ARG
|
||||
{
|
||||
if ($1 == 0) {
|
||||
stop("Comma without preceding argument in arg list",
|
||||
EX_DATAERR);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
$$ = $1 + 1;
|
||||
add_macro_arg($3, $$);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
static void
|
||||
add_macro_arg(const char *argtext, int argnum)
|
||||
{
|
||||
struct macro_arg *marg;
|
||||
int i;
|
||||
|
||||
if (macro_symbol == NULL || macro_symbol->type != MACRO) {
|
||||
stop("Invalid current symbol for adding macro arg",
|
||||
EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/*
|
||||
* Macro Invocation. Find the appropriate argument and fill
|
||||
* in the replace ment text for this call.
|
||||
*/
|
||||
i = 0;
|
||||
STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) {
|
||||
i++;
|
||||
if (i == argnum)
|
||||
break;
|
||||
}
|
||||
if (marg == NULL) {
|
||||
stop("Too many arguments for macro invocation", EX_DATAERR);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
marg->replacement_text = strdup(argtext);
|
||||
if (marg->replacement_text == NULL) {
|
||||
stop("Unable to replicate replacement text", EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mmerror(const char *string)
|
||||
{
|
||||
stop(string, EX_DATAERR);
|
||||
}
|
157
drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
Normal file
157
drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
Normal file
|
@ -0,0 +1,157 @@
|
|||
%{
|
||||
/*
|
||||
* Sub-Lexical Analyzer for macro invokation in
|
||||
* the Aic7xxx SCSI Host adapter sequencer assembler.
|
||||
*
|
||||
* Copyright (c) 2001 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#8 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#ifdef __linux__
|
||||
#include "../queue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
#include "aicasm.h"
|
||||
#include "aicasm_symbol.h"
|
||||
#include "aicasm_macro_gram.h"
|
||||
|
||||
#define MAX_STR_CONST 4096
|
||||
static char string_buf[MAX_STR_CONST];
|
||||
static char *string_buf_ptr;
|
||||
static int parren_count;
|
||||
static char buf[255];
|
||||
int mmlineno;
|
||||
%}
|
||||
|
||||
WORD [A-Za-z_][-A-Za-z_0-9]*
|
||||
SPACE [ \t]+
|
||||
MCARG [^(), \t]+
|
||||
|
||||
%x ARGLIST
|
||||
|
||||
%%
|
||||
\n {
|
||||
++mmlineno;
|
||||
}
|
||||
\r ;
|
||||
<ARGLIST>{SPACE} ;
|
||||
<ARGLIST>\( {
|
||||
parren_count++;
|
||||
if (parren_count == 1) {
|
||||
string_buf_ptr = string_buf;
|
||||
return ('(');
|
||||
}
|
||||
*string_buf_ptr++ = '(';
|
||||
}
|
||||
<ARGLIST>\) {
|
||||
if (parren_count == 1) {
|
||||
if (string_buf_ptr != string_buf) {
|
||||
/*
|
||||
* Return an argument and
|
||||
* rescan this parren so we
|
||||
* can return it as well.
|
||||
*/
|
||||
*string_buf_ptr = '\0';
|
||||
mmlval.str = string_buf;
|
||||
string_buf_ptr = string_buf;
|
||||
unput(')');
|
||||
return T_ARG;
|
||||
}
|
||||
BEGIN INITIAL;
|
||||
return (')');
|
||||
}
|
||||
parren_count--;
|
||||
*string_buf_ptr++ = ')';
|
||||
}
|
||||
<ARGLIST>{MCARG} {
|
||||
char *yptr;
|
||||
|
||||
yptr = mmtext;
|
||||
while (*yptr)
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
}
|
||||
<ARGLIST>\, {
|
||||
if (string_buf_ptr != string_buf) {
|
||||
/*
|
||||
* Return an argument and
|
||||
* rescan this comma so we
|
||||
* can return it as well.
|
||||
*/
|
||||
*string_buf_ptr = '\0';
|
||||
mmlval.str = string_buf;
|
||||
string_buf_ptr = string_buf;
|
||||
unput(',');
|
||||
return T_ARG;
|
||||
}
|
||||
return ',';
|
||||
}
|
||||
{WORD}[(] {
|
||||
/* May be a symbol or a macro invocation. */
|
||||
mmlval.sym = symtable_get(mmtext);
|
||||
if (mmlval.sym->type != MACRO) {
|
||||
stop("Expecting Macro Name",
|
||||
EX_DATAERR);
|
||||
}
|
||||
unput('(');
|
||||
parren_count = 0;
|
||||
BEGIN ARGLIST;
|
||||
return T_SYMBOL;
|
||||
}
|
||||
. {
|
||||
snprintf(buf, sizeof(buf), "Invalid character "
|
||||
"'%c'", mmtext[0]);
|
||||
stop(buf, EX_DATAERR);
|
||||
}
|
||||
%%
|
||||
|
||||
int
|
||||
mmwrap()
|
||||
{
|
||||
stop("EOF encountered in macro call", EX_DATAERR);
|
||||
}
|
622
drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
Normal file
622
drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
Normal file
|
@ -0,0 +1,622 @@
|
|||
%{
|
||||
/*
|
||||
* Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
|
||||
*
|
||||
* Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
|
||||
* Copyright (c) 2001, 2002 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#ifdef __linux__
|
||||
#include "../queue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
#include "aicasm.h"
|
||||
#include "aicasm_symbol.h"
|
||||
#include "aicasm_gram.h"
|
||||
|
||||
/* This is used for macro body capture too, so err on the large size. */
|
||||
#define MAX_STR_CONST 4096
|
||||
static char string_buf[MAX_STR_CONST];
|
||||
static char *string_buf_ptr;
|
||||
static int parren_count;
|
||||
static int quote_count;
|
||||
static char buf[255];
|
||||
%}
|
||||
|
||||
PATH ([/]*[-A-Za-z0-9_.])+
|
||||
WORD [A-Za-z_][-A-Za-z_0-9]*
|
||||
SPACE [ \t]+
|
||||
MCARG [^(), \t]+
|
||||
MBODY ((\\[^\n])*[^\n\\]*)+
|
||||
|
||||
%x COMMENT
|
||||
%x CEXPR
|
||||
%x INCLUDE
|
||||
%x STRING
|
||||
%x MACRODEF
|
||||
%x MACROARGLIST
|
||||
%x MACROCALLARGS
|
||||
%x MACROBODY
|
||||
|
||||
%%
|
||||
\n { ++yylineno; }
|
||||
\r ;
|
||||
"/*" { BEGIN COMMENT; /* Enter comment eating state */ }
|
||||
<COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); }
|
||||
<COMMENT>\n { ++yylineno; }
|
||||
<COMMENT>[^*/\n]* ;
|
||||
<COMMENT>"*"+[^*/\n]* ;
|
||||
<COMMENT>"/"+[^*/\n]* ;
|
||||
<COMMENT>"*"+"/" { BEGIN INITIAL; }
|
||||
if[ \t]*\( {
|
||||
string_buf_ptr = string_buf;
|
||||
parren_count = 1;
|
||||
BEGIN CEXPR;
|
||||
return T_IF;
|
||||
}
|
||||
<CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; }
|
||||
<CEXPR>\) {
|
||||
parren_count--;
|
||||
if (parren_count == 0) {
|
||||
/* All done */
|
||||
BEGIN INITIAL;
|
||||
*string_buf_ptr = '\0';
|
||||
yylval.sym = symtable_get(string_buf);
|
||||
return T_CEXPR;
|
||||
} else {
|
||||
*string_buf_ptr++ = ')';
|
||||
}
|
||||
}
|
||||
<CEXPR>\n { ++yylineno; }
|
||||
<CEXPR>\r ;
|
||||
<CEXPR>[^()\n]+ {
|
||||
char *yptr;
|
||||
|
||||
yptr = yytext;
|
||||
while (*yptr != '\0') {
|
||||
/* Remove duplicate spaces */
|
||||
if (*yptr == '\t')
|
||||
*yptr = ' ';
|
||||
if (*yptr == ' '
|
||||
&& string_buf_ptr != string_buf
|
||||
&& string_buf_ptr[-1] == ' ')
|
||||
yptr++;
|
||||
else
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
}
|
||||
}
|
||||
else { return T_ELSE; }
|
||||
VERSION { return T_VERSION; }
|
||||
PREFIX { return T_PREFIX; }
|
||||
PATCH_ARG_LIST { return T_PATCH_ARG_LIST; }
|
||||
\" {
|
||||
string_buf_ptr = string_buf;
|
||||
BEGIN STRING;
|
||||
}
|
||||
<STRING>[^"]+ {
|
||||
char *yptr;
|
||||
|
||||
yptr = yytext;
|
||||
while (*yptr)
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
}
|
||||
<STRING>\" {
|
||||
/* All done */
|
||||
BEGIN INITIAL;
|
||||
*string_buf_ptr = '\0';
|
||||
yylval.str = string_buf;
|
||||
return T_STRING;
|
||||
}
|
||||
{SPACE} ;
|
||||
|
||||
/* Register/SCB/SRAM definition keywords */
|
||||
export { return T_EXPORT; }
|
||||
register { return T_REGISTER; }
|
||||
const { yylval.value = FALSE; return T_CONST; }
|
||||
download { return T_DOWNLOAD; }
|
||||
address { return T_ADDRESS; }
|
||||
count { return T_COUNT; }
|
||||
access_mode { return T_ACCESS_MODE; }
|
||||
dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
|
||||
modes { return T_MODES; }
|
||||
RW|RO|WO {
|
||||
if (strcmp(yytext, "RW") == 0)
|
||||
yylval.value = RW;
|
||||
else if (strcmp(yytext, "RO") == 0)
|
||||
yylval.value = RO;
|
||||
else
|
||||
yylval.value = WO;
|
||||
return T_MODE;
|
||||
}
|
||||
field { return T_FIELD; }
|
||||
enum { return T_ENUM; }
|
||||
mask { return T_MASK; }
|
||||
alias { return T_ALIAS; }
|
||||
size { return T_SIZE; }
|
||||
scb { return T_SCB; }
|
||||
scratch_ram { return T_SRAM; }
|
||||
accumulator { return T_ACCUM; }
|
||||
mode_pointer { return T_MODE_PTR; }
|
||||
allones { return T_ALLONES; }
|
||||
allzeros { return T_ALLZEROS; }
|
||||
none { return T_NONE; }
|
||||
sindex { return T_SINDEX; }
|
||||
A { return T_A; }
|
||||
|
||||
/* Instruction Formatting */
|
||||
PAD_PAGE { return T_PAD_PAGE; }
|
||||
BEGIN_CRITICAL { return T_BEGIN_CS; }
|
||||
END_CRITICAL { return T_END_CS; }
|
||||
SET_SRC_MODE { return T_SET_SRC_MODE; }
|
||||
SET_DST_MODE { return T_SET_DST_MODE; }
|
||||
|
||||
/* Opcodes */
|
||||
shl { return T_SHL; }
|
||||
shr { return T_SHR; }
|
||||
ror { return T_ROR; }
|
||||
rol { return T_ROL; }
|
||||
mvi { return T_MVI; }
|
||||
mov { return T_MOV; }
|
||||
clr { return T_CLR; }
|
||||
jmp { return T_JMP; }
|
||||
jc { return T_JC; }
|
||||
jnc { return T_JNC; }
|
||||
je { return T_JE; }
|
||||
jne { return T_JNE; }
|
||||
jz { return T_JZ; }
|
||||
jnz { return T_JNZ; }
|
||||
call { return T_CALL; }
|
||||
add { return T_ADD; }
|
||||
adc { return T_ADC; }
|
||||
bmov { return T_BMOV; }
|
||||
inc { return T_INC; }
|
||||
dec { return T_DEC; }
|
||||
stc { return T_STC; }
|
||||
clc { return T_CLC; }
|
||||
cmp { return T_CMP; }
|
||||
not { return T_NOT; }
|
||||
xor { return T_XOR; }
|
||||
test { return T_TEST;}
|
||||
and { return T_AND; }
|
||||
or { return T_OR; }
|
||||
ret { return T_RET; }
|
||||
nop { return T_NOP; }
|
||||
|
||||
/* ARP2 16bit extensions */
|
||||
/* or16 { return T_OR16; } */
|
||||
/* and16 { return T_AND16; }*/
|
||||
/* xor16 { return T_XOR16; }*/
|
||||
/* add16 { return T_ADD16; }*/
|
||||
/* adc16 { return T_ADC16; }*/
|
||||
/* mvi16 { return T_MVI16; }*/
|
||||
/* test16 { return T_TEST16; }*/
|
||||
/* cmp16 { return T_CMP16; }*/
|
||||
/* cmpxchg { return T_CMPXCHG; }*/
|
||||
|
||||
/* Allowed Symbols */
|
||||
\<\< { return T_EXPR_LSHIFT; }
|
||||
\>\> { return T_EXPR_RSHIFT; }
|
||||
[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
|
||||
|
||||
/* Number processing */
|
||||
0[0-7]* {
|
||||
yylval.value = strtol(yytext, NULL, 8);
|
||||
return T_NUMBER;
|
||||
}
|
||||
|
||||
0[xX][0-9a-fA-F]+ {
|
||||
yylval.value = strtoul(yytext + 2, NULL, 16);
|
||||
return T_NUMBER;
|
||||
}
|
||||
|
||||
[1-9][0-9]* {
|
||||
yylval.value = strtol(yytext, NULL, 10);
|
||||
return T_NUMBER;
|
||||
}
|
||||
/* Include Files */
|
||||
#include{SPACE} {
|
||||
BEGIN INCLUDE;
|
||||
quote_count = 0;
|
||||
return T_INCLUDE;
|
||||
}
|
||||
<INCLUDE>[<] { return yytext[0]; }
|
||||
<INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; }
|
||||
<INCLUDE>[\"] {
|
||||
if (quote_count != 0)
|
||||
BEGIN INITIAL;
|
||||
quote_count++;
|
||||
return yytext[0];
|
||||
}
|
||||
<INCLUDE>{PATH} {
|
||||
char *yptr;
|
||||
|
||||
yptr = yytext;
|
||||
string_buf_ptr = string_buf;
|
||||
while (*yptr)
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
yylval.str = string_buf;
|
||||
*string_buf_ptr = '\0';
|
||||
return T_PATH;
|
||||
}
|
||||
<INCLUDE>. { stop("Invalid include line", EX_DATAERR); }
|
||||
#define{SPACE} {
|
||||
BEGIN MACRODEF;
|
||||
return T_DEFINE;
|
||||
}
|
||||
<MACRODEF>{WORD}{SPACE} {
|
||||
char *yptr;
|
||||
|
||||
/* Strip space and return as a normal symbol */
|
||||
yptr = yytext;
|
||||
while (*yptr != ' ' && *yptr != '\t')
|
||||
yptr++;
|
||||
*yptr = '\0';
|
||||
yylval.sym = symtable_get(yytext);
|
||||
string_buf_ptr = string_buf;
|
||||
BEGIN MACROBODY;
|
||||
return T_SYMBOL;
|
||||
}
|
||||
<MACRODEF>{WORD}\( {
|
||||
/*
|
||||
* We store the symbol with its opening
|
||||
* parren so we can differentiate macros
|
||||
* that take args from macros with the
|
||||
* same name that do not take args as
|
||||
* is allowed in C.
|
||||
*/
|
||||
BEGIN MACROARGLIST;
|
||||
yylval.sym = symtable_get(yytext);
|
||||
unput('(');
|
||||
return T_SYMBOL;
|
||||
}
|
||||
<MACROARGLIST>{WORD} {
|
||||
yylval.str = yytext;
|
||||
return T_ARG;
|
||||
}
|
||||
<MACROARGLIST>{SPACE} ;
|
||||
<MACROARGLIST>[(,] {
|
||||
return yytext[0];
|
||||
}
|
||||
<MACROARGLIST>[)] {
|
||||
string_buf_ptr = string_buf;
|
||||
BEGIN MACROBODY;
|
||||
return ')';
|
||||
}
|
||||
<MACROARGLIST>. {
|
||||
snprintf(buf, sizeof(buf), "Invalid character "
|
||||
"'%c' in macro argument list",
|
||||
yytext[0]);
|
||||
stop(buf, EX_DATAERR);
|
||||
}
|
||||
<MACROCALLARGS>{SPACE} ;
|
||||
<MACROCALLARGS>\( {
|
||||
parren_count++;
|
||||
if (parren_count == 1)
|
||||
return ('(');
|
||||
*string_buf_ptr++ = '(';
|
||||
}
|
||||
<MACROCALLARGS>\) {
|
||||
parren_count--;
|
||||
if (parren_count == 0) {
|
||||
BEGIN INITIAL;
|
||||
return (')');
|
||||
}
|
||||
*string_buf_ptr++ = ')';
|
||||
}
|
||||
<MACROCALLARGS>{MCARG} {
|
||||
char *yptr;
|
||||
|
||||
yptr = yytext;
|
||||
while (*yptr)
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
}
|
||||
<MACROCALLARGS>\, {
|
||||
if (string_buf_ptr != string_buf) {
|
||||
/*
|
||||
* Return an argument and
|
||||
* rescan this comma so we
|
||||
* can return it as well.
|
||||
*/
|
||||
*string_buf_ptr = '\0';
|
||||
yylval.str = string_buf;
|
||||
string_buf_ptr = string_buf;
|
||||
unput(',');
|
||||
return T_ARG;
|
||||
}
|
||||
return ',';
|
||||
}
|
||||
<MACROBODY>\\\n {
|
||||
/* Eat escaped newlines. */
|
||||
++yylineno;
|
||||
}
|
||||
<MACROBODY>\r ;
|
||||
<MACROBODY>\n {
|
||||
/* Macros end on the first unescaped newline. */
|
||||
BEGIN INITIAL;
|
||||
*string_buf_ptr = '\0';
|
||||
yylval.str = string_buf;
|
||||
++yylineno;
|
||||
return T_MACROBODY;
|
||||
}
|
||||
<MACROBODY>{MBODY} {
|
||||
char *yptr;
|
||||
char c;
|
||||
|
||||
yptr = yytext;
|
||||
while (c = *yptr++) {
|
||||
/*
|
||||
* Strip carriage returns.
|
||||
*/
|
||||
if (c == '\r')
|
||||
continue;
|
||||
*string_buf_ptr++ = c;
|
||||
}
|
||||
}
|
||||
{WORD}\( {
|
||||
char *yptr;
|
||||
char *ycopy;
|
||||
|
||||
/* May be a symbol or a macro invocation. */
|
||||
yylval.sym = symtable_get(yytext);
|
||||
if (yylval.sym->type == MACRO) {
|
||||
YY_BUFFER_STATE old_state;
|
||||
YY_BUFFER_STATE temp_state;
|
||||
|
||||
ycopy = strdup(yytext);
|
||||
yptr = ycopy + yyleng;
|
||||
while (yptr > ycopy)
|
||||
unput(*--yptr);
|
||||
old_state = YY_CURRENT_BUFFER;
|
||||
temp_state =
|
||||
yy_create_buffer(stdin,
|
||||
YY_BUF_SIZE);
|
||||
yy_switch_to_buffer(temp_state);
|
||||
mm_switch_to_buffer(old_state);
|
||||
mmparse();
|
||||
mm_switch_to_buffer(temp_state);
|
||||
yy_switch_to_buffer(old_state);
|
||||
mm_delete_buffer(temp_state);
|
||||
expand_macro(yylval.sym);
|
||||
} else {
|
||||
if (yylval.sym->type == UNINITIALIZED) {
|
||||
/* Try without the '(' */
|
||||
symbol_delete(yylval.sym);
|
||||
yytext[yyleng-1] = '\0';
|
||||
yylval.sym =
|
||||
symtable_get(yytext);
|
||||
}
|
||||
unput('(');
|
||||
return T_SYMBOL;
|
||||
}
|
||||
}
|
||||
{WORD} {
|
||||
yylval.sym = symtable_get(yytext);
|
||||
if (yylval.sym->type == MACRO) {
|
||||
expand_macro(yylval.sym);
|
||||
} else {
|
||||
return T_SYMBOL;
|
||||
}
|
||||
}
|
||||
. {
|
||||
snprintf(buf, sizeof(buf), "Invalid character "
|
||||
"'%c'", yytext[0]);
|
||||
stop(buf, EX_DATAERR);
|
||||
}
|
||||
%%
|
||||
|
||||
typedef struct include {
|
||||
YY_BUFFER_STATE buffer;
|
||||
int lineno;
|
||||
char *filename;
|
||||
SLIST_ENTRY(include) links;
|
||||
}include_t;
|
||||
|
||||
SLIST_HEAD(, include) include_stack;
|
||||
|
||||
void
|
||||
include_file(char *file_name, include_type type)
|
||||
{
|
||||
FILE *newfile;
|
||||
include_t *include;
|
||||
|
||||
newfile = NULL;
|
||||
/* Try the current directory first */
|
||||
if (includes_search_curdir != 0 || type == SOURCE_FILE)
|
||||
newfile = fopen(file_name, "r");
|
||||
|
||||
if (newfile == NULL && type != SOURCE_FILE) {
|
||||
path_entry_t include_dir;
|
||||
for (include_dir = search_path.slh_first;
|
||||
include_dir != NULL;
|
||||
include_dir = include_dir->links.sle_next) {
|
||||
char fullname[PATH_MAX];
|
||||
|
||||
if ((include_dir->quoted_includes_only == TRUE)
|
||||
&& (type != QUOTED_INCLUDE))
|
||||
continue;
|
||||
|
||||
snprintf(fullname, sizeof(fullname),
|
||||
"%s/%s", include_dir->directory, file_name);
|
||||
|
||||
if ((newfile = fopen(fullname, "r")) != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newfile == NULL) {
|
||||
perror(file_name);
|
||||
stop("Unable to open input file", EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (type != SOURCE_FILE) {
|
||||
include = (include_t *)malloc(sizeof(include_t));
|
||||
if (include == NULL) {
|
||||
stop("Unable to allocate include stack entry",
|
||||
EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
include->buffer = YY_CURRENT_BUFFER;
|
||||
include->lineno = yylineno;
|
||||
include->filename = yyfilename;
|
||||
SLIST_INSERT_HEAD(&include_stack, include, links);
|
||||
}
|
||||
yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
|
||||
yylineno = 1;
|
||||
yyfilename = strdup(file_name);
|
||||
}
|
||||
|
||||
static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
|
||||
const char **next_match,
|
||||
struct macro_arg **match_marg, regmatch_t *match);
|
||||
|
||||
void
|
||||
expand_macro(struct symbol *macro_symbol)
|
||||
{
|
||||
struct macro_arg *marg;
|
||||
struct macro_arg *match_marg;
|
||||
const char *body_head;
|
||||
const char *body_pos;
|
||||
const char *next_match;
|
||||
|
||||
/*
|
||||
* Due to the nature of unput, we must work
|
||||
* backwards through the macro body performing
|
||||
* any expansions.
|
||||
*/
|
||||
body_head = macro_symbol->info.macroinfo->body;
|
||||
body_pos = body_head + strlen(body_head);
|
||||
while (body_pos > body_head) {
|
||||
regmatch_t match;
|
||||
|
||||
next_match = body_head;
|
||||
match_marg = NULL;
|
||||
next_substitution(macro_symbol, body_pos, &next_match,
|
||||
&match_marg, &match);
|
||||
|
||||
/* Put back everything up until the replacement. */
|
||||
while (body_pos > next_match)
|
||||
unput(*--body_pos);
|
||||
|
||||
/* Perform the replacement. */
|
||||
if (match_marg != NULL) {
|
||||
const char *strp;
|
||||
|
||||
next_match = match_marg->replacement_text;
|
||||
strp = next_match + strlen(next_match);
|
||||
while (strp > next_match)
|
||||
unput(*--strp);
|
||||
|
||||
/* Skip past the unexpanded macro arg. */
|
||||
body_pos -= match.rm_eo - match.rm_so;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup replacement text. */
|
||||
STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) {
|
||||
free(marg->replacement_text);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next substitution in the macro working backwards from
|
||||
* body_pos until the beginning of the macro buffer. next_match
|
||||
* should be initialized to the beginning of the macro buffer prior
|
||||
* to calling this routine.
|
||||
*/
|
||||
static void
|
||||
next_substitution(struct symbol *mac_symbol, const char *body_pos,
|
||||
const char **next_match, struct macro_arg **match_marg,
|
||||
regmatch_t *match)
|
||||
{
|
||||
regmatch_t matches[2];
|
||||
struct macro_arg *marg;
|
||||
const char *search_pos;
|
||||
int retval;
|
||||
|
||||
do {
|
||||
search_pos = *next_match;
|
||||
|
||||
STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
|
||||
|
||||
retval = regexec(&marg->arg_regex, search_pos, 2,
|
||||
matches, 0);
|
||||
if (retval == 0
|
||||
&& (matches[1].rm_eo + search_pos) <= body_pos
|
||||
&& (matches[1].rm_eo + search_pos) > *next_match) {
|
||||
*match = matches[1];
|
||||
*next_match = match->rm_eo + search_pos;
|
||||
*match_marg = marg;
|
||||
}
|
||||
}
|
||||
} while (search_pos != *next_match);
|
||||
}
|
||||
|
||||
int
|
||||
yywrap()
|
||||
{
|
||||
include_t *include;
|
||||
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
(void)fclose(yyin);
|
||||
if (yyfilename != NULL)
|
||||
free(yyfilename);
|
||||
yyfilename = NULL;
|
||||
include = include_stack.slh_first;
|
||||
if (include != NULL) {
|
||||
yy_switch_to_buffer(include->buffer);
|
||||
yylineno = include->lineno;
|
||||
yyfilename = include->filename;
|
||||
SLIST_REMOVE_HEAD(&include_stack, links);
|
||||
free(include);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
693
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
Normal file
693
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
Normal file
|
@ -0,0 +1,693 @@
|
|||
/*
|
||||
* Aic7xxx SCSI host adapter firmware assembler symbol table implementation
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* Copyright (c) 2002 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.c#24 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include "aicdb.h"
|
||||
#else
|
||||
#include <db.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "aicasm_symbol.h"
|
||||
#include "aicasm.h"
|
||||
|
||||
static DB *symtable;
|
||||
|
||||
symbol_t *
|
||||
symbol_create(char *name)
|
||||
{
|
||||
symbol_t *new_symbol;
|
||||
|
||||
new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
|
||||
if (new_symbol == NULL) {
|
||||
perror("Unable to create new symbol");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
memset(new_symbol, 0, sizeof(*new_symbol));
|
||||
new_symbol->name = strdup(name);
|
||||
if (new_symbol->name == NULL)
|
||||
stop("Unable to strdup symbol name", EX_SOFTWARE);
|
||||
new_symbol->type = UNINITIALIZED;
|
||||
new_symbol->count = 1;
|
||||
return (new_symbol);
|
||||
}
|
||||
|
||||
void
|
||||
symbol_delete(symbol_t *symbol)
|
||||
{
|
||||
if (symtable != NULL) {
|
||||
DBT key;
|
||||
|
||||
key.data = symbol->name;
|
||||
key.size = strlen(symbol->name);
|
||||
symtable->del(symtable, &key, /*flags*/0);
|
||||
}
|
||||
switch(symbol->type) {
|
||||
case SCBLOC:
|
||||
case SRAMLOC:
|
||||
case REGISTER:
|
||||
if (symbol->info.rinfo != NULL)
|
||||
free(symbol->info.rinfo);
|
||||
break;
|
||||
case ALIAS:
|
||||
if (symbol->info.ainfo != NULL)
|
||||
free(symbol->info.ainfo);
|
||||
break;
|
||||
case MASK:
|
||||
case FIELD:
|
||||
case ENUM:
|
||||
case ENUM_ENTRY:
|
||||
if (symbol->info.finfo != NULL) {
|
||||
symlist_free(&symbol->info.finfo->symrefs);
|
||||
free(symbol->info.finfo);
|
||||
}
|
||||
break;
|
||||
case DOWNLOAD_CONST:
|
||||
case CONST:
|
||||
if (symbol->info.cinfo != NULL)
|
||||
free(symbol->info.cinfo);
|
||||
break;
|
||||
case LABEL:
|
||||
if (symbol->info.linfo != NULL)
|
||||
free(symbol->info.linfo);
|
||||
break;
|
||||
case UNINITIALIZED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(symbol->name);
|
||||
free(symbol);
|
||||
}
|
||||
|
||||
void
|
||||
symtable_open()
|
||||
{
|
||||
symtable = dbopen(/*filename*/NULL,
|
||||
O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
|
||||
/*openinfo*/NULL);
|
||||
|
||||
if (symtable == NULL) {
|
||||
perror("Symbol table creation failed");
|
||||
exit(EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
symtable_close()
|
||||
{
|
||||
if (symtable != NULL) {
|
||||
DBT key;
|
||||
DBT data;
|
||||
|
||||
while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
|
||||
symbol_t *stored_ptr;
|
||||
|
||||
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
|
||||
symbol_delete(stored_ptr);
|
||||
}
|
||||
symtable->close(symtable);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The semantics of get is to return an uninitialized symbol entry
|
||||
* if a lookup fails.
|
||||
*/
|
||||
symbol_t *
|
||||
symtable_get(char *name)
|
||||
{
|
||||
symbol_t *stored_ptr;
|
||||
DBT key;
|
||||
DBT data;
|
||||
int retval;
|
||||
|
||||
key.data = (void *)name;
|
||||
key.size = strlen(name);
|
||||
|
||||
if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
|
||||
if (retval == -1) {
|
||||
perror("Symbol table get operation failed");
|
||||
exit(EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
} else if (retval == 1) {
|
||||
/* Symbol wasn't found, so create a new one */
|
||||
symbol_t *new_symbol;
|
||||
|
||||
new_symbol = symbol_create(name);
|
||||
data.data = &new_symbol;
|
||||
data.size = sizeof(new_symbol);
|
||||
if (symtable->put(symtable, &key, &data,
|
||||
/*flags*/0) !=0) {
|
||||
perror("Symtable put failed");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
return (new_symbol);
|
||||
} else {
|
||||
perror("Unexpected return value from db get routine");
|
||||
exit(EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
|
||||
stored_ptr->count++;
|
||||
data.data = &stored_ptr;
|
||||
if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
|
||||
perror("Symtable put failed");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
return (stored_ptr);
|
||||
}
|
||||
|
||||
symbol_node_t *
|
||||
symlist_search(symlist_t *symlist, char *symname)
|
||||
{
|
||||
symbol_node_t *curnode;
|
||||
|
||||
curnode = SLIST_FIRST(symlist);
|
||||
while(curnode != NULL) {
|
||||
if (strcmp(symname, curnode->symbol->name) == 0)
|
||||
break;
|
||||
curnode = SLIST_NEXT(curnode, links);
|
||||
}
|
||||
return (curnode);
|
||||
}
|
||||
|
||||
void
|
||||
symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
|
||||
{
|
||||
symbol_node_t *newnode;
|
||||
|
||||
newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
|
||||
if (newnode == NULL) {
|
||||
stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
newnode->symbol = symbol;
|
||||
if (how == SYMLIST_SORT) {
|
||||
symbol_node_t *curnode;
|
||||
int field;
|
||||
|
||||
field = FALSE;
|
||||
switch(symbol->type) {
|
||||
case REGISTER:
|
||||
case SCBLOC:
|
||||
case SRAMLOC:
|
||||
break;
|
||||
case FIELD:
|
||||
case MASK:
|
||||
case ENUM:
|
||||
case ENUM_ENTRY:
|
||||
field = TRUE;
|
||||
break;
|
||||
default:
|
||||
stop("symlist_add: Invalid symbol type for sorting",
|
||||
EX_SOFTWARE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
curnode = SLIST_FIRST(symlist);
|
||||
if (curnode == NULL
|
||||
|| (field
|
||||
&& (curnode->symbol->type > newnode->symbol->type
|
||||
|| (curnode->symbol->type == newnode->symbol->type
|
||||
&& (curnode->symbol->info.finfo->value >
|
||||
newnode->symbol->info.finfo->value))))
|
||||
|| (!field && (curnode->symbol->info.rinfo->address >
|
||||
newnode->symbol->info.rinfo->address))) {
|
||||
SLIST_INSERT_HEAD(symlist, newnode, links);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (SLIST_NEXT(curnode, links) == NULL) {
|
||||
SLIST_INSERT_AFTER(curnode, newnode,
|
||||
links);
|
||||
break;
|
||||
} else {
|
||||
symbol_t *cursymbol;
|
||||
|
||||
cursymbol = SLIST_NEXT(curnode, links)->symbol;
|
||||
if ((field
|
||||
&& (cursymbol->type > symbol->type
|
||||
|| (cursymbol->type == symbol->type
|
||||
&& (cursymbol->info.finfo->value >
|
||||
symbol->info.finfo->value))))
|
||||
|| (!field
|
||||
&& (cursymbol->info.rinfo->address >
|
||||
symbol->info.rinfo->address))) {
|
||||
SLIST_INSERT_AFTER(curnode, newnode,
|
||||
links);
|
||||
break;
|
||||
}
|
||||
}
|
||||
curnode = SLIST_NEXT(curnode, links);
|
||||
}
|
||||
} else {
|
||||
SLIST_INSERT_HEAD(symlist, newnode, links);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
symlist_free(symlist_t *symlist)
|
||||
{
|
||||
symbol_node_t *node1, *node2;
|
||||
|
||||
node1 = SLIST_FIRST(symlist);
|
||||
while (node1 != NULL) {
|
||||
node2 = SLIST_NEXT(node1, links);
|
||||
free(node1);
|
||||
node1 = node2;
|
||||
}
|
||||
SLIST_INIT(symlist);
|
||||
}
|
||||
|
||||
void
|
||||
symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
|
||||
symlist_t *symlist_src2)
|
||||
{
|
||||
symbol_node_t *node;
|
||||
|
||||
*symlist_dest = *symlist_src1;
|
||||
while((node = SLIST_FIRST(symlist_src2)) != NULL) {
|
||||
SLIST_REMOVE_HEAD(symlist_src2, links);
|
||||
SLIST_INSERT_HEAD(symlist_dest, node, links);
|
||||
}
|
||||
|
||||
/* These are now empty */
|
||||
SLIST_INIT(symlist_src1);
|
||||
SLIST_INIT(symlist_src2);
|
||||
}
|
||||
|
||||
void
|
||||
aic_print_file_prologue(FILE *ofile)
|
||||
{
|
||||
|
||||
if (ofile == NULL)
|
||||
return;
|
||||
|
||||
fprintf(ofile,
|
||||
"/*\n"
|
||||
" * DO NOT EDIT - This file is automatically generated\n"
|
||||
" * from the following source files:\n"
|
||||
" *\n"
|
||||
"%s */\n",
|
||||
versions);
|
||||
}
|
||||
|
||||
void
|
||||
aic_print_include(FILE *dfile, char *include_file)
|
||||
{
|
||||
|
||||
if (dfile == NULL)
|
||||
return;
|
||||
fprintf(dfile, "\n#include \"%s\"\n\n", include_file);
|
||||
}
|
||||
|
||||
void
|
||||
aic_print_reg_dump_types(FILE *ofile)
|
||||
{
|
||||
if (ofile == NULL)
|
||||
return;
|
||||
|
||||
fprintf(ofile,
|
||||
"typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
|
||||
"typedef struct %sreg_parse_entry {\n"
|
||||
" char *name;\n"
|
||||
" uint8_t value;\n"
|
||||
" uint8_t mask;\n"
|
||||
"} %sreg_parse_entry_t;\n"
|
||||
"\n",
|
||||
prefix, prefix, prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
|
||||
{
|
||||
if (dfile == NULL)
|
||||
return;
|
||||
|
||||
fprintf(dfile,
|
||||
"static const %sreg_parse_entry_t %s_parse_table[] = {\n",
|
||||
prefix,
|
||||
regnode->symbol->name);
|
||||
}
|
||||
|
||||
static void
|
||||
aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
|
||||
symbol_node_t *regnode, u_int num_entries)
|
||||
{
|
||||
char *lower_name;
|
||||
char *letter;
|
||||
|
||||
lower_name = strdup(regnode->symbol->name);
|
||||
if (lower_name == NULL)
|
||||
stop("Unable to strdup symbol name", EX_SOFTWARE);
|
||||
|
||||
for (letter = lower_name; *letter != '\0'; letter++)
|
||||
*letter = tolower(*letter);
|
||||
|
||||
if (dfile != NULL) {
|
||||
if (num_entries != 0)
|
||||
fprintf(dfile,
|
||||
"\n"
|
||||
"};\n"
|
||||
"\n");
|
||||
|
||||
fprintf(dfile,
|
||||
"int\n"
|
||||
"%s%s_print(u_int regvalue, u_int *cur_col, u_int wrap)\n"
|
||||
"{\n"
|
||||
" return (%sprint_register(%s%s, %d, \"%s\",\n"
|
||||
" 0x%02x, regvalue, cur_col, wrap));\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
prefix,
|
||||
lower_name,
|
||||
prefix,
|
||||
num_entries != 0 ? regnode->symbol->name : "NULL",
|
||||
num_entries != 0 ? "_parse_table" : "",
|
||||
num_entries,
|
||||
regnode->symbol->name,
|
||||
regnode->symbol->info.rinfo->address);
|
||||
}
|
||||
|
||||
fprintf(ofile,
|
||||
"#if AIC_DEBUG_REGISTERS\n"
|
||||
"%sreg_print_t %s%s_print;\n"
|
||||
"#else\n"
|
||||
"#define %s%s_print(regvalue, cur_col, wrap) \\\n"
|
||||
" %sprint_register(NULL, 0, \"%s\", 0x%02x, regvalue, cur_col, wrap)\n"
|
||||
"#endif\n"
|
||||
"\n",
|
||||
prefix,
|
||||
prefix,
|
||||
lower_name,
|
||||
prefix,
|
||||
lower_name,
|
||||
prefix,
|
||||
regnode->symbol->name,
|
||||
regnode->symbol->info.rinfo->address);
|
||||
}
|
||||
|
||||
static void
|
||||
aic_print_reg_dump_entry(FILE *dfile, symbol_node_t *curnode)
|
||||
{
|
||||
int num_tabs;
|
||||
|
||||
if (dfile == NULL)
|
||||
return;
|
||||
|
||||
fprintf(dfile,
|
||||
" { \"%s\",",
|
||||
curnode->symbol->name);
|
||||
|
||||
num_tabs = 3 - (strlen(curnode->symbol->name) + 5) / 8;
|
||||
|
||||
while (num_tabs-- > 0)
|
||||
fputc('\t', dfile);
|
||||
fprintf(dfile, "0x%02x, 0x%02x }",
|
||||
curnode->symbol->info.finfo->value,
|
||||
curnode->symbol->info.finfo->mask);
|
||||
}
|
||||
|
||||
void
|
||||
symtable_dump(FILE *ofile, FILE *dfile)
|
||||
{
|
||||
/*
|
||||
* Sort the registers by address with a simple insertion sort.
|
||||
* Put bitmasks next to the first register that defines them.
|
||||
* Put constants at the end.
|
||||
*/
|
||||
symlist_t registers;
|
||||
symlist_t masks;
|
||||
symlist_t constants;
|
||||
symlist_t download_constants;
|
||||
symlist_t aliases;
|
||||
symlist_t exported_labels;
|
||||
symbol_node_t *curnode;
|
||||
symbol_node_t *regnode;
|
||||
DBT key;
|
||||
DBT data;
|
||||
int flag;
|
||||
int reg_count = 0, reg_used = 0;
|
||||
u_int i;
|
||||
|
||||
if (symtable == NULL)
|
||||
return;
|
||||
|
||||
SLIST_INIT(®isters);
|
||||
SLIST_INIT(&masks);
|
||||
SLIST_INIT(&constants);
|
||||
SLIST_INIT(&download_constants);
|
||||
SLIST_INIT(&aliases);
|
||||
SLIST_INIT(&exported_labels);
|
||||
flag = R_FIRST;
|
||||
while (symtable->seq(symtable, &key, &data, flag) == 0) {
|
||||
symbol_t *cursym;
|
||||
|
||||
memcpy(&cursym, data.data, sizeof(cursym));
|
||||
switch(cursym->type) {
|
||||
case REGISTER:
|
||||
case SCBLOC:
|
||||
case SRAMLOC:
|
||||
symlist_add(®isters, cursym, SYMLIST_SORT);
|
||||
break;
|
||||
case MASK:
|
||||
case FIELD:
|
||||
case ENUM:
|
||||
case ENUM_ENTRY:
|
||||
symlist_add(&masks, cursym, SYMLIST_SORT);
|
||||
break;
|
||||
case CONST:
|
||||
symlist_add(&constants, cursym,
|
||||
SYMLIST_INSERT_HEAD);
|
||||
break;
|
||||
case DOWNLOAD_CONST:
|
||||
symlist_add(&download_constants, cursym,
|
||||
SYMLIST_INSERT_HEAD);
|
||||
break;
|
||||
case ALIAS:
|
||||
symlist_add(&aliases, cursym,
|
||||
SYMLIST_INSERT_HEAD);
|
||||
break;
|
||||
case LABEL:
|
||||
if (cursym->info.linfo->exported == 0)
|
||||
break;
|
||||
symlist_add(&exported_labels, cursym,
|
||||
SYMLIST_INSERT_HEAD);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
flag = R_NEXT;
|
||||
}
|
||||
|
||||
/* Register dianostic functions/declarations first. */
|
||||
aic_print_file_prologue(ofile);
|
||||
aic_print_reg_dump_types(ofile);
|
||||
aic_print_file_prologue(dfile);
|
||||
aic_print_include(dfile, stock_include_file);
|
||||
SLIST_FOREACH(curnode, ®isters, links) {
|
||||
|
||||
if (curnode->symbol->dont_generate_debug_code)
|
||||
continue;
|
||||
|
||||
switch(curnode->symbol->type) {
|
||||
case REGISTER:
|
||||
case SCBLOC:
|
||||
case SRAMLOC:
|
||||
{
|
||||
symlist_t *fields;
|
||||
symbol_node_t *fieldnode;
|
||||
int num_entries;
|
||||
|
||||
num_entries = 0;
|
||||
reg_count++;
|
||||
if (curnode->symbol->count == 1)
|
||||
break;
|
||||
fields = &curnode->symbol->info.rinfo->fields;
|
||||
SLIST_FOREACH(fieldnode, fields, links) {
|
||||
if (num_entries == 0)
|
||||
aic_print_reg_dump_start(dfile,
|
||||
curnode);
|
||||
else if (dfile != NULL)
|
||||
fputs(",\n", dfile);
|
||||
num_entries++;
|
||||
aic_print_reg_dump_entry(dfile, fieldnode);
|
||||
}
|
||||
aic_print_reg_dump_end(ofile, dfile,
|
||||
curnode, num_entries);
|
||||
reg_used++;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
|
||||
reg_used, reg_count);
|
||||
|
||||
/* Fold in the masks and bits */
|
||||
while (SLIST_FIRST(&masks) != NULL) {
|
||||
char *regname;
|
||||
|
||||
curnode = SLIST_FIRST(&masks);
|
||||
SLIST_REMOVE_HEAD(&masks, links);
|
||||
|
||||
regnode = SLIST_FIRST(&curnode->symbol->info.finfo->symrefs);
|
||||
regname = regnode->symbol->name;
|
||||
regnode = symlist_search(®isters, regname);
|
||||
SLIST_INSERT_AFTER(regnode, curnode, links);
|
||||
}
|
||||
|
||||
/* Add the aliases */
|
||||
while (SLIST_FIRST(&aliases) != NULL) {
|
||||
char *regname;
|
||||
|
||||
curnode = SLIST_FIRST(&aliases);
|
||||
SLIST_REMOVE_HEAD(&aliases, links);
|
||||
|
||||
regname = curnode->symbol->info.ainfo->parent->name;
|
||||
regnode = symlist_search(®isters, regname);
|
||||
SLIST_INSERT_AFTER(regnode, curnode, links);
|
||||
}
|
||||
|
||||
/* Output generated #defines. */
|
||||
while (SLIST_FIRST(®isters) != NULL) {
|
||||
symbol_node_t *curnode;
|
||||
u_int value;
|
||||
char *tab_str;
|
||||
char *tab_str2;
|
||||
|
||||
curnode = SLIST_FIRST(®isters);
|
||||
SLIST_REMOVE_HEAD(®isters, links);
|
||||
switch(curnode->symbol->type) {
|
||||
case REGISTER:
|
||||
case SCBLOC:
|
||||
case SRAMLOC:
|
||||
fprintf(ofile, "\n");
|
||||
value = curnode->symbol->info.rinfo->address;
|
||||
tab_str = "\t";
|
||||
tab_str2 = "\t\t";
|
||||
break;
|
||||
case ALIAS:
|
||||
{
|
||||
symbol_t *parent;
|
||||
|
||||
parent = curnode->symbol->info.ainfo->parent;
|
||||
value = parent->info.rinfo->address;
|
||||
tab_str = "\t";
|
||||
tab_str2 = "\t\t";
|
||||
break;
|
||||
}
|
||||
case MASK:
|
||||
case FIELD:
|
||||
case ENUM:
|
||||
case ENUM_ENTRY:
|
||||
value = curnode->symbol->info.finfo->value;
|
||||
tab_str = "\t\t";
|
||||
tab_str2 = "\t";
|
||||
break;
|
||||
default:
|
||||
value = 0; /* Quiet compiler */
|
||||
tab_str = NULL;
|
||||
tab_str2 = NULL;
|
||||
stop("symtable_dump: Invalid symbol type "
|
||||
"encountered", EX_SOFTWARE);
|
||||
break;
|
||||
}
|
||||
fprintf(ofile, "#define%s%-16s%s0x%02x\n",
|
||||
tab_str, curnode->symbol->name, tab_str2,
|
||||
value);
|
||||
free(curnode);
|
||||
}
|
||||
fprintf(ofile, "\n\n");
|
||||
|
||||
while (SLIST_FIRST(&constants) != NULL) {
|
||||
symbol_node_t *curnode;
|
||||
|
||||
curnode = SLIST_FIRST(&constants);
|
||||
SLIST_REMOVE_HEAD(&constants, links);
|
||||
fprintf(ofile, "#define\t%-8s\t0x%02x\n",
|
||||
curnode->symbol->name,
|
||||
curnode->symbol->info.cinfo->value);
|
||||
free(curnode);
|
||||
}
|
||||
|
||||
fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
|
||||
|
||||
for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
|
||||
symbol_node_t *curnode;
|
||||
|
||||
curnode = SLIST_FIRST(&download_constants);
|
||||
SLIST_REMOVE_HEAD(&download_constants, links);
|
||||
fprintf(ofile, "#define\t%-8s\t0x%02x\n",
|
||||
curnode->symbol->name,
|
||||
curnode->symbol->info.cinfo->value);
|
||||
free(curnode);
|
||||
}
|
||||
fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i);
|
||||
|
||||
fprintf(ofile, "\n\n/* Exported Labels */\n");
|
||||
|
||||
while (SLIST_FIRST(&exported_labels) != NULL) {
|
||||
symbol_node_t *curnode;
|
||||
|
||||
curnode = SLIST_FIRST(&exported_labels);
|
||||
SLIST_REMOVE_HEAD(&exported_labels, links);
|
||||
fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n",
|
||||
curnode->symbol->name,
|
||||
curnode->symbol->info.linfo->address);
|
||||
free(curnode);
|
||||
}
|
||||
}
|
||||
|
209
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
Normal file
209
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Aic7xxx SCSI host adapter firmware assembler symbol table definitions
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* Copyright (c) 2002 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.h#17 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#include "../queue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
UNINITIALIZED,
|
||||
REGISTER,
|
||||
ALIAS,
|
||||
SCBLOC,
|
||||
SRAMLOC,
|
||||
ENUM_ENTRY,
|
||||
FIELD,
|
||||
MASK,
|
||||
ENUM,
|
||||
CONST,
|
||||
DOWNLOAD_CONST,
|
||||
LABEL,
|
||||
CONDITIONAL,
|
||||
MACRO
|
||||
} symtype;
|
||||
|
||||
typedef enum {
|
||||
RO = 0x01,
|
||||
WO = 0x02,
|
||||
RW = 0x03
|
||||
}amode_t;
|
||||
|
||||
typedef SLIST_HEAD(symlist, symbol_node) symlist_t;
|
||||
|
||||
struct reg_info {
|
||||
u_int address;
|
||||
int size;
|
||||
amode_t mode;
|
||||
symlist_t fields;
|
||||
uint8_t valid_bitmask;
|
||||
uint8_t modes;
|
||||
int typecheck_masks;
|
||||
};
|
||||
|
||||
struct field_info {
|
||||
symlist_t symrefs;
|
||||
uint8_t value;
|
||||
uint8_t mask;
|
||||
};
|
||||
|
||||
struct const_info {
|
||||
u_int value;
|
||||
int define;
|
||||
};
|
||||
|
||||
struct alias_info {
|
||||
struct symbol *parent;
|
||||
};
|
||||
|
||||
struct label_info {
|
||||
int address;
|
||||
int exported;
|
||||
};
|
||||
|
||||
struct cond_info {
|
||||
int func_num;
|
||||
};
|
||||
|
||||
struct macro_arg {
|
||||
STAILQ_ENTRY(macro_arg) links;
|
||||
regex_t arg_regex;
|
||||
char *replacement_text;
|
||||
};
|
||||
STAILQ_HEAD(macro_arg_list, macro_arg) args;
|
||||
|
||||
struct macro_info {
|
||||
struct macro_arg_list args;
|
||||
int narg;
|
||||
const char* body;
|
||||
};
|
||||
|
||||
typedef struct expression_info {
|
||||
symlist_t referenced_syms;
|
||||
int value;
|
||||
} expression_t;
|
||||
|
||||
typedef struct symbol {
|
||||
char *name;
|
||||
symtype type;
|
||||
int count;
|
||||
union {
|
||||
struct reg_info *rinfo;
|
||||
struct field_info *finfo;
|
||||
struct const_info *cinfo;
|
||||
struct alias_info *ainfo;
|
||||
struct label_info *linfo;
|
||||
struct cond_info *condinfo;
|
||||
struct macro_info *macroinfo;
|
||||
} info;
|
||||
int dont_generate_debug_code;
|
||||
} symbol_t;
|
||||
|
||||
typedef struct symbol_ref {
|
||||
symbol_t *symbol;
|
||||
int offset;
|
||||
} symbol_ref_t;
|
||||
|
||||
typedef struct symbol_node {
|
||||
SLIST_ENTRY(symbol_node) links;
|
||||
symbol_t *symbol;
|
||||
} symbol_node_t;
|
||||
|
||||
typedef struct critical_section {
|
||||
TAILQ_ENTRY(critical_section) links;
|
||||
int begin_addr;
|
||||
int end_addr;
|
||||
} critical_section_t;
|
||||
|
||||
typedef enum {
|
||||
SCOPE_ROOT,
|
||||
SCOPE_IF,
|
||||
SCOPE_ELSE_IF,
|
||||
SCOPE_ELSE
|
||||
} scope_type;
|
||||
|
||||
typedef struct patch_info {
|
||||
int skip_patch;
|
||||
int skip_instr;
|
||||
} patch_info_t;
|
||||
|
||||
typedef struct scope {
|
||||
SLIST_ENTRY(scope) scope_stack_links;
|
||||
TAILQ_ENTRY(scope) scope_links;
|
||||
TAILQ_HEAD(, scope) inner_scope;
|
||||
scope_type type;
|
||||
int inner_scope_patches;
|
||||
int begin_addr;
|
||||
int end_addr;
|
||||
patch_info_t patches[2];
|
||||
int func_num;
|
||||
} scope_t;
|
||||
|
||||
TAILQ_HEAD(cs_tailq, critical_section);
|
||||
SLIST_HEAD(scope_list, scope);
|
||||
TAILQ_HEAD(scope_tailq, scope);
|
||||
|
||||
void symbol_delete(symbol_t *symbol);
|
||||
|
||||
void symtable_open(void);
|
||||
|
||||
void symtable_close(void);
|
||||
|
||||
symbol_t *
|
||||
symtable_get(char *name);
|
||||
|
||||
symbol_node_t *
|
||||
symlist_search(symlist_t *symlist, char *symname);
|
||||
|
||||
void
|
||||
symlist_add(symlist_t *symlist, symbol_t *symbol, int how);
|
||||
#define SYMLIST_INSERT_HEAD 0x00
|
||||
#define SYMLIST_SORT 0x01
|
||||
|
||||
void symlist_free(symlist_t *symlist);
|
||||
|
||||
void symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
|
||||
symlist_t *symlist_src2);
|
||||
void symtable_dump(FILE *ofile, FILE *dfile);
|
34
drivers/scsi/aic7xxx/aiclib.c
Normal file
34
drivers/scsi/aic7xxx/aiclib.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Implementation of Utility functions for all SCSI device types.
|
||||
*
|
||||
* Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
|
||||
* Copyright (c) 1997, 1998 Kenneth D. Merry.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.38 2002/09/23 04:56:35 mjacob Exp $
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "aiclib.h"
|
||||
|
195
drivers/scsi/aic7xxx/aiclib.h
Normal file
195
drivers/scsi/aic7xxx/aiclib.h
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Largely written by Julian Elischer (julian@tfs.com)
|
||||
* for TRW Financial Systems.
|
||||
*
|
||||
* TRW Financial Systems, in accordance with their agreement with Carnegie
|
||||
* Mellon University, makes this software available to CMU to distribute
|
||||
* or use in any manner that they see fit as long as this message is kept with
|
||||
* the software. For this reason TFS also grants any other persons or
|
||||
* organisations permission to use or modify this software.
|
||||
*
|
||||
* TFS supplies this software to be publicly redistributed
|
||||
* on the understanding that TFS is not responsible for the correct
|
||||
* functioning of this software in any circumstances.
|
||||
*
|
||||
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
|
||||
*
|
||||
* $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.21 2002/10/08 17:12:44 ken Exp $
|
||||
*
|
||||
* Copyright (c) 2003 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _AICLIB_H
|
||||
#define _AICLIB_H
|
||||
|
||||
struct scsi_sense
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t byte2;
|
||||
uint8_t unused[2];
|
||||
uint8_t length;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
#define SCSI_REV_0 0
|
||||
#define SCSI_REV_CCS 1
|
||||
#define SCSI_REV_2 2
|
||||
#define SCSI_REV_SPC 3
|
||||
#define SCSI_REV_SPC2 4
|
||||
|
||||
struct scsi_sense_data
|
||||
{
|
||||
uint8_t error_code;
|
||||
#define SSD_ERRCODE 0x7F
|
||||
#define SSD_CURRENT_ERROR 0x70
|
||||
#define SSD_DEFERRED_ERROR 0x71
|
||||
#define SSD_ERRCODE_VALID 0x80
|
||||
uint8_t segment;
|
||||
uint8_t flags;
|
||||
#define SSD_KEY 0x0F
|
||||
#define SSD_KEY_NO_SENSE 0x00
|
||||
#define SSD_KEY_RECOVERED_ERROR 0x01
|
||||
#define SSD_KEY_NOT_READY 0x02
|
||||
#define SSD_KEY_MEDIUM_ERROR 0x03
|
||||
#define SSD_KEY_HARDWARE_ERROR 0x04
|
||||
#define SSD_KEY_ILLEGAL_REQUEST 0x05
|
||||
#define SSD_KEY_UNIT_ATTENTION 0x06
|
||||
#define SSD_KEY_DATA_PROTECT 0x07
|
||||
#define SSD_KEY_BLANK_CHECK 0x08
|
||||
#define SSD_KEY_Vendor_Specific 0x09
|
||||
#define SSD_KEY_COPY_ABORTED 0x0a
|
||||
#define SSD_KEY_ABORTED_COMMAND 0x0b
|
||||
#define SSD_KEY_EQUAL 0x0c
|
||||
#define SSD_KEY_VOLUME_OVERFLOW 0x0d
|
||||
#define SSD_KEY_MISCOMPARE 0x0e
|
||||
#define SSD_KEY_RESERVED 0x0f
|
||||
#define SSD_ILI 0x20
|
||||
#define SSD_EOM 0x40
|
||||
#define SSD_FILEMARK 0x80
|
||||
uint8_t info[4];
|
||||
uint8_t extra_len;
|
||||
uint8_t cmd_spec_info[4];
|
||||
uint8_t add_sense_code;
|
||||
uint8_t add_sense_code_qual;
|
||||
uint8_t fru;
|
||||
uint8_t sense_key_spec[3];
|
||||
#define SSD_SCS_VALID 0x80
|
||||
#define SSD_FIELDPTR_CMD 0x40
|
||||
#define SSD_BITPTR_VALID 0x08
|
||||
#define SSD_BITPTR_VALUE 0x07
|
||||
#define SSD_MIN_SIZE 18
|
||||
uint8_t extra_bytes[14];
|
||||
#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
|
||||
};
|
||||
|
||||
/*
|
||||
* Status Byte
|
||||
*/
|
||||
#define SCSI_STATUS_OK 0x00
|
||||
#define SCSI_STATUS_CHECK_COND 0x02
|
||||
#define SCSI_STATUS_COND_MET 0x04
|
||||
#define SCSI_STATUS_BUSY 0x08
|
||||
#define SCSI_STATUS_INTERMED 0x10
|
||||
#define SCSI_STATUS_INTERMED_COND_MET 0x14
|
||||
#define SCSI_STATUS_RESERV_CONFLICT 0x18
|
||||
#define SCSI_STATUS_CMD_TERMINATED 0x22 /* Obsolete in SAM-2 */
|
||||
#define SCSI_STATUS_QUEUE_FULL 0x28
|
||||
#define SCSI_STATUS_ACA_ACTIVE 0x30
|
||||
#define SCSI_STATUS_TASK_ABORTED 0x40
|
||||
|
||||
/************************* Large Disk Handling ********************************/
|
||||
static inline int
|
||||
aic_sector_div(sector_t capacity, int heads, int sectors)
|
||||
{
|
||||
/* ugly, ugly sector_div calling convention.. */
|
||||
sector_div(capacity, (heads * sectors));
|
||||
return (int)capacity;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
scsi_4btoul(uint8_t *bytes)
|
||||
{
|
||||
uint32_t rv;
|
||||
|
||||
rv = (bytes[0] << 24) |
|
||||
(bytes[1] << 16) |
|
||||
(bytes[2] << 8) |
|
||||
bytes[3];
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* Macros for generating the elements of the PCI ID tables. */
|
||||
|
||||
#define GETID(v, s) (unsigned)(((v) >> (s)) & 0xFFFF ?: PCI_ANY_ID)
|
||||
|
||||
#define ID_C(x, c) \
|
||||
{ \
|
||||
GETID(x,32), GETID(x,48), GETID(x,0), GETID(x,16), \
|
||||
(c) << 8, 0xFFFF00, 0 \
|
||||
}
|
||||
|
||||
#define ID2C(x) \
|
||||
ID_C(x, PCI_CLASS_STORAGE_SCSI), \
|
||||
ID_C(x, PCI_CLASS_STORAGE_RAID)
|
||||
|
||||
#define IDIROC(x) ((x) | ~ID_ALL_IROC_MASK)
|
||||
|
||||
/* Generate IDs for all 16 possibilites.
|
||||
* The argument has already masked out
|
||||
* the 4 least significant bits of the device id.
|
||||
* (e.g., mask: ID_9005_GENERIC_MASK).
|
||||
*/
|
||||
#define ID16(x) \
|
||||
ID(x), \
|
||||
ID((x) | 0x0001000000000000ull), \
|
||||
ID((x) | 0x0002000000000000ull), \
|
||||
ID((x) | 0x0003000000000000ull), \
|
||||
ID((x) | 0x0004000000000000ull), \
|
||||
ID((x) | 0x0005000000000000ull), \
|
||||
ID((x) | 0x0006000000000000ull), \
|
||||
ID((x) | 0x0007000000000000ull), \
|
||||
ID((x) | 0x0008000000000000ull), \
|
||||
ID((x) | 0x0009000000000000ull), \
|
||||
ID((x) | 0x000A000000000000ull), \
|
||||
ID((x) | 0x000B000000000000ull), \
|
||||
ID((x) | 0x000C000000000000ull), \
|
||||
ID((x) | 0x000D000000000000ull), \
|
||||
ID((x) | 0x000E000000000000ull), \
|
||||
ID((x) | 0x000F000000000000ull)
|
||||
|
||||
#endif /*_AICLIB_H */
|
111
drivers/scsi/aic7xxx/cam.h
Normal file
111
drivers/scsi/aic7xxx/cam.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Data structures and definitions for the CAM system.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* Copyright (c) 2000 Adaptec Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL").
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/cam.h#15 $
|
||||
*/
|
||||
|
||||
#ifndef _AIC7XXX_CAM_H
|
||||
#define _AIC7XXX_CAM_H 1
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define CAM_BUS_WILDCARD ((u_int)~0)
|
||||
#define CAM_TARGET_WILDCARD ((u_int)~0)
|
||||
#define CAM_LUN_WILDCARD ((u_int)~0)
|
||||
|
||||
/* CAM Status field values */
|
||||
typedef enum {
|
||||
CAM_REQ_INPROG, /* CCB request is in progress */
|
||||
CAM_REQ_CMP, /* CCB request completed without error */
|
||||
CAM_REQ_ABORTED, /* CCB request aborted by the host */
|
||||
CAM_UA_ABORT, /* Unable to abort CCB request */
|
||||
CAM_REQ_CMP_ERR, /* CCB request completed with an error */
|
||||
CAM_BUSY, /* CAM subsystem is busy */
|
||||
CAM_REQ_INVALID, /* CCB request was invalid */
|
||||
CAM_PATH_INVALID, /* Supplied Path ID is invalid */
|
||||
CAM_SEL_TIMEOUT, /* Target Selection Timeout */
|
||||
CAM_CMD_TIMEOUT, /* Command timeout */
|
||||
CAM_SCSI_STATUS_ERROR, /* SCSI error, look at error code in CCB */
|
||||
CAM_SCSI_BUS_RESET, /* SCSI Bus Reset Sent/Received */
|
||||
CAM_UNCOR_PARITY, /* Uncorrectable parity error occurred */
|
||||
CAM_AUTOSENSE_FAIL, /* Autosense: request sense cmd fail */
|
||||
CAM_NO_HBA, /* No HBA Detected Error */
|
||||
CAM_DATA_RUN_ERR, /* Data Overrun error */
|
||||
CAM_UNEXP_BUSFREE, /* Unexpected Bus Free */
|
||||
CAM_SEQUENCE_FAIL, /* Protocol Violation */
|
||||
CAM_CCB_LEN_ERR, /* CCB length supplied is inadequate */
|
||||
CAM_PROVIDE_FAIL, /* Unable to provide requested capability */
|
||||
CAM_BDR_SENT, /* A SCSI BDR msg was sent to target */
|
||||
CAM_REQ_TERMIO, /* CCB request terminated by the host */
|
||||
CAM_UNREC_HBA_ERROR, /* Unrecoverable Host Bus Adapter Error */
|
||||
CAM_REQ_TOO_BIG, /* The request was too large for this host */
|
||||
CAM_UA_TERMIO, /* Unable to terminate I/O CCB request */
|
||||
CAM_MSG_REJECT_REC, /* Message Reject Received */
|
||||
CAM_DEV_NOT_THERE, /* SCSI Device Not Installed/there */
|
||||
CAM_RESRC_UNAVAIL, /* Resource Unavailable */
|
||||
/*
|
||||
* This request should be requeued to preserve
|
||||
* transaction ordering. This typically occurs
|
||||
* when the SIM recognizes an error that should
|
||||
* freeze the queue and must place additional
|
||||
* requests for the target at the sim level
|
||||
* back into the XPT queue.
|
||||
*/
|
||||
CAM_REQUEUE_REQ,
|
||||
CAM_DEV_QFRZN = 0x40,
|
||||
|
||||
CAM_STATUS_MASK = 0x3F
|
||||
} cam_status;
|
||||
|
||||
/*
|
||||
* Definitions for the asynchronous callback CCB fields.
|
||||
*/
|
||||
typedef enum {
|
||||
AC_GETDEV_CHANGED = 0x800,/* Getdev info might have changed */
|
||||
AC_INQ_CHANGED = 0x400,/* Inquiry info might have changed */
|
||||
AC_TRANSFER_NEG = 0x200,/* New transfer settings in effect */
|
||||
AC_LOST_DEVICE = 0x100,/* A device went away */
|
||||
AC_FOUND_DEVICE = 0x080,/* A new device was found */
|
||||
AC_PATH_DEREGISTERED = 0x040,/* A path has de-registered */
|
||||
AC_PATH_REGISTERED = 0x020,/* A new path has been registered */
|
||||
AC_SENT_BDR = 0x010,/* A BDR message was sent to target */
|
||||
AC_SCSI_AEN = 0x008,/* A SCSI AEN has been received */
|
||||
AC_UNSOL_RESEL = 0x002,/* Unsolicited reselection occurred */
|
||||
AC_BUS_RESET = 0x001 /* A SCSI bus reset occurred */
|
||||
} ac_code;
|
||||
|
||||
typedef enum {
|
||||
CAM_DIR_IN = DMA_FROM_DEVICE,
|
||||
CAM_DIR_OUT = DMA_TO_DEVICE,
|
||||
CAM_DIR_NONE = DMA_NONE,
|
||||
} ccb_flags;
|
||||
|
||||
#endif /* _AIC7XXX_CAM_H */
|
501
drivers/scsi/aic7xxx/queue.h
Normal file
501
drivers/scsi/aic7xxx/queue.h
Normal file
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD: src/sys/sys/queue.h,v 1.38 2000/05/26 02:06:56 jake Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists, tail queues, and circular queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ CIRCLEQ
|
||||
* _HEAD + + + + +
|
||||
* _HEAD_INITIALIZER + + + + +
|
||||
* _ENTRY + + + + +
|
||||
* _INIT + + + + +
|
||||
* _EMPTY + + + + +
|
||||
* _FIRST + + + + +
|
||||
* _NEXT + + + + +
|
||||
* _PREV - - - + +
|
||||
* _LAST - - + + +
|
||||
* _FOREACH + + + + +
|
||||
* _FOREACH_REVERSE - - - + +
|
||||
* _INSERT_HEAD + + + + +
|
||||
* _INSERT_BEFORE - + - + +
|
||||
* _INSERT_AFTER + + + + +
|
||||
* _INSERT_TAIL - - + + +
|
||||
* _REMOVE_HEAD + - + - -
|
||||
* _REMOVE + + + + +
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
STAILQ_LAST((head)) = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head) (*(head)->stqh_last)
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD(head, field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Circular queue declarations.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||
{ (void *)&(head), (void *)&(head) }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
|
||||
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
|
||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = CIRCLEQ_FIRST((head)); \
|
||||
(var) != (void *)(head); \
|
||||
(var) = CIRCLEQ_NEXT((var), field))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||
for ((var) = CIRCLEQ_LAST((head)); \
|
||||
(var) != (void *)(head); \
|
||||
(var) = CIRCLEQ_PREV((var), field))
|
||||
|
||||
#define CIRCLEQ_INIT(head) do { \
|
||||
CIRCLEQ_FIRST((head)) = (void *)(head); \
|
||||
CIRCLEQ_LAST((head)) = (void *)(head); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
|
||||
CIRCLEQ_PREV((elm), field) = (listelm); \
|
||||
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
|
||||
CIRCLEQ_NEXT((listelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = (listelm); \
|
||||
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
|
||||
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
|
||||
CIRCLEQ_PREV((listelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
|
||||
CIRCLEQ_PREV((elm), field) = (void *)(head); \
|
||||
if (CIRCLEQ_LAST((head)) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = (void *)(head); \
|
||||
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
|
||||
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
|
||||
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
|
||||
|
||||
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
|
||||
CIRCLEQ_PREV((elm), field); \
|
||||
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
|
||||
CIRCLEQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
39
drivers/scsi/aic7xxx/scsi_iu.h
Normal file
39
drivers/scsi/aic7xxx/scsi_iu.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This file is in the public domain.
|
||||
*/
|
||||
#ifndef _SCSI_SCSI_IU_H
|
||||
#define _SCSI_SCSI_IU_H 1
|
||||
|
||||
struct scsi_status_iu_header
|
||||
{
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t flags;
|
||||
#define SIU_SNSVALID 0x2
|
||||
#define SIU_RSPVALID 0x1
|
||||
u_int8_t status;
|
||||
u_int8_t sense_length[4];
|
||||
u_int8_t pkt_failures_length[4];
|
||||
u_int8_t pkt_failures[1];
|
||||
};
|
||||
|
||||
#define SIU_PKTFAIL_OFFSET(siu) 12
|
||||
#define SIU_PKTFAIL_CODE(siu) (scsi_4btoul((siu)->pkt_failures) & 0xFF)
|
||||
#define SIU_PFC_NONE 0
|
||||
#define SIU_PFC_CIU_FIELDS_INVALID 2
|
||||
#define SIU_PFC_TMF_NOT_SUPPORTED 4
|
||||
#define SIU_PFC_TMF_FAILED 5
|
||||
#define SIU_PFC_INVALID_TYPE_CODE 6
|
||||
#define SIU_PFC_ILLEGAL_REQUEST 7
|
||||
#define SIU_SENSE_OFFSET(siu) \
|
||||
(12 + (((siu)->flags & SIU_RSPVALID) \
|
||||
? scsi_4btoul((siu)->pkt_failures_length) \
|
||||
: 0))
|
||||
|
||||
#define SIU_TASKMGMT_NONE 0x00
|
||||
#define SIU_TASKMGMT_ABORT_TASK 0x01
|
||||
#define SIU_TASKMGMT_ABORT_TASK_SET 0x02
|
||||
#define SIU_TASKMGMT_CLEAR_TASK_SET 0x04
|
||||
#define SIU_TASKMGMT_LUN_RESET 0x08
|
||||
#define SIU_TASKMGMT_TARGET_RESET 0x20
|
||||
#define SIU_TASKMGMT_CLEAR_ACA 0x40
|
||||
#endif /*_SCSI_SCSI_IU_H*/
|
70
drivers/scsi/aic7xxx/scsi_message.h
Normal file
70
drivers/scsi/aic7xxx/scsi_message.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* This file is in the public domain.
|
||||
* $FreeBSD: src/sys/cam/scsi/scsi_message.h,v 1.2 2000/05/01 20:21:29 peter Exp $
|
||||
*/
|
||||
|
||||
/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */
|
||||
#define MSG_CMDCOMPLETE 0x00 /* M/M */
|
||||
#define MSG_TASK_COMPLETE 0x00 /* M/M */ /* SPI3 Terminology */
|
||||
#define MSG_EXTENDED 0x01 /* O/O */
|
||||
#define MSG_SAVEDATAPOINTER 0x02 /* O/O */
|
||||
#define MSG_RESTOREPOINTERS 0x03 /* O/O */
|
||||
#define MSG_DISCONNECT 0x04 /* O/O */
|
||||
#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */
|
||||
#define MSG_ABORT 0x06 /* O/M */
|
||||
#define MSG_ABORT_TASK_SET 0x06 /* O/M */ /* SPI3 Terminology */
|
||||
#define MSG_MESSAGE_REJECT 0x07 /* M/M */
|
||||
#define MSG_NOOP 0x08 /* M/M */
|
||||
#define MSG_PARITY_ERROR 0x09 /* M/M */
|
||||
#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */
|
||||
#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */
|
||||
#define MSG_BUS_DEV_RESET 0x0c /* O/M */
|
||||
#define MSG_TARGET_RESET 0x0c /* O/M */ /* SPI3 Terminology */
|
||||
#define MSG_ABORT_TAG 0x0d /* O/O */
|
||||
#define MSG_ABORT_TASK 0x0d /* O/O */ /* SPI3 Terminology */
|
||||
#define MSG_CLEAR_QUEUE 0x0e /* O/O */
|
||||
#define MSG_CLEAR_TASK_SET 0x0e /* O/O */ /* SPI3 Terminology */
|
||||
#define MSG_INIT_RECOVERY 0x0f /* O/O */ /* Deprecated in SPI3 */
|
||||
#define MSG_REL_RECOVERY 0x10 /* O/O */ /* Deprecated in SPI3 */
|
||||
#define MSG_TERM_IO_PROC 0x11 /* O/O */ /* Deprecated in SPI3 */
|
||||
#define MSG_CLEAR_ACA 0x16 /* O/O */ /* SPI3 */
|
||||
#define MSG_LOGICAL_UNIT_RESET 0x17 /* O/O */ /* SPI3 */
|
||||
#define MSG_QAS_REQUEST 0x55 /* O/O */ /* SPI3 */
|
||||
|
||||
/* Messages (2 byte) */
|
||||
#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
|
||||
#define MSG_SIMPLE_TASK 0x20 /* O/O */ /* SPI3 Terminology */
|
||||
#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */
|
||||
#define MSG_HEAD_OF_QUEUE_TASK 0x21 /* O/O */ /* SPI3 Terminology */
|
||||
#define MSG_ORDERED_Q_TAG 0x22 /* O/O */
|
||||
#define MSG_ORDERED_TASK 0x22 /* O/O */ /* SPI3 Terminology */
|
||||
#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */
|
||||
#define MSG_ACA_TASK 0x24 /* 0/0 */ /* SPI3 */
|
||||
|
||||
/* Identify message */ /* M/M */
|
||||
#define MSG_IDENTIFYFLAG 0x80
|
||||
#define MSG_IDENTIFY_DISCFLAG 0x40
|
||||
#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun))
|
||||
#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG)
|
||||
#define MSG_IDENTIFY_LUNMASK 0x3F
|
||||
|
||||
/* Extended messages (opcode and length) */
|
||||
#define MSG_EXT_SDTR 0x01
|
||||
#define MSG_EXT_SDTR_LEN 0x03
|
||||
|
||||
#define MSG_EXT_WDTR 0x03
|
||||
#define MSG_EXT_WDTR_LEN 0x02
|
||||
#define MSG_EXT_WDTR_BUS_8_BIT 0x00
|
||||
#define MSG_EXT_WDTR_BUS_16_BIT 0x01
|
||||
#define MSG_EXT_WDTR_BUS_32_BIT 0x02 /* Deprecated in SPI3 */
|
||||
|
||||
#define MSG_EXT_PPR 0x04 /* SPI3 */
|
||||
#define MSG_EXT_PPR_LEN 0x06
|
||||
#define MSG_EXT_PPR_PCOMP_EN 0x80
|
||||
#define MSG_EXT_PPR_RTI 0x40
|
||||
#define MSG_EXT_PPR_RD_STRM 0x20
|
||||
#define MSG_EXT_PPR_WR_FLOW 0x10
|
||||
#define MSG_EXT_PPR_HOLD_MCS 0x08
|
||||
#define MSG_EXT_PPR_QAS_REQ 0x04
|
||||
#define MSG_EXT_PPR_DT_REQ 0x02
|
||||
#define MSG_EXT_PPR_IU_REQ 0x01
|
Loading…
Add table
Add a link
Reference in a new issue