summaryrefslogtreecommitdiffstats
path: root/sys/dev/sym/sym_hipd.c
diff options
context:
space:
mode:
authorgroudier <groudier@FreeBSD.org>2000-04-29 10:20:16 +0000
committergroudier <groudier@FreeBSD.org>2000-04-29 10:20:16 +0000
commit22b8c23cfa70ae85832d75bd7e71984b28507497 (patch)
treeb5d865d29a9faee6c30a80fc0208481489c3034a /sys/dev/sym/sym_hipd.c
parent706084939e6e22a3e98307ed10974cabdff2837c (diff)
downloadFreeBSD-src-22b8c23cfa70ae85832d75bd7e71984b28507497.zip
FreeBSD-src-22b8c23cfa70ae85832d75bd7e71984b28507497.tar.gz
This new version adds support for early NCR chips.
53C810 non 'A', 53C815 and 53C825 non 'A' are now attached by the driver (by default). The driver uses a different SCRIPTS set based on MEMORY MOVE instructions for these chips. 2 SCRIPTS sets (firmwares) numbered #1 and #2 are used for the whole support of the 53C8XX family to get possible: - FW #1 : Only based on MEMORY MOVE instructions. Selected for 810, 815, 825. - FW #2 : LOAD/STORE based. This is the firmware also used by previous driver versions. Selected for other chips. When both `ncr' and `sym' are configured, `sym' will now attach all the 53C8XX devices by default. Previous balancing between `ncr' and `sym' can be preserved by: - Either editing sym_conf.h and commenting the following compile option: #define SYM_CONF_GENERIC_SUPPORT (This also saves about 3.5Kb of kernel memory). - Or setting kernel config option SYM_SETUP_LP_PROBE_MAP to 64 (bit 0x40)
Diffstat (limited to 'sys/dev/sym/sym_hipd.c')
-rw-r--r--sys/dev/sym/sym_hipd.c2751
1 files changed, 646 insertions, 2105 deletions
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index e2fb26b..28140a5 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -5,10 +5,9 @@
* Copyright (C) 1999-2000 Gerard Roudier <groudier@club-internet.fr>
*
* This driver also supports the following Symbios/LSI PCI-SCSI chips:
- * 53C810A, 53C825A, 53C860, 53C875, 53C876, 53C885, 53C895.
+ * 53C810A, 53C825A, 53C860, 53C875, 53C876, 53C885, 53C895,
+ * 53C810, 53C815, 53C825 and the 53C1510D is 53C8XX mode.
*
- * but does not support earlier chips as the following ones:
- * 53C810, 53C815, 53C825.
*
* This driver for FreeBSD-CAM is derived from the Linux sym53c8xx driver.
* Copyright (C) 1998-1999 Gerard Roudier
@@ -58,7 +57,7 @@
/* $FreeBSD$ */
-#define SYM_DRIVER_NAME "sym-1.4.3-20000415"
+#define SYM_DRIVER_NAME "sym-1.5.1-20000429"
#include <pci.h>
#include <stddef.h> /* For offsetof */
@@ -128,10 +127,12 @@ typedef u_int32_t u32;
#include "opt_sym.h"
#include <dev/sym/sym_conf.h>
#include <dev/sym/sym_defs.h>
+#include <dev/sym/sym_fw.h>
#else
#include "ncr.h" /* To know if the ncr has been configured */
#include <pci/sym_conf.h>
#include <pci/sym_defs.h>
+#include <pci/sym_fw.h>
#endif
/*
@@ -1129,8 +1130,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;
-typedef struct sym_scra *scripta_p;
-typedef struct sym_scrb *scriptb_p;
/*
* Gather negotiable parameters value
@@ -1152,19 +1151,49 @@ struct sym_tinfo {
#define BUS_16_BIT MSG_EXT_WDTR_BUS_16_BIT
/*
- * Target Control Block
+ * Global TCB HEADER.
+ *
+ * Due to lack of indirect addressing on earlier NCR chips,
+ * this substructure is copied from the TCB to a global
+ * address after selection.
+ * For SYMBIOS chips that support LOAD/STORE this copy is
+ * not needed and thus not performed.
*/
-struct sym_tcb {
+struct sym_tcbh {
/*
- * LUN table used by the SCRIPTS processor.
- * An array of bus addresses is used on reselection.
+ * Scripts bus addresses of LUN table accessed from scripts.
* LUN #0 is a special case, since multi-lun devices are rare,
* and we we want to speed-up the general case and not waste
* resources.
*/
- u32 *luntbl; /* LCBs bus address table */
u32 luntbl_sa; /* bus address of this table */
u32 lun0_sa; /* bus address of LCB #0 */
+ /*
+ * Actual SYNC/WIDE IO registers value for this target.
+ * 'sval', 'wval' and 'uval' are read from SCRIPTS and
+ * so have alignment constraints.
+ */
+/*0*/ u_char uval; /* -> SCNTL4 register */
+/*1*/ u_char sval; /* -> SXFER io register */
+/*2*/ u_char filler1;
+/*3*/ u_char wval; /* -> SCNTL3 io register */
+};
+
+/*
+ * Target Control Block
+ */
+struct sym_tcb {
+ /*
+ * TCB header.
+ * Assumed at offset 0.
+ */
+/*0*/ struct sym_tcbh head;
+
+ /*
+ * LUN table used by the SCRIPTS processor.
+ * An array of bus addresses is used on reselection.
+ */
+ u32 *luntbl; /* LCBs bus address table */
/*
* LUN table used by the C code.
@@ -1188,16 +1217,6 @@ struct sym_tcb {
u32 busy0_map[(SYM_CONF_MAX_LUN+31)/32];
/*
- * Actual SYNC/WIDE IO registers value for this target.
- * 'sval', 'wval' and 'uval' are read from SCRIPTS and
- * so have alignment constraints.
- */
-/*0*/ u_char uval; /* -> SCNTL4 register */
-/*1*/ u_char sval; /* -> SXFER io register */
-/*2*/ u_char filler1;
-/*3*/ u_char wval; /* -> SCNTL3 io register */
-
- /*
* Transfer capabilities (SIP)
*/
struct sym_tinfo tinfo;
@@ -1222,14 +1241,20 @@ struct sym_tcb {
};
/*
- * Logical Unit Control Block
+ * Global LCB HEADER.
+ *
+ * Due to lack of indirect addressing on earlier NCR chips,
+ * this substructure is copied from the LCB to a global
+ * address after selection.
+ * For SYMBIOS chips that support LOAD/STORE this copy is
+ * not needed and thus not performed.
*/
-struct sym_lcb {
+struct sym_lcbh {
/*
* SCRIPTS address jumped by SCRIPTS on reselection.
* For not probed logical units, this address points to
* SCRIPTS that deal with bad LU handling (must be at
- * offset zero for that reason).
+ * offset zero of the LCB for that reason).
*/
/*0*/ u32 resel_sa;
@@ -1240,11 +1265,27 @@ struct sym_lcb {
u32 itl_task_sa;
/*
+ * Task table bus address (read from SCRIPTS).
+ */
+ u32 itlq_tbl_sa;
+};
+
+/*
+ * Logical Unit Control Block
+ */
+struct sym_lcb {
+ /*
+ * TCB header.
+ * Assumed at offset 0.
+ */
+/*0*/ struct sym_lcbh head;
+
+ /*
* Task table read from SCRIPTS that contains pointers to
- * ITLQ nexuses (bus addresses read from SCRIPTS).
+ * ITLQ nexuses. The bus address read from SCRIPTS is
+ * inside the header.
*/
u32 *itlq_tbl; /* Kernel virtual address */
- u32 itlq_tbl_sa; /* Bus address used by SCRIPTS */
/*
* Busy CCBs management.
@@ -1329,10 +1370,10 @@ struct sym_pmc {
/*
* Last four bytes (host)
*/
-#define actualquirks phys.status[0]
-#define host_status phys.status[1]
-#define ssss_status phys.status[2]
-#define host_flags phys.status[3]
+#define actualquirks phys.head.status[0]
+#define host_status phys.head.status[1]
+#define ssss_status phys.head.status[2]
+#define host_flags phys.head.status[3]
/*
* Host flags
@@ -1349,13 +1390,17 @@ struct sym_pmc {
#endif
/*
- * Data Structure Block
+ * Global CCB HEADER.
*
- * During execution of a ccb by the script processor, the
- * DSA (data structure address) register points to this
- * substructure of the ccb.
+ * Due to lack of indirect addressing on earlier NCR chips,
+ * this substructure is copied from the ccb to a global
+ * address after selection (or reselection) and copied back
+ * before disconnect.
+ * For SYMBIOS chips that support LOAD/STORE this copy is
+ * not needed and thus not performed.
*/
-struct dsb {
+
+struct sym_ccbh {
/*
* Start and restart SCRIPTS addresses (must be at 0).
*/
@@ -1364,17 +1409,41 @@ struct dsb {
/*
* SCRIPTS jump address that deal with data pointers.
* 'savep' points to the position in the script responsible
- * for the actual transfer of data.
+ * for the actual transfer of data.
* It's written on reception of a SAVE_DATA_POINTER message.
*/
u32 savep; /* Jump address to saved data pointer */
u32 lastp; /* SCRIPTS address at end of data */
- u32 goalp; /* Not used for now */
+ u32 goalp; /* Not accessed for now from SCRIPTS */
/*
* Status fields.
*/
u8 status[4];
+};
+
+/*
+ * Data Structure Block
+ *
+ * During execution of a ccb by the script processor, the
+ * DSA (data structure address) register points to this
+ * substructure of the ccb.
+ */
+struct sym_dsb {
+ /*
+ * CCB header.
+ * Also Assumed at offset 0 of the sym_ccb structure.
+ */
+/*0*/ struct sym_ccbh head;
+
+ /*
+ * Phase mismatch contexts.
+ * We need two to handle correctly the SAVED DATA POINTER.
+ * MUST BOTH BE AT OFFSET < 256, due to using 8 bit arithmetic
+ * for address calculation from SCRIPTS.
+ */
+ struct sym_pmc pm0;
+ struct sym_pmc pm1;
/*
* Table data for Script
@@ -1386,13 +1455,6 @@ struct dsb {
struct sym_tblmove sense;
struct sym_tblmove wresid;
struct sym_tblmove data [SYM_CONF_MAX_SG];
-
- /*
- * Phase mismatch contexts.
- * We need two to handle correctly the SAVED DATA POINTER.
- */
- struct sym_pmc pm0;
- struct sym_pmc pm1;
};
/*
@@ -1404,7 +1466,7 @@ struct sym_ccb {
* register when it is executed by the script processor.
* It must be the first entry.
*/
- struct dsb phys;
+ struct sym_dsb phys;
/*
* Pointer to CAM ccb and related stuff.
@@ -1478,6 +1540,17 @@ struct sym_ccb {
*/
struct sym_hcb {
/*
+ * Global headers.
+ * Due to poorness of addressing capabilities, earlier
+ * chips (810, 815, 825) copy part of the data structures
+ * (CCB, TCB and LCB) in fixed areas.
+ */
+#ifdef SYM_CONF_GENERIC_SUPPORT
+ struct sym_ccbh ccb_head;
+ struct sym_tcbh tcb_head;
+ struct sym_lcbh lcb_head;
+#endif
+ /*
* Idle task and invalid task actions and
* their bus addresses.
*/
@@ -1541,6 +1614,7 @@ struct sym_hcb {
* on reselection.
*/
u32 *targtbl;
+ u32 targtbl_ba;
/*
* CAM SIM information for this instance.
@@ -1607,11 +1681,23 @@ struct sym_hcb {
* 'scripth' stays in main memory for all chips except the
* 53C895A, 53C896 and 53C1010 that provide 8K on-chip RAM.
*/
- struct sym_scra *scripta0; /* Copies of script and scripth */
- struct sym_scrb *scriptb0; /* relocated for this host. */
+ u_char *scripta0; /* Copies of script and scripth */
+ u_char *scriptb0; /* Copies of script and scripth */
vm_offset_t scripta_ba; /* Actual script and scripth */
vm_offset_t scriptb_ba; /* bus addresses. */
vm_offset_t scriptb0_ba;
+ u_short scripta_sz; /* Actual size of script A */
+ u_short scriptb_sz; /* Actual size of script B */
+
+ /*
+ * Bus addresses, setup and patch methods for
+ * the selected firmware.
+ */
+ struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
+ struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
+ void (*fw_setup)(hcb_p np, struct sym_fw *fw);
+ void (*fw_patch)(hcb_p np);
+ char *fw_name;
/*
* General controller parameters and configuration.
@@ -1649,6 +1735,7 @@ struct sym_hcb {
u_short dqueueget; /* Next position to scan */
volatile /* Prevent code optimizations */
u32 *dqueue; /* Completion (done) queue */
+ u32 dqueue_ba; /* Done queue BUS address */
/*
* Miscellaneous buffers accessed by the scripts-processor.
@@ -1717,1987 +1804,307 @@ struct sym_hcb {
u_char istat_sem; /* Tells the chip to stop (SEM) */
};
-#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl))
-#define SCRIPTA_BA(np,lbl) (np->scripta_ba + offsetof(struct sym_scra, lbl))
-#define SCRIPTB_BA(np,lbl) (np->scriptb_ba + offsetof(struct sym_scrb,lbl))
-#define SCRIPTB0_BA(np,lbl) (np->scriptb0_ba + offsetof(struct sym_scrb,lbl))
+#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl))
/*
- * Scripts for SYMBIOS-Processor
- *
- * Use sym_fill_scripts() to create the variable parts.
- * Use sym_bind_script() to make a copy and bind to
- * physical bus addresses.
- * We have to know the offsets of all labels before we reach
- * them (for forward jumps). Therefore we declare a struct
- * here. If you make changes inside the script,
- *
- * DONT FORGET TO CHANGE THE LENGTHS HERE!
+ * Return the name of the controller.
*/
+static __inline char *sym_name(hcb_p np)
+{
+ return np->inst_name;
+}
-/*
- * Script fragments which are loaded into the on-chip RAM
- * of 825A, 875, 876, 895, 895A, 896 and 1010 chips.
- * Must not exceed 4K bytes.
- */
-struct sym_scra {
- u32 start [ 14];
- u32 getjob_begin [ 4];
- u32 getjob_end [ 4];
- u32 select [ 8];
- u32 wf_sel_done [ 2];
- u32 send_ident [ 2];
-#ifdef SYM_CONF_IARB_SUPPORT
- u32 select2 [ 8];
-#else
- u32 select2 [ 2];
-#endif
- u32 command [ 2];
- u32 dispatch [ 28];
- u32 sel_no_cmd [ 10];
- u32 init [ 6];
- u32 clrack [ 4];
- u32 disp_status [ 4];
- u32 datai_done [ 26];
- u32 datao_done [ 12];
- u32 datai_phase [ 2];
- u32 datao_phase [ 2];
- u32 msg_in [ 2];
- u32 msg_in2 [ 10];
-#ifdef SYM_CONF_IARB_SUPPORT
- u32 status [ 14];
-#else
- u32 status [ 10];
-#endif
- u32 complete [ 8];
- u32 complete2 [ 12];
- u32 complete_error [ 4];
- u32 done [ 14];
- u32 done_end [ 2];
- u32 save_dp [ 8];
- u32 restore_dp [ 4];
- u32 disconnect [ 20];
-#ifdef SYM_CONF_IARB_SUPPORT
- u32 idle [ 4];
-#else
- u32 idle [ 2];
-#endif
-#ifdef SYM_CONF_IARB_SUPPORT
- u32 ungetjob [ 6];
-#else
- u32 ungetjob [ 4];
-#endif
- u32 reselect [ 4];
- u32 reselected [ 20];
- u32 resel_scntl4 [ 28];
-#if SYM_CONF_MAX_TASK*4 > 512
- u32 resel_tag [ 26];
-#elif SYM_CONF_MAX_TASK*4 > 256
- u32 resel_tag [ 20];
-#else
- u32 resel_tag [ 16];
-#endif
- u32 resel_dsa [ 2];
- u32 resel_dsa1 [ 6];
- u32 resel_no_tag [ 6];
- u32 data_in [SYM_CONF_MAX_SG * 2];
- u32 data_in2 [ 4];
- u32 data_out [SYM_CONF_MAX_SG * 2];
- u32 data_out2 [ 4];
- u32 pm0_data [ 12];
- u32 pm0_data_out [ 6];
- u32 pm0_data_end [ 6];
- u32 pm1_data [ 12];
- u32 pm1_data_out [ 6];
- u32 pm1_data_end [ 6];
-};
+/*--------------------------------------------------------------------------*/
+/*------------------------------ FIRMWARES ---------------------------------*/
+/*--------------------------------------------------------------------------*/
/*
- * Script fragments which stay in main memory for all chips
- * except for chips that support 8K on-chip RAM.
- */
-struct sym_scrb {
- u32 start64 [ 2];
- u32 no_data [ 2];
- u32 sel_for_abort [ 18];
- u32 sel_for_abort_1 [ 2];
- u32 msg_in_etc [ 14];
- u32 msg_received [ 4];
- u32 msg_weird_seen [ 4];
- u32 msg_extended [ 20];
- u32 msg_bad [ 6];
- u32 msg_weird [ 4];
- u32 msg_weird1 [ 8];
-
- u32 wdtr_resp [ 6];
- u32 send_wdtr [ 4];
- u32 sdtr_resp [ 6];
- u32 send_sdtr [ 4];
- u32 ppr_resp [ 6];
- u32 send_ppr [ 4];
- u32 nego_bad_phase [ 4];
- u32 msg_out [ 4];
- u32 msg_out_done [ 4];
- u32 data_ovrun [ 2];
- u32 data_ovrun1 [ 22];
- u32 data_ovrun2 [ 8];
- u32 abort_resel [ 16];
- u32 resend_ident [ 4];
- u32 ident_break [ 4];
- u32 ident_break_atn [ 4];
- u32 sdata_in [ 6];
- u32 resel_bad_lun [ 4];
- u32 bad_i_t_l [ 4];
- u32 bad_i_t_l_q [ 4];
- u32 bad_status [ 6];
- u32 pm_handle [ 20];
- u32 pm_handle1 [ 4];
- u32 pm_save [ 4];
- u32 pm0_save [ 14];
- u32 pm1_save [ 14];
-
- /* WSR handling */
- u32 pm_wsr_handle [ 42];
- u32 wsr_ma_helper [ 4];
-
- /* Data area */
- u32 zero [ 1];
- u32 scratch [ 1];
- u32 pm0_data_addr [ 1];
- u32 pm1_data_addr [ 1];
- u32 saved_dsa [ 1];
- u32 saved_drs [ 1];
- u32 done_pos [ 1];
- u32 startpos [ 1];
- u32 targtbl [ 1];
- /* End of data area */
-
- u32 snooptest [ 6];
- u32 snoopend [ 2];
-};
+ * This stuff will be moved to a separate source file when
+ * the driver will be broken into several source modules.
+ */
/*
- * Function prototypes.
+ * Macros used for all firmwares.
*/
-static void sym_fill_scripts (scripta_p scra, scriptb_p scrb);
-static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len);
-static void sym_save_initial_setting (hcb_p np);
-static int sym_prepare_setting (hcb_p np, struct sym_nvram *nvram);
-static int sym_prepare_nego (hcb_p np, ccb_p cp, int nego, u_char *msgptr);
-static void sym_put_start_queue (hcb_p np, ccb_p cp);
-static void sym_chip_reset (hcb_p np);
-static void sym_soft_reset (hcb_p np);
-static void sym_start_reset (hcb_p np);
-static int sym_reset_scsi_bus (hcb_p np, int enab_int);
-static int sym_wakeup_done (hcb_p np);
-static void sym_flush_busy_queue (hcb_p np, int cam_status);
-static void sym_flush_comp_queue (hcb_p np, int cam_status);
-static void sym_init (hcb_p np, int reason);
-static int sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp,
- u_char *fakp);
-static void sym_setsync (hcb_p np, ccb_p cp, u_char ofs, u_char per,
- u_char div, u_char fak);
-static void sym_setwide (hcb_p np, ccb_p cp, u_char wide);
-static void sym_setpprot(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
- u_char per, u_char wide, u_char div, u_char fak);
-static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
- u_char per, u_char wide, u_char div, u_char fak);
-static void sym_log_hard_error (hcb_p np, u_short sist, u_char dstat);
-static void sym_intr (void *arg);
-static void sym_poll (struct cam_sim *sim);
-static void sym_recover_scsi_int (hcb_p np, u_char hsts);
-static void sym_int_sto (hcb_p np);
-static void sym_int_udc (hcb_p np);
-static void sym_int_sbmc (hcb_p np);
-static void sym_int_par (hcb_p np, u_short sist);
-static void sym_int_ma (hcb_p np);
-static int sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun,
- int task);
-static void sym_sir_bad_scsi_status (hcb_p np, int num, ccb_p cp);
-static int sym_clear_tasks (hcb_p np, int status, int targ, int lun, int task);
-static void sym_sir_task_recovery (hcb_p np, int num);
-static int sym_evaluate_dp (hcb_p np, ccb_p cp, u32 scr, int *ofs);
-static void sym_modify_dp (hcb_p np, tcb_p tp, ccb_p cp, int ofs);
-static int sym_compute_residual (hcb_p np, ccb_p cp);
-static int sym_show_msg (u_char * msg);
-static void sym_print_msg (ccb_p cp, char *label, u_char *msg);
-static void sym_sync_nego (hcb_p np, tcb_p tp, ccb_p cp);
-static void sym_ppr_nego (hcb_p np, tcb_p tp, ccb_p cp);
-static void sym_wide_nego (hcb_p np, tcb_p tp, ccb_p cp);
-static void sym_nego_default (hcb_p np, tcb_p tp, ccb_p cp);
-static void sym_nego_rejected (hcb_p np, tcb_p tp, ccb_p cp);
-static void sym_int_sir (hcb_p np);
-static void sym_free_ccb (hcb_p np, ccb_p cp);
-static ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
-static ccb_p sym_alloc_ccb (hcb_p np);
-static ccb_p sym_ccb_from_dsa (hcb_p np, u_long dsa);
-static lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
-static int sym_snooptest (hcb_p np);
-static void sym_selectclock(hcb_p np, u_char scntl3);
-static void sym_getclock (hcb_p np, int mult);
-static int sym_getpciclock (hcb_p np);
-static void sym_complete_ok (hcb_p np, ccb_p cp);
-static void sym_complete_error (hcb_p np, ccb_p cp);
-static void sym_timeout (void *arg);
-static int sym_abort_scsiio (hcb_p np, union ccb *ccb, int timed_out);
-static void sym_reset_dev (hcb_p np, union ccb *ccb);
-static void sym_action (struct cam_sim *sim, union ccb *ccb);
-static void sym_action1 (struct cam_sim *sim, union ccb *ccb);
-static int sym_setup_cdb (hcb_p np, struct ccb_scsiio *csio, ccb_p cp);
-static void sym_setup_data_and_start (hcb_p np, struct ccb_scsiio *csio,
- ccb_p cp);
-#ifdef FreeBSD_Bus_Dma_Abstraction
-static int sym_fast_scatter_sg_physical(hcb_p np, ccb_p cp,
- bus_dma_segment_t *psegs, int nsegs);
-#else
-static int sym_scatter_virtual (hcb_p np, ccb_p cp, vm_offset_t vaddr,
- vm_size_t len);
-static int sym_scatter_sg_virtual (hcb_p np, ccb_p cp,
- bus_dma_segment_t *psegs, int nsegs);
-static int sym_scatter_physical (hcb_p np, ccb_p cp, vm_offset_t paddr,
- vm_size_t len);
-#endif
-static int sym_scatter_sg_physical (hcb_p np, ccb_p cp,
- bus_dma_segment_t *psegs, int nsegs);
-static void sym_action2 (struct cam_sim *sim, union ccb *ccb);
-static void sym_update_trans (hcb_p np, tcb_p tp, struct sym_trans *tip,
- struct ccb_trans_settings *cts);
-static void sym_update_dflags(hcb_p np, u_char *flags,
- struct ccb_trans_settings *cts);
+#define SYM_GEN_A(s, label) ((short) offsetof(s, label)),
+#define SYM_GEN_B(s, label) ((short) offsetof(s, label)),
+#define PADDR_A(label) SYM_GEN_PADDR_A(struct SYM_FWA_SCR, label)
+#define PADDR_B(label) SYM_GEN_PADDR_B(struct SYM_FWB_SCR, label)
-#ifdef FreeBSD_Bus_Io_Abstraction
-static struct sym_pci_chip *sym_find_pci_chip (device_t dev);
-static int sym_pci_probe (device_t dev);
-static int sym_pci_attach (device_t dev);
-#else
-static struct sym_pci_chip *sym_find_pci_chip (pcici_t tag);
-static const char *sym_pci_probe (pcici_t tag, pcidi_t type);
-static void sym_pci_attach (pcici_t tag, int unit);
-static int sym_pci_attach2 (pcici_t tag, int unit);
-#endif
-
-static void sym_pci_free (hcb_p np);
-static int sym_cam_attach (hcb_p np);
-static void sym_cam_free (hcb_p np);
-
-static void sym_nvram_setup_host (hcb_p np, struct sym_nvram *nvram);
-static void sym_nvram_setup_target (hcb_p np, int targ, struct sym_nvram *nvp);
-static int sym_read_nvram (hcb_p np, struct sym_nvram *nvp);
+#ifdef SYM_CONF_GENERIC_SUPPORT
/*
- * Return the name of the controller.
+ * Allocate firmware #1 script area.
*/
-static __inline char *sym_name(hcb_p np)
-{
- return np->inst_name;
-}
+#define SYM_FWA_SCR sym_fw1a_scr
+#define SYM_FWB_SCR sym_fw1b_scr
+#include <dev/sym/sym_fw1.h>
+struct sym_fwa_ofs sym_fw1a_ofs = {
+ SYM_GEN_FW_A(struct SYM_FWA_SCR)
+};
+struct sym_fwb_ofs sym_fw1b_ofs = {
+ SYM_GEN_FW_B(struct SYM_FWB_SCR)
+};
+#undef SYM_FWA_SCR
+#undef SYM_FWB_SCR
+#endif /* SYM_CONF_GENERIC_SUPPORT */
/*
- * Scripts for SYMBIOS-Processor
- *
- * Use sym_bind_script for binding to physical addresses.
- *
- * HADDR_1 generates a reference to a field of the controller data.
- * PADDR_A generates a reference to another part of script A.
- * PADDR_B generates a reference to another part of script B.
- * RADDR_1 generates a reference to a script processor register.
- * RADDR_2 generates a reference to a script processor register
- * with offset.
- *
+ * Allocate firmware #2 script area.
*/
-#define RELOC_SOFTC 0x40000000
-#define RELOC_LABELA 0x50000000
-#define RELOC_REGISTER 0x60000000
-#define RELOC_LABELB 0x80000000
-#define RELOC_MASK 0xf0000000
+#define SYM_FWA_SCR sym_fw2a_scr
+#define SYM_FWB_SCR sym_fw2b_scr
+#include <dev/sym/sym_fw2.h>
+struct sym_fwa_ofs sym_fw2a_ofs = {
+ SYM_GEN_FW_A(struct SYM_FWA_SCR)
+};
+struct sym_fwb_ofs sym_fw2b_ofs = {
+ SYM_GEN_FW_B(struct SYM_FWB_SCR)
+ SYM_GEN_B(struct SYM_FWB_SCR, start64)
+ SYM_GEN_B(struct SYM_FWB_SCR, pm_handle)
+};
+#undef SYM_FWA_SCR
+#undef SYM_FWB_SCR
-#define HADDR_1(label) (RELOC_SOFTC | offsetof(struct sym_hcb, label))
-#define PADDR_A(label) (RELOC_LABELA | offsetof(struct sym_scra, label))
-#define PADDR_B(label) (RELOC_LABELB | offsetof(struct sym_scrb, label))
-#define RADDR_1(label) (RELOC_REGISTER | REG(label))
-#define RADDR_2(label,ofs) (RELOC_REGISTER | ((REG(label))+(ofs)))
+#undef SYM_GEN_A
+#undef SYM_GEN_B
+#undef PADDR_A
+#undef PADDR_B
-#define SCR_DATA_ZERO 0xf00ff00f
+#ifdef SYM_CONF_GENERIC_SUPPORT
+/*
+ * Patch routine for firmware #1.
+ */
+static void
+sym_fw1_patch(hcb_p np)
+{
+ struct sym_fw1a_scr *scripta0;
+ struct sym_fw1b_scr *scriptb0;
+
+ scripta0 = (struct sym_fw1a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
-static struct sym_scra scripta0 = {
-/*--------------------------< START >----------------------------*/ {
- /*
- * Switch the LED on.
- * Will be patched with a NO_OP if LED
- * not needed or not desired.
- */
- SCR_REG_REG (gpreg, SCR_AND, 0xfe),
- 0,
- /*
- * Clear SIGP.
- */
- SCR_FROM_REG (ctest2),
- 0,
- /*
- * Stop here if the C code wants to perform
- * some error recovery procedure manually.
- * (Indicate this by setting SEM in ISTAT)
- */
- SCR_FROM_REG (istat),
- 0,
- /*
- * Report to the C code the next position in
- * the start queue the SCRIPTS will schedule.
- * The C code must not change SCRATCHA.
- */
- SCR_LOAD_ABS (scratcha, 4),
- PADDR_B (startpos),
- SCR_INT ^ IFTRUE (MASK (SEM, SEM)),
- SIR_SCRIPT_STOPPED,
- /*
- * Start the next job.
- *
- * @DSA = start point for this job.
- * SCRATCHA = address of this job in the start queue.
- *
- * We will restore startpos with SCRATCHA if we fails the
- * arbitration or if it is the idle job.
- *
- * The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS
- * is a critical path. If it is partially executed, it then
- * may happen that the job address is not yet in the DSA
- * and the the next queue position points to the next JOB.
- */
- SCR_LOAD_ABS (dsa, 4),
- PADDR_B (startpos),
- SCR_LOAD_REL (temp, 4),
- 4,
-}/*-------------------------< GETJOB_BEGIN >---------------------*/,{
- SCR_STORE_ABS (temp, 4),
- PADDR_B (startpos),
- SCR_LOAD_REL (dsa, 4),
- 0,
-}/*-------------------------< GETJOB_END >-----------------------*/,{
- SCR_LOAD_REL (temp, 4),
- 0,
- SCR_RETURN,
- 0,
-}/*-------------------------< SELECT >---------------------------*/,{
- /*
- * DSA contains the address of a scheduled
- * data structure.
- *
- * SCRATCHA contains the address of the start queue
- * entry which points to the next job.
- *
- * Set Initiator mode.
- *
- * (Target mode is left as an exercise for the reader)
- */
- SCR_CLR (SCR_TRG),
- 0,
- /*
- * And try to select this target.
- */
- SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select),
- PADDR_A (ungetjob),
- /*
- * Now there are 4 possibilities:
- *
- * (1) The chip looses arbitration.
- * This is ok, because it will try again,
- * when the bus becomes idle.
- * (But beware of the timeout function!)
- *
- * (2) The chip is reselected.
- * Then the script processor takes the jump
- * to the RESELECT label.
- *
- * (3) The chip wins arbitration.
- * Then it will execute SCRIPTS instruction until
- * the next instruction that checks SCSI phase.
- * Then will stop and wait for selection to be
- * complete or selection time-out to occur.
- *
- * After having won arbitration, the SCRIPTS
- * processor is able to execute instructions while
- * the SCSI core is performing SCSI selection.
- */
- /*
- * load the savep (saved data pointer) into
- * the actual data pointer.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof (struct sym_ccb, phys.savep),
- /*
- * Initialize the status registers
- */
- SCR_LOAD_REL (scr0, 4),
- offsetof (struct sym_ccb, phys.status),
-}/*-------------------------< WF_SEL_DONE >----------------------*/,{
- SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- SIR_SEL_ATN_NO_MSG_OUT,
-}/*-------------------------< SEND_IDENT >-----------------------*/,{
- /*
- * Selection complete.
- * Send the IDENTIFY and possibly the TAG message
- * and negotiation message if present.
- */
- SCR_MOVE_TBL ^ SCR_MSG_OUT,
- offsetof (struct dsb, smsg),
-}/*-------------------------< SELECT2 >--------------------------*/,{
-#ifdef SYM_CONF_IARB_SUPPORT
- /*
- * Set IMMEDIATE ARBITRATION if we have been given
- * a hint to do so. (Some job to do after this one).
- */
- SCR_FROM_REG (HF_REG),
- 0,
- SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)),
- 8,
- SCR_REG_REG (scntl1, SCR_OR, IARB),
- 0,
-#endif
- /*
- * Anticipate the COMMAND phase.
- * This is the PHASE we expect at this point.
- */
- SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)),
- PADDR_A (sel_no_cmd),
-}/*-------------------------< COMMAND >--------------------------*/,{
- /*
- * ... and send the command
- */
- SCR_MOVE_TBL ^ SCR_COMMAND,
- offsetof (struct dsb, cmd),
-}/*-------------------------< DISPATCH >-------------------------*/,{
- /*
- * MSG_IN is the only phase that shall be
- * entered at least once for each (re)selection.
- * So we test it first.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
- PADDR_A (msg_in),
- SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)),
- PADDR_A (datao_phase),
- SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)),
- PADDR_A (datai_phase),
- SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
- PADDR_A (status),
- SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
- PADDR_A (command),
- SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
- PADDR_B (msg_out),
- /*
- * Discard as many illegal phases as
- * required and tell the C code about.
- */
- SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)),
- 16,
- SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
- HADDR_1 (scratch),
- SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)),
- -16,
- SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)),
- 16,
- SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
- HADDR_1 (scratch),
- SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)),
- -16,
- SCR_INT,
- SIR_BAD_PHASE,
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< SEL_NO_CMD >-----------------------*/,{
- /*
- * The target does not switch to command
- * phase after IDENTIFY has been sent.
- *
- * If it stays in MSG OUT phase send it
- * the IDENTIFY again.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
- PADDR_B (resend_ident),
- /*
- * If target does not switch to MSG IN phase
- * and we sent a negotiation, assert the
- * failure immediately.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
- PADDR_A (dispatch),
- SCR_FROM_REG (HS_REG),
- 0,
- SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
- SIR_NEGO_FAILED,
- /*
- * Jump to dispatcher.
- */
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< INIT >-----------------------------*/,{
- /*
- * Wait for the SCSI RESET signal to be
- * inactive before restarting operations,
- * since the chip may hang on SEL_ATN
- * if SCSI RESET is active.
- */
- SCR_FROM_REG (sstat0),
- 0,
- SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)),
- -16,
- SCR_JUMP,
- PADDR_A (start),
-}/*-------------------------< CLRACK >---------------------------*/,{
- /*
- * Terminate possible pending message phase.
- */
- SCR_CLR (SCR_ACK),
- 0,
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< DISP_STATUS >----------------------*/,{
- /*
- * Anticipate STATUS phase.
- *
- * Does spare 3 SCRIPTS instructions when we have
- * completed the INPUT of the data.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)),
- PADDR_A (status),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< DATAI_DONE >-----------------------*/,{
- /*
- * If the device still wants to send us data,
- * we must count the extra bytes.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)),
- PADDR_B (data_ovrun),
- /*
- * If the SWIDE is not full, jump to dispatcher.
- * We anticipate a STATUS phase.
- */
- SCR_FROM_REG (scntl2),
- 0,
- SCR_JUMP ^ IFFALSE (MASK (WSR, WSR)),
- PADDR_A (disp_status),
- /*
- * The SWIDE is full.
- * Clear this condition.
- */
- SCR_REG_REG (scntl2, SCR_OR, WSR),
- 0,
- /*
- * We are expecting an IGNORE RESIDUE message
- * from the device, otherwise we are in data
- * overrun condition. Check against MSG_IN phase.
- */
- SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
- SIR_SWIDE_OVERRUN,
- SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
- PADDR_A (disp_status),
- /*
- * We are in MSG_IN phase,
- * Read the first byte of the message.
- * If it is not an IGNORE RESIDUE message,
- * signal overrun and jump to message
- * processing.
- */
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (msgin[0]),
- SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)),
- SIR_SWIDE_OVERRUN,
- SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)),
- PADDR_A (msg_in2),
- /*
- * We got the message we expected.
- * Read the 2nd byte, and jump to dispatcher.
- */
- SCR_CLR (SCR_ACK),
- 0,
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (msgin[1]),
- SCR_CLR (SCR_ACK),
- 0,
- SCR_JUMP,
- PADDR_A (disp_status),
-}/*-------------------------< DATAO_DONE >-----------------------*/,{
- /*
- * If the device wants us to send more data,
- * we must count the extra bytes.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
- PADDR_B (data_ovrun),
- /*
- * If the SODL is not full jump to dispatcher.
- * We anticipate a STATUS phase.
- */
- SCR_FROM_REG (scntl2),
- 0,
- SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)),
- PADDR_A (disp_status),
- /*
- * The SODL is full, clear this condition.
- */
- SCR_REG_REG (scntl2, SCR_OR, WSS),
- 0,
- /*
- * And signal a DATA UNDERRUN condition
- * to the C code.
- */
- SCR_INT,
- SIR_SODL_UNDERRUN,
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< DATAI_PHASE >----------------------*/,{
- SCR_RETURN,
- 0,
-}/*-------------------------< DATAO_PHASE >----------------------*/,{
- SCR_RETURN,
- 0,
-}/*-------------------------< MSG_IN >---------------------------*/,{
- /*
- * Get the first byte of the message.
- *
- * The script processor doesn't negate the
- * ACK signal after this transfer.
- */
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (msgin[0]),
-}/*-------------------------< MSG_IN2 >--------------------------*/,{
- /*
- * Check first against 1 byte messages
- * that we handle from SCRIPTS.
- */
- SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
- PADDR_A (complete),
- SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
- PADDR_A (disconnect),
- SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
- PADDR_A (save_dp),
- SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
- PADDR_A (restore_dp),
- /*
- * We handle all other messages from the
- * C code, so no need to waste on-chip RAM
- * for those ones.
- */
- SCR_JUMP,
- PADDR_B (msg_in_etc),
-}/*-------------------------< STATUS >---------------------------*/,{
/*
- * get the status
+ * Remove LED support if not needed.
*/
- SCR_MOVE_ABS (1) ^ SCR_STATUS,
- HADDR_1 (scratch),
+ if (!(np->features & FE_LED0)) {
+ scripta0->idle[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->start[0] = cpu_to_scr(SCR_NO_OP);
+ }
+
#ifdef SYM_CONF_IARB_SUPPORT
/*
- * If STATUS is not GOOD, clear IMMEDIATE ARBITRATION,
- * since we may have to tamper the start queue from
- * the C code.
+ * If user does not want to use IMMEDIATE ARBITRATION
+ * when we are reselected while attempting to arbitrate,
+ * patch the SCRIPTS accordingly with a SCRIPT NO_OP.
*/
- SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)),
- 8,
- SCR_REG_REG (scntl1, SCR_AND, ~IARB),
- 0,
+ if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
+ scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
#endif
/*
- * save status to scsi_status.
- * mark as complete.
- */
- SCR_TO_REG (SS_REG),
- 0,
- SCR_LOAD_REG (HS_REG, HS_COMPLETE),
- 0,
- /*
- * Anticipate the MESSAGE PHASE for
- * the TASK COMPLETE message.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
- PADDR_A (msg_in),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< COMPLETE >-------------------------*/,{
- /*
- * Complete message.
- *
- * Copy the data pointer to LASTP.
- */
- SCR_STORE_REL (temp, 4),
- offsetof (struct sym_ccb, phys.lastp),
- /*
- * When we terminate the cycle by clearing ACK,
- * the target may disconnect immediately.
- *
- * We don't want to be told of an "unexpected disconnect",
- * so we disable this feature.
- */
- SCR_REG_REG (scntl2, SCR_AND, 0x7f),
- 0,
- /*
- * Terminate cycle ...
- */
- SCR_CLR (SCR_ACK|SCR_ATN),
- 0,
- /*
- * ... and wait for the disconnect.
- */
- SCR_WAIT_DISC,
- 0,
-}/*-------------------------< COMPLETE2 >------------------------*/,{
- /*
- * Save host status.
- */
- SCR_STORE_REL (scr0, 4),
- offsetof (struct sym_ccb, phys.status),
- /*
- * Some bridges may reorder DMA writes to memory.
- * We donnot want the CPU to deal with completions
- * without all the posted write having been flushed
- * to memory. This DUMMY READ should flush posted
- * buffers prior to the CPU having to deal with
- * completions.
- */
- SCR_LOAD_REL (scr0, 4), /* DUMMY READ */
- offsetof (struct sym_ccb, phys.status),
-
- /*
- * If command resulted in not GOOD status,
- * call the C code if needed.
- */
- SCR_FROM_REG (SS_REG),
- 0,
- SCR_CALL ^ IFFALSE (DATA (S_GOOD)),
- PADDR_B (bad_status),
- /*
- * If we performed an auto-sense, call
- * the C code to synchronyze task aborts
- * with UNIT ATTENTION conditions.
- */
- SCR_FROM_REG (HF_REG),
- 0,
- SCR_JUMPR ^ IFTRUE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))),
- 16,
-}/*-------------------------< COMPLETE_ERROR >-------------------*/,{
- SCR_LOAD_ABS (scratcha, 4),
- PADDR_B (startpos),
- SCR_INT,
- SIR_COMPLETE_ERROR,
-}/*-------------------------< DONE >-----------------------------*/,{
- /*
- * Copy the DSA to the DONE QUEUE and
- * signal completion to the host.
- * If we are interrupted between DONE
- * and DONE_END, we must reset, otherwise
- * the completed CCB may be lost.
- */
- SCR_STORE_ABS (dsa, 4),
- PADDR_B (saved_dsa),
- SCR_LOAD_ABS (dsa, 4),
- PADDR_B (done_pos),
- SCR_LOAD_ABS (scratcha, 4),
- PADDR_B (saved_dsa),
- SCR_STORE_REL (scratcha, 4),
- 0,
- /*
- * The instruction below reads the DONE QUEUE next
- * free position from memory.
- * In addition it ensures that all PCI posted writes
- * are flushed and so the DSA value of the done
- * CCB is visible by the CPU before INTFLY is raised.
- */
- SCR_LOAD_REL (temp, 4),
- 4,
- SCR_INT_FLY,
- 0,
- SCR_STORE_ABS (temp, 4),
- PADDR_B (done_pos),
-}/*-------------------------< DONE_END >-------------------------*/,{
- SCR_JUMP,
- PADDR_A (start),
-}/*-------------------------< SAVE_DP >--------------------------*/,{
- /*
- * Clear ACK immediately.
- * No need to delay it.
- */
- SCR_CLR (SCR_ACK),
- 0,
- /*
- * Keep track we received a SAVE DP, so
- * we will switch to the other PM context
- * on the next PM since the DP may point
- * to the current PM context.
- */
- SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
- 0,
- /*
- * SAVE_DP message:
- * Copy the data pointer to SAVEP.
- */
- SCR_STORE_REL (temp, 4),
- offsetof (struct sym_ccb, phys.savep),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< RESTORE_DP >-----------------------*/,{
- /*
- * RESTORE_DP message:
- * Copy SAVEP to actual data pointer.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof (struct sym_ccb, phys.savep),
- SCR_JUMP,
- PADDR_A (clrack),
-}/*-------------------------< DISCONNECT >-----------------------*/,{
- /*
- * DISCONNECTing ...
- *
- * disable the "unexpected disconnect" feature,
- * and remove the ACK signal.
- */
- SCR_REG_REG (scntl2, SCR_AND, 0x7f),
- 0,
- SCR_CLR (SCR_ACK|SCR_ATN),
- 0,
- /*
- * Wait for the disconnect.
- */
- SCR_WAIT_DISC,
- 0,
- /*
- * Status is: DISCONNECTED.
- */
- SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
- 0,
- /*
- * Save host status.
- */
- SCR_STORE_REL (scr0, 4),
- offsetof (struct sym_ccb, phys.status),
- /*
- * If QUIRK_AUTOSAVE is set,
- * do an "save pointer" operation.
+ * Patch some data in SCRIPTS.
+ * - start and done queue initial bus address.
+ * - target bus address table bus address.
*/
- SCR_FROM_REG (QU_REG),
- 0,
- SCR_JUMP ^ IFFALSE (MASK (SYM_QUIRK_AUTOSAVE, SYM_QUIRK_AUTOSAVE)),
- PADDR_A (start),
- /*
- * like SAVE_DP message:
- * Remember we saved the data pointer.
- * Copy data pointer to SAVEP.
- */
- SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
- 0,
- SCR_STORE_REL (temp, 4),
- offsetof (struct sym_ccb, phys.savep),
- SCR_JUMP,
- PADDR_A (start),
-}/*-------------------------< IDLE >-----------------------------*/,{
+ scriptb0->startpos[0] = cpu_to_scr(np->squeue_ba);
+ scriptb0->done_pos[0] = cpu_to_scr(np->dqueue_ba);
+ scriptb0->targtbl[0] = cpu_to_scr(np->targtbl_ba);
+}
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+
+/*
+ * Patch routine for firmware 2.
+ */
+static void
+sym_fw2_patch(hcb_p np)
+{
+ struct sym_fw2a_scr *scripta0;
+ struct sym_fw2b_scr *scriptb0;
+
+ scripta0 = (struct sym_fw2a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
+
/*
- * Nothing to do?
- * Switch the LED off and wait for reselect.
- * Will be patched with a NO_OP if LED
- * not needed or not desired.
+ * Remove LED support if not needed.
*/
- SCR_REG_REG (gpreg, SCR_OR, 0x01),
- 0,
-#ifdef SYM_CONF_IARB_SUPPORT
- SCR_JUMPR,
- 8,
-#endif
-}/*-------------------------< UNGETJOB >-------------------------*/,{
+ if (!(np->features & FE_LED0)) {
+ scripta0->idle[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->start[0] = cpu_to_scr(SCR_NO_OP);
+ }
+
#ifdef SYM_CONF_IARB_SUPPORT
/*
- * Set IMMEDIATE ARBITRATION, for the next time.
- * This will give us better chance to win arbitration
- * for the job we just wanted to do.
- */
- SCR_REG_REG (scntl1, SCR_OR, IARB),
- 0,
-#endif
- /*
- * We are not able to restart the SCRIPTS if we are
- * interrupted and these instruction haven't been
- * all executed. BTW, this is very unlikely to
- * happen, but we check that from the C code.
- */
- SCR_LOAD_REG (dsa, 0xff),
- 0,
- SCR_STORE_ABS (scratcha, 4),
- PADDR_B (startpos),
-}/*-------------------------< RESELECT >-------------------------*/,{
- /*
- * Make sure we are in initiator mode.
- */
- SCR_CLR (SCR_TRG),
- 0,
- /*
- * Sleep waiting for a reselection.
- */
- SCR_WAIT_RESEL,
- PADDR_A(start),
-}/*-------------------------< RESELECTED >-----------------------*/,{
- /*
- * Switch the LED on.
- * Will be patched with a NO_OP if LED
- * not needed or not desired.
- */
- SCR_REG_REG (gpreg, SCR_AND, 0xfe),
- 0,
- /*
- * load the target id into the sdid
- */
- SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
- 0,
- SCR_TO_REG (sdid),
- 0,
- /*
- * Load the target control block address
+ * If user does not want to use IMMEDIATE ARBITRATION
+ * when we are reselected while attempting to arbitrate,
+ * patch the SCRIPTS accordingly with a SCRIPT NO_OP.
*/
- SCR_LOAD_ABS (dsa, 4),
- PADDR_B (targtbl),
- SCR_SFBR_REG (dsa, SCR_SHL, 0),
- 0,
- SCR_REG_REG (dsa, SCR_SHL, 0),
- 0,
- SCR_REG_REG (dsa, SCR_AND, 0x3c),
- 0,
- SCR_LOAD_REL (dsa, 4),
- 0,
- /*
- * Load the legacy synchronous transfer registers.
- */
- SCR_LOAD_REL (scntl3, 1),
- offsetof(struct sym_tcb, wval),
- SCR_LOAD_REL (sxfer, 1),
- offsetof(struct sym_tcb, sval),
-}/*-------------------------< RESEL_SCNTL4 >---------------------*/,{
- /*
- * The C1010 uses a new synchronous timing scheme.
- * Will be patched with a NO_OP if not a C1010.
- */
- SCR_LOAD_REL (scntl4, 1),
- offsetof(struct sym_tcb, uval),
- /*
- * We expect MESSAGE IN phase.
- * If not, get help from the C code.
- */
- SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
- SIR_RESEL_NO_MSG_IN,
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (msgin),
- /*
- * If IDENTIFY LUN #0, use a faster path
- * to find the LCB structure.
- */
- SCR_JUMPR ^ IFTRUE (MASK (0x80, 0xbf)),
- 56,
- /*
- * If message isn't an IDENTIFY,
- * tell the C code about.
- */
- SCR_INT ^ IFFALSE (MASK (0x80, 0x80)),
- SIR_RESEL_NO_IDENTIFY,
- /*
- * It is an IDENTIFY message,
- * Load the LUN control block address.
- */
- SCR_LOAD_REL (dsa, 4),
- offsetof(struct sym_tcb, luntbl_sa),
- SCR_SFBR_REG (dsa, SCR_SHL, 0),
- 0,
- SCR_REG_REG (dsa, SCR_SHL, 0),
- 0,
- SCR_REG_REG (dsa, SCR_AND, 0xfc),
- 0,
- SCR_LOAD_REL (dsa, 4),
- 0,
- SCR_JUMPR,
- 8,
- /*
- * LUN 0 special case (but usual one :))
- */
- SCR_LOAD_REL (dsa, 4),
- offsetof(struct sym_tcb, lun0_sa),
- /*
- * Jump indirectly to the reselect action for this LUN.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof(struct sym_lcb, resel_sa),
- SCR_RETURN,
- 0,
- /* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */
-}/*-------------------------< RESEL_TAG >------------------------*/,{
- /*
- * ACK the IDENTIFY or TAG previously received.
- */
- SCR_CLR (SCR_ACK),
- 0,
- /*
- * It shall be a tagged command.
- * Read SIMPLE+TAG.
- * The C code will deal with errors.
- * Agressive optimization, is'nt it? :)
- */
- SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
- HADDR_1 (msgin),
- /*
- * Load the pointer to the tagged task
- * table for this LUN.
- */
- SCR_LOAD_REL (dsa, 4),
- offsetof(struct sym_lcb, itlq_tbl_sa),
- /*
- * The SIDL still contains the TAG value.
- * Agressive optimization, isn't it? :):)
- */
- SCR_REG_SFBR (sidl, SCR_SHL, 0),
- 0,
-#if SYM_CONF_MAX_TASK*4 > 512
- SCR_JUMPR ^ IFFALSE (CARRYSET),
- 8,
- SCR_REG_REG (dsa1, SCR_OR, 2),
- 0,
- SCR_REG_REG (sfbr, SCR_SHL, 0),
- 0,
- SCR_JUMPR ^ IFFALSE (CARRYSET),
- 8,
- SCR_REG_REG (dsa1, SCR_OR, 1),
- 0,
-#elif SYM_CONF_MAX_TASK*4 > 256
- SCR_JUMPR ^ IFFALSE (CARRYSET),
- 8,
- SCR_REG_REG (dsa1, SCR_OR, 1),
- 0,
+ if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
+ scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
#endif
/*
- * Retrieve the DSA of this task.
- * JUMP indirectly to the restart point of the CCB.
+ * Patch some variable in SCRIPTS.
+ * - start and done queue initial bus address.
+ * - target bus address table bus address.
*/
- SCR_SFBR_REG (dsa, SCR_AND, 0xfc),
- 0,
- SCR_LOAD_REL (dsa, 4),
- 0,
- SCR_LOAD_REL (temp, 4),
- offsetof(struct sym_ccb, phys.go.restart),
- SCR_RETURN,
- 0,
- /* In normal situations we branch to RESEL_DSA */
-}/*-------------------------< RESEL_DSA >------------------------*/,{
- /*
- * ACK the IDENTIFY or TAG previously received.
- */
- SCR_CLR (SCR_ACK),
- 0,
-}/*-------------------------< RESEL_DSA1 >-----------------------*/,{
- /*
- * load the savep (saved pointer) into
- * the actual data pointer.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof (struct sym_ccb, phys.savep),
- /*
- * Initialize the status registers
- */
- SCR_LOAD_REL (scr0, 4),
- offsetof (struct sym_ccb, phys.status),
- /*
- * Jump to dispatcher.
- */
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< RESEL_NO_TAG >---------------------*/,{
+ scriptb0->startpos[0] = cpu_to_scr(np->squeue_ba);
+ scriptb0->done_pos[0] = cpu_to_scr(np->dqueue_ba);
+ scriptb0->targtbl[0] = cpu_to_scr(np->targtbl_ba);
+
/*
- * Load the DSA with the unique ITL task.
+ * Remove the load of SCNTL4 on reselection if not a C10.
*/
- SCR_LOAD_REL (dsa, 4),
- offsetof(struct sym_lcb, itl_task_sa),
+ if (!(np->features & FE_C10)) {
+ scripta0->resel_scntl4[0] = cpu_to_scr(SCR_NO_OP);
+ scripta0->resel_scntl4[1] = cpu_to_scr(0);
+ }
+
/*
- * JUMP indirectly to the restart point of the CCB.
+ * Patch some other variables in SCRIPTS.
+ * These ones are loaded by the SCRIPTS processor.
*/
- SCR_LOAD_REL (temp, 4),
- offsetof(struct sym_ccb, phys.go.restart),
- SCR_RETURN,
- 0,
- /* In normal situations we branch to RESEL_DSA */
-}/*-------------------------< DATA_IN >--------------------------*/,{
+ scriptb0->pm0_data_addr[0] =
+ cpu_to_scr(np->scriptb_ba +
+ offsetof(struct sym_fw2a_scr, pm0_data));
+ scriptb0->pm1_data_addr[0] =
+ cpu_to_scr(np->scriptb_ba +
+ offsetof(struct sym_fw2a_scr, pm1_data));
+}
+
/*
- * Because the size depends on the
- * #define SYM_CONF_MAX_SG parameter,
- * it is filled in at runtime.
- *
- * ##===========< i=0; i<SYM_CONF_MAX_SG >=========
- * || SCR_CHMOV_TBL ^ SCR_DATA_IN,
- * || offsetof (struct dsb, data[ i]),
- * ##==========================================
- */
-0
-}/*-------------------------< DATA_IN2 >-------------------------*/,{
- SCR_CALL,
- PADDR_A (datai_done),
- SCR_JUMP,
- PADDR_B (data_ovrun),
-}/*-------------------------< DATA_OUT >-------------------------*/,{
-/*
- * Because the size depends on the
- * #define SYM_CONF_MAX_SG parameter,
- * it is filled in at runtime.
- *
- * ##===========< i=0; i<SYM_CONF_MAX_SG >=========
- * || SCR_CHMOV_TBL ^ SCR_DATA_OUT,
- * || offsetof (struct dsb, data[ i]),
- * ##==========================================
+ * Fill the data area in scripts.
+ * To be done for all firmwares.
*/
-0
-}/*-------------------------< DATA_OUT2 >------------------------*/,{
- SCR_CALL,
- PADDR_A (datao_done),
- SCR_JUMP,
- PADDR_B (data_ovrun),
-}/*-------------------------< PM0_DATA >-------------------------*/,{
- /*
- * Read our host flags to SFBR, so we will be able
- * to check against the data direction we expect.
- */
- SCR_FROM_REG (HF_REG),
- 0,
- /*
- * Check against actual DATA PHASE.
- */
- SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
- PADDR_A (pm0_data_out),
- /*
- * Actual phase is DATA IN.
- * Check against expected direction.
- */
- SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
- PADDR_B (data_ovrun),
- /*
- * Keep track we are moving data from the
- * PM0 DATA mini-script.
- */
- SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
- 0,
- /*
- * Move the data to memory.
- */
- SCR_CHMOV_TBL ^ SCR_DATA_IN,
- offsetof (struct sym_ccb, phys.pm0.sg),
- SCR_JUMP,
- PADDR_A (pm0_data_end),
-}/*-------------------------< PM0_DATA_OUT >---------------------*/,{
- /*
- * Actual phase is DATA OUT.
- * Check against expected direction.
- */
- SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
- PADDR_B (data_ovrun),
- /*
- * Keep track we are moving data from the
- * PM0 DATA mini-script.
- */
- SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
- 0,
- /*
- * Move the data from memory.
- */
- SCR_CHMOV_TBL ^ SCR_DATA_OUT,
- offsetof (struct sym_ccb, phys.pm0.sg),
-}/*-------------------------< PM0_DATA_END >---------------------*/,{
- /*
- * Clear the flag that told we were moving
- * data from the PM0 DATA mini-script.
- */
- SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)),
- 0,
- /*
- * Return to the previous DATA script which
- * is guaranteed by design (if no bug) to be
- * the main DATA script for this transfer.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof (struct sym_ccb, phys.pm0.ret),
- SCR_RETURN,
- 0,
-}/*-------------------------< PM1_DATA >-------------------------*/,{
- /*
- * Read our host flags to SFBR, so we will be able
- * to check against the data direction we expect.
- */
- SCR_FROM_REG (HF_REG),
- 0,
- /*
- * Check against actual DATA PHASE.
- */
- SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
- PADDR_A (pm1_data_out),
- /*
- * Actual phase is DATA IN.
- * Check against expected direction.
- */
- SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
- PADDR_B (data_ovrun),
- /*
- * Keep track we are moving data from the
- * PM1 DATA mini-script.
- */
- SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
- 0,
- /*
- * Move the data to memory.
- */
- SCR_CHMOV_TBL ^ SCR_DATA_IN,
- offsetof (struct sym_ccb, phys.pm1.sg),
- SCR_JUMP,
- PADDR_A (pm1_data_end),
-}/*-------------------------< PM1_DATA_OUT >---------------------*/,{
- /*
- * Actual phase is DATA OUT.
- * Check against expected direction.
- */
- SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
- PADDR_B (data_ovrun),
+static void
+sym_fw_fill_data (u32 *in, u32 *out)
+{
+ int i;
+
+ for (i = 0; i < SYM_CONF_MAX_SG; i++) {
+ *in++ = SCR_CHMOV_TBL ^ SCR_DATA_IN;
+ *in++ = offsetof (struct sym_dsb, data[i]);
+ *out++ = SCR_CHMOV_TBL ^ SCR_DATA_OUT;
+ *out++ = offsetof (struct sym_dsb, data[i]);
+ }
+}
+
+/*
+ * Setup useful script bus addresses.
+ * To be done for all firmwares.
+ */
+static void
+sym_fw_setup_bus_addresses(hcb_p np, struct sym_fw *fw)
+{
+ u32 *pa;
+ u_short *po;
+ int i;
+
/*
- * Keep track we are moving data from the
- * PM1 DATA mini-script.
+ * Build the bus address table for script A
+ * from the script A offset table.
*/
- SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
- 0,
+ po = (u_short *) fw->a_ofs;
+ pa = (u32 *) &np->fwa_bas;
+ for (i = 0 ; i < sizeof(np->fwa_bas)/sizeof(u32) ; i++)
+ pa[i] = np->scripta_ba + po[i];
+
/*
- * Move the data from memory.
+ * Same for script B.
*/
- SCR_CHMOV_TBL ^ SCR_DATA_OUT,
- offsetof (struct sym_ccb, phys.pm1.sg),
-}/*-------------------------< PM1_DATA_END >---------------------*/,{
+ po = (u_short *) fw->b_ofs;
+ pa = (u32 *) &np->fwb_bas;
+ for (i = 0 ; i < sizeof(np->fwb_bas)/sizeof(u32) ; i++)
+ pa[i] = np->scriptb_ba + po[i];
+}
+
+#ifdef SYM_CONF_GENERIC_SUPPORT
+/*
+ * Setup routine for firmware #1.
+ */
+static void
+sym_fw1_setup(hcb_p np, struct sym_fw *fw)
+{
+ struct sym_fw1a_scr *scripta0;
+ struct sym_fw1b_scr *scriptb0;
+
+ scripta0 = (struct sym_fw1a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
+
/*
- * Clear the flag that told we were moving
- * data from the PM1 DATA mini-script.
+ * Fill variable parts in scripts.
*/
- SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)),
- 0,
+ sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
+
/*
- * Return to the previous DATA script which
- * is guaranteed by design (if no bug) to be
- * the main DATA script for this transfer.
+ * Setup bus addresses used from the C code..
*/
- SCR_LOAD_REL (temp, 4),
- offsetof (struct sym_ccb, phys.pm1.ret),
- SCR_RETURN,
- 0,
-}/*-------------------------<>-----------------------------------*/
-};
+ sym_fw_setup_bus_addresses(np, fw);
+}
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+
+/*
+ * Setup routine for firmware 2.
+ */
+static void
+sym_fw2_setup(hcb_p np, struct sym_fw *fw)
+{
+ struct sym_fw2a_scr *scripta0;
+ struct sym_fw2b_scr *scriptb0;
+
+ scripta0 = (struct sym_fw2a_scr *) np->scripta0;
+ scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
-static struct sym_scrb scriptb0 = {
-/*--------------------------< START64 >--------------------------*/ {
/*
- * SCRIPT entry point for the 895A, 896 and 1010.
- * For now, there is no specific stuff for those
- * chips at this point, but this may come.
+ * Fill variable parts in scripts.
*/
- SCR_JUMP,
- PADDR_A (init),
-}/*-------------------------< NO_DATA >--------------------------*/,{
- SCR_JUMP,
- PADDR_B (data_ovrun),
-}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{
+ sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
+
/*
- * We are jumped here by the C code, if we have
- * some target to reset or some disconnected
- * job to abort. Since error recovery is a serious
- * busyness, we will really reset the SCSI BUS, if
- * case of a SCSI interrupt occuring in this path.
+ * Setup bus addresses used from the C code..
*/
+ sym_fw_setup_bus_addresses(np, fw);
+}
- /*
- * Set initiator mode.
- */
- SCR_CLR (SCR_TRG),
- 0,
- /*
- * And try to select this target.
- */
- SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel),
- PADDR_A (reselect),
- /*
- * Wait for the selection to complete or
- * the selection to time out.
- */
- SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- -8,
- /*
- * Call the C code.
- */
- SCR_INT,
- SIR_TARGET_SELECTED,
- /*
- * The C code should let us continue here.
- * Send the 'kiss of death' message.
- * We expect an immediate disconnect once
- * the target has eaten the message.
- */
- SCR_REG_REG (scntl2, SCR_AND, 0x7f),
- 0,
- SCR_MOVE_TBL ^ SCR_MSG_OUT,
- offsetof (struct sym_hcb, abrt_tbl),
- SCR_CLR (SCR_ACK|SCR_ATN),
- 0,
- SCR_WAIT_DISC,
- 0,
- /*
- * Tell the C code that we are done.
- */
- SCR_INT,
- SIR_ABORT_SENT,
-}/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{
- /*
- * Jump at scheduler.
- */
- SCR_JUMP,
- PADDR_A (start),
-}/*-------------------------< MSG_IN_ETC >-----------------------*/,{
- /*
- * If it is an EXTENDED (variable size message)
- * Handle it.
- */
- SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
- PADDR_B (msg_extended),
- /*
- * Let the C code handle any other
- * 1 byte message.
- */
- SCR_INT ^ IFTRUE (MASK (0x00, 0xf0)),
- SIR_MSG_RECEIVED,
- SCR_INT ^ IFTRUE (MASK (0x10, 0xf0)),
- SIR_MSG_RECEIVED,
- /*
- * We donnot handle 2 bytes messages from SCRIPTS.
- * So, let the C code deal with these ones too.
- */
- SCR_INT ^ IFFALSE (MASK (0x20, 0xf0)),
- SIR_MSG_WEIRD,
- SCR_CLR (SCR_ACK),
- 0,
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (msgin[1]),
- SCR_INT,
- SIR_MSG_RECEIVED,
-}/*-------------------------< MSG_RECEIVED >---------------------*/,{
- SCR_LOAD_REL (scratcha, 4), /* DUMMY READ */
- 0,
- SCR_INT,
- SIR_MSG_RECEIVED,
-}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{
- SCR_LOAD_REL (scratcha, 4), /* DUMMY READ */
- 0,
- SCR_INT,
- SIR_MSG_WEIRD,
-}/*-------------------------< MSG_EXTENDED >---------------------*/,{
- /*
- * Clear ACK and get the next byte
- * assumed to be the message length.
- */
- SCR_CLR (SCR_ACK),
- 0,
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (msgin[1]),
- /*
- * Try to catch some unlikely situations as 0 length
- * or too large the length.
- */
- SCR_JUMP ^ IFTRUE (DATA (0)),
- PADDR_B (msg_weird_seen),
- SCR_TO_REG (scratcha),
- 0,
- SCR_REG_REG (sfbr, SCR_ADD, (256-8)),
- 0,
- SCR_JUMP ^ IFTRUE (CARRYSET),
- PADDR_B (msg_weird_seen),
- /*
- * We donnot handle extended messages from SCRIPTS.
- * Read the amount of data correponding to the
- * message length and call the C code.
- */
- SCR_STORE_REL (scratcha, 1),
- offsetof (struct dsb, smsg_ext.size),
- SCR_CLR (SCR_ACK),
- 0,
- SCR_MOVE_TBL ^ SCR_MSG_IN,
- offsetof (struct dsb, smsg_ext),
- SCR_JUMP,
- PADDR_B (msg_received),
-}/*-------------------------< MSG_BAD >--------------------------*/,{
- /*
- * unimplemented message - reject it.
- */
- SCR_INT,
- SIR_REJECT_TO_SEND,
- SCR_SET (SCR_ATN),
- 0,
- SCR_JUMP,
- PADDR_A (clrack),
-}/*-------------------------< MSG_WEIRD >------------------------*/,{
- /*
- * weird message received
- * ignore all MSG IN phases and reject it.
- */
- SCR_INT,
- SIR_REJECT_TO_SEND,
- SCR_SET (SCR_ATN),
- 0,
-}/*-------------------------< MSG_WEIRD1 >-----------------------*/,{
- SCR_CLR (SCR_ACK),
- 0,
- SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
- PADDR_A (dispatch),
- SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
- HADDR_1 (scratch),
- SCR_JUMP,
- PADDR_B (msg_weird1),
-}/*-------------------------< WDTR_RESP >------------------------*/,{
- /*
- * let the target fetch our answer.
- */
- SCR_SET (SCR_ATN),
- 0,
- SCR_CLR (SCR_ACK),
- 0,
- SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- PADDR_B (nego_bad_phase),
-}/*-------------------------< SEND_WDTR >------------------------*/,{
- /*
- * Send the M_X_WIDE_REQ
- */
- SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
- HADDR_1 (msgout),
- SCR_JUMP,
- PADDR_B (msg_out_done),
-}/*-------------------------< SDTR_RESP >------------------------*/,{
- /*
- * let the target fetch our answer.
- */
- SCR_SET (SCR_ATN),
- 0,
- SCR_CLR (SCR_ACK),
- 0,
- SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- PADDR_B (nego_bad_phase),
-}/*-------------------------< SEND_SDTR >------------------------*/,{
- /*
- * Send the M_X_SYNC_REQ
- */
- SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
- HADDR_1 (msgout),
- SCR_JUMP,
- PADDR_B (msg_out_done),
-}/*-------------------------< PPR_RESP >-------------------------*/,{
- /*
- * let the target fetch our answer.
- */
- SCR_SET (SCR_ATN),
- 0,
- SCR_CLR (SCR_ACK),
- 0,
- SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
- PADDR_B (nego_bad_phase),
-}/*-------------------------< SEND_PPR >-------------------------*/,{
- /*
- * Send the M_X_PPR_REQ
- */
- SCR_MOVE_ABS (8) ^ SCR_MSG_OUT,
- HADDR_1 (msgout),
- SCR_JUMP,
- PADDR_B (msg_out_done),
-}/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{
- SCR_INT,
- SIR_NEGO_PROTO,
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< MSG_OUT >--------------------------*/,{
- /*
- * The target requests a message.
- * We donnot send messages that may
- * require the device to go to bus free.
- */
- SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
- HADDR_1 (msgout),
- /*
- * ... wait for the next phase
- * if it's a message out, send it again, ...
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
- PADDR_B (msg_out),
-}/*-------------------------< MSG_OUT_DONE >---------------------*/,{
- /*
- * Let the C code be aware of the
- * sent message and clear the message.
- */
- SCR_INT,
- SIR_MSG_OUT_DONE,
- /*
- * ... and process the next phase
- */
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< DATA_OVRUN >-----------------------*/,{
- /*
- * Use scratcha to count the extra bytes.
- */
- SCR_LOAD_ABS (scratcha, 4),
- PADDR_B (zero),
-}/*-------------------------< DATA_OVRUN1 >----------------------*/,{
- /*
- * The target may want to transfer too much data.
- *
- * If phase is DATA OUT write 1 byte and count it.
- */
- SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
- 16,
- SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT,
- HADDR_1 (scratch),
- SCR_JUMP,
- PADDR_B (data_ovrun2),
- /*
- * If WSR is set, clear this condition, and
- * count this byte.
- */
- SCR_FROM_REG (scntl2),
- 0,
- SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
- 16,
- SCR_REG_REG (scntl2, SCR_OR, WSR),
- 0,
- SCR_JUMP,
- PADDR_B (data_ovrun2),
- /*
- * Finally check against DATA IN phase.
- * Signal data overrun to the C code
- * and jump to dispatcher if not so.
- * Read 1 byte otherwise and count it.
- */
- SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)),
- 16,
- SCR_INT,
- SIR_DATA_OVERRUN,
- SCR_JUMP,
- PADDR_A (dispatch),
- SCR_CHMOV_ABS (1) ^ SCR_DATA_IN,
- HADDR_1 (scratch),
-}/*-------------------------< DATA_OVRUN2 >----------------------*/,{
- /*
- * Count this byte.
- * This will allow to return a negative
- * residual to user.
- */
- SCR_REG_REG (scratcha, SCR_ADD, 0x01),
- 0,
- SCR_REG_REG (scratcha1, SCR_ADDC, 0),
- 0,
- SCR_REG_REG (scratcha2, SCR_ADDC, 0),
- 0,
- /*
- * .. and repeat as required.
- */
- SCR_JUMP,
- PADDR_B (data_ovrun1),
-}/*-------------------------< ABORT_RESEL >----------------------*/,{
- SCR_SET (SCR_ATN),
- 0,
- SCR_CLR (SCR_ACK),
- 0,
- /*
- * send the abort/abortag/reset message
- * we expect an immediate disconnect
- */
- SCR_REG_REG (scntl2, SCR_AND, 0x7f),
- 0,
- SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
- HADDR_1 (msgout),
- SCR_CLR (SCR_ACK|SCR_ATN),
- 0,
- SCR_WAIT_DISC,
- 0,
- SCR_INT,
- SIR_RESEL_ABORTED,
- SCR_JUMP,
- PADDR_A (start),
-}/*-------------------------< RESEND_IDENT >---------------------*/,{
- /*
- * The target stays in MSG OUT phase after having acked
- * Identify [+ Tag [+ Extended message ]]. Targets shall
- * behave this way on parity error.
- * We must send it again all the messages.
- */
- SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */
- 0, /* 1rst ACK = 90 ns. Hope the chip isn't too fast */
- SCR_JUMP,
- PADDR_A (send_ident),
-}/*-------------------------< IDENT_BREAK >----------------------*/,{
- SCR_CLR (SCR_ATN),
- 0,
- SCR_JUMP,
- PADDR_A (select2),
-}/*-------------------------< IDENT_BREAK_ATN >------------------*/,{
- SCR_SET (SCR_ATN),
- 0,
- SCR_JUMP,
- PADDR_A (select2),
-}/*-------------------------< SDATA_IN >-------------------------*/,{
- SCR_CHMOV_TBL ^ SCR_DATA_IN,
- offsetof (struct dsb, sense),
- SCR_CALL,
- PADDR_A (datai_done),
- SCR_JUMP,
- PADDR_B (data_ovrun),
-}/*-------------------------< RESEL_BAD_LUN >--------------------*/,{
- /*
- * Message is an IDENTIFY, but lun is unknown.
- * Signal problem to C code for logging the event.
- * Send a M_ABORT to clear all pending tasks.
- */
- SCR_INT,
- SIR_RESEL_BAD_LUN,
- SCR_JUMP,
- PADDR_B (abort_resel),
-}/*-------------------------< BAD_I_T_L >------------------------*/,{
- /*
- * We donnot have a task for that I_T_L.
- * Signal problem to C code for logging the event.
- * Send a M_ABORT message.
- */
- SCR_INT,
- SIR_RESEL_BAD_I_T_L,
- SCR_JUMP,
- PADDR_B (abort_resel),
-}/*-------------------------< BAD_I_T_L_Q >----------------------*/,{
- /*
- * We donnot have a task that matches the tag.
- * Signal problem to C code for logging the event.
- * Send a M_ABORTTAG message.
- */
- SCR_INT,
- SIR_RESEL_BAD_I_T_L_Q,
- SCR_JUMP,
- PADDR_B (abort_resel),
-}/*-------------------------< BAD_STATUS >-----------------------*/,{
- /*
- * Anything different from INTERMEDIATE
- * CONDITION MET should be a bad SCSI status,
- * given that GOOD status has already been tested.
- * Call the C code.
- */
- SCR_LOAD_ABS (scratcha, 4),
- PADDR_B (startpos),
- SCR_INT ^ IFFALSE (DATA (S_COND_MET)),
- SIR_BAD_SCSI_STATUS,
- SCR_RETURN,
- 0,
-}/*-------------------------< PM_HANDLE >------------------------*/,{
- /*
- * Phase mismatch handling.
- *
- * Since we have to deal with 2 SCSI data pointers
- * (current and saved), we need at least 2 contexts.
- * Each context (pm0 and pm1) has a saved area, a
- * SAVE mini-script and a DATA phase mini-script.
- */
- /*
- * Get the PM handling flags.
- */
- SCR_FROM_REG (HF_REG),
- 0,
- /*
- * If no flags (1rst PM for example), avoid
- * all the below heavy flags testing.
- * This makes the normal case a bit faster.
- */
- SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED))),
- PADDR_B (pm_handle1),
- /*
- * If we received a SAVE DP, switch to the
- * other PM context since the savep may point
- * to the current PM context.
- */
- SCR_JUMPR ^ IFFALSE (MASK (HF_DP_SAVED, HF_DP_SAVED)),
- 8,
- SCR_REG_REG (sfbr, SCR_XOR, HF_ACT_PM),
- 0,
- /*
- * If we have been interrupt in a PM DATA mini-script,
- * we take the return address from the corresponding
- * saved area.
- * This ensure the return address always points to the
- * main DATA script for this transfer.
- */
- SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1))),
- PADDR_B (pm_handle1),
- SCR_JUMPR ^ IFFALSE (MASK (HF_IN_PM0, HF_IN_PM0)),
- 16,
- SCR_LOAD_REL (ia, 4),
- offsetof(struct sym_ccb, phys.pm0.ret),
- SCR_JUMP,
- PADDR_B (pm_save),
- SCR_LOAD_REL (ia, 4),
- offsetof(struct sym_ccb, phys.pm1.ret),
- SCR_JUMP,
- PADDR_B (pm_save),
-}/*-------------------------< PM_HANDLE1 >-----------------------*/,{
- /*
- * Normal case.
- * Update the return address so that it
- * will point after the interrupted MOVE.
- */
- SCR_REG_REG (ia, SCR_ADD, 8),
- 0,
- SCR_REG_REG (ia1, SCR_ADDC, 0),
- 0,
-}/*-------------------------< PM_SAVE >--------------------------*/,{
- /*
- * Clear all the flags that told us if we were
- * interrupted in a PM DATA mini-script and/or
- * we received a SAVE DP.
- */
- SCR_SFBR_REG (HF_REG, SCR_AND, (~(HF_IN_PM0|HF_IN_PM1|HF_DP_SAVED))),
- 0,
- /*
- * Choose the current PM context.
- */
- SCR_JUMP ^ IFTRUE (MASK (HF_ACT_PM, HF_ACT_PM)),
- PADDR_B (pm1_save),
-}/*-------------------------< PM0_SAVE >-------------------------*/,{
- SCR_STORE_REL (ia, 4),
- offsetof(struct sym_ccb, phys.pm0.ret),
- /*
- * If WSR bit is set, either UA and RBC may
- * have to be changed whether the device wants
- * to ignore this residue or not.
- */
- SCR_FROM_REG (scntl2),
- 0,
- SCR_CALL ^ IFTRUE (MASK (WSR, WSR)),
- PADDR_B (pm_wsr_handle),
- /*
- * Save the remaining byte count, the updated
- * address and the return address.
- */
- SCR_STORE_REL (rbc, 4),
- offsetof(struct sym_ccb, phys.pm0.sg.size),
- SCR_STORE_REL (ua, 4),
- offsetof(struct sym_ccb, phys.pm0.sg.addr),
- /*
- * Set the current pointer at the PM0 DATA mini-script.
- */
- SCR_LOAD_ABS (temp, 4),
- PADDR_B (pm0_data_addr),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< PM1_SAVE >-------------------------*/,{
- SCR_STORE_REL (ia, 4),
- offsetof(struct sym_ccb, phys.pm1.ret),
- /*
- * If WSR bit is set, either UA and RBC may
- * have to be changed whether the device wants
- * to ignore this residue or not.
- */
- SCR_FROM_REG (scntl2),
- 0,
- SCR_CALL ^ IFTRUE (MASK (WSR, WSR)),
- PADDR_B (pm_wsr_handle),
- /*
- * Save the remaining byte count, the updated
- * address and the return address.
- */
- SCR_STORE_REL (rbc, 4),
- offsetof(struct sym_ccb, phys.pm1.sg.size),
- SCR_STORE_REL (ua, 4),
- offsetof(struct sym_ccb, phys.pm1.sg.addr),
- /*
- * Set the current pointer at the PM1 DATA mini-script.
- */
- SCR_LOAD_ABS (temp, 4),
- PADDR_B (pm1_data_addr),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< PM_WSR_HANDLE >--------------------*/,{
- /*
- * Phase mismatch handling from SCRIPT with WSR set.
- * Such a condition can occur if the chip wants to
- * execute a CHMOV(size > 1) when the WSR bit is
- * set and the target changes PHASE.
- *
- * We must move the residual byte to memory.
- *
- * UA contains bit 0..31 of the address to
- * move the residual byte.
- * Move it to the table indirect.
- */
- SCR_STORE_REL (ua, 4),
- offsetof (struct sym_ccb, phys.wresid.addr),
- /*
- * Increment UA (move address to next position).
- */
- SCR_REG_REG (ua, SCR_ADD, 1),
- 0,
- SCR_REG_REG (ua1, SCR_ADDC, 0),
- 0,
- SCR_REG_REG (ua2, SCR_ADDC, 0),
- 0,
- SCR_REG_REG (ua3, SCR_ADDC, 0),
- 0,
- /*
- * Compute SCRATCHA as:
- * - size to transfer = 1 byte.
- * - bit 24..31 = high address bit [32...39].
- */
- SCR_LOAD_ABS (scratcha, 4),
- PADDR_B (zero),
- SCR_REG_REG (scratcha, SCR_OR, 1),
- 0,
- SCR_FROM_REG (rbc3),
- 0,
- SCR_TO_REG (scratcha3),
- 0,
- /*
- * Move this value to the table indirect.
- */
- SCR_STORE_REL (scratcha, 4),
- offsetof (struct sym_ccb, phys.wresid.size),
- /*
- * Wait for a valid phase.
- * While testing with bogus QUANTUM drives, the C1010
- * sometimes raised a spurious phase mismatch with
- * WSR and the CHMOV(1) triggered another PM.
- * Waiting explicitely for the PHASE seemed to avoid
- * the nested phase mismatch. Btw, this didn't happen
- * using my IBM drives.
- */
- SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)),
- 0,
- /*
- * Perform the move of the residual byte.
- */
- SCR_CHMOV_TBL ^ SCR_DATA_IN,
- offsetof (struct sym_ccb, phys.wresid),
- /*
- * We can now handle the phase mismatch with UA fixed.
- * RBC[0..23]=0 is a special case that does not require
- * a PM context. The C code also checks against this.
- */
- SCR_FROM_REG (rbc),
- 0,
- SCR_RETURN ^ IFFALSE (DATA (0)),
- 0,
- SCR_FROM_REG (rbc1),
- 0,
- SCR_RETURN ^ IFFALSE (DATA (0)),
- 0,
- SCR_FROM_REG (rbc2),
- 0,
- SCR_RETURN ^ IFFALSE (DATA (0)),
- 0,
- /*
- * RBC[0..23]=0.
- * Not only we donnot need a PM context, but this would
- * lead to a bogus CHMOV(0). This condition means that
- * the residual was the last byte to move from this CHMOV.
- * So, we just have to move the current data script pointer
- * (i.e. TEMP) to the SCRIPTS address following the
- * interrupted CHMOV and jump to dispatcher.
- */
- SCR_STORE_ABS (ia, 4),
- PADDR_B (scratch),
- SCR_LOAD_ABS (temp, 4),
- PADDR_B (scratch),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< WSR_MA_HELPER >--------------------*/,{
- /*
- * Helper for the C code when WSR bit is set.
- * Perform the move of the residual byte.
- */
- SCR_CHMOV_TBL ^ SCR_DATA_IN,
- offsetof (struct sym_ccb, phys.wresid),
- SCR_JUMP,
- PADDR_A (dispatch),
-}/*-------------------------< ZERO >-----------------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< SCRATCH >--------------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< PM0_DATA_ADDR >--------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< PM1_DATA_ADDR >--------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< SAVED_DSA >------------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< SAVED_DRS >------------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< DONE_POS >-------------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< STARTPOS >-------------------------*/,{
- SCR_DATA_ZERO,
-}/*-------------------------< TARGTBL >--------------------------*/,{
- SCR_DATA_ZERO,
-
-}/*-------------------------< SNOOPTEST >------------------------*/,{
- /*
- * Read the variable from memory.
- */
- SCR_LOAD_REL (scratcha, 4),
- offsetof(struct sym_hcb, cache),
- /*
- * Write the variable to memory.
- */
- SCR_STORE_REL (temp, 4),
- offsetof(struct sym_hcb, cache),
- /*
- * Read back the variable from memory.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof(struct sym_hcb, cache),
-}/*-------------------------< SNOOPEND >-------------------------*/,{
- /*
- * And stop.
- */
- SCR_INT,
- 99,
-}/*-------------------------<>-----------------------------------*/
-};
+/*
+ * Allocate firmware descriptors.
+ */
+#ifdef SYM_CONF_GENERIC_SUPPORT
+static struct sym_fw sym_fw1 = SYM_FW_ENTRY(sym_fw1, "NCR-generic");
+#endif /* SYM_CONF_GENERIC_SUPPORT */
+static struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based");
/*
- * Fill in #define dependent parts of the scripts
+ * Find the most appropriate firmware for a chip.
*/
-static void sym_fill_scripts (scripta_p scra, scriptb_p scrb)
+static struct sym_fw *
+sym_find_firmware(struct sym_pci_chip *chip)
{
- int i;
- u32 *p;
-
- p = scra->data_in;
- for (i=0; i<SYM_CONF_MAX_SG; i++) {
- *p++ =SCR_CHMOV_TBL ^ SCR_DATA_IN;
- *p++ =offsetof (struct dsb, data[i]);
- };
- assert ((u_long)p == (u_long)&scra->data_in + sizeof (scra->data_in));
-
- p = scra->data_out;
- for (i=0; i<SYM_CONF_MAX_SG; i++) {
- *p++ =SCR_CHMOV_TBL ^ SCR_DATA_OUT;
- *p++ =offsetof (struct dsb, data[i]);
- };
- assert ((u_long)p == (u_long)&scra->data_out + sizeof (scra->data_out));
+ if (chip->features & FE_LDSTR)
+ return &sym_fw2;
+#ifdef SYM_CONF_GENERIC_SUPPORT
+ else if (!(chip->features & (FE_PFEN|FE_NOPM|FE_64BIT)))
+ return &sym_fw1;
+#endif
+ else
+ return 0;
}
/*
- * Copy and bind a script.
+ * Bind a script to physical addresses.
*/
-static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
+static void sym_fw_bind_script (hcb_p np, u32 *start, int len)
{
u32 opcode, new, old, tmp1, tmp2;
- u32 *start, *end;
+ u32 *end, *cur;
int relocs;
- int opchanged = 0;
- start = src;
- end = src + len/4;
+ cur = start;
+ end = start + len/4;
- while (src < end) {
+ while (cur < end) {
- opcode = *src++;
- *dst++ = cpu_to_scr(opcode);
+ opcode = *cur;
/*
* If we forget to change the length
@@ -3707,8 +2114,9 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
*/
if (opcode == 0) {
printf ("%s: ERROR0 IN SCRIPT at %d.\n",
- sym_name(np), (int) (src-start-1));
+ sym_name(np), (int) (cur-start));
MDELAY (10000);
+ ++cur;
continue;
};
@@ -3717,12 +2125,12 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
* to reserve data area in SCRIPTS.
*/
if (opcode == SCR_DATA_ZERO) {
- dst[-1] = 0;
+ *cur++ = 0;
continue;
}
if (DEBUG_FLAGS & DEBUG_SCRIPT)
- printf ("%p: <%x>\n", (src-1), (unsigned)opcode);
+ printf ("%x: <%x>\n", cur-start, (unsigned)opcode);
/*
* We don't have to decode ALL commands
@@ -3745,12 +2153,12 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
* COPY has TWO arguments.
*/
relocs = 2;
- tmp1 = src[0];
- tmp2 = src[1];
+ tmp1 = cur[1];
+ tmp2 = cur[2];
if ((tmp1 ^ tmp2) & 3) {
printf ("%s: ERROR1 IN SCRIPT at %d.\n",
- sym_name(np), (int) (src-start-1));
- MDELAY (1000);
+ sym_name(np), (int) (cur-start));
+ MDELAY (10000);
}
/*
* If PREFETCH feature not enabled, remove
@@ -3758,8 +2166,7 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
*/
if ((opcode & SCR_NO_FLUSH) &&
!(np->features & FE_PFEN)) {
- dst[-1] = cpu_to_scr(opcode & ~SCR_NO_FLUSH);
- ++opchanged;
+ opcode = (opcode & ~SCR_NO_FLUSH);
}
break;
case 0x0:
@@ -3767,7 +2174,7 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
* MOVE/CHMOV (absolute address)
*/
if (!(np->features & FE_WIDE))
- dst[-1] = cpu_to_scr(opcode | OPC_MOVE);
+ opcode = (opcode | OPC_MOVE);
relocs = 1;
break;
case 0x1:
@@ -3775,7 +2182,7 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
* MOVE/CHMOV (table indirect)
*/
if (!(np->features & FE_WIDE))
- dst[-1] = cpu_to_scr(opcode | OPC_MOVE);
+ opcode = (opcode | OPC_MOVE);
relocs = 0;
break;
case 0x8:
@@ -3801,45 +2208,174 @@ static void sym_bind_script (hcb_p np, u32 *src, u32 *dst, int len)
break;
};
+ /*
+ * Scriptify:) the opcode.
+ */
+ *cur++ = cpu_to_scr(opcode);
+
+ /*
+ * If no relocation, assume 1 argument
+ * and just scriptize:) it.
+ */
if (!relocs) {
- *dst++ = cpu_to_scr(*src++);
+ *cur = cpu_to_scr(*cur);
+ ++cur;
continue;
}
+
+ /*
+ * Otherwise performs all needed relocations.
+ */
while (relocs--) {
- old = *src++;
+ old = *cur;
switch (old & RELOC_MASK) {
case RELOC_REGISTER:
new = (old & ~RELOC_MASK) + np->mmio_ba;
break;
- case RELOC_LABELA:
+ case RELOC_LABEL_A:
new = (old & ~RELOC_MASK) + np->scripta_ba;
break;
- case RELOC_LABELB:
+ case RELOC_LABEL_B:
new = (old & ~RELOC_MASK) + np->scriptb_ba;
break;
case RELOC_SOFTC:
new = (old & ~RELOC_MASK) + np->hcb_ba;
break;
case 0:
- /* Don't relocate a 0 address. */
+ /*
+ * Don't relocate a 0 address.
+ * They are mostly used for patched or
+ * script self-modified areas.
+ */
if (old == 0) {
new = old;
break;
}
/* fall through */
default:
- new = 0; /* For 'cc' not to complain */
- panic("sym_bind_script: "
+ new = 0;
+ panic("sym_fw_bind_script: "
"weird relocation %x\n", old);
break;
}
- *dst++ = cpu_to_scr(new);
+ *cur++ = cpu_to_scr(new);
}
};
}
+/*--------------------------------------------------------------------------*/
+/*--------------------------- END OF FIRMARES -----------------------------*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Function prototypes.
+ */
+static void sym_save_initial_setting (hcb_p np);
+static int sym_prepare_setting (hcb_p np, struct sym_nvram *nvram);
+static int sym_prepare_nego (hcb_p np, ccb_p cp, int nego, u_char *msgptr);
+static void sym_put_start_queue (hcb_p np, ccb_p cp);
+static void sym_chip_reset (hcb_p np);
+static void sym_soft_reset (hcb_p np);
+static void sym_start_reset (hcb_p np);
+static int sym_reset_scsi_bus (hcb_p np, int enab_int);
+static int sym_wakeup_done (hcb_p np);
+static void sym_flush_busy_queue (hcb_p np, int cam_status);
+static void sym_flush_comp_queue (hcb_p np, int cam_status);
+static void sym_init (hcb_p np, int reason);
+static int sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp,
+ u_char *fakp);
+static void sym_setsync (hcb_p np, ccb_p cp, u_char ofs, u_char per,
+ u_char div, u_char fak);
+static void sym_setwide (hcb_p np, ccb_p cp, u_char wide);
+static void sym_setpprot(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
+ u_char per, u_char wide, u_char div, u_char fak);
+static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
+ u_char per, u_char wide, u_char div, u_char fak);
+static void sym_log_hard_error (hcb_p np, u_short sist, u_char dstat);
+static void sym_intr (void *arg);
+static void sym_poll (struct cam_sim *sim);
+static void sym_recover_scsi_int (hcb_p np, u_char hsts);
+static void sym_int_sto (hcb_p np);
+static void sym_int_udc (hcb_p np);
+static void sym_int_sbmc (hcb_p np);
+static void sym_int_par (hcb_p np, u_short sist);
+static void sym_int_ma (hcb_p np);
+static int sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun,
+ int task);
+static void sym_sir_bad_scsi_status (hcb_p np, int num, ccb_p cp);
+static int sym_clear_tasks (hcb_p np, int status, int targ, int lun, int task);
+static void sym_sir_task_recovery (hcb_p np, int num);
+static int sym_evaluate_dp (hcb_p np, ccb_p cp, u32 scr, int *ofs);
+static void sym_modify_dp (hcb_p np, tcb_p tp, ccb_p cp, int ofs);
+static int sym_compute_residual (hcb_p np, ccb_p cp);
+static int sym_show_msg (u_char * msg);
+static void sym_print_msg (ccb_p cp, char *label, u_char *msg);
+static void sym_sync_nego (hcb_p np, tcb_p tp, ccb_p cp);
+static void sym_ppr_nego (hcb_p np, tcb_p tp, ccb_p cp);
+static void sym_wide_nego (hcb_p np, tcb_p tp, ccb_p cp);
+static void sym_nego_default (hcb_p np, tcb_p tp, ccb_p cp);
+static void sym_nego_rejected (hcb_p np, tcb_p tp, ccb_p cp);
+static void sym_int_sir (hcb_p np);
+static void sym_free_ccb (hcb_p np, ccb_p cp);
+static ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
+static ccb_p sym_alloc_ccb (hcb_p np);
+static ccb_p sym_ccb_from_dsa (hcb_p np, u_long dsa);
+static lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
+static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
+static int sym_snooptest (hcb_p np);
+static void sym_selectclock(hcb_p np, u_char scntl3);
+static void sym_getclock (hcb_p np, int mult);
+static int sym_getpciclock (hcb_p np);
+static void sym_complete_ok (hcb_p np, ccb_p cp);
+static void sym_complete_error (hcb_p np, ccb_p cp);
+static void sym_timeout (void *arg);
+static int sym_abort_scsiio (hcb_p np, union ccb *ccb, int timed_out);
+static void sym_reset_dev (hcb_p np, union ccb *ccb);
+static void sym_action (struct cam_sim *sim, union ccb *ccb);
+static void sym_action1 (struct cam_sim *sim, union ccb *ccb);
+static int sym_setup_cdb (hcb_p np, struct ccb_scsiio *csio, ccb_p cp);
+static void sym_setup_data_and_start (hcb_p np, struct ccb_scsiio *csio,
+ ccb_p cp);
+#ifdef FreeBSD_Bus_Dma_Abstraction
+static int sym_fast_scatter_sg_physical(hcb_p np, ccb_p cp,
+ bus_dma_segment_t *psegs, int nsegs);
+#else
+static int sym_scatter_virtual (hcb_p np, ccb_p cp, vm_offset_t vaddr,
+ vm_size_t len);
+static int sym_scatter_sg_virtual (hcb_p np, ccb_p cp,
+ bus_dma_segment_t *psegs, int nsegs);
+static int sym_scatter_physical (hcb_p np, ccb_p cp, vm_offset_t paddr,
+ vm_size_t len);
+#endif
+static int sym_scatter_sg_physical (hcb_p np, ccb_p cp,
+ bus_dma_segment_t *psegs, int nsegs);
+static void sym_action2 (struct cam_sim *sim, union ccb *ccb);
+static void sym_update_trans (hcb_p np, tcb_p tp, struct sym_trans *tip,
+ struct ccb_trans_settings *cts);
+static void sym_update_dflags(hcb_p np, u_char *flags,
+ struct ccb_trans_settings *cts);
+
+#ifdef FreeBSD_Bus_Io_Abstraction
+static struct sym_pci_chip *sym_find_pci_chip (device_t dev);
+static int sym_pci_probe (device_t dev);
+static int sym_pci_attach (device_t dev);
+#else
+static struct sym_pci_chip *sym_find_pci_chip (pcici_t tag);
+static const char *sym_pci_probe (pcici_t tag, pcidi_t type);
+static void sym_pci_attach (pcici_t tag, int unit);
+static int sym_pci_attach2 (pcici_t tag, int unit);
+#endif
+
+static void sym_pci_free (hcb_p np);
+static int sym_cam_attach (hcb_p np);
+static void sym_cam_free (hcb_p np);
+
+static void sym_nvram_setup_host (hcb_p np, struct sym_nvram *nvram);
+static void sym_nvram_setup_target (hcb_p np, int targ, struct sym_nvram *nvp);
+static int sym_read_nvram (hcb_p np, struct sym_nvram *nvp);
+
/*
* Print something which allows to retrieve the controler type,
* unit, target, lun concerned by a kernel message.
@@ -4319,6 +2855,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
sym_name(np),
np->rv_dcntl & IRQM ? "totem pole" : "open drain",
np->ram_ba ? ", using on-chip SRAM" : "");
+ printf("%s: using %s firmware.\n", sym_name(np), np->fw_name);
if (np->features & FE_NOPM)
printf("%s: handling phase mismatch from SCRIPTS.\n",
sym_name(np));
@@ -4681,12 +3218,11 @@ static void sym_init (hcb_p np, int reason)
* Start at first entry.
*/
np->squeueput = 0;
- np->scriptb0->startpos[0] = cpu_to_scr(phys);
/*
* Clear Done Queue
*/
- phys = vtobus(np->dqueue);
+ phys = np->dqueue_ba;
for (i = 0; i < MAX_QUEUE*2; i += 2) {
np->dqueue[i] = 0;
np->dqueue[i+1] = cpu_to_scr(phys + (i+2)*4);
@@ -4696,10 +3232,16 @@ static void sym_init (hcb_p np, int reason)
/*
* Start at first entry.
*/
- np->scriptb0->done_pos[0] = cpu_to_scr(phys);
np->dqueueget = 0;
/*
+ * Install patches in scripts.
+ * This also let point to first position the start
+ * and done queue pointers used from SCRIPTS.
+ */
+ np->fw_patch(np);
+
+ /*
* Wakeup all pending jobs.
*/
sym_flush_busy_queue(np, CAM_SCSI_BUS_RESET);
@@ -4813,10 +3355,10 @@ static void sym_init (hcb_p np, int reason)
for (i=0;i<SYM_CONF_MAX_TARGET;i++) {
tcb_p tp = &np->target[i];
- tp->to_reset = 0;
- tp->sval = 0;
- tp->wval = np->rv_scntl3;
- tp->uval = 0;
+ tp->to_reset = 0;
+ tp->head.sval = 0;
+ tp->head.wval = np->rv_scntl3;
+ tp->head.uval = 0;
tp->tinfo.current.period = 0;
tp->tinfo.current.offset = 0;
@@ -4834,7 +3376,7 @@ static void sym_init (hcb_p np, int reason)
sym_name(np));
if (np->ram_ws == 8192) {
memcpy_to_pci(np->ram_va + 4096,
- np->scriptb0, sizeof(struct sym_scrb));
+ np->scriptb0, np->scriptb_sz);
OUTL (nc_mmws, np->scr_ram_seg);
OUTL (nc_mmrs, np->scr_ram_seg);
OUTL (nc_sfs, np->scr_ram_seg);
@@ -4842,7 +3384,7 @@ static void sym_init (hcb_p np, int reason)
}
else
phys = SCRIPTA_BA (np, init);
- memcpy_to_pci(np->ram_va,np->scripta0,sizeof(struct sym_scra));
+ memcpy_to_pci(np->ram_va, np->scripta0, np->scripta_sz);
}
else
phys = SCRIPTA_BA (np, init);
@@ -5062,9 +3604,9 @@ static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
assert (target == (cp->target & 0xf));
tp = &np->target[target];
- sval = tp->sval;
- wval = tp->wval;
- uval = tp->uval;
+ sval = tp->head.sval;
+ wval = tp->head.wval;
+ uval = tp->head.uval;
#if 0
printf("XXXX sval=%x wval=%x uval=%x (%x)\n",
@@ -5117,10 +3659,13 @@ static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
/*
* Stop there if sync parameters are unchanged.
*/
- if (tp->sval == sval && tp->wval == wval && tp->uval == uval) return;
- tp->sval = sval;
- tp->wval = wval;
- tp->uval = uval;
+ if (tp->head.sval == sval &&
+ tp->head.wval == wval &&
+ tp->head.uval == uval)
+ return;
+ tp->head.sval = sval;
+ tp->head.wval = wval;
+ tp->head.uval = uval;
/*
* Disable extended Sreq/Sack filtering if per < 50.
@@ -5132,11 +3677,11 @@ static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
/*
* set actual value and sync_status
*/
- OUTB (nc_sxfer, tp->sval);
- OUTB (nc_scntl3, tp->wval);
+ OUTB (nc_sxfer, tp->head.sval);
+ OUTB (nc_scntl3, tp->head.wval);
if (np->features & FE_C10) {
- OUTB (nc_scntl4, tp->uval);
+ OUTB (nc_scntl4, tp->head.uval);
}
/*
@@ -5146,10 +3691,10 @@ static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs,
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->target != target)
continue;
- cp->phys.select.sel_scntl3 = tp->wval;
- cp->phys.select.sel_sxfer = tp->sval;
+ cp->phys.select.sel_scntl3 = tp->head.wval;
+ cp->phys.select.sel_sxfer = tp->head.sval;
if (np->features & FE_C10) {
- cp->phys.select.sel_scntl4 = tp->uval;
+ cp->phys.select.sel_scntl4 = tp->head.uval;
}
}
}
@@ -5192,16 +3737,16 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
dsp = INL (nc_dsp);
if (dsp > np->scripta_ba &&
- dsp <= np->scripta_ba + sizeof(struct sym_scra)) {
+ dsp <= np->scripta_ba + np->scripta_sz) {
script_ofs = dsp - np->scripta_ba;
- script_size = sizeof(struct sym_scra);
+ script_size = np->scripta_sz;
script_base = (u_char *) np->scripta0;
script_name = "scripta";
}
else if (np->scriptb_ba < dsp &&
- dsp <= np->scriptb_ba + sizeof(struct sym_scrb)) {
+ dsp <= np->scriptb_ba + np->scriptb_sz) {
script_ofs = dsp - np->scriptb_ba;
- script_size = sizeof(struct sym_scrb);
+ script_size = np->scriptb_sz;
script_base = (u_char *) np->scriptb0;
script_name = "scriptb";
} else {
@@ -5794,12 +4339,12 @@ static void sym_int_ma (hcb_p np)
vdsp = 0;
nxtdsp = 0;
if (dsp > np->scripta_ba &&
- dsp <= np->scripta_ba + sizeof(struct sym_scra)) {
+ dsp <= np->scripta_ba + np->scripta_sz) {
vdsp = (u32 *)((char*)np->scripta0 + (dsp-np->scripta_ba-8));
nxtdsp = dsp;
}
else if (dsp > np->scriptb_ba &&
- dsp <= np->scriptb_ba + sizeof(struct sym_scrb)) {
+ dsp <= np->scriptb_ba + np->scriptb_sz) {
vdsp = (u32 *)((char*)np->scriptb0 + (dsp-np->scriptb_ba-8));
nxtdsp = dsp;
}
@@ -6272,9 +4817,9 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
*/
startp = SCRIPTB_BA (np, sdata_in);
- cp->phys.savep = cpu_to_scr(startp);
- cp->phys.goalp = cpu_to_scr(startp + 16);
- cp->phys.lastp = cpu_to_scr(startp);
+ cp->phys.head.savep = cpu_to_scr(startp);
+ cp->phys.head.goalp = cpu_to_scr(startp + 16);
+ cp->phys.head.lastp = cpu_to_scr(startp);
cp->startp = cpu_to_scr(startp);
cp->actualquirks = SYM_QUIRK_AUTOSAVE;
@@ -6284,8 +4829,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
cp->xerr_status = 0;
cp->extra_bytes = 0;
- cp->phys.go.start =
- cpu_to_scr(SCRIPTA_BA (np, select));
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
/*
* Requeue the command.
@@ -6458,8 +5002,8 @@ static void sym_sir_task_recovery(hcb_p np, int num)
if (target != -1) {
tp = &np->target[target];
np->abrt_sel.sel_id = target;
- np->abrt_sel.sel_scntl3 = tp->wval;
- np->abrt_sel.sel_sxfer = tp->sval;
+ np->abrt_sel.sel_scntl3 = tp->head.wval;
+ np->abrt_sel.sel_sxfer = tp->head.sval;
OUTL(nc_dsa, np->hcb_ba);
OUTL (nc_dsp, SCRIPTB_BA (np, sel_for_abort));
return;
@@ -6666,9 +5210,9 @@ static void sym_sir_task_recovery(hcb_p np, int num)
lun = -1;
task = -1;
if (np->abrt_msg[0] == M_RESET) {
- tp->sval = 0;
- tp->wval = np->rv_scntl3;
- tp->uval = 0;
+ tp->head.sval = 0;
+ tp->head.wval = np->rv_scntl3;
+ tp->head.uval = 0;
tp->tinfo.current.period = 0;
tp->tinfo.current.offset = 0;
tp->tinfo.current.width = BUS_8_BIT;
@@ -6786,7 +5330,7 @@ static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
* If result is dp_sg = SYM_CONF_MAX_SG, then we are at the
* end of the data.
*/
- tmp = scr_to_cpu(cp->phys.goalp);
+ tmp = scr_to_cpu(cp->phys.head.goalp);
dp_sg = SYM_CONF_MAX_SG;
if (dp_scr != tmp)
dp_sg -= (tmp - 8 - (int)dp_scr) / (2*4);
@@ -6893,7 +5437,7 @@ static void sym_modify_dp(hcb_p np, tcb_p tp, ccb_p cp, int ofs)
* And our alchemy:) allows to easily calculate the data
* script address we want to return for the next data phase.
*/
- dp_ret = cpu_to_scr(cp->phys.goalp);
+ dp_ret = cpu_to_scr(cp->phys.head.goalp);
dp_ret = dp_ret - 8 - (SYM_CONF_MAX_SG - dp_sg) * (2*4);
/*
@@ -6989,15 +5533,16 @@ static int sym_compute_residual(hcb_p np, ccb_p cp)
* If all data has been transferred,
* there is no residual.
*/
- if (cp->phys.lastp == cp->phys.goalp)
+ if (cp->phys.head.lastp == cp->phys.head.goalp)
return resid;
/*
* If no data transfer occurs, or if the data
* pointer is weird, return full residual.
*/
- if (cp->startp == cp->phys.lastp ||
- sym_evaluate_dp(np, cp, scr_to_cpu(cp->phys.lastp), &dp_ofs) < 0) {
+ if (cp->startp == cp->phys.head.lastp ||
+ sym_evaluate_dp(np, cp, scr_to_cpu(cp->phys.head.lastp),
+ &dp_ofs) < 0) {
return cp->data_len;
}
@@ -7026,7 +5571,7 @@ static int sym_compute_residual(hcb_p np, ccb_p cp)
}
/*
- * Print out the containt of a SCSI message.
+ * Print out the content of a SCSI message.
*/
static int sym_show_msg (u_char * msg)
@@ -7369,7 +5914,7 @@ static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
if (chg) /* Answer wasn't acceptable. */
goto reject_it;
sym_setwide (np, cp, wide);
-#if 1
+
/*
* Negotiate for SYNC immediately after WIDE response.
* This allows to negotiate for both WIDE and SYNC on
@@ -7391,7 +5936,7 @@ static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
OUTL (nc_dsp, SCRIPTB_BA (np, sdtr_resp));
return;
}
-#endif
+
OUTL (nc_dsp, SCRIPTA_BA (np, clrack));
return;
};
@@ -7791,7 +6336,7 @@ static ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
lp->ia_tag = 0;
lp->itlq_tbl[tag] = cpu_to_scr(cp->ccb_ba);
++lp->busy_itlq;
- lp->resel_sa =
+ lp->head.resel_sa =
cpu_to_scr(SCRIPTA_BA (np, resel_tag));
}
else
@@ -7813,9 +6358,9 @@ static ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
* Toggle reselect path to untagged.
*/
if (++lp->busy_itl == 1) {
- lp->itl_task_sa = cpu_to_scr(cp->ccb_ba);
- lp->resel_sa =
- cpu_to_scr(SCRIPTA_BA (np,resel_no_tag));
+ lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba);
+ lp->head.resel_sa =
+ cpu_to_scr(SCRIPTA_BA (np, resel_no_tag));
}
else
goto out_free;
@@ -7884,14 +6429,14 @@ static void sym_free_ccb (hcb_p np, ccb_p cp)
* Make the reselect path invalid,
* and uncount this CCB.
*/
- lp->itl_task_sa = cpu_to_scr(np->bad_itl_ba);
+ lp->head.itl_task_sa = cpu_to_scr(np->bad_itl_ba);
--lp->busy_itl;
}
/*
* If no JOB active, make the LUN reselect path invalid.
*/
if (lp->busy_itlq == 0 && lp->busy_itl == 0)
- lp->resel_sa =
+ lp->head.resel_sa =
cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
}
/*
@@ -7993,8 +6538,8 @@ static ccb_p sym_alloc_ccb(hcb_p np)
/*
* Initialyze the start and restart actions.
*/
- cp->phys.go.start = cpu_to_scr(SCRIPTA_BA (np, idle));
- cp->phys.go.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, idle));
+ cp->phys.head.go.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
/*
* Initilialyze some other fields.
@@ -8045,9 +6590,9 @@ static void sym_init_tcb (hcb_p np, u_char tn)
* Check some alignments required by the chip.
*/
assert (((offsetof(struct sym_reg, nc_sxfer) ^
- offsetof(struct sym_tcb, sval)) &3) == 0);
+ offsetof(struct sym_tcb, head.sval)) &3) == 0);
assert (((offsetof(struct sym_reg, nc_scntl3) ^
- offsetof(struct sym_tcb, wval)) &3) == 0);
+ offsetof(struct sym_tcb, head.wval)) &3) == 0);
}
/*
@@ -8085,7 +6630,7 @@ static lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
goto fail;
for (i = 0 ; i < 64 ; i++)
tp->luntbl[i] = cpu_to_scr(vtobus(&np->badlun_sa));
- tp->luntbl_sa = cpu_to_scr(vtobus(tp->luntbl));
+ tp->head.luntbl_sa = cpu_to_scr(vtobus(tp->luntbl));
}
/*
@@ -8111,18 +6656,18 @@ static lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
}
else {
tp->lun0p = lp;
- tp->lun0_sa = cpu_to_scr(vtobus(lp));
+ tp->head.lun0_sa = cpu_to_scr(vtobus(lp));
}
/*
* Let the itl task point to error handling.
*/
- lp->itl_task_sa = cpu_to_scr(np->bad_itl_ba);
+ lp->head.itl_task_sa = cpu_to_scr(np->bad_itl_ba);
/*
* Set the reselect pattern to our default. :)
*/
- lp->resel_sa = cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+ lp->head.resel_sa = cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
/*
* Set user capabilities.
@@ -8178,7 +6723,7 @@ static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
* Make the task table available to SCRIPTS,
* And accept tagged commands now.
*/
- lp->itlq_tbl_sa = cpu_to_scr(vtobus(lp->itlq_tbl));
+ lp->head.itlq_tbl_sa = cpu_to_scr(vtobus(lp->itlq_tbl));
return;
fail:
@@ -8290,6 +6835,7 @@ static int sym_snooptest (hcb_p np)
(int) sym_wr, (int) sym_bk);
err |= 4;
};
+
return (err);
}
@@ -8732,7 +7278,7 @@ static void sym_complete_ok (hcb_p np, ccb_p cp)
* extended error did occur, there is no residual.
*/
csio->resid = 0;
- if (cp->phys.lastp != cp->phys.goalp)
+ if (cp->phys.head.lastp != cp->phys.head.goalp)
csio->resid = sym_compute_residual(np, cp);
/*
@@ -9031,16 +7577,16 @@ static void sym_action1(struct cam_sim *sim, union ccb *ccb)
/*
* Startqueue
*/
- cp->phys.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
- cp->phys.go.restart = cpu_to_scr(SCRIPTA_BA (np, resel_dsa));
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
+ cp->phys.head.go.restart = cpu_to_scr(SCRIPTA_BA (np, resel_dsa));
/*
* select
*/
cp->phys.select.sel_id = cp->target;
- cp->phys.select.sel_scntl3 = tp->wval;
- cp->phys.select.sel_sxfer = tp->sval;
- cp->phys.select.sel_scntl4 = tp->uval;
+ cp->phys.select.sel_scntl3 = tp->head.wval;
+ cp->phys.select.sel_sxfer = tp->head.sval;
+ cp->phys.select.sel_scntl4 = tp->head.uval;
/*
* message
@@ -9166,10 +7712,10 @@ sym_setup_data_pointers(hcb_p np, ccb_p cp, int dir)
break;
}
- cp->phys.lastp = cpu_to_scr(lastp);
- cp->phys.goalp = cpu_to_scr(goalp);
- cp->phys.savep = cpu_to_scr(lastp);
- cp->startp = cp->phys.savep;
+ cp->phys.head.lastp = cpu_to_scr(lastp);
+ cp->phys.head.goalp = cpu_to_scr(goalp);
+ cp->phys.head.savep = cpu_to_scr(lastp);
+ cp->startp = cp->phys.head.savep;
}
@@ -9895,13 +8441,22 @@ DATA_SET (pcidevice_set, sym_pci_driver);
#endif /* FreeBSD_Bus_Io_Abstraction */
static struct sym_pci_chip sym_pci_dev_table[] = {
- {PCI_ID_SYM53C810, 0x0f, "810", 4, 8, 4, 0,
+ {PCI_ID_SYM53C810, 0x0f, "810", 4, 8, 4, 64,
FE_ERL}
,
+#ifdef SYM_DEBUG_GENERIC_SUPPORT
+ {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ FE_BOF}
+ ,
+#else
{PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF}
,
- {PCI_ID_SYM53C825, 0x0f, "825", 6, 8, 4, 0,
+#endif
+ {PCI_ID_SYM53C815, 0xff, "815", 4, 8, 4, 64,
+ FE_BOF|FE_ERL}
+ ,
+ {PCI_ID_SYM53C825, 0x0f, "825", 6, 8, 4, 64,
FE_WIDE|FE_BOF|FE_ERL|FE_DIFF}
,
{PCI_ID_SYM53C825, 0xff, "825a", 6, 8, 4, 2,
@@ -9926,10 +8481,17 @@ static struct sym_pci_chip sym_pci_dev_table[] = {
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF}
,
+#ifdef SYM_DEBUG_GENERIC_SUPPORT
+ {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|
+ FE_RAM|FE_LCKFRQ}
+ ,
+#else
{PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_LCKFRQ}
,
+#endif
{PCI_ID_SYM53C896, 0xff, "896", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
@@ -9999,9 +8561,7 @@ sym_find_pci_chip(pcici_t pci_tag)
continue;
if (revision > chip->revision_id)
continue;
- if (FE_LDSTR & chip->features)
- return chip;
- break;
+ return chip;
}
return 0;
@@ -10017,7 +8577,7 @@ sym_pci_probe(device_t dev)
struct sym_pci_chip *chip;
chip = sym_find_pci_chip(dev);
- if (chip) {
+ if (chip && sym_find_firmware(chip)) {
device_set_desc(dev, chip->name);
return (chip->lp_probe_bit & SYM_SETUP_LP_PROBE_MAP)? -2000 : 0;
}
@@ -10030,13 +8590,15 @@ sym_pci_probe(pcici_t pci_tag, pcidi_t type)
struct sym_pci_chip *chip;
chip = sym_find_pci_chip(pci_tag);
+ if (chip && sym_find_firmware(chip)) {
#if NNCR > 0
/* Only claim chips we are allowed to take precedence over the ncr */
- if (chip && !(chip->lp_probe_bit & SYM_SETUP_LP_PROBE_MAP))
+ if (!(chip->lp_probe_bit & SYM_SETUP_LP_PROBE_MAP))
#else
- if (chip)
+ if (1)
#endif
return chip->name;
+ }
return 0;
}
#endif
@@ -10064,6 +8626,7 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
u_char cachelnsz;
struct sym_hcb *np = 0;
struct sym_nvram nvram;
+ struct sym_fw *fw = 0;
int i;
#ifdef FreeBSD_Bus_Dma_Abstraction
bus_dma_tag_t bus_dmat;
@@ -10084,7 +8647,7 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
#else
chip = sym_find_pci_chip(pci_tag);
#endif
- if (chip == NULL)
+ if (chip == NULL || (fw = sym_find_firmware(chip)) == NULL)
return (ENXIO);
/*
@@ -10125,6 +8688,11 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
np->clock_divn = chip->nr_divisor;
np->maxoffs = chip->offset_max;
np->maxburst = chip->burst_max;
+ np->scripta_sz = fw->a_size;
+ np->scriptb_sz = fw->b_size;
+ np->fw_setup = fw->setup;
+ np->fw_patch = fw->patch;
+ np->fw_name = fw->name;
/*
* Edit its name.
@@ -10347,6 +8915,7 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
np->dqueue = (u32 *) sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"DQUEUE");
if (!np->dqueue)
goto attach_failed;
+ np->dqueue_ba = vtobus(np->dqueue);
/*
* Allocate the target bus address array.
@@ -10354,14 +8923,13 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
np->targtbl = (u32 *) sym_calloc_dma(256, "TARGTBL");
if (!np->targtbl)
goto attach_failed;
+ np->targtbl_ba = cpu_to_scr(vtobus(np->targtbl));
/*
* Allocate SCRIPTS areas.
*/
- np->scripta0 = (struct sym_scra *)
- sym_calloc_dma(sizeof(struct sym_scra), "SCRIPTA0");
- np->scriptb0 = (struct sym_scrb *)
- sym_calloc_dma(sizeof(struct sym_scrb), "SCRIPTB0");
+ np->scripta0 = sym_calloc_dma(np->scripta_sz, "SCRIPTA0");
+ np->scriptb0 = sym_calloc_dma(np->scriptb_sz, "SCRIPTB0");
if (!np->scripta0 || !np->scriptb0)
goto attach_failed;
@@ -10381,11 +8949,6 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
sym_que_init(&np->cam_ccbq);
/*
- * Fill-up variable-size parts of the SCRIPTS.
- */
- sym_fill_scripts(&scripta0, &scriptb0);
-
- /*
* Calculate BUS addresses where we are going
* to load the SCRIPTS.
*/
@@ -10407,49 +8970,26 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
}
/*
- * Bind SCRIPTS with physical addresses usable by the
- * SCRIPTS processor (as seen from the BUS = BUS addresses).
+ * Copy scripts to controller instance.
*/
- sym_bind_script(np, (u32 *) &scripta0,
- (u32 *) np->scripta0, sizeof(struct sym_scra));
- sym_bind_script(np, (u32 *) &scriptb0,
- (u32 *) np->scriptb0, sizeof(struct sym_scrb));
+ bcopy(fw->a_base, np->scripta0, np->scripta_sz);
+ bcopy(fw->b_base, np->scriptb0, np->scriptb_sz);
/*
- * Patch some variables in SCRIPTS.
- * These ones are loaded by the SCRIPTS processor.
+ * Setup variable parts in scripts and compute
+ * scripts bus addresses used from the C code.
*/
- np->scriptb0->pm0_data_addr[0] = cpu_to_scr(SCRIPTA_BA (np, pm0_data));
- np->scriptb0->pm1_data_addr[0] = cpu_to_scr(SCRIPTA_BA (np, pm1_data));
-
+ np->fw_setup(np, fw);
/*
- * Still some for removing LED support.
- */
- if (!(np->features & FE_LED0)) {
- np->scripta0->idle[0] = cpu_to_scr(SCR_NO_OP);
- np->scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
- np->scripta0->start[0] = cpu_to_scr(SCR_NO_OP);
- }
-
- /*
- * Remove the load of SCNTL4 on reselection if not a C10.
+ * Bind SCRIPTS with physical addresses usable by the
+ * SCRIPTS processor (as seen from the BUS = BUS addresses).
*/
- if (!(np->features & FE_C10)) {
- np->scripta0->resel_scntl4[0] = cpu_to_scr(SCR_NO_OP);
- np->scripta0->resel_scntl4[1] = cpu_to_scr(0);
- }
+ sym_fw_bind_script(np, (u32 *) np->scripta0, np->scripta_sz);
+ sym_fw_bind_script(np, (u32 *) np->scriptb0, np->scriptb_sz);
#ifdef SYM_CONF_IARB_SUPPORT
/*
- * If user does not want to use IMMEDIATE ARBITRATION
- * when we are reselected while attempting to arbitrate,
- * patch the SCRIPTS accordingly with a SCRIPT NO_OP.
- */
- if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
- np->scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
-
- /*
* If user wants IARB to be set when we win arbitration
* and have other jobs, compute the max number of consecutive
* settings of IARB hints before we leave devices a chance to
@@ -10500,11 +9040,12 @@ sym_pci_attach2(pcici_t pci_tag, int unit)
* address of each target control bloc.
* For now, assume all logical unit are wrong. :)
*/
- np->scriptb0->targtbl[0] = cpu_to_scr(vtobus(np->targtbl));
for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
np->targtbl[i] = cpu_to_scr(vtobus(&np->target[i]));
- np->target[i].luntbl_sa = cpu_to_scr(vtobus(np->badluntbl));
- np->target[i].lun0_sa = cpu_to_scr(vtobus(&np->badlun_sa));
+ np->target[i].head.luntbl_sa =
+ cpu_to_scr(vtobus(np->badluntbl));
+ np->target[i].head.lun0_sa =
+ cpu_to_scr(vtobus(&np->badlun_sa));
}
/*
@@ -10587,9 +9128,9 @@ static void sym_pci_free(hcb_p np)
#endif
if (np->scriptb0)
- sym_mfree_dma(np->scriptb0, sizeof(struct sym_scrb),"SCRIPTB0");
+ sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0");
if (np->scripta0)
- sym_mfree_dma(np->scripta0, sizeof(struct sym_scra),"SCRIPTA0");
+ sym_mfree_dma(np->scripta0, np->scripta_sz, "SCRIPTA0");
if (np->squeue)
sym_mfree_dma(np->squeue, sizeof(u32)*(MAX_QUEUE*2), "SQUEUE");
if (np->dqueue)
OpenPOWER on IntegriCloud