Commit c6788a13 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by James Bottomley

[PATCH] sym2 version 2.1.18n

sym2 version 2.1.18n:
 - Prevent querying for DT clocking on a single ended bus
 - Check the U3EN bit instead of the ULTRA3 bit
 - Only use PPR if SDTR is incapable of negotiating the desired options or
   speed
 - minsync bugfix (James Bottomley)
 - Always calculate what negotiation to perform inside sym_prepare_nego()
 - Delete unused SYM_OPT_HANDLE_IO_TIMEOUT and SYM_CONF_TIMEOUT_ORDER_MAX
   code (Christoph Hellwig)
 - Use SCSI-3 message names instead of SCSI-2 names
 - Remove private definitions of PCI IDs
 - Reorganise DMA mask setup
 - Fix comment tpyo
 - Make some needlessly global code static (Adrian Bunk)
 - Reorder some functions to eliminate predeclaration
 - Use memset instead of bzero
 - Consolidate and abstract SPARC's special IRQ printing
 - Convert hcb_p to struct sym_hcb *
 - Remove cam_ccb_p and cam_scsiio_p typedefs
 - Treat PA-RISC firmware as if it were a type of NVRAM
Signed-off-by: default avatarMatthew Wilcox <matthew@wil.cx>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 0ca47a67
......@@ -78,14 +78,6 @@
*/
/* #define SYM_CONF_IARB_SUPPORT */
/*
* Number of lists for the optimization of the IO timeout handling.
* Not used under FreeBSD and Linux.
*/
#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
#define SYM_CONF_TIMEOUT_ORDER_MAX (8)
#endif
/*
* Only relevant if IARB support configured.
* - Max number of successive settings of IARB hints.
......
......@@ -40,29 +40,9 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
#define SYM_VERSION "2.1.18m"
#define SYM_VERSION "2.1.18n"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
* PCI device identifier of SYMBIOS chips.
*/
#define PCI_ID_SYM53C810 PCI_DEVICE_ID_NCR_53C810
#define PCI_ID_SYM53C810AP PCI_DEVICE_ID_LSI_53C810AP
#define PCI_ID_SYM53C815 PCI_DEVICE_ID_NCR_53C815
#define PCI_ID_SYM53C820 PCI_DEVICE_ID_NCR_53C820
#define PCI_ID_SYM53C825 PCI_DEVICE_ID_NCR_53C825
#define PCI_ID_SYM53C860 PCI_DEVICE_ID_NCR_53C860
#define PCI_ID_SYM53C875 PCI_DEVICE_ID_NCR_53C875
#define PCI_ID_SYM53C875_2 PCI_DEVICE_ID_NCR_53C875J
#define PCI_ID_SYM53C885 PCI_DEVICE_ID_NCR_53C885
#define PCI_ID_SYM53C895 PCI_DEVICE_ID_NCR_53C895
#define PCI_ID_SYM53C896 PCI_DEVICE_ID_NCR_53C896
#define PCI_ID_SYM53C895A PCI_DEVICE_ID_LSI_53C895A
#define PCI_ID_SYM53C875A PCI_DEVICE_ID_LSI_53C875A
#define PCI_ID_LSI53C1010_33 PCI_DEVICE_ID_LSI_53C1010_33
#define PCI_ID_LSI53C1010_66 PCI_DEVICE_ID_LSI_53C1010_66
#define PCI_ID_LSI53C1510D PCI_DEVICE_ID_LSI_53C1510
/*
* SYM53C8XX device features descriptor.
*/
......@@ -764,27 +744,27 @@ struct sym_tblsel {
#define M_RESTORE_DP RESTORE_POINTERS
#define M_DISCONNECT DISCONNECT
#define M_ID_ERROR INITIATOR_ERROR
#define M_ABORT ABORT
#define M_ABORT ABORT_TASK_SET
#define M_REJECT MESSAGE_REJECT
#define M_NOOP NOP
#define M_PARITY MSG_PARITY_ERROR
#define M_LCOMPLETE LINKED_CMD_COMPLETE
#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
#define M_RESET BUS_DEVICE_RESET
#define M_ABORT_TAG (0x0d)
#define M_CLEAR_QUEUE (0x0e)
#define M_RESET TARGET_RESET
#define M_ABORT_TAG ABORT_TASK
#define M_CLEAR_QUEUE CLEAR_TASK_SET
#define M_INIT_REC INITIATE_RECOVERY
#define M_REL_REC RELEASE_RECOVERY
#define M_TERMINATE (0x11)
#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
#define M_ORDERED_TAG ORDERED_QUEUE_TAG
#define M_IGN_RESIDUE (0x23)
#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
#define M_X_SYNC_REQ EXTENDED_SDTR
#define M_X_WIDE_REQ EXTENDED_WDTR
#define M_X_PPR_REQ (0x04)
#define M_X_PPR_REQ EXTENDED_PPR
/*
* PPR protocol options
......
......@@ -223,13 +223,13 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
if (!(np->device_id == PCI_ID_LSI53C1010_66 &&
if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
np->revision_id < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
if (!(np->device_id == PCI_ID_LSI53C1010_33 &&
if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
/* np->revision_id < 0xff */ 1)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
......
......@@ -55,6 +55,15 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
/* SPARC just has to be different ... */
#ifdef __sparc__
#define IRQ_FMT "%s"
#define IRQ_PRM(x) __irq_itoa(x)
#else
#define IRQ_FMT "%d"
#define IRQ_PRM(x) (x)
#endif
struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
unsigned int sym_debug_flags = 0;
......@@ -147,7 +156,7 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
}
/* This lock protects only the memory allocation/free. */
spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
static struct scsi_transport_template *sym2_transport_template = NULL;
......@@ -285,7 +294,7 @@ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
ccb->scsi_done(ccb);
}
void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
{
sym_set_cam_status(ccb, cam_status);
sym_xpt_done(np, ccb);
......@@ -379,7 +388,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
/*
* Bounce back the sense data to user.
*/
bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
memcpy(csio->sense_buffer, cp->sns_bbuf,
min(sizeof(csio->sense_buffer),
(size_t)SYM_SNS_BBUF_LEN));
......@@ -513,7 +522,7 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
}
/*
* Retreive the target descriptor.
* Retrieve the target descriptor.
*/
tp = &np->target[ccb->device->id];
......@@ -1277,7 +1286,7 @@ static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
int arg_len;
u_long target;
bzero(uc, sizeof(*uc));
memset(uc, 0, sizeof(*uc));
if (len > 0 && ptr[len-1] == '\n')
--len;
......@@ -1467,18 +1476,8 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
"revision id 0x%x\n",
np->s.chip_name, np->device_id, np->revision_id);
copy_info(&info, "At PCI address %s, "
#ifdef __sparc__
"IRQ %s\n",
#else
"IRQ %d\n",
#endif
pci_name(np->s.device),
#ifdef __sparc__
__irq_itoa(np->s.irq));
#else
(int) np->s.irq);
#endif
copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
pci_name(np->s.device), IRQ_PRM(np->s.irq));
copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
(int) (np->minsync_dt ? np->minsync_dt : np->minsync),
np->maxwide ? "Wide" : "Narrow",
......@@ -1558,32 +1557,23 @@ static void sym_free_resources(struct sym_hcb *np)
*/
static int sym_setup_bus_dma_mask(struct sym_hcb *np)
{
#if SYM_CONF_DMA_ADDRESSING_MODE == 0
if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
goto out_err32;
#else
#if SYM_CONF_DMA_ADDRESSING_MODE > 0
#if SYM_CONF_DMA_ADDRESSING_MODE == 1
#define PciDmaMask 0xffffffffffULL
#define DMA_DAC_MASK 0x000000ffffffffffULL /* 40-bit */
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
#define PciDmaMask 0xffffffffffffffffULL
#define DMA_DAC_MASK DMA_64BIT_MASK
#endif
if (np->features & FE_DAC) {
if (!pci_set_dma_mask(np->s.device, PciDmaMask)) {
np->use_dac = 1;
printf_info("%s: using 64 bit DMA addressing\n",
sym_name(np));
} else {
if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
goto out_err32;
}
if ((np->features & FE_DAC) &&
!pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
np->use_dac = 1;
return 0;
}
#undef PciDmaMask
#endif
return 0;
out_err32:
printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n",
sym_name(np));
if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
return 0;
printf_warning("%s: No suitable DMA available\n", sym_name(np));
return -1;
}
......@@ -1606,19 +1596,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
struct sym_fw *fw;
printk(KERN_INFO
"sym%d: <%s> rev 0x%x at pci %s "
#ifdef __sparc__
"irq %s\n",
#else
"irq %d\n",
#endif
"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
unit, dev->chip.name, dev->chip.revision_id,
pci_name(dev->pdev),
#ifdef __sparc__
__irq_itoa(dev->s.irq));
#else
dev->s.irq);
#endif
pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
/*
* Get the firmware for this chip.
......@@ -1672,9 +1652,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
/*
* Ask/tell the system about DMA addressing.
*/
if (sym_setup_bus_dma_mask(np))
goto attach_failed;
......@@ -2010,7 +1987,7 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device)
* the preset SCSI ID (which may be zero) must be read in from
* a special configuration space register of the 875.
*/
void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
{
int slot;
u8 tmp;
......
......@@ -58,13 +58,6 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#ifndef bzero
#define bzero(d, n) memset((d), 0, (n))
#endif
/*
* General driver includes.
*/
#include "sym_conf.h"
#include "sym_defs.h"
#include "sym_misc.h"
......@@ -123,14 +116,6 @@
typedef struct sym_tcb *tcb_p;
typedef struct sym_lcb *lcb_p;
typedef struct sym_ccb *ccb_p;
typedef struct sym_hcb *hcb_p;
/*
* Define a reference to the O/S dependent IO request.
*/
typedef struct scsi_cmnd *cam_ccb_p; /* Generic */
typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
/*
* IO functions definition for big/little endian CPU support.
......@@ -525,7 +510,7 @@ sym_get_cam_status(struct scsi_cmnd *ccb)
/*
* Async handler for negotiations.
*/
void sym_xpt_async_nego_wide(hcb_p np, int target);
void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
#define sym_xpt_async_nego_sync(np, target) \
sym_announce_transfer_rate(np, target)
#define sym_xpt_async_nego_ppr(np, target) \
......@@ -534,14 +519,14 @@ void sym_xpt_async_nego_wide(hcb_p np, int target);
/*
* Build CAM result for a successful IO and for a failed IO.
*/
static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
{
struct scsi_cmnd *cmd = cp->cam_ccb;
cmd->resid = resid;
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
}
void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
/*
* Other O/S specific methods.
......@@ -549,13 +534,12 @@ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
#define sym_cam_target_id(ccb) (ccb)->target
#define sym_cam_target_lun(ccb) (ccb)->lun
#define sym_freeze_cam_ccb(ccb) do { ; } while (0)
void sym_xpt_done(hcb_p np, cam_ccb_p ccb);
void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
void sym_print_addr (ccb_p cp);
void sym_xpt_async_bus_reset(hcb_p np);
void sym_xpt_async_sent_bdr(hcb_p np, int target);
int sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
void sym_log_bus_error(hcb_p np);
void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid);
void sym_xpt_async_bus_reset(struct sym_hcb *np);
void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
void sym_log_bus_error(struct sym_hcb *np);
void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
#endif /* SYM_GLUE_H */
This diff is collapsed.
......@@ -749,7 +749,7 @@ struct sym_ccb {
/*
* Pointer to CAM ccb and related stuff.
*/
cam_ccb_p cam_ccb; /* CAM scsiio ccb */
struct scsi_cmnd *cam_ccb; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */
u8 *sns_bbuf; /* Bounce buffer for sense data */
#ifndef SYM_SNS_BBUF_LEN
......@@ -796,10 +796,6 @@ struct sym_ccb {
/*
* Other fields.
*/
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
SYM_QUEHEAD tmo_linkq; /* Optional timeout handling */
u_int tmo_clock; /* (link and dealine value) */
#endif
u32 ccb_ba; /* BUS address of this CCB */
u_short tag; /* Tag for this transfer */
/* NO_TAG means no tag */
......@@ -946,8 +942,8 @@ struct sym_hcb {
struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
void (*fw_setup)(hcb_p np, struct sym_fw *fw);
void (*fw_patch)(hcb_p np);
void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
void (*fw_patch)(struct sym_hcb *np);
char *fw_name;
/*
......@@ -1025,15 +1021,6 @@ struct sym_hcb {
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
SYM_QUEHEAD dummy_ccbq;
#endif
/*
* Optional handling of IO timeouts.
*/
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
SYM_QUEHEAD tmo0_ccbq;
SYM_QUEHEAD *tmo_ccbq; /* [2*SYM_TIMEOUT_ORDER_MAX] */
u_int tmo_clock;
u_int tmo_actq;
#endif
/*
* IMMEDIATE ARBITRATION (IARB) control.
......@@ -1082,54 +1069,39 @@ struct sym_hcb {
* FIRMWARES (sym_fw.c)
*/
struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
void sym_fw_bind_script (hcb_p np, u32 *start, int len);
void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len);
/*
* Driver methods called from O/S specific code.
*/
char *sym_driver_name(void);
void sym_print_xerr(ccb_p cp, int x_status);
int sym_reset_scsi_bus(hcb_p np, int enab_int);
int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_pci_chip *
sym_lookup_pci_chip_table (u_short device_id, u_char revision);
void sym_put_start_queue(hcb_p np, ccb_p cp);
void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn);
#endif
void sym_start_up (hcb_p np, int reason);
void sym_interrupt (hcb_p np);
void sym_flush_comp_queue(hcb_p np, int cam_status);
int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
void sym_free_ccb (hcb_p np, ccb_p cp);
lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
int sym_reset_scsi_target(hcb_p np, int target);
void sym_hcb_free(hcb_p np);
int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Optionnaly, the driver may handle IO timeouts.
*/
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
{
sym_remque(&cp->tmo_linkq);
sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
}
void sym_clock(hcb_p np);
#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
void sym_start_up (struct sym_hcb *np, int reason);
void sym_interrupt (struct sym_hcb *np);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order);
void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln);
int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
int sym_reset_scsi_target(struct sym_hcb *np, int target);
void sym_hcb_free(struct sym_hcb *np);
int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Optionnaly, the driver may provide a function
* to announce transfer rate changes.
*/
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
void sym_announce_transfer_rate(hcb_p np, int target);
void sym_announce_transfer_rate(struct sym_hcb *np, int target);
#endif
/*
......@@ -1153,9 +1125,9 @@ do { \
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
int sym_lookup_dmap(hcb_p np, u32 h, int s);
int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
int s = (h&SYM_DMAP_MASK);
......
......@@ -170,7 +170,7 @@ static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
}
if (p)
bzero(p, size);
memset(p, 0, size);
else if (uflags & SYM_MEM_WARN)
printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
return p;
......
......@@ -37,109 +37,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __FreeBSD__
#include <dev/sym/sym_glue.h>
#else
#include "sym_glue.h"
#endif
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
/*
* Optional CCB timeout handling.
*
* This code is useful for O/Ses that allow or expect
* SIMs (low-level drivers) to handle SCSI IO timeouts.
* It uses a power-of-two based algorithm of my own:)
* that avoids scanning of lists, provided that:
*
* - The IO does complete in less than half the associated
* timeout value.
* - The greatest delay between the queuing of the IO and
* its completion is less than
* (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
*
* For example, if tick is 1 second and the max order is 8,
* any IO that is completed within less than 64 seconds will
* just be put into some list at queuing and be removed
* at completion without any additionnal overhead.
*/
/*
* Set a timeout condition on a CCB.
*/
void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)
{
sym_remque(&cp->tmo_linkq);
cp->tmo_clock = np->tmo_clock + ticks;
if (!ticks) {
sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
}
else {
int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
while (i > 0) {
if (ticks >= (1<<(i+1)))
break;
--i;
}
if (!(np->tmo_actq & (1<<i)))
i += SYM_CONF_TIMEOUT_ORDER_MAX;
sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
}
}
/*
* Walk a list of CCB and handle timeout conditions.
* Should never be called in normal situations.
*/
static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
{
SYM_QUEHEAD qtmp, *qp;
ccb_p cp;
sym_que_move(tmoq, &qtmp);
while ((qp = sym_remque_head(&qtmp)) != 0) {
sym_insque_head(qp, &np->tmo0_ccbq);
cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
if (cp->tmo_clock != np->tmo_clock &&
cp->tmo_clock + 1 != np->tmo_clock)
sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
else
sym_abort_ccb(np, cp, 1);
}
}
/*
* Our clock handler called from the O/S specific side.
*/
void sym_clock(hcb_p np)
{
int i, j;
u_int tmp;
tmp = np->tmo_clock;
tmp ^= (++np->tmo_clock);
for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
if (!(tmp & 1))
continue;
j = i;
if (np->tmo_actq & (1<<i))
j += SYM_CONF_TIMEOUT_ORDER_MAX;
if (!sym_que_empty(&np->tmo_ccbq[j])) {
sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
}
np->tmo_actq ^= (1<<i);
}
}
#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
/*
* Announce transfer rate if anything changed since last announcement.
*/
void sym_announce_transfer_rate(hcb_p np, int target)
void sym_announce_transfer_rate(struct sym_hcb *np, int target)
{
tcb_p tp = &np->target[target];
......
......@@ -68,6 +68,21 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
case SYM_TEKRAM_NVRAM:
np->myaddr = nvram->data.Tekram.host_id & 0x0f;
break;
#ifdef CONFIG_PARISC
case SYM_PARISC_PDC:
if (nvram->data.parisc.host_id != -1)
np->myaddr = nvram->data.parisc.host_id;
if (nvram->data.parisc.factor != -1)
np->minsync = nvram->data.parisc.factor;
if (nvram->data.parisc.width != -1)
np->maxwide = nvram->data.parisc.width;
switch (nvram->data.parisc.mode) {
case 0: np->scsi_mode = SMODE_SE; break;
case 1: np->scsi_mode = SMODE_HVD; break;
case 2: np->scsi_mode = SMODE_LVD; break;
default: break;
}
#endif
default:
break;
}
......@@ -702,6 +717,28 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram)
return 0;
}
#ifdef CONFIG_PARISC
/*
* Host firmware (PDC) keeps a table for altering SCSI capabilities.
* Many newer machines export one channel of 53c896 chip as SE, 50-pin HD.
* Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID.
*/
static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
{
struct hardware_path hwpath;
get_pci_node_path(np->pdev, &hwpath);
if (!pdc_get_initiator(&hwpath, pdc))
return 0;
return SYM_PARISC_PDC;
}
#else
static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
{
return 0;
}
#endif
/*
* Try reading Symbios or Tekram NVRAM
*/
......@@ -714,7 +751,7 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
nvp->type = SYM_TEKRAM_NVRAM;
sym_display_Tekram_nvram(np, &nvp->data.Tekram);
} else {
nvp->type = 0;
nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc);
}
return nvp->type;
}
......@@ -171,6 +171,10 @@ struct Tekram_nvram {
typedef struct Tekram_nvram Tekram_nvram;
typedef struct Tekram_target Tekram_target;
#ifndef CONFIG_PARISC
struct pdc_initiator { int dummy; };
#endif
/*
* Union of supported NVRAM formats.
*/
......@@ -178,10 +182,12 @@ struct sym_nvram {
int type;
#define SYM_SYMBIOS_NVRAM (1)
#define SYM_TEKRAM_NVRAM (2)
#define SYM_PARISC_PDC (3)
#if SYM_CONF_NVRAM_SUPPORT
union {
Symbios_nvram Symbios;
Tekram_nvram Tekram;
struct pdc_initiator parisc;
} data;
#endif
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment