diff options
Diffstat (limited to 'sys/dev/asr/asr.c')
-rw-r--r-- | sys/dev/asr/asr.c | 7958 |
1 files changed, 3979 insertions, 3979 deletions
diff --git a/sys/dev/asr/asr.c b/sys/dev/asr/asr.c index a3c8d1d..16aaabb 100644 --- a/sys/dev/asr/asr.c +++ b/sys/dev/asr/asr.c @@ -22,121 +22,121 @@ * * SCSI I2O host adapter driver * - * V1.08 2001/08/21 Mark_Salyzyn@adaptec.com - * - The 2000S and 2005S do not initialize on some machines, + * V1.08 2001/08/21 Mark_Salyzyn@adaptec.com + * - The 2000S and 2005S do not initialize on some machines, * increased timeout to 255ms from 50ms for the StatusGet * command. - * V1.07 2001/05/22 Mark_Salyzyn@adaptec.com - * - I knew this one was too good to be true. The error return - * on ioctl commands needs to be compared to CAM_REQ_CMP, not - * to the bit masked status. - * V1.06 2001/05/08 Mark_Salyzyn@adaptec.com - * - The 2005S that was supported is affectionately called the - * Conjoined BAR Firmware. In order to support RAID-5 in a - * 16MB low-cost configuration, Firmware was forced to go - * to a Split BAR Firmware. This requires a separate IOP and - * Messaging base address. - * V1.05 2001/04/25 Mark_Salyzyn@adaptec.com - * - Handle support for 2005S Zero Channel RAID solution. - * - System locked up if the Adapter locked up. Do not try - * to send other commands if the resetIOP command fails. The - * fail outstanding command discovery loop was flawed as the - * removal of the command from the list prevented discovering - * all the commands. - * - Comment changes to clarify driver. - * - SysInfo searched for an EATA SmartROM, not an I2O SmartROM. - * - We do not use the AC_FOUND_DEV event because of I2O. - * Removed asr_async. - * V1.04 2000/09/22 Mark_Salyzyn@adaptec.com, msmith@freebsd.org, - * lampa@fee.vutbr.cz and Scott_Long@adaptec.com. - * - Removed support for PM1554, PM2554 and PM2654 in Mode-0 - * mode as this is confused with competitor adapters in run - * mode. - * - critical locking needed in ASR_ccbAdd and ASR_ccbRemove - * to prevent operating system panic. - * - moved default major number to 154 from 97. - * V1.03 2000/07/12 Mark_Salyzyn@adaptec.com - * - The controller is not actually an ASR (Adaptec SCSI RAID) - * series that is visible, it's more of an internal code name. - * remove any visible references within reason for now. - * - bus_ptr->LUN was not correctly zeroed when initially - * allocated causing a possible panic of the operating system - * during boot. - * V1.02 2000/06/26 Mark_Salyzyn@adaptec.com - * - Code always fails for ASR_getTid affecting performance. - * - initiated a set of changes that resulted from a formal - * code inspection by Mark_Salyzyn@adaptec.com, - * George_Dake@adaptec.com, Jeff_Zeak@adaptec.com, - * Martin_Wilson@adaptec.com and Vincent_Trandoan@adaptec.com. - * Their findings were focussed on the LCT & TID handler, and - * all resulting changes were to improve code readability, - * consistency or have a positive effect on performance. - * V1.01 2000/06/14 Mark_Salyzyn@adaptec.com - * - Passthrough returned an incorrect error. - * - Passthrough did not migrate the intrinsic scsi layer wakeup - * on command completion. - * - generate control device nodes using make_dev and delete_dev. - * - Performance affected by TID caching reallocing. - * - Made suggested changes by Justin_Gibbs@adaptec.com - * - use splcam instead of splbio. - * - use cam_imask instead of bio_imask. - * - use u_int8_t instead of u_char. - * - use u_int16_t instead of u_short. - * - use u_int32_t instead of u_long where appropriate. - * - use 64 bit context handler instead of 32 bit. - * - create_ccb should only allocate the worst case - * requirements for the driver since CAM may evolve - * making union ccb much larger than needed here. - * renamed create_ccb to asr_alloc_ccb. - * - go nutz justifying all debug prints as macros - * defined at the top and remove unsightly ifdefs. - * - INLINE STATIC viewed as confusing. Historically - * utilized to affect code performance and debug - * issues in OS, Compiler or OEM specific situations. - * V1.00 2000/05/31 Mark_Salyzyn@adaptec.com - * - Ported from FreeBSD 2.2.X DPT I2O driver. - * changed struct scsi_xfer to union ccb/struct ccb_hdr - * changed variable name xs to ccb - * changed struct scsi_link to struct cam_path - * changed struct scsibus_data to struct cam_sim - * stopped using fordriver for holding on to the TID - * use proprietary packet creation instead of scsi_inquire - * CAM layer sends synchronize commands. + * V1.07 2001/05/22 Mark_Salyzyn@adaptec.com + * - I knew this one was too good to be true. The error return + * on ioctl commands needs to be compared to CAM_REQ_CMP, not + * to the bit masked status. + * V1.06 2001/05/08 Mark_Salyzyn@adaptec.com + * - The 2005S that was supported is affectionately called the + * Conjoined BAR Firmware. In order to support RAID-5 in a + * 16MB low-cost configuration, Firmware was forced to go + * to a Split BAR Firmware. This requires a separate IOP and + * Messaging base address. + * V1.05 2001/04/25 Mark_Salyzyn@adaptec.com + * - Handle support for 2005S Zero Channel RAID solution. + * - System locked up if the Adapter locked up. Do not try + * to send other commands if the resetIOP command fails. The + * fail outstanding command discovery loop was flawed as the + * removal of the command from the list prevented discovering + * all the commands. + * - Comment changes to clarify driver. + * - SysInfo searched for an EATA SmartROM, not an I2O SmartROM. + * - We do not use the AC_FOUND_DEV event because of I2O. + * Removed asr_async. + * V1.04 2000/09/22 Mark_Salyzyn@adaptec.com, msmith@freebsd.org, + * lampa@fee.vutbr.cz and Scott_Long@adaptec.com. + * - Removed support for PM1554, PM2554 and PM2654 in Mode-0 + * mode as this is confused with competitor adapters in run + * mode. + * - critical locking needed in ASR_ccbAdd and ASR_ccbRemove + * to prevent operating system panic. + * - moved default major number to 154 from 97. + * V1.03 2000/07/12 Mark_Salyzyn@adaptec.com + * - The controller is not actually an ASR (Adaptec SCSI RAID) + * series that is visible, it's more of an internal code name. + * remove any visible references within reason for now. + * - bus_ptr->LUN was not correctly zeroed when initially + * allocated causing a possible panic of the operating system + * during boot. + * V1.02 2000/06/26 Mark_Salyzyn@adaptec.com + * - Code always fails for ASR_getTid affecting performance. + * - initiated a set of changes that resulted from a formal + * code inspection by Mark_Salyzyn@adaptec.com, + * George_Dake@adaptec.com, Jeff_Zeak@adaptec.com, + * Martin_Wilson@adaptec.com and Vincent_Trandoan@adaptec.com. + * Their findings were focussed on the LCT & TID handler, and + * all resulting changes were to improve code readability, + * consistency or have a positive effect on performance. + * V1.01 2000/06/14 Mark_Salyzyn@adaptec.com + * - Passthrough returned an incorrect error. + * - Passthrough did not migrate the intrinsic scsi layer wakeup + * on command completion. + * - generate control device nodes using make_dev and delete_dev. + * - Performance affected by TID caching reallocing. + * - Made suggested changes by Justin_Gibbs@adaptec.com + * - use splcam instead of splbio. + * - use cam_imask instead of bio_imask. + * - use u_int8_t instead of u_char. + * - use u_int16_t instead of u_short. + * - use u_int32_t instead of u_long where appropriate. + * - use 64 bit context handler instead of 32 bit. + * - create_ccb should only allocate the worst case + * requirements for the driver since CAM may evolve + * making union ccb much larger than needed here. + * renamed create_ccb to asr_alloc_ccb. + * - go nutz justifying all debug prints as macros + * defined at the top and remove unsightly ifdefs. + * - INLINE STATIC viewed as confusing. Historically + * utilized to affect code performance and debug + * issues in OS, Compiler or OEM specific situations. + * V1.00 2000/05/31 Mark_Salyzyn@adaptec.com + * - Ported from FreeBSD 2.2.X DPT I2O driver. + * changed struct scsi_xfer to union ccb/struct ccb_hdr + * changed variable name xs to ccb + * changed struct scsi_link to struct cam_path + * changed struct scsibus_data to struct cam_sim + * stopped using fordriver for holding on to the TID + * use proprietary packet creation instead of scsi_inquire + * CAM layer sends synchronize commands. * * $FreeBSD$ */ -#define ASR_VERSION 1 -#define ASR_REVISION '0' -#define ASR_SUBREVISION '8' -#define ASR_MONTH 8 -#define ASR_DAY 21 -#define ASR_YEAR 2001 - 1980 +#define ASR_VERSION 1 +#define ASR_REVISION '0' +#define ASR_SUBREVISION '8' +#define ASR_MONTH 8 +#define ASR_DAY 21 +#define ASR_YEAR 2001 - 1980 /* - * Debug macros to reduce the unsightly ifdefs + * Debug macros to reduce the unsightly ifdefs */ #if (defined(DEBUG_ASR) || defined(DEBUG_ASR_USR_CMD) || defined(DEBUG_ASR_CMD)) -# define debug_asr_message(message) \ - { \ - u_int32_t * pointer = (u_int32_t *)message; \ - u_int32_t length = I2O_MESSAGE_FRAME_getMessageSize(message);\ - u_int32_t counter = 0; \ - \ - while (length--) { \ - printf ("%08lx%c", (u_long)*(pointer++), \ - (((++counter & 7) == 0) || (length == 0)) \ - ? '\n' \ - : ' '); \ - } \ - } +# define debug_asr_message(message) \ + { \ + u_int32_t * pointer = (u_int32_t *)message; \ + u_int32_t length = I2O_MESSAGE_FRAME_getMessageSize(message);\ + u_int32_t counter = 0; \ + \ + while (length--) { \ + printf ("%08lx%c", (u_long)*(pointer++), \ + (((++counter & 7) == 0) || (length == 0)) \ + ? '\n' \ + : ' '); \ + } \ + } #endif /* DEBUG_ASR || DEBUG_ASR_USR_CMD || DEBUG_ASR_CMD */ #if (defined(DEBUG_ASR)) /* Breaks on none STDC based compilers :-( */ -# define debug_asr_printf(fmt,args...) printf(fmt, ##args) +# define debug_asr_printf(fmt,args...) printf(fmt, ##args) # define debug_asr_dump_message(message) debug_asr_message(message) -# define debug_asr_print_path(ccb) xpt_print_path(ccb->ccb_h.path); +# define debug_asr_print_path(ccb) xpt_print_path(ccb->ccb_h.path); /* None fatal version of the ASSERT macro */ # if (defined(__STDC__)) # define ASSERT(phrase) if(!(phrase))printf(#phrase " at line %d file %s\n",__LINE__,__FILE__) @@ -151,30 +151,30 @@ #endif /* DEBUG_ASR */ /* - * If DEBUG_ASR_CMD is defined: - * 0 - Display incoming SCSI commands - * 1 - add in a quick character before queueing. - * 2 - add in outgoing message frames. + * If DEBUG_ASR_CMD is defined: + * 0 - Display incoming SCSI commands + * 1 - add in a quick character before queueing. + * 2 - add in outgoing message frames. */ #if (defined(DEBUG_ASR_CMD)) # define debug_asr_cmd_printf(fmt,args...) printf(fmt,##args) -# define debug_asr_dump_ccb(ccb) \ - { \ - u_int8_t * cp = (unsigned char *)&(ccb->csio.cdb_io); \ - int len = ccb->csio.cdb_len; \ - \ - while (len) { \ - debug_asr_cmd_printf (" %02x", *(cp++)); \ - --len; \ - } \ - } +# define debug_asr_dump_ccb(ccb) \ + { \ + u_int8_t * cp = (unsigned char *)&(ccb->csio.cdb_io); \ + int len = ccb->csio.cdb_len; \ + \ + while (len) { \ + debug_asr_cmd_printf (" %02x", *(cp++)); \ + --len; \ + } \ + } # if (DEBUG_ASR_CMD > 0) -# define debug_asr_cmd1_printf debug_asr_cmd_printf +# define debug_asr_cmd1_printf debug_asr_cmd_printf # else # define debug_asr_cmd1_printf(fmt,args...) # endif # if (DEBUG_ASR_CMD > 1) -# define debug_asr_cmd2_printf debug_asr_cmd_printf +# define debug_asr_cmd2_printf debug_asr_cmd_printf # define debug_asr_cmd2_dump_message(message) debug_asr_message(message) # else # define debug_asr_cmd2_printf(fmt,args...) @@ -196,22 +196,22 @@ # define debug_usr_cmd_dump_message(message) #endif /* DEBUG_ASR_USR_CMD */ -#define dsDescription_size 46 /* Snug as a bug in a rug */ +#define dsDescription_size 46 /* Snug as a bug in a rug */ #include "dev/asr/dptsig.h" static dpt_sig_S ASR_sig = { - { 'd', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, PROC_INTEL, - PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, FT_HBADRVR, 0, - OEM_DPT, OS_FREE_BSD, CAP_ABOVE16MB, DEV_ALL, - ADF_ALL_SC5, - 0, 0, ASR_VERSION, ASR_REVISION, ASR_SUBREVISION, - ASR_MONTH, ASR_DAY, ASR_YEAR, -/* 01234567890123456789012345678901234567890123456789 < 50 chars */ - "Adaptec FreeBSD 4.0.0 Unix SCSI I2O HBA Driver" - /* ^^^^^ asr_attach alters these to match OS */ + { 'd', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, PROC_INTEL, + PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, FT_HBADRVR, 0, + OEM_DPT, OS_FREE_BSD, CAP_ABOVE16MB, DEV_ALL, + ADF_ALL_SC5, + 0, 0, ASR_VERSION, ASR_REVISION, ASR_SUBREVISION, + ASR_MONTH, ASR_DAY, ASR_YEAR, +/* 01234567890123456789012345678901234567890123456789 < 50 chars */ + "Adaptec FreeBSD 4.0.0 Unix SCSI I2O HBA Driver" + /* ^^^^^ asr_attach alters these to match OS */ }; -#include <sys/param.h> /* TRUE=1 and FALSE=0 defined here */ +#include <sys/param.h> /* TRUE=1 and FALSE=0 defined here */ #include <sys/kernel.h> #include <sys/systm.h> #include <sys/malloc.h> @@ -246,8 +246,8 @@ static dpt_sig_S ASR_sig = { #include <pci/pcivar.h> #include <pci/pcireg.h> -#define STATIC static -#define INLINE +#define STATIC static +#define INLINE #if (defined(DEBUG_ASR) && (DEBUG_ASR > 0)) # undef STATIC @@ -255,33 +255,33 @@ static dpt_sig_S ASR_sig = { # undef INLINE # define INLINE #endif -#define IN -#define OUT -#define INOUT +#define IN +#define OUT +#define INOUT -#define osdSwap4(x) ((u_long)ntohl((u_long)(x))) -#define KVTOPHYS(x) vtophys(x) -#include "dev/asr/dptalign.h" -#include "dev/asr/i2oexec.h" -#include "dev/asr/i2obscsi.h" -#include "dev/asr/i2odpt.h" -#include "dev/asr/i2oadptr.h" -#include "opt_asr.h" +#define osdSwap4(x) ((u_long)ntohl((u_long)(x))) +#define KVTOPHYS(x) vtophys(x) +#include "dev/asr/dptalign.h" +#include "dev/asr/i2oexec.h" +#include "dev/asr/i2obscsi.h" +#include "dev/asr/i2odpt.h" +#include "dev/asr/i2oadptr.h" +#include "opt_asr.h" -#include "dev/asr/sys_info.h" +#include "dev/asr/sys_info.h" /* Configuration Definitions */ -#define SG_SIZE 58 /* Scatter Gather list Size */ -#define MAX_TARGET_ID 126 /* Maximum Target ID supported */ -#define MAX_LUN 255 /* Maximum LUN Supported */ -#define MAX_CHANNEL 7 /* Maximum Channel # Supported by driver */ -#define MAX_INBOUND 2000 /* Max CCBs, Also Max Queue Size */ -#define MAX_OUTBOUND 256 /* Maximum outbound frames/adapter */ -#define MAX_INBOUND_SIZE 512 /* Maximum inbound frame size */ -#define MAX_MAP 4194304L /* Maximum mapping size of IOP */ - /* Also serves as the minimum map for */ - /* the 2005S zero channel RAID product */ +#define SG_SIZE 58 /* Scatter Gather list Size */ +#define MAX_TARGET_ID 126 /* Maximum Target ID supported */ +#define MAX_LUN 255 /* Maximum LUN Supported */ +#define MAX_CHANNEL 7 /* Maximum Channel # Supported by driver */ +#define MAX_INBOUND 2000 /* Max CCBs, Also Max Queue Size */ +#define MAX_OUTBOUND 256 /* Maximum outbound frames/adapter */ +#define MAX_INBOUND_SIZE 512 /* Maximum inbound frame size */ +#define MAX_MAP 4194304L /* Maximum mapping size of IOP */ + /* Also serves as the minimum map for */ + /* the 2005S zero channel RAID product */ /************************************************************************** ** ASR Host Adapter structure - One Structure For Each Host Adapter That ** @@ -291,13 +291,13 @@ static dpt_sig_S ASR_sig = { /* I2O register set */ typedef struct { - U8 Address[0x30]; - volatile U32 Status; - volatile U32 Mask; -# define Mask_InterruptsDisabled 0x08 - U32 x[2]; - volatile U32 ToFIFO; /* In Bound FIFO */ - volatile U32 FromFIFO; /* Out Bound FIFO */ + U8 Address[0x30]; + volatile U32 Status; + volatile U32 Mask; +# define Mask_InterruptsDisabled 0x08 + U32 x[2]; + volatile U32 ToFIFO; /* In Bound FIFO */ + volatile U32 FromFIFO; /* Out Bound FIFO */ } i2oRegs_t; /* @@ -306,141 +306,141 @@ typedef struct { typedef u_int16_t tid_t; typedef struct { - u_int32_t size; /* up to MAX_LUN */ - tid_t TID[1]; + u_int32_t size; /* up to MAX_LUN */ + tid_t TID[1]; } lun2tid_t; typedef struct { - u_int32_t size; /* up to MAX_TARGET */ - lun2tid_t * LUN[1]; + u_int32_t size; /* up to MAX_TARGET */ + lun2tid_t * LUN[1]; } target2lun_t; /* - * To ensure that we only allocate and use the worst case ccb here, lets - * make our own local ccb union. If asr_alloc_ccb is utilized for another - * ccb type, ensure that you add the additional structures into our local - * ccb union. To ensure strict type checking, we will utilize the local - * ccb definition wherever possible. + * To ensure that we only allocate and use the worst case ccb here, lets + * make our own local ccb union. If asr_alloc_ccb is utilized for another + * ccb type, ensure that you add the additional structures into our local + * ccb union. To ensure strict type checking, we will utilize the local + * ccb definition wherever possible. */ union asr_ccb { - struct ccb_hdr ccb_h; /* For convenience */ - struct ccb_scsiio csio; - struct ccb_setasync csa; + struct ccb_hdr ccb_h; /* For convenience */ + struct ccb_scsiio csio; + struct ccb_setasync csa; }; typedef struct Asr_softc { - u_int16_t ha_irq; - void * ha_Base; /* base port for each board */ - u_int8_t * volatile ha_blinkLED; - i2oRegs_t * ha_Virt; /* Base address of IOP */ - U8 * ha_Fvirt; /* Base address of Frames */ - I2O_IOP_ENTRY ha_SystemTable; - LIST_HEAD(,ccb_hdr) ha_ccb; /* ccbs in use */ - struct cam_path * ha_path[MAX_CHANNEL+1]; - struct cam_sim * ha_sim[MAX_CHANNEL+1]; + u_int16_t ha_irq; + void * ha_Base; /* base port for each board */ + u_int8_t * volatile ha_blinkLED; + i2oRegs_t * ha_Virt; /* Base address of IOP */ + U8 * ha_Fvirt; /* Base address of Frames */ + I2O_IOP_ENTRY ha_SystemTable; + LIST_HEAD(,ccb_hdr) ha_ccb; /* ccbs in use */ + struct cam_path * ha_path[MAX_CHANNEL+1]; + struct cam_sim * ha_sim[MAX_CHANNEL+1]; #if __FreeBSD_version >= 400000 - struct resource * ha_mem_res; - struct resource * ha_mes_res; - struct resource * ha_irq_res; - void * ha_intr; + struct resource * ha_mem_res; + struct resource * ha_mes_res; + struct resource * ha_irq_res; + void * ha_intr; #endif - PI2O_LCT ha_LCT; /* Complete list of devices */ -# define le_type IdentityTag[0] -# define I2O_BSA 0x20 -# define I2O_FCA 0x40 -# define I2O_SCSI 0x00 -# define I2O_PORT 0x80 -# define I2O_UNKNOWN 0x7F -# define le_bus IdentityTag[1] -# define le_target IdentityTag[2] -# define le_lun IdentityTag[3] - target2lun_t * ha_targets[MAX_CHANNEL+1]; - PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME ha_Msgs; - u_long ha_Msgs_Phys; - - u_int8_t ha_in_reset; -# define HA_OPERATIONAL 0 -# define HA_IN_RESET 1 -# define HA_OFF_LINE 2 -# define HA_OFF_LINE_RECOVERY 3 - /* Configuration information */ - /* The target id maximums we take */ - u_int8_t ha_MaxBus; /* Maximum bus */ - u_int8_t ha_MaxId; /* Maximum target ID */ - u_int8_t ha_MaxLun; /* Maximum target LUN */ - u_int8_t ha_SgSize; /* Max SG elements */ - u_int8_t ha_pciBusNum; - u_int8_t ha_pciDeviceNum; - u_int8_t ha_adapter_target[MAX_CHANNEL+1]; - u_int16_t ha_QueueSize; /* Max outstanding commands */ - u_int16_t ha_Msgs_Count; - - /* Links into other parents and HBAs */ - struct Asr_softc * ha_next; /* HBA list */ + PI2O_LCT ha_LCT; /* Complete list of devices */ +# define le_type IdentityTag[0] +# define I2O_BSA 0x20 +# define I2O_FCA 0x40 +# define I2O_SCSI 0x00 +# define I2O_PORT 0x80 +# define I2O_UNKNOWN 0x7F +# define le_bus IdentityTag[1] +# define le_target IdentityTag[2] +# define le_lun IdentityTag[3] + target2lun_t * ha_targets[MAX_CHANNEL+1]; + PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME ha_Msgs; + u_long ha_Msgs_Phys; + + u_int8_t ha_in_reset; +# define HA_OPERATIONAL 0 +# define HA_IN_RESET 1 +# define HA_OFF_LINE 2 +# define HA_OFF_LINE_RECOVERY 3 + /* Configuration information */ + /* The target id maximums we take */ + u_int8_t ha_MaxBus; /* Maximum bus */ + u_int8_t ha_MaxId; /* Maximum target ID */ + u_int8_t ha_MaxLun; /* Maximum target LUN */ + u_int8_t ha_SgSize; /* Max SG elements */ + u_int8_t ha_pciBusNum; + u_int8_t ha_pciDeviceNum; + u_int8_t ha_adapter_target[MAX_CHANNEL+1]; + u_int16_t ha_QueueSize; /* Max outstanding commands */ + u_int16_t ha_Msgs_Count; + + /* Links into other parents and HBAs */ + struct Asr_softc * ha_next; /* HBA list */ #ifdef ASR_MEASURE_PERFORMANCE -#define MAX_TIMEQ_SIZE 256 /* assumes MAX 256 scsi commands sent */ - asr_perf_t ha_performance; - u_int32_t ha_submitted_ccbs_count; - - /* Queueing macros for a circular queue */ -#define TIMEQ_FREE_LIST_EMPTY(head, tail) (-1 == (head) && -1 == (tail)) -#define TIMEQ_FREE_LIST_FULL(head, tail) ((((tail) + 1) % MAX_TIMEQ_SIZE) == (head)) -#define ENQ_TIMEQ_FREE_LIST(item, Q, head, tail) \ - if (!TIMEQ_FREE_LIST_FULL((head), (tail))) { \ - if TIMEQ_FREE_LIST_EMPTY((head),(tail)) { \ - (head) = (tail) = 0; \ - } \ - else (tail) = ((tail) + 1) % MAX_TIMEQ_SIZE; \ - Q[(tail)] = (item); \ - } \ - else { \ - debug_asr_printf("asr: Enqueueing when TimeQ Free List is full... This should not happen!\n"); \ - } -#define DEQ_TIMEQ_FREE_LIST(item, Q, head, tail) \ - if (!TIMEQ_FREE_LIST_EMPTY((head), (tail))) { \ - item = Q[(head)]; \ - if ((head) == (tail)) { (head) = (tail) = -1; } \ - else (head) = ((head) + 1) % MAX_TIMEQ_SIZE; \ - } \ - else { \ - (item) = -1; \ - debug_asr_printf("asr: Dequeueing when TimeQ Free List is empty... This should not happen!\n"); \ - } - - /* Circular queue of time stamps */ - struct timeval ha_timeQ[MAX_TIMEQ_SIZE]; - u_int32_t ha_timeQFreeList[MAX_TIMEQ_SIZE]; - int ha_timeQFreeHead; - int ha_timeQFreeTail; +#define MAX_TIMEQ_SIZE 256 /* assumes MAX 256 scsi commands sent */ + asr_perf_t ha_performance; + u_int32_t ha_submitted_ccbs_count; + + /* Queueing macros for a circular queue */ +#define TIMEQ_FREE_LIST_EMPTY(head, tail) (-1 == (head) && -1 == (tail)) +#define TIMEQ_FREE_LIST_FULL(head, tail) ((((tail) + 1) % MAX_TIMEQ_SIZE) == (head)) +#define ENQ_TIMEQ_FREE_LIST(item, Q, head, tail) \ + if (!TIMEQ_FREE_LIST_FULL((head), (tail))) { \ + if TIMEQ_FREE_LIST_EMPTY((head),(tail)) { \ + (head) = (tail) = 0; \ + } \ + else (tail) = ((tail) + 1) % MAX_TIMEQ_SIZE; \ + Q[(tail)] = (item); \ + } \ + else { \ + debug_asr_printf("asr: Enqueueing when TimeQ Free List is full... This should not happen!\n"); \ + } +#define DEQ_TIMEQ_FREE_LIST(item, Q, head, tail) \ + if (!TIMEQ_FREE_LIST_EMPTY((head), (tail))) { \ + item = Q[(head)]; \ + if ((head) == (tail)) { (head) = (tail) = -1; } \ + else (head) = ((head) + 1) % MAX_TIMEQ_SIZE; \ + } \ + else { \ + (item) = -1; \ + debug_asr_printf("asr: Dequeueing when TimeQ Free List is empty... This should not happen!\n"); \ + } + + /* Circular queue of time stamps */ + struct timeval ha_timeQ[MAX_TIMEQ_SIZE]; + u_int32_t ha_timeQFreeList[MAX_TIMEQ_SIZE]; + int ha_timeQFreeHead; + int ha_timeQFreeTail; #endif } Asr_softc_t; STATIC Asr_softc_t * Asr_softc; /* - * Prototypes of the routines we have in this object. + * Prototypes of the routines we have in this object. */ /* Externally callable routines */ #if __FreeBSD_version >= 400000 -#define PROBE_ARGS IN device_t tag -#define PROBE_RET int -#define PROBE_SET() u_int32_t id = (pci_get_device(tag)<<16)|pci_get_vendor(tag) -#define PROBE_RETURN(retval) if(retval){device_set_desc(tag,retval);return(0);}else{return(ENXIO);} -#define ATTACH_ARGS IN device_t tag -#define ATTACH_RET int -#define ATTACH_SET() int unit = device_get_unit(tag) -#define ATTACH_RETURN(retval) return(retval) +#define PROBE_ARGS IN device_t tag +#define PROBE_RET int +#define PROBE_SET() u_int32_t id = (pci_get_device(tag)<<16)|pci_get_vendor(tag) +#define PROBE_RETURN(retval) if(retval){device_set_desc(tag,retval);return(0);}else{return(ENXIO);} +#define ATTACH_ARGS IN device_t tag +#define ATTACH_RET int +#define ATTACH_SET() int unit = device_get_unit(tag) +#define ATTACH_RETURN(retval) return(retval) #else -#define PROBE_ARGS IN pcici_t tag, IN pcidi_t id -#define PROBE_RET const char * -#define PROBE_SET() -#define PROBE_RETURN(retval) return(retval) -#define ATTACH_ARGS IN pcici_t tag, IN int unit -#define ATTACH_RET void -#define ATTACH_SET() -#define ATTACH_RETURN(retval) return +#define PROBE_ARGS IN pcici_t tag, IN pcidi_t id +#define PROBE_RET const char * +#define PROBE_SET() +#define PROBE_RETURN(retval) return(retval) +#define ATTACH_ARGS IN pcici_t tag, IN int unit +#define ATTACH_RET void +#define ATTACH_SET() +#define ATTACH_RETURN(retval) return #endif /* I2O HDM interface */ STATIC PROBE_RET asr_probe(PROBE_ARGS); @@ -453,54 +453,54 @@ STATIC PROBE_RET mode0_probe(PROBE_ARGS); STATIC ATTACH_RET mode0_attach(ATTACH_ARGS); STATIC Asr_softc_t * ASR_get_sc( - IN dev_t dev); -STATIC int asr_ioctl( - IN dev_t dev, - IN u_long cmd, - INOUT caddr_t data, - int flag, - struct thread * td); -STATIC int asr_open( - IN dev_t dev, - int32_t flags, - int32_t ifmt, - IN struct thread * td); -STATIC int asr_close( - dev_t dev, - int flags, - int ifmt, - struct thread * td); -STATIC int asr_intr( - IN Asr_softc_t * sc); -STATIC void asr_timeout( - INOUT void * arg); -STATIC int ASR_init( - IN Asr_softc_t * sc); + IN dev_t dev); +STATIC int asr_ioctl( + IN dev_t dev, + IN u_long cmd, + INOUT caddr_t data, + int flag, + struct thread * td); +STATIC int asr_open( + IN dev_t dev, + int32_t flags, + int32_t ifmt, + IN struct thread * td); +STATIC int asr_close( + dev_t dev, + int flags, + int ifmt, + struct thread * td); +STATIC int asr_intr( + IN Asr_softc_t * sc); +STATIC void asr_timeout( + INOUT void * arg); +STATIC int ASR_init( + IN Asr_softc_t * sc); STATIC INLINE int ASR_acquireLct( - INOUT Asr_softc_t * sc); + INOUT Asr_softc_t * sc); STATIC INLINE int ASR_acquireHrt( - INOUT Asr_softc_t * sc); -STATIC void asr_action( - IN struct cam_sim * sim, - IN union ccb * ccb); -STATIC void asr_poll( - IN struct cam_sim * sim); + INOUT Asr_softc_t * sc); +STATIC void asr_action( + IN struct cam_sim * sim, + IN union ccb * ccb); +STATIC void asr_poll( + IN struct cam_sim * sim); /* - * Here is the auto-probe structure used to nest our tests appropriately - * during the startup phase of the operating system. + * Here is the auto-probe structure used to nest our tests appropriately + * during the startup phase of the operating system. */ #if __FreeBSD_version >= 400000 STATIC device_method_t asr_methods[] = { - DEVMETHOD(device_probe, asr_probe), - DEVMETHOD(device_attach, asr_attach), - { 0, 0 } + DEVMETHOD(device_probe, asr_probe), + DEVMETHOD(device_attach, asr_attach), + { 0, 0 } }; STATIC driver_t asr_driver = { - "asr", - asr_methods, - sizeof(Asr_softc_t) + "asr", + asr_methods, + sizeof(Asr_softc_t) }; STATIC devclass_t asr_devclass; @@ -508,15 +508,15 @@ STATIC devclass_t asr_devclass; DRIVER_MODULE(asr, pci, asr_driver, asr_devclass, 0, 0); STATIC device_method_t domino_methods[] = { - DEVMETHOD(device_probe, domino_probe), - DEVMETHOD(device_attach, domino_attach), - { 0, 0 } + DEVMETHOD(device_probe, domino_probe), + DEVMETHOD(device_attach, domino_attach), + { 0, 0 } }; STATIC driver_t domino_driver = { - "domino", - domino_methods, - 0 + "domino", + domino_methods, + 0 }; STATIC devclass_t domino_devclass; @@ -524,15 +524,15 @@ STATIC devclass_t domino_devclass; DRIVER_MODULE(domino, pci, domino_driver, domino_devclass, 0, 0); STATIC device_method_t mode0_methods[] = { - DEVMETHOD(device_probe, mode0_probe), - DEVMETHOD(device_attach, mode0_attach), - { 0, 0 } + DEVMETHOD(device_probe, mode0_probe), + DEVMETHOD(device_attach, mode0_attach), + { 0, 0 } }; STATIC driver_t mode0_driver = { - "mode0", - mode0_methods, - 0 + "mode0", + mode0_methods, + 0 }; STATIC devclass_t mode0_devclass; @@ -541,31 +541,31 @@ DRIVER_MODULE(mode0, pci, mode0_driver, mode0_devclass, 0, 0); #else STATIC u_long asr_pcicount = 0; STATIC struct pci_device asr_pcidev = { - "asr", - asr_probe, - asr_attach, - &asr_pcicount, - NULL + "asr", + asr_probe, + asr_attach, + &asr_pcicount, + NULL }; DATA_SET (asr_pciset, asr_pcidev); STATIC u_long domino_pcicount = 0; STATIC struct pci_device domino_pcidev = { - "domino", - domino_probe, - domino_attach, - &domino_pcicount, - NULL + "domino", + domino_probe, + domino_attach, + &domino_pcicount, + NULL }; DATA_SET (domino_pciset, domino_pcidev); STATIC u_long mode0_pcicount = 0; STATIC struct pci_device mode0_pcidev = { - "mode0", - mode0_probe, - mode0_attach, - &mode0_pcicount, - NULL + "mode0", + mode0_probe, + mode0_attach, + &mode0_pcicount, + NULL }; DATA_SET (mode0_pciset, mode0_pcidev); #endif @@ -575,26 +575,26 @@ DATA_SET (mode0_pciset, mode0_pcidev); * * only ioctl is used. the sd driver provides all other access. */ -#define CDEV_MAJOR 154 /* preferred default character major */ +#define CDEV_MAJOR 154 /* preferred default character major */ STATIC struct cdevsw asr_cdevsw = { - asr_open, /* open */ - asr_close, /* close */ - noread, /* read */ - nowrite, /* write */ - asr_ioctl, /* ioctl */ - nopoll, /* poll */ - nommap, /* mmap */ - nostrategy, /* strategy */ - "asr", /* name */ - CDEV_MAJOR, /* maj */ - nodump, /* dump */ - nopsize, /* psize */ - 0, /* flags */ + asr_open, /* open */ + asr_close, /* close */ + noread, /* read */ + nowrite, /* write */ + asr_ioctl, /* ioctl */ + nopoll, /* poll */ + nommap, /* mmap */ + nostrategy, /* strategy */ + "asr", /* name */ + CDEV_MAJOR, /* maj */ + nodump, /* dump */ + nopsize, /* psize */ + 0, /* flags */ }; #ifdef ASR_MEASURE_PERFORMANCE -STATIC u_int32_t asr_time_delta(IN struct timeval start, - IN struct timeval end); +STATIC u_int32_t asr_time_delta(IN struct timeval start, + IN struct timeval end); #endif #ifdef ASR_VERY_BROKEN @@ -603,36 +603,36 @@ STATIC u_int32_t asr_time_delta(IN struct timeval start, */ STATIC void asr_drvinit ( - void * unused) + void * unused) { - static int asr_devsw_installed = 0; - - if (asr_devsw_installed) { - return; - } - asr_devsw_installed++; - /* - * Find a free spot (the report during driver load used by - * osd layer in engine to generate the controlling nodes). - */ - while ((asr_cdevsw.d_maj < NUMCDEVSW) - && (devsw(makedev(asr_cdevsw.d_maj,0)) != (struct cdevsw *)NULL)) { - ++asr_cdevsw.d_maj; - } - if (asr_cdevsw.d_maj >= NUMCDEVSW) for ( - asr_cdevsw.d_maj = 0; - (asr_cdevsw.d_maj < CDEV_MAJOR) - && (devsw(makedev(asr_cdevsw.d_maj,0)) != (struct cdevsw *)NULL); - ++asr_cdevsw.d_maj); - /* - * Come to papa - */ - cdevsw_add(&asr_cdevsw); - /* - * delete any nodes that would attach to the primary adapter, - * let the adapter scans add them. - */ - destroy_dev(makedev(asr_cdevsw.d_maj,0)); + static int asr_devsw_installed = 0; + + if (asr_devsw_installed) { + return; + } + asr_devsw_installed++; + /* + * Find a free spot (the report during driver load used by + * osd layer in engine to generate the controlling nodes). + */ + while ((asr_cdevsw.d_maj < NUMCDEVSW) + && (devsw(makedev(asr_cdevsw.d_maj,0)) != (struct cdevsw *)NULL)) { + ++asr_cdevsw.d_maj; + } + if (asr_cdevsw.d_maj >= NUMCDEVSW) for ( + asr_cdevsw.d_maj = 0; + (asr_cdevsw.d_maj < CDEV_MAJOR) + && (devsw(makedev(asr_cdevsw.d_maj,0)) != (struct cdevsw *)NULL); + ++asr_cdevsw.d_maj); + /* + * Come to papa + */ + cdevsw_add(&asr_cdevsw); + /* + * delete any nodes that would attach to the primary adapter, + * let the adapter scans add them. + */ + destroy_dev(makedev(asr_cdevsw.d_maj,0)); } /* asr_drvinit */ /* Must initialize before CAM layer picks up our HBA driver */ @@ -640,185 +640,185 @@ SYSINIT(asrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,asr_drvinit,NULL) #endif /* I2O support routines */ -#define defAlignLong(STRUCT,NAME) char NAME[sizeof(STRUCT)] -#define getAlignLong(STRUCT,NAME) ((STRUCT *)(NAME)) +#define defAlignLong(STRUCT,NAME) char NAME[sizeof(STRUCT)] +#define getAlignLong(STRUCT,NAME) ((STRUCT *)(NAME)) /* - * Fill message with default. + * Fill message with default. */ STATIC PI2O_MESSAGE_FRAME ASR_fillMessage ( - IN char * Message, - IN u_int16_t size) + IN char * Message, + IN u_int16_t size) { - OUT PI2O_MESSAGE_FRAME Message_Ptr; - - Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message); - bzero ((void *)Message_Ptr, size); - I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11); - I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, - (size + sizeof(U32) - 1) >> 2); - I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1); - return (Message_Ptr); + OUT PI2O_MESSAGE_FRAME Message_Ptr; + + Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message); + bzero ((void *)Message_Ptr, size); + I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11); + I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, + (size + sizeof(U32) - 1) >> 2); + I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1); + return (Message_Ptr); } /* ASR_fillMessage */ -#define EMPTY_QUEUE ((U32)-1L) +#define EMPTY_QUEUE ((U32)-1L) STATIC INLINE U32 ASR_getMessage( - IN i2oRegs_t * virt) + IN i2oRegs_t * virt) { - OUT U32 MessageOffset; + OUT U32 MessageOffset; - if ((MessageOffset = virt->ToFIFO) == EMPTY_QUEUE) { - MessageOffset = virt->ToFIFO; - } - return (MessageOffset); + if ((MessageOffset = virt->ToFIFO) == EMPTY_QUEUE) { + MessageOffset = virt->ToFIFO; + } + return (MessageOffset); } /* ASR_getMessage */ /* Issue a polled command */ STATIC U32 ASR_initiateCp ( - INOUT i2oRegs_t * virt, - INOUT U8 * fvirt, - IN PI2O_MESSAGE_FRAME Message) + INOUT i2oRegs_t * virt, + INOUT U8 * fvirt, + IN PI2O_MESSAGE_FRAME Message) { - OUT U32 Mask = -1L; - U32 MessageOffset; - u_int Delay = 1500; - - /* - * ASR_initiateCp is only used for synchronous commands and will - * be made more resiliant to adapter delays since commands like - * resetIOP can cause the adapter to be deaf for a little time. - */ - while (((MessageOffset = ASR_getMessage(virt)) == EMPTY_QUEUE) - && (--Delay != 0)) { - DELAY (10000); - } - if (MessageOffset != EMPTY_QUEUE) { - bcopy (Message, fvirt + MessageOffset, - I2O_MESSAGE_FRAME_getMessageSize(Message) << 2); - /* - * Disable the Interrupts - */ - virt->Mask = (Mask = virt->Mask) | Mask_InterruptsDisabled; - virt->ToFIFO = MessageOffset; - } - return (Mask); + OUT U32 Mask = -1L; + U32 MessageOffset; + u_int Delay = 1500; + + /* + * ASR_initiateCp is only used for synchronous commands and will + * be made more resiliant to adapter delays since commands like + * resetIOP can cause the adapter to be deaf for a little time. + */ + while (((MessageOffset = ASR_getMessage(virt)) == EMPTY_QUEUE) + && (--Delay != 0)) { + DELAY (10000); + } + if (MessageOffset != EMPTY_QUEUE) { + bcopy (Message, fvirt + MessageOffset, + I2O_MESSAGE_FRAME_getMessageSize(Message) << 2); + /* + * Disable the Interrupts + */ + virt->Mask = (Mask = virt->Mask) | Mask_InterruptsDisabled; + virt->ToFIFO = MessageOffset; + } + return (Mask); } /* ASR_initiateCp */ /* - * Reset the adapter. + * Reset the adapter. */ STATIC U32 ASR_resetIOP ( - INOUT i2oRegs_t * virt, - INOUT U8 * fvirt) + INOUT i2oRegs_t * virt, + INOUT U8 * fvirt) { - struct resetMessage { - I2O_EXEC_IOP_RESET_MESSAGE M; - U32 R; - }; - defAlignLong(struct resetMessage,Message); - PI2O_EXEC_IOP_RESET_MESSAGE Message_Ptr; - OUT U32 * volatile Reply_Ptr; - U32 Old; - - /* - * Build up our copy of the Message. - */ - Message_Ptr = (PI2O_EXEC_IOP_RESET_MESSAGE)ASR_fillMessage(Message, - sizeof(I2O_EXEC_IOP_RESET_MESSAGE)); - I2O_EXEC_IOP_RESET_MESSAGE_setFunction(Message_Ptr, I2O_EXEC_IOP_RESET); - /* - * Reset the Reply Status - */ - *(Reply_Ptr = (U32 *)((char *)Message_Ptr - + sizeof(I2O_EXEC_IOP_RESET_MESSAGE))) = 0; - I2O_EXEC_IOP_RESET_MESSAGE_setStatusWordLowAddress(Message_Ptr, - KVTOPHYS((void *)Reply_Ptr)); - /* - * Send the Message out - */ - if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { - /* - * Wait for a response (Poll), timeouts are dangerous if - * the card is truly responsive. We assume response in 2s. - */ - u_int8_t Delay = 200; - - while ((*Reply_Ptr == 0) && (--Delay != 0)) { - DELAY (10000); - } - /* - * Re-enable the interrupts. - */ - virt->Mask = Old; - ASSERT (*Reply_Ptr); - return (*Reply_Ptr); - } - ASSERT (Old != (U32)-1L); - return (0); + struct resetMessage { + I2O_EXEC_IOP_RESET_MESSAGE M; + U32 R; + }; + defAlignLong(struct resetMessage,Message); + PI2O_EXEC_IOP_RESET_MESSAGE Message_Ptr; + OUT U32 * volatile Reply_Ptr; + U32 Old; + + /* + * Build up our copy of the Message. + */ + Message_Ptr = (PI2O_EXEC_IOP_RESET_MESSAGE)ASR_fillMessage(Message, + sizeof(I2O_EXEC_IOP_RESET_MESSAGE)); + I2O_EXEC_IOP_RESET_MESSAGE_setFunction(Message_Ptr, I2O_EXEC_IOP_RESET); + /* + * Reset the Reply Status + */ + *(Reply_Ptr = (U32 *)((char *)Message_Ptr + + sizeof(I2O_EXEC_IOP_RESET_MESSAGE))) = 0; + I2O_EXEC_IOP_RESET_MESSAGE_setStatusWordLowAddress(Message_Ptr, + KVTOPHYS((void *)Reply_Ptr)); + /* + * Send the Message out + */ + if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { + /* + * Wait for a response (Poll), timeouts are dangerous if + * the card is truly responsive. We assume response in 2s. + */ + u_int8_t Delay = 200; + + while ((*Reply_Ptr == 0) && (--Delay != 0)) { + DELAY (10000); + } + /* + * Re-enable the interrupts. + */ + virt->Mask = Old; + ASSERT (*Reply_Ptr); + return (*Reply_Ptr); + } + ASSERT (Old != (U32)-1L); + return (0); } /* ASR_resetIOP */ /* - * Get the curent state of the adapter + * Get the curent state of the adapter */ STATIC INLINE PI2O_EXEC_STATUS_GET_REPLY ASR_getStatus ( - INOUT i2oRegs_t * virt, - INOUT U8 * fvirt, - OUT PI2O_EXEC_STATUS_GET_REPLY buffer) + INOUT i2oRegs_t * virt, + INOUT U8 * fvirt, + OUT PI2O_EXEC_STATUS_GET_REPLY buffer) { - defAlignLong(I2O_EXEC_STATUS_GET_MESSAGE,Message); - PI2O_EXEC_STATUS_GET_MESSAGE Message_Ptr; - U32 Old; - - /* - * Build up our copy of the Message. - */ - Message_Ptr = (PI2O_EXEC_STATUS_GET_MESSAGE)ASR_fillMessage(Message, - sizeof(I2O_EXEC_STATUS_GET_MESSAGE)); - I2O_EXEC_STATUS_GET_MESSAGE_setFunction(Message_Ptr, - I2O_EXEC_STATUS_GET); - I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferAddressLow(Message_Ptr, - KVTOPHYS((void *)buffer)); - /* This one is a Byte Count */ - I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferLength(Message_Ptr, - sizeof(I2O_EXEC_STATUS_GET_REPLY)); - /* - * Reset the Reply Status - */ - bzero ((void *)buffer, sizeof(I2O_EXEC_STATUS_GET_REPLY)); - /* - * Send the Message out - */ - if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { - /* - * Wait for a response (Poll), timeouts are dangerous if - * the card is truly responsive. We assume response in 50ms. - */ - u_int8_t Delay = 255; - - while (*((U8 * volatile)&(buffer->SyncByte)) == 0) { - if (--Delay == 0) { - buffer = (PI2O_EXEC_STATUS_GET_REPLY)NULL; - break; - } - DELAY (1000); - } - /* - * Re-enable the interrupts. - */ - virt->Mask = Old; - return (buffer); - } - return ((PI2O_EXEC_STATUS_GET_REPLY)NULL); + defAlignLong(I2O_EXEC_STATUS_GET_MESSAGE,Message); + PI2O_EXEC_STATUS_GET_MESSAGE Message_Ptr; + U32 Old; + + /* + * Build up our copy of the Message. + */ + Message_Ptr = (PI2O_EXEC_STATUS_GET_MESSAGE)ASR_fillMessage(Message, + sizeof(I2O_EXEC_STATUS_GET_MESSAGE)); + I2O_EXEC_STATUS_GET_MESSAGE_setFunction(Message_Ptr, + I2O_EXEC_STATUS_GET); + I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferAddressLow(Message_Ptr, + KVTOPHYS((void *)buffer)); + /* This one is a Byte Count */ + I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferLength(Message_Ptr, + sizeof(I2O_EXEC_STATUS_GET_REPLY)); + /* + * Reset the Reply Status + */ + bzero ((void *)buffer, sizeof(I2O_EXEC_STATUS_GET_REPLY)); + /* + * Send the Message out + */ + if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { + /* + * Wait for a response (Poll), timeouts are dangerous if + * the card is truly responsive. We assume response in 50ms. + */ + u_int8_t Delay = 255; + + while (*((U8 * volatile)&(buffer->SyncByte)) == 0) { + if (--Delay == 0) { + buffer = (PI2O_EXEC_STATUS_GET_REPLY)NULL; + break; + } + DELAY (1000); + } + /* + * Re-enable the interrupts. + */ + virt->Mask = Old; + return (buffer); + } + return ((PI2O_EXEC_STATUS_GET_REPLY)NULL); } /* ASR_getStatus */ /* - * Check if the device is a SCSI I2O HBA, and add it to the list. + * Check if the device is a SCSI I2O HBA, and add it to the list. */ /* @@ -828,11 +828,11 @@ ASR_getStatus ( STATIC PROBE_RET asr_probe(PROBE_ARGS) { - PROBE_SET(); - if ((id == 0xA5011044) || (id == 0xA5111044)) { - PROBE_RETURN ("Adaptec Caching SCSI RAID"); - } - PROBE_RETURN (NULL); + PROBE_SET(); + if ((id == 0xA5011044) || (id == 0xA5111044)) { + PROBE_RETURN ("Adaptec Caching SCSI RAID"); + } + PROBE_RETURN (NULL); } /* asr_probe */ /* @@ -841,17 +841,17 @@ asr_probe(PROBE_ARGS) STATIC PROBE_RET domino_probe(PROBE_ARGS) { - PROBE_SET(); - if (id == 0x10121044) { - PROBE_RETURN ("Adaptec Caching Memory Controller"); - } - PROBE_RETURN (NULL); + PROBE_SET(); + if (id == 0x10121044) { + PROBE_RETURN ("Adaptec Caching Memory Controller"); + } + PROBE_RETURN (NULL); } /* domino_probe */ STATIC ATTACH_RET domino_attach (ATTACH_ARGS) { - ATTACH_RETURN (0); + ATTACH_RETURN (0); } /* domino_attach */ /* @@ -860,782 +860,782 @@ domino_attach (ATTACH_ARGS) STATIC PROBE_RET mode0_probe(PROBE_ARGS) { - PROBE_SET(); - - /* - * If/When we can get a business case to commit to a - * Mode0 driver here, we can make all these tests more - * specific and robust. Mode0 adapters have their processors - * turned off, this the chips are in a raw state. - */ - - /* This is a PLX9054 */ - if (id == 0x905410B5) { - PROBE_RETURN ("Adaptec Mode0 PM3757"); - } - /* This is a PLX9080 */ - if (id == 0x908010B5) { - PROBE_RETURN ("Adaptec Mode0 PM3754/PM3755"); - } - /* This is a ZION 80303 */ - if (id == 0x53098086) { - PROBE_RETURN ("Adaptec Mode0 3010S"); - } - /* This is an i960RS */ - if (id == 0x39628086) { - PROBE_RETURN ("Adaptec Mode0 2100S"); - } - /* This is an i960RN */ - if (id == 0x19648086) { - PROBE_RETURN ("Adaptec Mode0 PM2865/2400A/3200S/3400S"); - } -#if 0 /* this would match any generic i960 -- mjs */ - /* This is an i960RP (typically also on Motherboards) */ - if (id == 0x19608086) { - PROBE_RETURN ("Adaptec Mode0 PM2554/PM1554/PM2654"); - } + PROBE_SET(); + + /* + * If/When we can get a business case to commit to a + * Mode0 driver here, we can make all these tests more + * specific and robust. Mode0 adapters have their processors + * turned off, this the chips are in a raw state. + */ + + /* This is a PLX9054 */ + if (id == 0x905410B5) { + PROBE_RETURN ("Adaptec Mode0 PM3757"); + } + /* This is a PLX9080 */ + if (id == 0x908010B5) { + PROBE_RETURN ("Adaptec Mode0 PM3754/PM3755"); + } + /* This is a ZION 80303 */ + if (id == 0x53098086) { + PROBE_RETURN ("Adaptec Mode0 3010S"); + } + /* This is an i960RS */ + if (id == 0x39628086) { + PROBE_RETURN ("Adaptec Mode0 2100S"); + } + /* This is an i960RN */ + if (id == 0x19648086) { + PROBE_RETURN ("Adaptec Mode0 PM2865/2400A/3200S/3400S"); + } +#if 0 /* this would match any generic i960 -- mjs */ + /* This is an i960RP (typically also on Motherboards) */ + if (id == 0x19608086) { + PROBE_RETURN ("Adaptec Mode0 PM2554/PM1554/PM2654"); + } #endif - PROBE_RETURN (NULL); + PROBE_RETURN (NULL); } /* mode0_probe */ STATIC ATTACH_RET mode0_attach (ATTACH_ARGS) { - ATTACH_RETURN (0); + ATTACH_RETURN (0); } /* mode0_attach */ STATIC INLINE union asr_ccb * asr_alloc_ccb ( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - OUT union asr_ccb * new_ccb; - - if ((new_ccb = (union asr_ccb *)malloc(sizeof(*new_ccb), - M_DEVBUF, M_WAITOK | M_ZERO)) != (union asr_ccb *)NULL) { - new_ccb->ccb_h.pinfo.priority = 1; - new_ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; - new_ccb->ccb_h.spriv_ptr0 = sc; - } - return (new_ccb); + OUT union asr_ccb * new_ccb; + + if ((new_ccb = (union asr_ccb *)malloc(sizeof(*new_ccb), + M_DEVBUF, M_WAITOK | M_ZERO)) != (union asr_ccb *)NULL) { + new_ccb->ccb_h.pinfo.priority = 1; + new_ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; + new_ccb->ccb_h.spriv_ptr0 = sc; + } + return (new_ccb); } /* asr_alloc_ccb */ STATIC INLINE void asr_free_ccb ( - IN union asr_ccb * free_ccb) + IN union asr_ccb * free_ccb) { - free(free_ccb, M_DEVBUF); + free(free_ccb, M_DEVBUF); } /* asr_free_ccb */ /* - * Print inquiry data `carefully' + * Print inquiry data `carefully' */ STATIC void ASR_prstring ( - u_int8_t * s, - int len) + u_int8_t * s, + int len) { - while ((--len >= 0) && (*s) && (*s != ' ') && (*s != '-')) { - printf ("%c", *(s++)); - } + while ((--len >= 0) && (*s) && (*s != ' ') && (*s != '-')) { + printf ("%c", *(s++)); + } } /* ASR_prstring */ /* * Prototypes */ STATIC INLINE int ASR_queue( - IN Asr_softc_t * sc, - IN PI2O_MESSAGE_FRAME Message); + IN Asr_softc_t * sc, + IN PI2O_MESSAGE_FRAME Message); /* - * Send a message synchronously and without Interrupt to a ccb. + * Send a message synchronously and without Interrupt to a ccb. */ STATIC int ASR_queue_s ( - INOUT union asr_ccb * ccb, - IN PI2O_MESSAGE_FRAME Message) + INOUT union asr_ccb * ccb, + IN PI2O_MESSAGE_FRAME Message) { - int s; - U32 Mask; - Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); - - /* - * We do not need any (optional byteswapping) method access to - * the Initiator context field. - */ - I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb); - - /* Prevent interrupt service */ - s = splcam (); - sc->ha_Virt->Mask = (Mask = sc->ha_Virt->Mask) - | Mask_InterruptsDisabled; - - if (ASR_queue (sc, Message) == EMPTY_QUEUE) { - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_REQUEUE_REQ; - } - - /* - * Wait for this board to report a finished instruction. - */ - while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { - (void)asr_intr (sc); - } - - /* Re-enable Interrupts */ - sc->ha_Virt->Mask = Mask; - splx(s); - - return (ccb->ccb_h.status); + int s; + U32 Mask; + Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); + + /* + * We do not need any (optional byteswapping) method access to + * the Initiator context field. + */ + I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb); + + /* Prevent interrupt service */ + s = splcam (); + sc->ha_Virt->Mask = (Mask = sc->ha_Virt->Mask) + | Mask_InterruptsDisabled; + + if (ASR_queue (sc, Message) == EMPTY_QUEUE) { + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + } + + /* + * Wait for this board to report a finished instruction. + */ + while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + (void)asr_intr (sc); + } + + /* Re-enable Interrupts */ + sc->ha_Virt->Mask = Mask; + splx(s); + + return (ccb->ccb_h.status); } /* ASR_queue_s */ /* - * Send a message synchronously to a Asr_softc_t + * Send a message synchronously to a Asr_softc_t */ STATIC int ASR_queue_c ( - IN Asr_softc_t * sc, - IN PI2O_MESSAGE_FRAME Message) + IN Asr_softc_t * sc, + IN PI2O_MESSAGE_FRAME Message) { - union asr_ccb * ccb; - OUT int status; + union asr_ccb * ccb; + OUT int status; - if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { - return (CAM_REQUEUE_REQ); - } + if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { + return (CAM_REQUEUE_REQ); + } - status = ASR_queue_s (ccb, Message); + status = ASR_queue_s (ccb, Message); - asr_free_ccb(ccb); + asr_free_ccb(ccb); - return (status); + return (status); } /* ASR_queue_c */ /* - * Add the specified ccb to the active queue + * Add the specified ccb to the active queue */ STATIC INLINE void ASR_ccbAdd ( - IN Asr_softc_t * sc, - INOUT union asr_ccb * ccb) + IN Asr_softc_t * sc, + INOUT union asr_ccb * ccb) { - int s; - - s = splcam(); - LIST_INSERT_HEAD(&(sc->ha_ccb), &(ccb->ccb_h), sim_links.le); - if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { - if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) { - /* - * RAID systems can take considerable time to - * complete some commands given the large cache - * flashes switching from write back to write thru. - */ - ccb->ccb_h.timeout = 6 * 60 * 1000; - } - ccb->ccb_h.timeout_ch = timeout(asr_timeout, (caddr_t)ccb, - (ccb->ccb_h.timeout * hz) / 1000); - } - splx(s); + int s; + + s = splcam(); + LIST_INSERT_HEAD(&(sc->ha_ccb), &(ccb->ccb_h), sim_links.le); + if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { + if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) { + /* + * RAID systems can take considerable time to + * complete some commands given the large cache + * flashes switching from write back to write thru. + */ + ccb->ccb_h.timeout = 6 * 60 * 1000; + } + ccb->ccb_h.timeout_ch = timeout(asr_timeout, (caddr_t)ccb, + (ccb->ccb_h.timeout * hz) / 1000); + } + splx(s); } /* ASR_ccbAdd */ /* - * Remove the specified ccb from the active queue. + * Remove the specified ccb from the active queue. */ STATIC INLINE void ASR_ccbRemove ( - IN Asr_softc_t * sc, - INOUT union asr_ccb * ccb) + IN Asr_softc_t * sc, + INOUT union asr_ccb * ccb) { - int s; + int s; - s = splcam(); - untimeout(asr_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch); - LIST_REMOVE(&(ccb->ccb_h), sim_links.le); - splx(s); + s = splcam(); + untimeout(asr_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch); + LIST_REMOVE(&(ccb->ccb_h), sim_links.le); + splx(s); } /* ASR_ccbRemove */ /* - * Fail all the active commands, so they get re-issued by the operating - * system. + * Fail all the active commands, so they get re-issued by the operating + * system. */ STATIC INLINE void ASR_failActiveCommands ( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - struct ccb_hdr * ccb; - int s; + struct ccb_hdr * ccb; + int s; #if 0 /* Currently handled by callers, unnecessary paranoia currently */ /* Left in for historical perspective. */ - defAlignLong(I2O_EXEC_LCT_NOTIFY_MESSAGE,Message); - PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr; - - /* Send a blind LCT command to wait for the enableSys to complete */ - Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)ASR_fillMessage(Message, - sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT)); - I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), - I2O_EXEC_LCT_NOTIFY); - I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr, - I2O_CLASS_MATCH_ANYCLASS); - (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + defAlignLong(I2O_EXEC_LCT_NOTIFY_MESSAGE,Message); + PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr; + + /* Send a blind LCT command to wait for the enableSys to complete */ + Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)ASR_fillMessage(Message, + sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT)); + I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), + I2O_EXEC_LCT_NOTIFY); + I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr, + I2O_CLASS_MATCH_ANYCLASS); + (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); #endif - s = splcam(); - /* - * We do not need to inform the CAM layer that we had a bus - * reset since we manage it on our own, this also prevents the - * SCSI_DELAY settling that would be required on other systems. - * The `SCSI_DELAY' has already been handled by the card via the - * acquisition of the LCT table while we are at CAM priority level. - * for (int bus = 0; bus <= sc->ha_MaxBus; ++bus) { - * xpt_async (AC_BUS_RESET, sc->ha_path[bus], NULL); - * } - */ - while ((ccb = LIST_FIRST(&(sc->ha_ccb))) != (struct ccb_hdr *)NULL) { - ASR_ccbRemove (sc, (union asr_ccb *)ccb); - - ccb->status &= ~CAM_STATUS_MASK; - ccb->status |= CAM_REQUEUE_REQ; - /* Nothing Transfered */ - ((struct ccb_scsiio *)ccb)->resid - = ((struct ccb_scsiio *)ccb)->dxfer_len; - - if (ccb->path) { - xpt_done ((union ccb *)ccb); - } else { - wakeup ((caddr_t)ccb); - } - } - splx(s); + s = splcam(); + /* + * We do not need to inform the CAM layer that we had a bus + * reset since we manage it on our own, this also prevents the + * SCSI_DELAY settling that would be required on other systems. + * The `SCSI_DELAY' has already been handled by the card via the + * acquisition of the LCT table while we are at CAM priority level. + * for (int bus = 0; bus <= sc->ha_MaxBus; ++bus) { + * xpt_async (AC_BUS_RESET, sc->ha_path[bus], NULL); + * } + */ + while ((ccb = LIST_FIRST(&(sc->ha_ccb))) != (struct ccb_hdr *)NULL) { + ASR_ccbRemove (sc, (union asr_ccb *)ccb); + + ccb->status &= ~CAM_STATUS_MASK; + ccb->status |= CAM_REQUEUE_REQ; + /* Nothing Transfered */ + ((struct ccb_scsiio *)ccb)->resid + = ((struct ccb_scsiio *)ccb)->dxfer_len; + + if (ccb->path) { + xpt_done ((union ccb *)ccb); + } else { + wakeup ((caddr_t)ccb); + } + } + splx(s); } /* ASR_failActiveCommands */ /* - * The following command causes the HBA to reset the specific bus + * The following command causes the HBA to reset the specific bus */ STATIC INLINE void ASR_resetBus( - IN Asr_softc_t * sc, - IN int bus) + IN Asr_softc_t * sc, + IN int bus) { - defAlignLong(I2O_HBA_BUS_RESET_MESSAGE,Message); - I2O_HBA_BUS_RESET_MESSAGE * Message_Ptr; - PI2O_LCT_ENTRY Device; - - Message_Ptr = (I2O_HBA_BUS_RESET_MESSAGE *)ASR_fillMessage(Message, - sizeof(I2O_HBA_BUS_RESET_MESSAGE)); - I2O_MESSAGE_FRAME_setFunction(&Message_Ptr->StdMessageFrame, - I2O_HBA_BUS_RESET); - for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) - (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); - ++Device) { - if (((Device->le_type & I2O_PORT) != 0) - && (Device->le_bus == bus)) { - I2O_MESSAGE_FRAME_setTargetAddress( - &Message_Ptr->StdMessageFrame, - I2O_LCT_ENTRY_getLocalTID(Device)); - /* Asynchronous command, with no expectations */ - (void)ASR_queue(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - break; - } - } + defAlignLong(I2O_HBA_BUS_RESET_MESSAGE,Message); + I2O_HBA_BUS_RESET_MESSAGE * Message_Ptr; + PI2O_LCT_ENTRY Device; + + Message_Ptr = (I2O_HBA_BUS_RESET_MESSAGE *)ASR_fillMessage(Message, + sizeof(I2O_HBA_BUS_RESET_MESSAGE)); + I2O_MESSAGE_FRAME_setFunction(&Message_Ptr->StdMessageFrame, + I2O_HBA_BUS_RESET); + for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) + (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); + ++Device) { + if (((Device->le_type & I2O_PORT) != 0) + && (Device->le_bus == bus)) { + I2O_MESSAGE_FRAME_setTargetAddress( + &Message_Ptr->StdMessageFrame, + I2O_LCT_ENTRY_getLocalTID(Device)); + /* Asynchronous command, with no expectations */ + (void)ASR_queue(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + break; + } + } } /* ASR_resetBus */ STATIC INLINE int ASR_getBlinkLedCode ( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - if ((sc != (Asr_softc_t *)NULL) - && (sc->ha_blinkLED != (u_int8_t *)NULL) - && (sc->ha_blinkLED[1] == 0xBC)) { - return (sc->ha_blinkLED[0]); - } - return (0); + if ((sc != (Asr_softc_t *)NULL) + && (sc->ha_blinkLED != (u_int8_t *)NULL) + && (sc->ha_blinkLED[1] == 0xBC)) { + return (sc->ha_blinkLED[0]); + } + return (0); } /* ASR_getBlinkCode */ /* - * Determine the address of an TID lookup. Must be done at high priority - * since the address can be changed by other threads of execution. + * Determine the address of an TID lookup. Must be done at high priority + * since the address can be changed by other threads of execution. * - * Returns NULL pointer if not indexible (but will attempt to generate - * an index if `new_entry' flag is set to TRUE). + * Returns NULL pointer if not indexible (but will attempt to generate + * an index if `new_entry' flag is set to TRUE). * - * All addressible entries are to be guaranteed zero if never initialized. + * All addressible entries are to be guaranteed zero if never initialized. */ STATIC INLINE tid_t * ASR_getTidAddress( - INOUT Asr_softc_t * sc, - IN int bus, - IN int target, - IN int lun, - IN int new_entry) + INOUT Asr_softc_t * sc, + IN int bus, + IN int target, + IN int lun, + IN int new_entry) { - target2lun_t * bus_ptr; - lun2tid_t * target_ptr; - unsigned new_size; - - /* - * Validity checking of incoming parameters. More of a bound - * expansion limit than an issue with the code dealing with the - * values. - * - * sc must be valid before it gets here, so that check could be - * dropped if speed a critical issue. - */ - if ((sc == (Asr_softc_t *)NULL) - || (bus > MAX_CHANNEL) - || (target > sc->ha_MaxId) - || (lun > sc->ha_MaxLun)) { - debug_asr_printf("(%lx,%d,%d,%d) target out of range\n", - (u_long)sc, bus, target, lun); - return ((tid_t *)NULL); - } - /* - * See if there is an associated bus list. - * - * for performance, allocate in size of BUS_CHUNK chunks. - * BUS_CHUNK must be a power of two. This is to reduce - * fragmentation effects on the allocations. - */ -# define BUS_CHUNK 8 - new_size = ((target + BUS_CHUNK - 1) & ~(BUS_CHUNK - 1)); - if ((bus_ptr = sc->ha_targets[bus]) == (target2lun_t *)NULL) { - /* - * Allocate a new structure? - * Since one element in structure, the +1 - * needed for size has been abstracted. - */ - if ((new_entry == FALSE) - || ((sc->ha_targets[bus] = bus_ptr = (target2lun_t *)malloc ( - sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size), - M_TEMP, M_WAITOK | M_ZERO)) - == (target2lun_t *)NULL)) { - debug_asr_printf("failed to allocate bus list\n"); - return ((tid_t *)NULL); - } - bus_ptr->size = new_size + 1; - } else if (bus_ptr->size <= new_size) { - target2lun_t * new_bus_ptr; - - /* - * Reallocate a new structure? - * Since one element in structure, the +1 - * needed for size has been abstracted. - */ - if ((new_entry == FALSE) - || ((new_bus_ptr = (target2lun_t *)malloc ( - sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size), - M_TEMP, M_WAITOK | M_ZERO)) - == (target2lun_t *)NULL)) { - debug_asr_printf("failed to reallocate bus list\n"); - return ((tid_t *)NULL); - } - /* - * Copy the whole thing, safer, simpler coding - * and not really performance critical at this point. - */ - bcopy (bus_ptr, new_bus_ptr, sizeof(*bus_ptr) - + (sizeof(bus_ptr->LUN) * (bus_ptr->size - 1))); - sc->ha_targets[bus] = new_bus_ptr; - free (bus_ptr, M_TEMP); - bus_ptr = new_bus_ptr; - bus_ptr->size = new_size + 1; - } - /* - * We now have the bus list, lets get to the target list. - * Since most systems have only *one* lun, we do not allocate - * in chunks as above, here we allow one, then in chunk sizes. - * TARGET_CHUNK must be a power of two. This is to reduce - * fragmentation effects on the allocations. - */ -# define TARGET_CHUNK 8 - if ((new_size = lun) != 0) { - new_size = ((lun + TARGET_CHUNK - 1) & ~(TARGET_CHUNK - 1)); - } - if ((target_ptr = bus_ptr->LUN[target]) == (lun2tid_t *)NULL) { - /* - * Allocate a new structure? - * Since one element in structure, the +1 - * needed for size has been abstracted. - */ - if ((new_entry == FALSE) - || ((bus_ptr->LUN[target] = target_ptr = (lun2tid_t *)malloc ( - sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size), - M_TEMP, M_WAITOK | M_ZERO)) - == (lun2tid_t *)NULL)) { - debug_asr_printf("failed to allocate target list\n"); - return ((tid_t *)NULL); - } - target_ptr->size = new_size + 1; - } else if (target_ptr->size <= new_size) { - lun2tid_t * new_target_ptr; - - /* - * Reallocate a new structure? - * Since one element in structure, the +1 - * needed for size has been abstracted. - */ - if ((new_entry == FALSE) - || ((new_target_ptr = (lun2tid_t *)malloc ( - sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size), - M_TEMP, M_WAITOK | M_ZERO)) - == (lun2tid_t *)NULL)) { - debug_asr_printf("failed to reallocate target list\n"); - return ((tid_t *)NULL); - } - /* - * Copy the whole thing, safer, simpler coding - * and not really performance critical at this point. - */ - bcopy (target_ptr, new_target_ptr, - sizeof(*target_ptr) - + (sizeof(target_ptr->TID) * (target_ptr->size - 1))); - bus_ptr->LUN[target] = new_target_ptr; - free (target_ptr, M_TEMP); - target_ptr = new_target_ptr; - target_ptr->size = new_size + 1; - } - /* - * Now, acquire the TID address from the LUN indexed list. - */ - return (&(target_ptr->TID[lun])); + target2lun_t * bus_ptr; + lun2tid_t * target_ptr; + unsigned new_size; + + /* + * Validity checking of incoming parameters. More of a bound + * expansion limit than an issue with the code dealing with the + * values. + * + * sc must be valid before it gets here, so that check could be + * dropped if speed a critical issue. + */ + if ((sc == (Asr_softc_t *)NULL) + || (bus > MAX_CHANNEL) + || (target > sc->ha_MaxId) + || (lun > sc->ha_MaxLun)) { + debug_asr_printf("(%lx,%d,%d,%d) target out of range\n", + (u_long)sc, bus, target, lun); + return ((tid_t *)NULL); + } + /* + * See if there is an associated bus list. + * + * for performance, allocate in size of BUS_CHUNK chunks. + * BUS_CHUNK must be a power of two. This is to reduce + * fragmentation effects on the allocations. + */ +# define BUS_CHUNK 8 + new_size = ((target + BUS_CHUNK - 1) & ~(BUS_CHUNK - 1)); + if ((bus_ptr = sc->ha_targets[bus]) == (target2lun_t *)NULL) { + /* + * Allocate a new structure? + * Since one element in structure, the +1 + * needed for size has been abstracted. + */ + if ((new_entry == FALSE) + || ((sc->ha_targets[bus] = bus_ptr = (target2lun_t *)malloc ( + sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size), + M_TEMP, M_WAITOK | M_ZERO)) + == (target2lun_t *)NULL)) { + debug_asr_printf("failed to allocate bus list\n"); + return ((tid_t *)NULL); + } + bus_ptr->size = new_size + 1; + } else if (bus_ptr->size <= new_size) { + target2lun_t * new_bus_ptr; + + /* + * Reallocate a new structure? + * Since one element in structure, the +1 + * needed for size has been abstracted. + */ + if ((new_entry == FALSE) + || ((new_bus_ptr = (target2lun_t *)malloc ( + sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size), + M_TEMP, M_WAITOK | M_ZERO)) + == (target2lun_t *)NULL)) { + debug_asr_printf("failed to reallocate bus list\n"); + return ((tid_t *)NULL); + } + /* + * Copy the whole thing, safer, simpler coding + * and not really performance critical at this point. + */ + bcopy (bus_ptr, new_bus_ptr, sizeof(*bus_ptr) + + (sizeof(bus_ptr->LUN) * (bus_ptr->size - 1))); + sc->ha_targets[bus] = new_bus_ptr; + free (bus_ptr, M_TEMP); + bus_ptr = new_bus_ptr; + bus_ptr->size = new_size + 1; + } + /* + * We now have the bus list, lets get to the target list. + * Since most systems have only *one* lun, we do not allocate + * in chunks as above, here we allow one, then in chunk sizes. + * TARGET_CHUNK must be a power of two. This is to reduce + * fragmentation effects on the allocations. + */ +# define TARGET_CHUNK 8 + if ((new_size = lun) != 0) { + new_size = ((lun + TARGET_CHUNK - 1) & ~(TARGET_CHUNK - 1)); + } + if ((target_ptr = bus_ptr->LUN[target]) == (lun2tid_t *)NULL) { + /* + * Allocate a new structure? + * Since one element in structure, the +1 + * needed for size has been abstracted. + */ + if ((new_entry == FALSE) + || ((bus_ptr->LUN[target] = target_ptr = (lun2tid_t *)malloc ( + sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size), + M_TEMP, M_WAITOK | M_ZERO)) + == (lun2tid_t *)NULL)) { + debug_asr_printf("failed to allocate target list\n"); + return ((tid_t *)NULL); + } + target_ptr->size = new_size + 1; + } else if (target_ptr->size <= new_size) { + lun2tid_t * new_target_ptr; + + /* + * Reallocate a new structure? + * Since one element in structure, the +1 + * needed for size has been abstracted. + */ + if ((new_entry == FALSE) + || ((new_target_ptr = (lun2tid_t *)malloc ( + sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size), + M_TEMP, M_WAITOK | M_ZERO)) + == (lun2tid_t *)NULL)) { + debug_asr_printf("failed to reallocate target list\n"); + return ((tid_t *)NULL); + } + /* + * Copy the whole thing, safer, simpler coding + * and not really performance critical at this point. + */ + bcopy (target_ptr, new_target_ptr, + sizeof(*target_ptr) + + (sizeof(target_ptr->TID) * (target_ptr->size - 1))); + bus_ptr->LUN[target] = new_target_ptr; + free (target_ptr, M_TEMP); + target_ptr = new_target_ptr; + target_ptr->size = new_size + 1; + } + /* + * Now, acquire the TID address from the LUN indexed list. + */ + return (&(target_ptr->TID[lun])); } /* ASR_getTidAddress */ /* - * Get a pre-existing TID relationship. + * Get a pre-existing TID relationship. * - * If the TID was never set, return (tid_t)-1. + * If the TID was never set, return (tid_t)-1. * - * should use mutex rather than spl. + * should use mutex rather than spl. */ STATIC INLINE tid_t ASR_getTid ( - IN Asr_softc_t * sc, - IN int bus, - IN int target, - IN int lun) + IN Asr_softc_t * sc, + IN int bus, + IN int target, + IN int lun) { - tid_t * tid_ptr; - int s; - OUT tid_t retval; - - s = splcam(); - if (((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, FALSE)) - == (tid_t *)NULL) - /* (tid_t)0 or (tid_t)-1 indicate no TID */ - || (*tid_ptr == (tid_t)0)) { - splx(s); - return ((tid_t)-1); - } - retval = *tid_ptr; - splx(s); - return (retval); + tid_t * tid_ptr; + int s; + OUT tid_t retval; + + s = splcam(); + if (((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, FALSE)) + == (tid_t *)NULL) + /* (tid_t)0 or (tid_t)-1 indicate no TID */ + || (*tid_ptr == (tid_t)0)) { + splx(s); + return ((tid_t)-1); + } + retval = *tid_ptr; + splx(s); + return (retval); } /* ASR_getTid */ /* - * Set a TID relationship. + * Set a TID relationship. * - * If the TID was not set, return (tid_t)-1. + * If the TID was not set, return (tid_t)-1. * - * should use mutex rather than spl. + * should use mutex rather than spl. */ STATIC INLINE tid_t ASR_setTid ( - INOUT Asr_softc_t * sc, - IN int bus, - IN int target, - IN int lun, - INOUT tid_t TID) + INOUT Asr_softc_t * sc, + IN int bus, + IN int target, + IN int lun, + INOUT tid_t TID) { - tid_t * tid_ptr; - int s; - - if (TID != (tid_t)-1) { - if (TID == 0) { - return ((tid_t)-1); - } - s = splcam(); - if ((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, TRUE)) - == (tid_t *)NULL) { - splx(s); - return ((tid_t)-1); - } - *tid_ptr = TID; - splx(s); - } - return (TID); + tid_t * tid_ptr; + int s; + + if (TID != (tid_t)-1) { + if (TID == 0) { + return ((tid_t)-1); + } + s = splcam(); + if ((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, TRUE)) + == (tid_t *)NULL) { + splx(s); + return ((tid_t)-1); + } + *tid_ptr = TID; + splx(s); + } + return (TID); } /* ASR_setTid */ /*-------------------------------------------------------------------------*/ -/* Function ASR_rescan */ +/* Function ASR_rescan */ /*-------------------------------------------------------------------------*/ -/* The Parameters Passed To This Function Are : */ -/* Asr_softc_t * : HBA miniport driver's adapter data storage. */ -/* */ -/* This Function Will rescan the adapter and resynchronize any data */ -/* */ -/* Return : 0 For OK, Error Code Otherwise */ +/* The Parameters Passed To This Function Are : */ +/* Asr_softc_t * : HBA miniport driver's adapter data storage. */ +/* */ +/* This Function Will rescan the adapter and resynchronize any data */ +/* */ +/* Return : 0 For OK, Error Code Otherwise */ /*-------------------------------------------------------------------------*/ STATIC INLINE int ASR_rescan( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - int bus; - OUT int error; - - /* - * Re-acquire the LCT table and synchronize us to the adapter. - */ - if ((error = ASR_acquireLct(sc)) == 0) { - error = ASR_acquireHrt(sc); - } - - if (error != 0) { - return error; - } - - bus = sc->ha_MaxBus; - /* Reset all existing cached TID lookups */ - do { - int target, event = 0; - - /* - * Scan for all targets on this bus to see if they - * got affected by the rescan. - */ - for (target = 0; target <= sc->ha_MaxId; ++target) { - int lun; - - /* Stay away from the controller ID */ - if (target == sc->ha_adapter_target[bus]) { - continue; - } - for (lun = 0; lun <= sc->ha_MaxLun; ++lun) { - PI2O_LCT_ENTRY Device; - tid_t TID = (tid_t)-1; - tid_t LastTID; - - /* - * See if the cached TID changed. Search for - * the device in our new LCT. - */ - for (Device = sc->ha_LCT->LCTEntry; - Device < (PI2O_LCT_ENTRY)(((U32 *)sc->ha_LCT) - + I2O_LCT_getTableSize(sc->ha_LCT)); - ++Device) { - if ((Device->le_type != I2O_UNKNOWN) - && (Device->le_bus == bus) - && (Device->le_target == target) - && (Device->le_lun == lun) - && (I2O_LCT_ENTRY_getUserTID(Device) - == 0xFFF)) { - TID = I2O_LCT_ENTRY_getLocalTID( - Device); - break; - } - } - /* - * Indicate to the OS that the label needs - * to be recalculated, or that the specific - * open device is no longer valid (Merde) - * because the cached TID changed. - */ - LastTID = ASR_getTid (sc, bus, target, lun); - if (LastTID != TID) { - struct cam_path * path; - - if (xpt_create_path(&path, - /*periph*/NULL, - cam_sim_path(sc->ha_sim[bus]), - target, lun) != CAM_REQ_CMP) { - if (TID == (tid_t)-1) { - event |= AC_LOST_DEVICE; - } else { - event |= AC_INQ_CHANGED - | AC_GETDEV_CHANGED; - } - } else { - if (TID == (tid_t)-1) { - xpt_async( - AC_LOST_DEVICE, - path, NULL); - } else if (LastTID == (tid_t)-1) { - struct ccb_getdev ccb; - - xpt_setup_ccb( - &(ccb.ccb_h), - path, /*priority*/5); - xpt_async( - AC_FOUND_DEVICE, - path, - &ccb); - } else { - xpt_async( - AC_INQ_CHANGED, - path, NULL); - xpt_async( - AC_GETDEV_CHANGED, - path, NULL); - } - } - } - /* - * We have the option of clearing the - * cached TID for it to be rescanned, or to - * set it now even if the device never got - * accessed. We chose the later since we - * currently do not use the condition that - * the TID ever got cached. - */ - ASR_setTid (sc, bus, target, lun, TID); - } - } - /* - * The xpt layer can not handle multiple events at the - * same call. - */ - if (event & AC_LOST_DEVICE) { - xpt_async(AC_LOST_DEVICE, sc->ha_path[bus], NULL); - } - if (event & AC_INQ_CHANGED) { - xpt_async(AC_INQ_CHANGED, sc->ha_path[bus], NULL); - } - if (event & AC_GETDEV_CHANGED) { - xpt_async(AC_GETDEV_CHANGED, sc->ha_path[bus], NULL); - } - } while (--bus >= 0); - return (error); + int bus; + OUT int error; + + /* + * Re-acquire the LCT table and synchronize us to the adapter. + */ + if ((error = ASR_acquireLct(sc)) == 0) { + error = ASR_acquireHrt(sc); + } + + if (error != 0) { + return error; + } + + bus = sc->ha_MaxBus; + /* Reset all existing cached TID lookups */ + do { + int target, event = 0; + + /* + * Scan for all targets on this bus to see if they + * got affected by the rescan. + */ + for (target = 0; target <= sc->ha_MaxId; ++target) { + int lun; + + /* Stay away from the controller ID */ + if (target == sc->ha_adapter_target[bus]) { + continue; + } + for (lun = 0; lun <= sc->ha_MaxLun; ++lun) { + PI2O_LCT_ENTRY Device; + tid_t TID = (tid_t)-1; + tid_t LastTID; + + /* + * See if the cached TID changed. Search for + * the device in our new LCT. + */ + for (Device = sc->ha_LCT->LCTEntry; + Device < (PI2O_LCT_ENTRY)(((U32 *)sc->ha_LCT) + + I2O_LCT_getTableSize(sc->ha_LCT)); + ++Device) { + if ((Device->le_type != I2O_UNKNOWN) + && (Device->le_bus == bus) + && (Device->le_target == target) + && (Device->le_lun == lun) + && (I2O_LCT_ENTRY_getUserTID(Device) + == 0xFFF)) { + TID = I2O_LCT_ENTRY_getLocalTID( + Device); + break; + } + } + /* + * Indicate to the OS that the label needs + * to be recalculated, or that the specific + * open device is no longer valid (Merde) + * because the cached TID changed. + */ + LastTID = ASR_getTid (sc, bus, target, lun); + if (LastTID != TID) { + struct cam_path * path; + + if (xpt_create_path(&path, + /*periph*/NULL, + cam_sim_path(sc->ha_sim[bus]), + target, lun) != CAM_REQ_CMP) { + if (TID == (tid_t)-1) { + event |= AC_LOST_DEVICE; + } else { + event |= AC_INQ_CHANGED + | AC_GETDEV_CHANGED; + } + } else { + if (TID == (tid_t)-1) { + xpt_async( + AC_LOST_DEVICE, + path, NULL); + } else if (LastTID == (tid_t)-1) { + struct ccb_getdev ccb; + + xpt_setup_ccb( + &(ccb.ccb_h), + path, /*priority*/5); + xpt_async( + AC_FOUND_DEVICE, + path, + &ccb); + } else { + xpt_async( + AC_INQ_CHANGED, + path, NULL); + xpt_async( + AC_GETDEV_CHANGED, + path, NULL); + } + } + } + /* + * We have the option of clearing the + * cached TID for it to be rescanned, or to + * set it now even if the device never got + * accessed. We chose the later since we + * currently do not use the condition that + * the TID ever got cached. + */ + ASR_setTid (sc, bus, target, lun, TID); + } + } + /* + * The xpt layer can not handle multiple events at the + * same call. + */ + if (event & AC_LOST_DEVICE) { + xpt_async(AC_LOST_DEVICE, sc->ha_path[bus], NULL); + } + if (event & AC_INQ_CHANGED) { + xpt_async(AC_INQ_CHANGED, sc->ha_path[bus], NULL); + } + if (event & AC_GETDEV_CHANGED) { + xpt_async(AC_GETDEV_CHANGED, sc->ha_path[bus], NULL); + } + } while (--bus >= 0); + return (error); } /* ASR_rescan */ /*-------------------------------------------------------------------------*/ -/* Function ASR_reset */ +/* Function ASR_reset */ /*-------------------------------------------------------------------------*/ -/* The Parameters Passed To This Function Are : */ -/* Asr_softc_t * : HBA miniport driver's adapter data storage. */ -/* */ -/* This Function Will reset the adapter and resynchronize any data */ -/* */ -/* Return : None */ +/* The Parameters Passed To This Function Are : */ +/* Asr_softc_t * : HBA miniport driver's adapter data storage. */ +/* */ +/* This Function Will reset the adapter and resynchronize any data */ +/* */ +/* Return : None */ /*-------------------------------------------------------------------------*/ STATIC INLINE int ASR_reset( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - int s, retVal; - - s = splcam(); - if ((sc->ha_in_reset == HA_IN_RESET) - || (sc->ha_in_reset == HA_OFF_LINE_RECOVERY)) { - splx (s); - return (EBUSY); - } - /* - * Promotes HA_OPERATIONAL to HA_IN_RESET, - * or HA_OFF_LINE to HA_OFF_LINE_RECOVERY. - */ - ++(sc->ha_in_reset); - if (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0) { - debug_asr_printf ("ASR_resetIOP failed\n"); - /* - * We really need to take this card off-line, easier said - * than make sense. Better to keep retrying for now since if a - * UART cable is connected the blinkLEDs the adapter is now in - * a hard state requiring action from the monitor commands to - * the HBA to continue. For debugging waiting forever is a - * good thing. In a production system, however, one may wish - * to instead take the card off-line ... - */ -# if 0 && (defined(HA_OFF_LINE)) - /* - * Take adapter off-line. - */ - printf ("asr%d: Taking adapter off-line\n", - sc->ha_path[0] - ? cam_sim_unit(xpt_path_sim(sc->ha_path[0])) - : 0); - sc->ha_in_reset = HA_OFF_LINE; - splx (s); - return (ENXIO); -# else - /* Wait Forever */ - while (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0); -# endif - } - retVal = ASR_init (sc); - splx (s); - if (retVal != 0) { - debug_asr_printf ("ASR_init failed\n"); - sc->ha_in_reset = HA_OFF_LINE; - return (ENXIO); - } - if (ASR_rescan (sc) != 0) { - debug_asr_printf ("ASR_rescan failed\n"); - } - ASR_failActiveCommands (sc); - if (sc->ha_in_reset == HA_OFF_LINE_RECOVERY) { - printf ("asr%d: Brining adapter back on-line\n", - sc->ha_path[0] - ? cam_sim_unit(xpt_path_sim(sc->ha_path[0])) - : 0); - } - sc->ha_in_reset = HA_OPERATIONAL; - return (0); + int s, retVal; + + s = splcam(); + if ((sc->ha_in_reset == HA_IN_RESET) + || (sc->ha_in_reset == HA_OFF_LINE_RECOVERY)) { + splx (s); + return (EBUSY); + } + /* + * Promotes HA_OPERATIONAL to HA_IN_RESET, + * or HA_OFF_LINE to HA_OFF_LINE_RECOVERY. + */ + ++(sc->ha_in_reset); + if (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0) { + debug_asr_printf ("ASR_resetIOP failed\n"); + /* + * We really need to take this card off-line, easier said + * than make sense. Better to keep retrying for now since if a + * UART cable is connected the blinkLEDs the adapter is now in + * a hard state requiring action from the monitor commands to + * the HBA to continue. For debugging waiting forever is a + * good thing. In a production system, however, one may wish + * to instead take the card off-line ... + */ +# if 0 && (defined(HA_OFF_LINE)) + /* + * Take adapter off-line. + */ + printf ("asr%d: Taking adapter off-line\n", + sc->ha_path[0] + ? cam_sim_unit(xpt_path_sim(sc->ha_path[0])) + : 0); + sc->ha_in_reset = HA_OFF_LINE; + splx (s); + return (ENXIO); +# else + /* Wait Forever */ + while (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0); +# endif + } + retVal = ASR_init (sc); + splx (s); + if (retVal != 0) { + debug_asr_printf ("ASR_init failed\n"); + sc->ha_in_reset = HA_OFF_LINE; + return (ENXIO); + } + if (ASR_rescan (sc) != 0) { + debug_asr_printf ("ASR_rescan failed\n"); + } + ASR_failActiveCommands (sc); + if (sc->ha_in_reset == HA_OFF_LINE_RECOVERY) { + printf ("asr%d: Brining adapter back on-line\n", + sc->ha_path[0] + ? cam_sim_unit(xpt_path_sim(sc->ha_path[0])) + : 0); + } + sc->ha_in_reset = HA_OPERATIONAL; + return (0); } /* ASR_reset */ /* - * Device timeout handler. + * Device timeout handler. */ STATIC void asr_timeout( - INOUT void * arg) + INOUT void * arg) { - union asr_ccb * ccb = (union asr_ccb *)arg; - Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); - int s; - - debug_asr_print_path(ccb); - debug_asr_printf("timed out"); - - /* - * Check if the adapter has locked up? - */ - if ((s = ASR_getBlinkLedCode(sc)) != 0) { - /* Reset Adapter */ - printf ("asr%d: Blink LED 0x%x resetting adapter\n", - cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), s); - if (ASR_reset (sc) == ENXIO) { - /* Try again later */ - ccb->ccb_h.timeout_ch = timeout(asr_timeout, - (caddr_t)ccb, - (ccb->ccb_h.timeout * hz) / 1000); - } - return; - } - /* - * Abort does not function on the ASR card!!! Walking away from - * the SCSI command is also *very* dangerous. A SCSI BUS reset is - * our best bet, followed by a complete adapter reset if that fails. - */ - s = splcam(); - /* Check if we already timed out once to raise the issue */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_CMD_TIMEOUT) { - debug_asr_printf (" AGAIN\nreinitializing adapter\n"); - if (ASR_reset (sc) == ENXIO) { - ccb->ccb_h.timeout_ch = timeout(asr_timeout, - (caddr_t)ccb, - (ccb->ccb_h.timeout * hz) / 1000); - } - splx(s); - return; - } - debug_asr_printf ("\nresetting bus\n"); - /* If the BUS reset does not take, then an adapter reset is next! */ - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_CMD_TIMEOUT; - ccb->ccb_h.timeout_ch = timeout(asr_timeout, (caddr_t)ccb, - (ccb->ccb_h.timeout * hz) / 1000); - ASR_resetBus (sc, cam_sim_bus(xpt_path_sim(ccb->ccb_h.path))); - xpt_async (AC_BUS_RESET, ccb->ccb_h.path, NULL); - splx(s); + union asr_ccb * ccb = (union asr_ccb *)arg; + Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); + int s; + + debug_asr_print_path(ccb); + debug_asr_printf("timed out"); + + /* + * Check if the adapter has locked up? + */ + if ((s = ASR_getBlinkLedCode(sc)) != 0) { + /* Reset Adapter */ + printf ("asr%d: Blink LED 0x%x resetting adapter\n", + cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), s); + if (ASR_reset (sc) == ENXIO) { + /* Try again later */ + ccb->ccb_h.timeout_ch = timeout(asr_timeout, + (caddr_t)ccb, + (ccb->ccb_h.timeout * hz) / 1000); + } + return; + } + /* + * Abort does not function on the ASR card!!! Walking away from + * the SCSI command is also *very* dangerous. A SCSI BUS reset is + * our best bet, followed by a complete adapter reset if that fails. + */ + s = splcam(); + /* Check if we already timed out once to raise the issue */ + if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_CMD_TIMEOUT) { + debug_asr_printf (" AGAIN\nreinitializing adapter\n"); + if (ASR_reset (sc) == ENXIO) { + ccb->ccb_h.timeout_ch = timeout(asr_timeout, + (caddr_t)ccb, + (ccb->ccb_h.timeout * hz) / 1000); + } + splx(s); + return; + } + debug_asr_printf ("\nresetting bus\n"); + /* If the BUS reset does not take, then an adapter reset is next! */ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_CMD_TIMEOUT; + ccb->ccb_h.timeout_ch = timeout(asr_timeout, (caddr_t)ccb, + (ccb->ccb_h.timeout * hz) / 1000); + ASR_resetBus (sc, cam_sim_bus(xpt_path_sim(ccb->ccb_h.path))); + xpt_async (AC_BUS_RESET, ccb->ccb_h.path, NULL); + splx(s); } /* asr_timeout */ /* @@ -1643,404 +1643,404 @@ asr_timeout( */ STATIC INLINE int ASR_queue( - IN Asr_softc_t * sc, - IN PI2O_MESSAGE_FRAME Message) + IN Asr_softc_t * sc, + IN PI2O_MESSAGE_FRAME Message) { - OUT U32 MessageOffset; - union asr_ccb * ccb; + OUT U32 MessageOffset; + union asr_ccb * ccb; - debug_asr_printf ("Host Command Dump:\n"); - debug_asr_dump_message (Message); + debug_asr_printf ("Host Command Dump:\n"); + debug_asr_dump_message (Message); - ccb = (union asr_ccb *)(long) - I2O_MESSAGE_FRAME_getInitiatorContext64(Message); + ccb = (union asr_ccb *)(long) + I2O_MESSAGE_FRAME_getInitiatorContext64(Message); - if ((MessageOffset = ASR_getMessage(sc->ha_Virt)) != EMPTY_QUEUE) { + if ((MessageOffset = ASR_getMessage(sc->ha_Virt)) != EMPTY_QUEUE) { #ifdef ASR_MEASURE_PERFORMANCE - int startTimeIndex; - - if (ccb) { - ++sc->ha_performance.command_count[ - (int) ccb->csio.cdb_io.cdb_bytes[0]]; - DEQ_TIMEQ_FREE_LIST(startTimeIndex, - sc->ha_timeQFreeList, - sc->ha_timeQFreeHead, - sc->ha_timeQFreeTail); - if (-1 != startTimeIndex) { - microtime(&(sc->ha_timeQ[startTimeIndex])); - } - /* Time stamp the command before we send it out */ - ((PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *) Message)-> - PrivateMessageFrame.TransactionContext - = (I2O_TRANSACTION_CONTEXT) startTimeIndex; - - ++sc->ha_submitted_ccbs_count; - if (sc->ha_performance.max_submit_count - < sc->ha_submitted_ccbs_count) { - sc->ha_performance.max_submit_count - = sc->ha_submitted_ccbs_count; - } - } + int startTimeIndex; + + if (ccb) { + ++sc->ha_performance.command_count[ + (int) ccb->csio.cdb_io.cdb_bytes[0]]; + DEQ_TIMEQ_FREE_LIST(startTimeIndex, + sc->ha_timeQFreeList, + sc->ha_timeQFreeHead, + sc->ha_timeQFreeTail); + if (-1 != startTimeIndex) { + microtime(&(sc->ha_timeQ[startTimeIndex])); + } + /* Time stamp the command before we send it out */ + ((PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *) Message)-> + PrivateMessageFrame.TransactionContext + = (I2O_TRANSACTION_CONTEXT) startTimeIndex; + + ++sc->ha_submitted_ccbs_count; + if (sc->ha_performance.max_submit_count + < sc->ha_submitted_ccbs_count) { + sc->ha_performance.max_submit_count + = sc->ha_submitted_ccbs_count; + } + } #endif - bcopy (Message, sc->ha_Fvirt + MessageOffset, - I2O_MESSAGE_FRAME_getMessageSize(Message) << 2); - if (ccb) { - ASR_ccbAdd (sc, ccb); - } - /* Post the command */ - sc->ha_Virt->ToFIFO = MessageOffset; - } else { - if (ASR_getBlinkLedCode(sc)) { - /* - * Unlikely we can do anything if we can't grab a - * message frame :-(, but lets give it a try. - */ - (void)ASR_reset (sc); - } - } - return (MessageOffset); + bcopy (Message, sc->ha_Fvirt + MessageOffset, + I2O_MESSAGE_FRAME_getMessageSize(Message) << 2); + if (ccb) { + ASR_ccbAdd (sc, ccb); + } + /* Post the command */ + sc->ha_Virt->ToFIFO = MessageOffset; + } else { + if (ASR_getBlinkLedCode(sc)) { + /* + * Unlikely we can do anything if we can't grab a + * message frame :-(, but lets give it a try. + */ + (void)ASR_reset (sc); + } + } + return (MessageOffset); } /* ASR_queue */ /* Simple Scatter Gather elements */ -#define SG(SGL,Index,Flags,Buffer,Size) \ - I2O_FLAGS_COUNT_setCount( \ - &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \ - Size); \ - I2O_FLAGS_COUNT_setFlags( \ - &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \ - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | (Flags)); \ - I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress( \ - &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index]), \ - (Buffer == NULL) ? NULL : KVTOPHYS(Buffer)) +#define SG(SGL,Index,Flags,Buffer,Size) \ + I2O_FLAGS_COUNT_setCount( \ + &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \ + Size); \ + I2O_FLAGS_COUNT_setFlags( \ + &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \ + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | (Flags)); \ + I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress( \ + &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index]), \ + (Buffer == NULL) ? NULL : KVTOPHYS(Buffer)) /* - * Retrieve Parameter Group. - * Buffer must be allocated using defAlignLong macro. + * Retrieve Parameter Group. + * Buffer must be allocated using defAlignLong macro. */ STATIC void * ASR_getParams( - IN Asr_softc_t * sc, - IN tid_t TID, - IN int Group, - OUT void * Buffer, - IN unsigned BufferSize) + IN Asr_softc_t * sc, + IN tid_t TID, + IN int Group, + OUT void * Buffer, + IN unsigned BufferSize) { - struct paramGetMessage { - I2O_UTIL_PARAMS_GET_MESSAGE M; - char F[ - sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)]; - struct Operations { - I2O_PARAM_OPERATIONS_LIST_HEADER Header; - I2O_PARAM_OPERATION_ALL_TEMPLATE Template[1]; - } O; - }; - defAlignLong(struct paramGetMessage, Message); - struct Operations * Operations_Ptr; - I2O_UTIL_PARAMS_GET_MESSAGE * Message_Ptr; - struct ParamBuffer { - I2O_PARAM_RESULTS_LIST_HEADER Header; - I2O_PARAM_READ_OPERATION_RESULT Read; - char Info[1]; - } * Buffer_Ptr; - - Message_Ptr = (I2O_UTIL_PARAMS_GET_MESSAGE *)ASR_fillMessage(Message, - sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)); - Operations_Ptr = (struct Operations *)((char *)Message_Ptr - + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)); - bzero ((void *)Operations_Ptr, sizeof(struct Operations)); - I2O_PARAM_OPERATIONS_LIST_HEADER_setOperationCount( - &(Operations_Ptr->Header), 1); - I2O_PARAM_OPERATION_ALL_TEMPLATE_setOperation( - &(Operations_Ptr->Template[0]), I2O_PARAMS_OPERATION_FIELD_GET); - I2O_PARAM_OPERATION_ALL_TEMPLATE_setFieldCount( - &(Operations_Ptr->Template[0]), 0xFFFF); - I2O_PARAM_OPERATION_ALL_TEMPLATE_setGroupNumber( - &(Operations_Ptr->Template[0]), Group); - bzero ((void *)(Buffer_Ptr = getAlignLong(struct ParamBuffer, Buffer)), - BufferSize); - - I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), - I2O_VERSION_11 - + (((sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4)); - I2O_MESSAGE_FRAME_setTargetAddress (&(Message_Ptr->StdMessageFrame), - TID); - I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame), - I2O_UTIL_PARAMS_GET); - /* - * Set up the buffers as scatter gather elements. - */ - SG(&(Message_Ptr->SGL), 0, - I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, - Operations_Ptr, sizeof(struct Operations)); - SG(&(Message_Ptr->SGL), 1, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - Buffer_Ptr, BufferSize); - - if ((ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) == CAM_REQ_CMP) - && (Buffer_Ptr->Header.ResultCount)) { - return ((void *)(Buffer_Ptr->Info)); - } - return ((void *)NULL); + struct paramGetMessage { + I2O_UTIL_PARAMS_GET_MESSAGE M; + char F[ + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)]; + struct Operations { + I2O_PARAM_OPERATIONS_LIST_HEADER Header; + I2O_PARAM_OPERATION_ALL_TEMPLATE Template[1]; + } O; + }; + defAlignLong(struct paramGetMessage, Message); + struct Operations * Operations_Ptr; + I2O_UTIL_PARAMS_GET_MESSAGE * Message_Ptr; + struct ParamBuffer { + I2O_PARAM_RESULTS_LIST_HEADER Header; + I2O_PARAM_READ_OPERATION_RESULT Read; + char Info[1]; + } * Buffer_Ptr; + + Message_Ptr = (I2O_UTIL_PARAMS_GET_MESSAGE *)ASR_fillMessage(Message, + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) + + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)); + Operations_Ptr = (struct Operations *)((char *)Message_Ptr + + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) + + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)); + bzero ((void *)Operations_Ptr, sizeof(struct Operations)); + I2O_PARAM_OPERATIONS_LIST_HEADER_setOperationCount( + &(Operations_Ptr->Header), 1); + I2O_PARAM_OPERATION_ALL_TEMPLATE_setOperation( + &(Operations_Ptr->Template[0]), I2O_PARAMS_OPERATION_FIELD_GET); + I2O_PARAM_OPERATION_ALL_TEMPLATE_setFieldCount( + &(Operations_Ptr->Template[0]), 0xFFFF); + I2O_PARAM_OPERATION_ALL_TEMPLATE_setGroupNumber( + &(Operations_Ptr->Template[0]), Group); + bzero ((void *)(Buffer_Ptr = getAlignLong(struct ParamBuffer, Buffer)), + BufferSize); + + I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), + I2O_VERSION_11 + + (((sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4)); + I2O_MESSAGE_FRAME_setTargetAddress (&(Message_Ptr->StdMessageFrame), + TID); + I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame), + I2O_UTIL_PARAMS_GET); + /* + * Set up the buffers as scatter gather elements. + */ + SG(&(Message_Ptr->SGL), 0, + I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, + Operations_Ptr, sizeof(struct Operations)); + SG(&(Message_Ptr->SGL), 1, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + Buffer_Ptr, BufferSize); + + if ((ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) == CAM_REQ_CMP) + && (Buffer_Ptr->Header.ResultCount)) { + return ((void *)(Buffer_Ptr->Info)); + } + return ((void *)NULL); } /* ASR_getParams */ /* - * Acquire the LCT information. + * Acquire the LCT information. */ STATIC INLINE int ASR_acquireLct ( - INOUT Asr_softc_t * sc) + INOUT Asr_softc_t * sc) { - PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr; - PI2O_SGE_SIMPLE_ELEMENT sg; - int MessageSizeInBytes; - caddr_t v; - int len; - I2O_LCT Table; - PI2O_LCT_ENTRY Entry; - - /* - * sc value assumed valid - */ - MessageSizeInBytes = sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT); - if ((Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)malloc ( - MessageSizeInBytes, M_TEMP, M_WAITOK)) - == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) { - return (ENOMEM); - } - (void)ASR_fillMessage((char *)Message_Ptr, MessageSizeInBytes); - I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), - (I2O_VERSION_11 + - (((sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4))); - I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), - I2O_EXEC_LCT_NOTIFY); - I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr, - I2O_CLASS_MATCH_ANYCLASS); - /* - * Call the LCT table to determine the number of device entries - * to reserve space for. - */ - SG(&(Message_Ptr->SGL), 0, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, &Table, - sizeof(I2O_LCT)); - /* - * since this code is reused in several systems, code efficiency - * is greater by using a shift operation rather than a divide by - * sizeof(u_int32_t). - */ - I2O_LCT_setTableSize(&Table, - (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2); - (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - /* - * Determine the size of the LCT table. - */ - if (sc->ha_LCT) { - free (sc->ha_LCT, M_TEMP); - } - /* - * malloc only generates contiguous memory when less than a - * page is expected. We must break the request up into an SG list ... - */ - if (((len = (I2O_LCT_getTableSize(&Table) << 2)) <= - (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY))) - || (len > (128 * 1024))) { /* Arbitrary */ - free (Message_Ptr, M_TEMP); - return (EINVAL); - } - if ((sc->ha_LCT = (PI2O_LCT)malloc (len, M_TEMP, M_WAITOK)) - == (PI2O_LCT)NULL) { - free (Message_Ptr, M_TEMP); - return (ENOMEM); - } - /* - * since this code is reused in several systems, code efficiency - * is greater by using a shift operation rather than a divide by - * sizeof(u_int32_t). - */ - I2O_LCT_setTableSize(sc->ha_LCT, - (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2); - /* - * Convert the access to the LCT table into a SG list. - */ - sg = Message_Ptr->SGL.u.Simple; - v = (caddr_t)(sc->ha_LCT); - for (;;) { - int next, base, span; - - span = 0; - next = base = KVTOPHYS(v); - I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base); - - /* How far can we go contiguously */ - while ((len > 0) && (base == next)) { - int size; - - next = trunc_page(base) + PAGE_SIZE; - size = next - base; - if (size > len) { - size = len; - } - span += size; - v += size; - len -= size; - base = KVTOPHYS(v); - } - - /* Construct the Flags */ - I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span); - { - int rw = I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT; - if (len <= 0) { - rw = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT - | I2O_SGL_FLAGS_LAST_ELEMENT - | I2O_SGL_FLAGS_END_OF_BUFFER); - } - I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), rw); - } - - if (len <= 0) { - break; - } - - /* - * Incrementing requires resizing of the packet. - */ - ++sg; - MessageSizeInBytes += sizeof(*sg); - I2O_MESSAGE_FRAME_setMessageSize( - &(Message_Ptr->StdMessageFrame), - I2O_MESSAGE_FRAME_getMessageSize( - &(Message_Ptr->StdMessageFrame)) - + (sizeof(*sg) / sizeof(U32))); - { - PI2O_EXEC_LCT_NOTIFY_MESSAGE NewMessage_Ptr; - - if ((NewMessage_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE) - malloc (MessageSizeInBytes, M_TEMP, M_WAITOK)) - == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) { - free (sc->ha_LCT, M_TEMP); - sc->ha_LCT = (PI2O_LCT)NULL; - free (Message_Ptr, M_TEMP); - return (ENOMEM); - } - span = ((caddr_t)sg) - (caddr_t)Message_Ptr; - bcopy ((caddr_t)Message_Ptr, - (caddr_t)NewMessage_Ptr, span); - free (Message_Ptr, M_TEMP); - sg = (PI2O_SGE_SIMPLE_ELEMENT) - (((caddr_t)NewMessage_Ptr) + span); - Message_Ptr = NewMessage_Ptr; - } - } - { int retval; - - retval = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - free (Message_Ptr, M_TEMP); - if (retval != CAM_REQ_CMP) { - return (ENODEV); - } - } - /* If the LCT table grew, lets truncate accesses */ - if (I2O_LCT_getTableSize(&Table) < I2O_LCT_getTableSize(sc->ha_LCT)) { - I2O_LCT_setTableSize(sc->ha_LCT, I2O_LCT_getTableSize(&Table)); - } - for (Entry = sc->ha_LCT->LCTEntry; Entry < (PI2O_LCT_ENTRY) - (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); - ++Entry) { - Entry->le_type = I2O_UNKNOWN; - switch (I2O_CLASS_ID_getClass(&(Entry->ClassID))) { - - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - Entry->le_type = I2O_BSA; - break; - - case I2O_CLASS_SCSI_PERIPHERAL: - Entry->le_type = I2O_SCSI; - break; - - case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: - Entry->le_type = I2O_FCA; - break; - - case I2O_CLASS_BUS_ADAPTER_PORT: - Entry->le_type = I2O_PORT | I2O_SCSI; - /* FALLTHRU */ - case I2O_CLASS_FIBRE_CHANNEL_PORT: - if (I2O_CLASS_ID_getClass(&(Entry->ClassID)) == - I2O_CLASS_FIBRE_CHANNEL_PORT) { - Entry->le_type = I2O_PORT | I2O_FCA; - } - { struct ControllerInfo { - I2O_PARAM_RESULTS_LIST_HEADER Header; - I2O_PARAM_READ_OPERATION_RESULT Read; - I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info; - }; - defAlignLong(struct ControllerInfo, Buffer); - PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info; - - Entry->le_bus = 0xff; - Entry->le_target = 0xff; - Entry->le_lun = 0xff; - - if ((Info = (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR) - ASR_getParams(sc, - I2O_LCT_ENTRY_getLocalTID(Entry), - I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, - Buffer, sizeof(struct ControllerInfo))) - == (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)NULL) { - continue; - } - Entry->le_target - = I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR_getInitiatorID( - Info); - Entry->le_lun = 0; - } /* FALLTHRU */ - default: - continue; - } - { struct DeviceInfo { - I2O_PARAM_RESULTS_LIST_HEADER Header; - I2O_PARAM_READ_OPERATION_RESULT Read; - I2O_DPT_DEVICE_INFO_SCALAR Info; - }; - defAlignLong (struct DeviceInfo, Buffer); - PI2O_DPT_DEVICE_INFO_SCALAR Info; - - Entry->le_bus = 0xff; - Entry->le_target = 0xff; - Entry->le_lun = 0xff; - - if ((Info = (PI2O_DPT_DEVICE_INFO_SCALAR) - ASR_getParams(sc, - I2O_LCT_ENTRY_getLocalTID(Entry), - I2O_DPT_DEVICE_INFO_GROUP_NO, - Buffer, sizeof(struct DeviceInfo))) - == (PI2O_DPT_DEVICE_INFO_SCALAR)NULL) { - continue; - } - Entry->le_type - |= I2O_DPT_DEVICE_INFO_SCALAR_getDeviceType(Info); - Entry->le_bus - = I2O_DPT_DEVICE_INFO_SCALAR_getBus(Info); - if ((Entry->le_bus > sc->ha_MaxBus) - && (Entry->le_bus <= MAX_CHANNEL)) { - sc->ha_MaxBus = Entry->le_bus; - } - Entry->le_target - = I2O_DPT_DEVICE_INFO_SCALAR_getIdentifier(Info); - Entry->le_lun - = I2O_DPT_DEVICE_INFO_SCALAR_getLunInfo(Info); - } - } - /* - * A zero return value indicates success. - */ - return (0); + PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr; + PI2O_SGE_SIMPLE_ELEMENT sg; + int MessageSizeInBytes; + caddr_t v; + int len; + I2O_LCT Table; + PI2O_LCT_ENTRY Entry; + + /* + * sc value assumed valid + */ + MessageSizeInBytes = sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) + - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT); + if ((Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)malloc ( + MessageSizeInBytes, M_TEMP, M_WAITOK)) + == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) { + return (ENOMEM); + } + (void)ASR_fillMessage((char *)Message_Ptr, MessageSizeInBytes); + I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), + (I2O_VERSION_11 + + (((sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4))); + I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), + I2O_EXEC_LCT_NOTIFY); + I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr, + I2O_CLASS_MATCH_ANYCLASS); + /* + * Call the LCT table to determine the number of device entries + * to reserve space for. + */ + SG(&(Message_Ptr->SGL), 0, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, &Table, + sizeof(I2O_LCT)); + /* + * since this code is reused in several systems, code efficiency + * is greater by using a shift operation rather than a divide by + * sizeof(u_int32_t). + */ + I2O_LCT_setTableSize(&Table, + (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2); + (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + /* + * Determine the size of the LCT table. + */ + if (sc->ha_LCT) { + free (sc->ha_LCT, M_TEMP); + } + /* + * malloc only generates contiguous memory when less than a + * page is expected. We must break the request up into an SG list ... + */ + if (((len = (I2O_LCT_getTableSize(&Table) << 2)) <= + (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY))) + || (len > (128 * 1024))) { /* Arbitrary */ + free (Message_Ptr, M_TEMP); + return (EINVAL); + } + if ((sc->ha_LCT = (PI2O_LCT)malloc (len, M_TEMP, M_WAITOK)) + == (PI2O_LCT)NULL) { + free (Message_Ptr, M_TEMP); + return (ENOMEM); + } + /* + * since this code is reused in several systems, code efficiency + * is greater by using a shift operation rather than a divide by + * sizeof(u_int32_t). + */ + I2O_LCT_setTableSize(sc->ha_LCT, + (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2); + /* + * Convert the access to the LCT table into a SG list. + */ + sg = Message_Ptr->SGL.u.Simple; + v = (caddr_t)(sc->ha_LCT); + for (;;) { + int next, base, span; + + span = 0; + next = base = KVTOPHYS(v); + I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base); + + /* How far can we go contiguously */ + while ((len > 0) && (base == next)) { + int size; + + next = trunc_page(base) + PAGE_SIZE; + size = next - base; + if (size > len) { + size = len; + } + span += size; + v += size; + len -= size; + base = KVTOPHYS(v); + } + + /* Construct the Flags */ + I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span); + { + int rw = I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT; + if (len <= 0) { + rw = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT + | I2O_SGL_FLAGS_LAST_ELEMENT + | I2O_SGL_FLAGS_END_OF_BUFFER); + } + I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), rw); + } + + if (len <= 0) { + break; + } + + /* + * Incrementing requires resizing of the packet. + */ + ++sg; + MessageSizeInBytes += sizeof(*sg); + I2O_MESSAGE_FRAME_setMessageSize( + &(Message_Ptr->StdMessageFrame), + I2O_MESSAGE_FRAME_getMessageSize( + &(Message_Ptr->StdMessageFrame)) + + (sizeof(*sg) / sizeof(U32))); + { + PI2O_EXEC_LCT_NOTIFY_MESSAGE NewMessage_Ptr; + + if ((NewMessage_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE) + malloc (MessageSizeInBytes, M_TEMP, M_WAITOK)) + == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) { + free (sc->ha_LCT, M_TEMP); + sc->ha_LCT = (PI2O_LCT)NULL; + free (Message_Ptr, M_TEMP); + return (ENOMEM); + } + span = ((caddr_t)sg) - (caddr_t)Message_Ptr; + bcopy ((caddr_t)Message_Ptr, + (caddr_t)NewMessage_Ptr, span); + free (Message_Ptr, M_TEMP); + sg = (PI2O_SGE_SIMPLE_ELEMENT) + (((caddr_t)NewMessage_Ptr) + span); + Message_Ptr = NewMessage_Ptr; + } + } + { int retval; + + retval = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + free (Message_Ptr, M_TEMP); + if (retval != CAM_REQ_CMP) { + return (ENODEV); + } + } + /* If the LCT table grew, lets truncate accesses */ + if (I2O_LCT_getTableSize(&Table) < I2O_LCT_getTableSize(sc->ha_LCT)) { + I2O_LCT_setTableSize(sc->ha_LCT, I2O_LCT_getTableSize(&Table)); + } + for (Entry = sc->ha_LCT->LCTEntry; Entry < (PI2O_LCT_ENTRY) + (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); + ++Entry) { + Entry->le_type = I2O_UNKNOWN; + switch (I2O_CLASS_ID_getClass(&(Entry->ClassID))) { + + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + Entry->le_type = I2O_BSA; + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + Entry->le_type = I2O_SCSI; + break; + + case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: + Entry->le_type = I2O_FCA; + break; + + case I2O_CLASS_BUS_ADAPTER_PORT: + Entry->le_type = I2O_PORT | I2O_SCSI; + /* FALLTHRU */ + case I2O_CLASS_FIBRE_CHANNEL_PORT: + if (I2O_CLASS_ID_getClass(&(Entry->ClassID)) == + I2O_CLASS_FIBRE_CHANNEL_PORT) { + Entry->le_type = I2O_PORT | I2O_FCA; + } + { struct ControllerInfo { + I2O_PARAM_RESULTS_LIST_HEADER Header; + I2O_PARAM_READ_OPERATION_RESULT Read; + I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info; + }; + defAlignLong(struct ControllerInfo, Buffer); + PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info; + + Entry->le_bus = 0xff; + Entry->le_target = 0xff; + Entry->le_lun = 0xff; + + if ((Info = (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR) + ASR_getParams(sc, + I2O_LCT_ENTRY_getLocalTID(Entry), + I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, + Buffer, sizeof(struct ControllerInfo))) + == (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)NULL) { + continue; + } + Entry->le_target + = I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR_getInitiatorID( + Info); + Entry->le_lun = 0; + } /* FALLTHRU */ + default: + continue; + } + { struct DeviceInfo { + I2O_PARAM_RESULTS_LIST_HEADER Header; + I2O_PARAM_READ_OPERATION_RESULT Read; + I2O_DPT_DEVICE_INFO_SCALAR Info; + }; + defAlignLong (struct DeviceInfo, Buffer); + PI2O_DPT_DEVICE_INFO_SCALAR Info; + + Entry->le_bus = 0xff; + Entry->le_target = 0xff; + Entry->le_lun = 0xff; + + if ((Info = (PI2O_DPT_DEVICE_INFO_SCALAR) + ASR_getParams(sc, + I2O_LCT_ENTRY_getLocalTID(Entry), + I2O_DPT_DEVICE_INFO_GROUP_NO, + Buffer, sizeof(struct DeviceInfo))) + == (PI2O_DPT_DEVICE_INFO_SCALAR)NULL) { + continue; + } + Entry->le_type + |= I2O_DPT_DEVICE_INFO_SCALAR_getDeviceType(Info); + Entry->le_bus + = I2O_DPT_DEVICE_INFO_SCALAR_getBus(Info); + if ((Entry->le_bus > sc->ha_MaxBus) + && (Entry->le_bus <= MAX_CHANNEL)) { + sc->ha_MaxBus = Entry->le_bus; + } + Entry->le_target + = I2O_DPT_DEVICE_INFO_SCALAR_getIdentifier(Info); + Entry->le_lun + = I2O_DPT_DEVICE_INFO_SCALAR_getLunInfo(Info); + } + } + /* + * A zero return value indicates success. + */ + return (0); } /* ASR_acquireLct */ /* @@ -2050,1405 +2050,1405 @@ ASR_acquireLct ( */ STATIC INLINE PI2O_MESSAGE_FRAME ASR_init_message( - IN union asr_ccb * ccb, - OUT PI2O_MESSAGE_FRAME Message) + IN union asr_ccb * ccb, + OUT PI2O_MESSAGE_FRAME Message) { - int next, span, base, rw; - OUT PI2O_MESSAGE_FRAME Message_Ptr; - Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); - PI2O_SGE_SIMPLE_ELEMENT sg; - caddr_t v; - vm_size_t size, len; - U32 MessageSize; - - /* We only need to zero out the PRIVATE_SCSI_SCB_EXECUTE_MESSAGE */ - bzero (Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message), - (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT))); - - { - int target = ccb->ccb_h.target_id; - int lun = ccb->ccb_h.target_lun; - int bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)); - tid_t TID; - - if ((TID = ASR_getTid (sc, bus, target, lun)) == (tid_t)-1) { - PI2O_LCT_ENTRY Device; - - TID = (tid_t)0; - for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) - (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); - ++Device) { - if ((Device->le_type != I2O_UNKNOWN) - && (Device->le_bus == bus) - && (Device->le_target == target) - && (Device->le_lun == lun) - && (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF)) { - TID = I2O_LCT_ENTRY_getLocalTID(Device); - ASR_setTid (sc, Device->le_bus, - Device->le_target, Device->le_lun, - TID); - break; - } - } - } - if (TID == (tid_t)0) { - return ((PI2O_MESSAGE_FRAME)NULL); - } - I2O_MESSAGE_FRAME_setTargetAddress(Message_Ptr, TID); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, TID); - } - I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11 | - (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4)); - I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, - (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT)) / sizeof(U32)); - I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1); - I2O_MESSAGE_FRAME_setFunction(Message_Ptr, I2O_PRIVATE_MESSAGE); - I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( - (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, I2O_SCSI_SCB_EXEC); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags ( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, - I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); - /* - * We do not need any (optional byteswapping) method access to - * the Initiator & Transaction context field. - */ - I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb); - - I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( - (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, DPT_ORGANIZATION_ID); - /* - * copy the cdb over - */ - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, ccb->csio.cdb_len); - bcopy (&(ccb->csio.cdb_io), - ((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->CDB, ccb->csio.cdb_len); - - /* - * Given a buffer describing a transfer, set up a scatter/gather map - * in a ccb to map that SCSI transfer. - */ - - rw = (ccb->ccb_h.flags & CAM_DIR_IN) ? 0 : I2O_SGL_FLAGS_DIR; - - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags ( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, - (ccb->csio.dxfer_len) - ? ((rw) ? (I2O_SCB_FLAG_XFER_TO_DEVICE - | I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER) - : (I2O_SCB_FLAG_XFER_FROM_DEVICE - | I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)) - : (I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); - - /* - * Given a transfer described by a `data', fill in the SG list. - */ - sg = &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->SGL.u.Simple[0]; - - len = ccb->csio.dxfer_len; - v = ccb->csio.data_ptr; - ASSERT (ccb->csio.dxfer_len >= 0); - MessageSize = I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, len); - while ((len > 0) && (sg < &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - Message_Ptr)->SGL.u.Simple[SG_SIZE])) { - span = 0; - next = base = KVTOPHYS(v); - I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base); - - /* How far can we go contiguously */ - while ((len > 0) && (base == next)) { - next = trunc_page(base) + PAGE_SIZE; - size = next - base; - if (size > len) { - size = len; - } - span += size; - v += size; - len -= size; - base = KVTOPHYS(v); - } - - I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span); - if (len == 0) { - rw |= I2O_SGL_FLAGS_LAST_ELEMENT; - } - I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | rw); - ++sg; - MessageSize += sizeof(*sg) / sizeof(U32); - } - /* We always do the request sense ... */ - if ((span = ccb->csio.sense_len) == 0) { - span = sizeof(ccb->csio.sense_data); - } - SG(sg, 0, I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - &(ccb->csio.sense_data), span); - I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, - MessageSize + (sizeof(*sg) / sizeof(U32))); - return (Message_Ptr); + int next, span, base, rw; + OUT PI2O_MESSAGE_FRAME Message_Ptr; + Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); + PI2O_SGE_SIMPLE_ELEMENT sg; + caddr_t v; + vm_size_t size, len; + U32 MessageSize; + + /* We only need to zero out the PRIVATE_SCSI_SCB_EXECUTE_MESSAGE */ + bzero (Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message), + (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT))); + + { + int target = ccb->ccb_h.target_id; + int lun = ccb->ccb_h.target_lun; + int bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)); + tid_t TID; + + if ((TID = ASR_getTid (sc, bus, target, lun)) == (tid_t)-1) { + PI2O_LCT_ENTRY Device; + + TID = (tid_t)0; + for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) + (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); + ++Device) { + if ((Device->le_type != I2O_UNKNOWN) + && (Device->le_bus == bus) + && (Device->le_target == target) + && (Device->le_lun == lun) + && (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF)) { + TID = I2O_LCT_ENTRY_getLocalTID(Device); + ASR_setTid (sc, Device->le_bus, + Device->le_target, Device->le_lun, + TID); + break; + } + } + } + if (TID == (tid_t)0) { + return ((PI2O_MESSAGE_FRAME)NULL); + } + I2O_MESSAGE_FRAME_setTargetAddress(Message_Ptr, TID); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, TID); + } + I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11 | + (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4)); + I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, + (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT)) / sizeof(U32)); + I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1); + I2O_MESSAGE_FRAME_setFunction(Message_Ptr, I2O_PRIVATE_MESSAGE); + I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( + (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, I2O_SCSI_SCB_EXEC); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags ( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, + I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); + /* + * We do not need any (optional byteswapping) method access to + * the Initiator & Transaction context field. + */ + I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb); + + I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( + (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, DPT_ORGANIZATION_ID); + /* + * copy the cdb over + */ + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, ccb->csio.cdb_len); + bcopy (&(ccb->csio.cdb_io), + ((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->CDB, ccb->csio.cdb_len); + + /* + * Given a buffer describing a transfer, set up a scatter/gather map + * in a ccb to map that SCSI transfer. + */ + + rw = (ccb->ccb_h.flags & CAM_DIR_IN) ? 0 : I2O_SGL_FLAGS_DIR; + + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags ( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, + (ccb->csio.dxfer_len) + ? ((rw) ? (I2O_SCB_FLAG_XFER_TO_DEVICE + | I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER) + : (I2O_SCB_FLAG_XFER_FROM_DEVICE + | I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)) + : (I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); + + /* + * Given a transfer described by a `data', fill in the SG list. + */ + sg = &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->SGL.u.Simple[0]; + + len = ccb->csio.dxfer_len; + v = ccb->csio.data_ptr; + ASSERT (ccb->csio.dxfer_len >= 0); + MessageSize = I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, len); + while ((len > 0) && (sg < &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + Message_Ptr)->SGL.u.Simple[SG_SIZE])) { + span = 0; + next = base = KVTOPHYS(v); + I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base); + + /* How far can we go contiguously */ + while ((len > 0) && (base == next)) { + next = trunc_page(base) + PAGE_SIZE; + size = next - base; + if (size > len) { + size = len; + } + span += size; + v += size; + len -= size; + base = KVTOPHYS(v); + } + + I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span); + if (len == 0) { + rw |= I2O_SGL_FLAGS_LAST_ELEMENT; + } + I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | rw); + ++sg; + MessageSize += sizeof(*sg) / sizeof(U32); + } + /* We always do the request sense ... */ + if ((span = ccb->csio.sense_len) == 0) { + span = sizeof(ccb->csio.sense_data); + } + SG(sg, 0, I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + &(ccb->csio.sense_data), span); + I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, + MessageSize + (sizeof(*sg) / sizeof(U32))); + return (Message_Ptr); } /* ASR_init_message */ /* - * Reset the adapter. + * Reset the adapter. */ STATIC INLINE U32 ASR_initOutBound ( - INOUT Asr_softc_t * sc) + INOUT Asr_softc_t * sc) { - struct initOutBoundMessage { - I2O_EXEC_OUTBOUND_INIT_MESSAGE M; - U32 R; - }; - defAlignLong(struct initOutBoundMessage,Message); - PI2O_EXEC_OUTBOUND_INIT_MESSAGE Message_Ptr; - OUT U32 * volatile Reply_Ptr; - U32 Old; - - /* - * Build up our copy of the Message. - */ - Message_Ptr = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)ASR_fillMessage(Message, - sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)); - I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), - I2O_EXEC_OUTBOUND_INIT); - I2O_EXEC_OUTBOUND_INIT_MESSAGE_setHostPageFrameSize(Message_Ptr, PAGE_SIZE); - I2O_EXEC_OUTBOUND_INIT_MESSAGE_setOutboundMFrameSize(Message_Ptr, - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)); - /* - * Reset the Reply Status - */ - *(Reply_Ptr = (U32 *)((char *)Message_Ptr - + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE))) = 0; - SG (&(Message_Ptr->SGL), 0, I2O_SGL_FLAGS_LAST_ELEMENT, Reply_Ptr, - sizeof(U32)); - /* - * Send the Message out - */ - if ((Old = ASR_initiateCp (sc->ha_Virt, sc->ha_Fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { - u_long size, addr; - - /* - * Wait for a response (Poll). - */ - while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED); - /* - * Re-enable the interrupts. - */ - sc->ha_Virt->Mask = Old; - /* - * Populate the outbound table. - */ - if (sc->ha_Msgs == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { - - /* Allocate the reply frames */ - size = sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) - * sc->ha_Msgs_Count; - - /* - * contigmalloc only works reliably at - * initialization time. - */ - if ((sc->ha_Msgs = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) - contigmalloc (size, M_DEVBUF, M_WAITOK, 0ul, - 0xFFFFFFFFul, (u_long)sizeof(U32), 0ul)) - != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { - (void)bzero ((char *)sc->ha_Msgs, size); - sc->ha_Msgs_Phys = KVTOPHYS(sc->ha_Msgs); - } - } - - /* Initialize the outbound FIFO */ - if (sc->ha_Msgs != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) - for (size = sc->ha_Msgs_Count, addr = sc->ha_Msgs_Phys; - size; --size) { - sc->ha_Virt->FromFIFO = addr; - addr += sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME); - } - return (*Reply_Ptr); - } - return (0); + struct initOutBoundMessage { + I2O_EXEC_OUTBOUND_INIT_MESSAGE M; + U32 R; + }; + defAlignLong(struct initOutBoundMessage,Message); + PI2O_EXEC_OUTBOUND_INIT_MESSAGE Message_Ptr; + OUT U32 * volatile Reply_Ptr; + U32 Old; + + /* + * Build up our copy of the Message. + */ + Message_Ptr = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)ASR_fillMessage(Message, + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)); + I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), + I2O_EXEC_OUTBOUND_INIT); + I2O_EXEC_OUTBOUND_INIT_MESSAGE_setHostPageFrameSize(Message_Ptr, PAGE_SIZE); + I2O_EXEC_OUTBOUND_INIT_MESSAGE_setOutboundMFrameSize(Message_Ptr, + sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)); + /* + * Reset the Reply Status + */ + *(Reply_Ptr = (U32 *)((char *)Message_Ptr + + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE))) = 0; + SG (&(Message_Ptr->SGL), 0, I2O_SGL_FLAGS_LAST_ELEMENT, Reply_Ptr, + sizeof(U32)); + /* + * Send the Message out + */ + if ((Old = ASR_initiateCp (sc->ha_Virt, sc->ha_Fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { + u_long size, addr; + + /* + * Wait for a response (Poll). + */ + while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED); + /* + * Re-enable the interrupts. + */ + sc->ha_Virt->Mask = Old; + /* + * Populate the outbound table. + */ + if (sc->ha_Msgs == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { + + /* Allocate the reply frames */ + size = sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) + * sc->ha_Msgs_Count; + + /* + * contigmalloc only works reliably at + * initialization time. + */ + if ((sc->ha_Msgs = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) + contigmalloc (size, M_DEVBUF, M_WAITOK, 0ul, + 0xFFFFFFFFul, (u_long)sizeof(U32), 0ul)) + != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { + (void)bzero ((char *)sc->ha_Msgs, size); + sc->ha_Msgs_Phys = KVTOPHYS(sc->ha_Msgs); + } + } + + /* Initialize the outbound FIFO */ + if (sc->ha_Msgs != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) + for (size = sc->ha_Msgs_Count, addr = sc->ha_Msgs_Phys; + size; --size) { + sc->ha_Virt->FromFIFO = addr; + addr += sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME); + } + return (*Reply_Ptr); + } + return (0); } /* ASR_initOutBound */ /* - * Set the system table + * Set the system table */ STATIC INLINE int ASR_setSysTab( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - PI2O_EXEC_SYS_TAB_SET_MESSAGE Message_Ptr; - PI2O_SET_SYSTAB_HEADER SystemTable; - Asr_softc_t * ha; - PI2O_SGE_SIMPLE_ELEMENT sg; - int retVal; - - if ((SystemTable = (PI2O_SET_SYSTAB_HEADER)malloc ( - sizeof(I2O_SET_SYSTAB_HEADER), M_TEMP, M_WAITOK | M_ZERO)) - == (PI2O_SET_SYSTAB_HEADER)NULL) { - return (ENOMEM); - } - for (ha = Asr_softc; ha; ha = ha->ha_next) { - ++SystemTable->NumberEntries; - } - if ((Message_Ptr = (PI2O_EXEC_SYS_TAB_SET_MESSAGE)malloc ( - sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT) - + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)), - M_TEMP, M_WAITOK)) == (PI2O_EXEC_SYS_TAB_SET_MESSAGE)NULL) { - free (SystemTable, M_TEMP); - return (ENOMEM); - } - (void)ASR_fillMessage((char *)Message_Ptr, - sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT) - + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT))); - I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), - (I2O_VERSION_11 + - (((sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4))); - I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), - I2O_EXEC_SYS_TAB_SET); - /* - * Call the LCT table to determine the number of device entries - * to reserve space for. - * since this code is reused in several systems, code efficiency - * is greater by using a shift operation rather than a divide by - * sizeof(u_int32_t). - */ - sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr - + ((I2O_MESSAGE_FRAME_getVersionOffset( - &(Message_Ptr->StdMessageFrame)) & 0xF0) >> 2)); - SG(sg, 0, I2O_SGL_FLAGS_DIR, SystemTable, sizeof(I2O_SET_SYSTAB_HEADER)); - ++sg; - for (ha = Asr_softc; ha; ha = ha->ha_next) { - SG(sg, 0, - ((ha->ha_next) - ? (I2O_SGL_FLAGS_DIR) - : (I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER)), - &(ha->ha_SystemTable), sizeof(ha->ha_SystemTable)); - ++sg; - } - SG(sg, 0, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0); - SG(sg, 1, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_LAST_ELEMENT - | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0); - retVal = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - free (Message_Ptr, M_TEMP); - free (SystemTable, M_TEMP); - return (retVal); + PI2O_EXEC_SYS_TAB_SET_MESSAGE Message_Ptr; + PI2O_SET_SYSTAB_HEADER SystemTable; + Asr_softc_t * ha; + PI2O_SGE_SIMPLE_ELEMENT sg; + int retVal; + + if ((SystemTable = (PI2O_SET_SYSTAB_HEADER)malloc ( + sizeof(I2O_SET_SYSTAB_HEADER), M_TEMP, M_WAITOK | M_ZERO)) + == (PI2O_SET_SYSTAB_HEADER)NULL) { + return (ENOMEM); + } + for (ha = Asr_softc; ha; ha = ha->ha_next) { + ++SystemTable->NumberEntries; + } + if ((Message_Ptr = (PI2O_EXEC_SYS_TAB_SET_MESSAGE)malloc ( + sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT) + + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)), + M_TEMP, M_WAITOK)) == (PI2O_EXEC_SYS_TAB_SET_MESSAGE)NULL) { + free (SystemTable, M_TEMP); + return (ENOMEM); + } + (void)ASR_fillMessage((char *)Message_Ptr, + sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT) + + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT))); + I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), + (I2O_VERSION_11 + + (((sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4))); + I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), + I2O_EXEC_SYS_TAB_SET); + /* + * Call the LCT table to determine the number of device entries + * to reserve space for. + * since this code is reused in several systems, code efficiency + * is greater by using a shift operation rather than a divide by + * sizeof(u_int32_t). + */ + sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr + + ((I2O_MESSAGE_FRAME_getVersionOffset( + &(Message_Ptr->StdMessageFrame)) & 0xF0) >> 2)); + SG(sg, 0, I2O_SGL_FLAGS_DIR, SystemTable, sizeof(I2O_SET_SYSTAB_HEADER)); + ++sg; + for (ha = Asr_softc; ha; ha = ha->ha_next) { + SG(sg, 0, + ((ha->ha_next) + ? (I2O_SGL_FLAGS_DIR) + : (I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER)), + &(ha->ha_SystemTable), sizeof(ha->ha_SystemTable)); + ++sg; + } + SG(sg, 0, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0); + SG(sg, 1, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_LAST_ELEMENT + | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0); + retVal = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + free (Message_Ptr, M_TEMP); + free (SystemTable, M_TEMP); + return (retVal); } /* ASR_setSysTab */ STATIC INLINE int ASR_acquireHrt ( - INOUT Asr_softc_t * sc) + INOUT Asr_softc_t * sc) { - defAlignLong(I2O_EXEC_HRT_GET_MESSAGE,Message); - I2O_EXEC_HRT_GET_MESSAGE * Message_Ptr; - struct { - I2O_HRT Header; - I2O_HRT_ENTRY Entry[MAX_CHANNEL]; - } Hrt; - u_int8_t NumberOfEntries; - PI2O_HRT_ENTRY Entry; - - bzero ((void *)&Hrt, sizeof (Hrt)); - Message_Ptr = (I2O_EXEC_HRT_GET_MESSAGE *)ASR_fillMessage(Message, - sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT) - + sizeof(I2O_SGE_SIMPLE_ELEMENT)); - I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), - (I2O_VERSION_11 - + (((sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4))); - I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame), - I2O_EXEC_HRT_GET); - - /* - * Set up the buffers as scatter gather elements. - */ - SG(&(Message_Ptr->SGL), 0, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - &Hrt, sizeof(Hrt)); - if (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != CAM_REQ_CMP) { - return (ENODEV); - } - if ((NumberOfEntries = I2O_HRT_getNumberEntries(&Hrt.Header)) - > (MAX_CHANNEL + 1)) { - NumberOfEntries = MAX_CHANNEL + 1; - } - for (Entry = Hrt.Header.HRTEntry; - NumberOfEntries != 0; - ++Entry, --NumberOfEntries) { - PI2O_LCT_ENTRY Device; - - for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) - (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); - ++Device) { - if (I2O_LCT_ENTRY_getLocalTID(Device) - == (I2O_HRT_ENTRY_getAdapterID(Entry) & 0xFFF)) { - Device->le_bus = I2O_HRT_ENTRY_getAdapterID( - Entry) >> 16; - if ((Device->le_bus > sc->ha_MaxBus) - && (Device->le_bus <= MAX_CHANNEL)) { - sc->ha_MaxBus = Device->le_bus; - } - } - } - } - return (0); + defAlignLong(I2O_EXEC_HRT_GET_MESSAGE,Message); + I2O_EXEC_HRT_GET_MESSAGE * Message_Ptr; + struct { + I2O_HRT Header; + I2O_HRT_ENTRY Entry[MAX_CHANNEL]; + } Hrt; + u_int8_t NumberOfEntries; + PI2O_HRT_ENTRY Entry; + + bzero ((void *)&Hrt, sizeof (Hrt)); + Message_Ptr = (I2O_EXEC_HRT_GET_MESSAGE *)ASR_fillMessage(Message, + sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT) + + sizeof(I2O_SGE_SIMPLE_ELEMENT)); + I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), + (I2O_VERSION_11 + + (((sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4))); + I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame), + I2O_EXEC_HRT_GET); + + /* + * Set up the buffers as scatter gather elements. + */ + SG(&(Message_Ptr->SGL), 0, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + &Hrt, sizeof(Hrt)); + if (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != CAM_REQ_CMP) { + return (ENODEV); + } + if ((NumberOfEntries = I2O_HRT_getNumberEntries(&Hrt.Header)) + > (MAX_CHANNEL + 1)) { + NumberOfEntries = MAX_CHANNEL + 1; + } + for (Entry = Hrt.Header.HRTEntry; + NumberOfEntries != 0; + ++Entry, --NumberOfEntries) { + PI2O_LCT_ENTRY Device; + + for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) + (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); + ++Device) { + if (I2O_LCT_ENTRY_getLocalTID(Device) + == (I2O_HRT_ENTRY_getAdapterID(Entry) & 0xFFF)) { + Device->le_bus = I2O_HRT_ENTRY_getAdapterID( + Entry) >> 16; + if ((Device->le_bus > sc->ha_MaxBus) + && (Device->le_bus <= MAX_CHANNEL)) { + sc->ha_MaxBus = Device->le_bus; + } + } + } + } + return (0); } /* ASR_acquireHrt */ /* - * Enable the adapter. + * Enable the adapter. */ STATIC INLINE int ASR_enableSys ( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - defAlignLong(I2O_EXEC_SYS_ENABLE_MESSAGE,Message); - PI2O_EXEC_SYS_ENABLE_MESSAGE Message_Ptr; - - Message_Ptr = (PI2O_EXEC_SYS_ENABLE_MESSAGE)ASR_fillMessage(Message, - sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE)); - I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), - I2O_EXEC_SYS_ENABLE); - return (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != 0); + defAlignLong(I2O_EXEC_SYS_ENABLE_MESSAGE,Message); + PI2O_EXEC_SYS_ENABLE_MESSAGE Message_Ptr; + + Message_Ptr = (PI2O_EXEC_SYS_ENABLE_MESSAGE)ASR_fillMessage(Message, + sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE)); + I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), + I2O_EXEC_SYS_ENABLE); + return (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != 0); } /* ASR_enableSys */ /* - * Perform the stages necessary to initialize the adapter + * Perform the stages necessary to initialize the adapter */ STATIC int ASR_init( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - return ((ASR_initOutBound(sc) == 0) - || (ASR_setSysTab(sc) != CAM_REQ_CMP) - || (ASR_enableSys(sc) != CAM_REQ_CMP)); + return ((ASR_initOutBound(sc) == 0) + || (ASR_setSysTab(sc) != CAM_REQ_CMP) + || (ASR_enableSys(sc) != CAM_REQ_CMP)); } /* ASR_init */ /* - * Send a Synchronize Cache command to the target device. + * Send a Synchronize Cache command to the target device. */ STATIC INLINE void ASR_sync ( - IN Asr_softc_t * sc, - IN int bus, - IN int target, - IN int lun) + IN Asr_softc_t * sc, + IN int bus, + IN int target, + IN int lun) { - tid_t TID; - - /* - * We will not synchronize the device when there are outstanding - * commands issued by the OS (this is due to a locked up device, - * as the OS normally would flush all outstanding commands before - * issuing a shutdown or an adapter reset). - */ - if ((sc != (Asr_softc_t *)NULL) - && (LIST_FIRST(&(sc->ha_ccb)) != (struct ccb_hdr *)NULL) - && ((TID = ASR_getTid (sc, bus, target, lun)) != (tid_t)-1) - && (TID != (tid_t)0)) { - defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message); - PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr; - - bzero (Message_Ptr - = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message), - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)); - - I2O_MESSAGE_FRAME_setVersionOffset( - (PI2O_MESSAGE_FRAME)Message_Ptr, - I2O_VERSION_11 - | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4)); - I2O_MESSAGE_FRAME_setMessageSize( - (PI2O_MESSAGE_FRAME)Message_Ptr, - (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)); - I2O_MESSAGE_FRAME_setInitiatorAddress ( - (PI2O_MESSAGE_FRAME)Message_Ptr, 1); - I2O_MESSAGE_FRAME_setFunction( - (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE); - I2O_MESSAGE_FRAME_setTargetAddress( - (PI2O_MESSAGE_FRAME)Message_Ptr, TID); - I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( - (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, - I2O_SCSI_SCB_EXEC); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(Message_Ptr, TID); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, - I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); - I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( - (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, - DPT_ORGANIZATION_ID); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6); - Message_Ptr->CDB[0] = SYNCHRONIZE_CACHE; - Message_Ptr->CDB[1] = (lun << 5); - - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, - (I2O_SCB_FLAG_XFER_FROM_DEVICE - | I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); - - (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - - } + tid_t TID; + + /* + * We will not synchronize the device when there are outstanding + * commands issued by the OS (this is due to a locked up device, + * as the OS normally would flush all outstanding commands before + * issuing a shutdown or an adapter reset). + */ + if ((sc != (Asr_softc_t *)NULL) + && (LIST_FIRST(&(sc->ha_ccb)) != (struct ccb_hdr *)NULL) + && ((TID = ASR_getTid (sc, bus, target, lun)) != (tid_t)-1) + && (TID != (tid_t)0)) { + defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message); + PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr; + + bzero (Message_Ptr + = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message), + sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)); + + I2O_MESSAGE_FRAME_setVersionOffset( + (PI2O_MESSAGE_FRAME)Message_Ptr, + I2O_VERSION_11 + | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4)); + I2O_MESSAGE_FRAME_setMessageSize( + (PI2O_MESSAGE_FRAME)Message_Ptr, + (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)); + I2O_MESSAGE_FRAME_setInitiatorAddress ( + (PI2O_MESSAGE_FRAME)Message_Ptr, 1); + I2O_MESSAGE_FRAME_setFunction( + (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE); + I2O_MESSAGE_FRAME_setTargetAddress( + (PI2O_MESSAGE_FRAME)Message_Ptr, TID); + I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( + (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, + I2O_SCSI_SCB_EXEC); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(Message_Ptr, TID); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, + I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); + I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( + (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, + DPT_ORGANIZATION_ID); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6); + Message_Ptr->CDB[0] = SYNCHRONIZE_CACHE; + Message_Ptr->CDB[1] = (lun << 5); + + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, + (I2O_SCB_FLAG_XFER_FROM_DEVICE + | I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); + + (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + + } } STATIC INLINE void ASR_synchronize ( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - int bus, target, lun; - - for (bus = 0; bus <= sc->ha_MaxBus; ++bus) { - for (target = 0; target <= sc->ha_MaxId; ++target) { - for (lun = 0; lun <= sc->ha_MaxLun; ++lun) { - ASR_sync(sc,bus,target,lun); - } - } - } + int bus, target, lun; + + for (bus = 0; bus <= sc->ha_MaxBus; ++bus) { + for (target = 0; target <= sc->ha_MaxId; ++target) { + for (lun = 0; lun <= sc->ha_MaxLun; ++lun) { + ASR_sync(sc,bus,target,lun); + } + } + } } /* - * Reset the HBA, targets and BUS. - * Currently this resets *all* the SCSI busses. + * Reset the HBA, targets and BUS. + * Currently this resets *all* the SCSI busses. */ STATIC INLINE void asr_hbareset( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - ASR_synchronize (sc); - (void)ASR_reset (sc); + ASR_synchronize (sc); + (void)ASR_reset (sc); } /* asr_hbareset */ /* - * A reduced copy of the real pci_map_mem, incorporating the MAX_MAP + * A reduced copy of the real pci_map_mem, incorporating the MAX_MAP * limit and a reduction in error checking (in the pre 4.0 case). */ STATIC int asr_pci_map_mem ( #if __FreeBSD_version >= 400000 - IN device_t tag, + IN device_t tag, #else - IN pcici_t tag, + IN pcici_t tag, #endif - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - int rid; - u_int32_t p, l, s; + int rid; + u_int32_t p, l, s; #if __FreeBSD_version >= 400000 - /* - * I2O specification says we must find first *memory* mapped BAR - */ - for (rid = PCIR_MAPS; - rid < (PCIR_MAPS + 4 * sizeof(u_int32_t)); - rid += sizeof(u_int32_t)) { - p = pci_read_config(tag, rid, sizeof(p)); - if ((p & 1) == 0) { - break; - } - } - /* - * Give up? - */ - if (rid >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) { - rid = PCIR_MAPS; - } - p = pci_read_config(tag, rid, sizeof(p)); - pci_write_config(tag, rid, -1, sizeof(p)); - l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15); - pci_write_config(tag, rid, p, sizeof(p)); - if (l > MAX_MAP) { - l = MAX_MAP; - } - /* - * The 2005S Zero Channel RAID solution is not a perfect PCI - * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once - * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to - * BAR0+2MB and sets it's size to 2MB. The IOP registers are - * accessible via BAR0, the messaging registers are accessible - * via BAR1. If the subdevice code is 50 to 59 decimal. - */ - s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s)); - if (s != 0xA5111044) { - s = pci_read_config(tag, PCIR_SUBVEND_0, sizeof(s)); - if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0) - && (ADPTDOMINATOR_SUB_ID_START <= s) - && (s <= ADPTDOMINATOR_SUB_ID_END)) { - l = MAX_MAP; /* Conjoined BAR Raptor Daptor */ - } - } - p &= ~15; - sc->ha_mem_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid, - p, p + l, l, RF_ACTIVE); - if (sc->ha_mem_res == (struct resource *)NULL) { - return (0); - } - sc->ha_Base = (void *)rman_get_start(sc->ha_mem_res); - if (sc->ha_Base == (void *)NULL) { - return (0); - } - sc->ha_Virt = (i2oRegs_t *) rman_get_virtual(sc->ha_mem_res); - if (s == 0xA5111044) { /* Split BAR Raptor Daptor */ - if ((rid += sizeof(u_int32_t)) - >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) { - return (0); - } - p = pci_read_config(tag, rid, sizeof(p)); - pci_write_config(tag, rid, -1, sizeof(p)); - l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15); - pci_write_config(tag, rid, p, sizeof(p)); - if (l > MAX_MAP) { - l = MAX_MAP; - } - p &= ~15; - sc->ha_mes_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid, - p, p + l, l, RF_ACTIVE); - if (sc->ha_mes_res == (struct resource *)NULL) { - return (0); - } - if ((void *)rman_get_start(sc->ha_mes_res) == (void *)NULL) { - return (0); - } - sc->ha_Fvirt = (U8 *) rman_get_virtual(sc->ha_mes_res); - } else { - sc->ha_Fvirt = (U8 *)(sc->ha_Virt); - } + /* + * I2O specification says we must find first *memory* mapped BAR + */ + for (rid = PCIR_MAPS; + rid < (PCIR_MAPS + 4 * sizeof(u_int32_t)); + rid += sizeof(u_int32_t)) { + p = pci_read_config(tag, rid, sizeof(p)); + if ((p & 1) == 0) { + break; + } + } + /* + * Give up? + */ + if (rid >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) { + rid = PCIR_MAPS; + } + p = pci_read_config(tag, rid, sizeof(p)); + pci_write_config(tag, rid, -1, sizeof(p)); + l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15); + pci_write_config(tag, rid, p, sizeof(p)); + if (l > MAX_MAP) { + l = MAX_MAP; + } + /* + * The 2005S Zero Channel RAID solution is not a perfect PCI + * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once + * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to + * BAR0+2MB and sets it's size to 2MB. The IOP registers are + * accessible via BAR0, the messaging registers are accessible + * via BAR1. If the subdevice code is 50 to 59 decimal. + */ + s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s)); + if (s != 0xA5111044) { + s = pci_read_config(tag, PCIR_SUBVEND_0, sizeof(s)); + if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0) + && (ADPTDOMINATOR_SUB_ID_START <= s) + && (s <= ADPTDOMINATOR_SUB_ID_END)) { + l = MAX_MAP; /* Conjoined BAR Raptor Daptor */ + } + } + p &= ~15; + sc->ha_mem_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid, + p, p + l, l, RF_ACTIVE); + if (sc->ha_mem_res == (struct resource *)NULL) { + return (0); + } + sc->ha_Base = (void *)rman_get_start(sc->ha_mem_res); + if (sc->ha_Base == (void *)NULL) { + return (0); + } + sc->ha_Virt = (i2oRegs_t *) rman_get_virtual(sc->ha_mem_res); + if (s == 0xA5111044) { /* Split BAR Raptor Daptor */ + if ((rid += sizeof(u_int32_t)) + >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) { + return (0); + } + p = pci_read_config(tag, rid, sizeof(p)); + pci_write_config(tag, rid, -1, sizeof(p)); + l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15); + pci_write_config(tag, rid, p, sizeof(p)); + if (l > MAX_MAP) { + l = MAX_MAP; + } + p &= ~15; + sc->ha_mes_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid, + p, p + l, l, RF_ACTIVE); + if (sc->ha_mes_res == (struct resource *)NULL) { + return (0); + } + if ((void *)rman_get_start(sc->ha_mes_res) == (void *)NULL) { + return (0); + } + sc->ha_Fvirt = (U8 *) rman_get_virtual(sc->ha_mes_res); + } else { + sc->ha_Fvirt = (U8 *)(sc->ha_Virt); + } #else - vm_size_t psize, poffs; - - /* - * I2O specification says we must find first *memory* mapped BAR - */ - for (rid = PCI_MAP_REG_START; - rid < (PCI_MAP_REG_START + 4 * sizeof(u_int32_t)); - rid += sizeof(u_int32_t)) { - p = pci_conf_read (tag, rid); - if ((p & 1) == 0) { - break; - } - } - if (rid >= (PCI_MAP_REG_START + 4 * sizeof(u_int32_t))) { - rid = PCI_MAP_REG_START; - } - /* - ** save old mapping, get size and type of memory - ** - ** type is in the lowest four bits. - ** If device requires 2^n bytes, the next - ** n-4 bits are read as 0. - */ - - sc->ha_Base = (void *)((p = pci_conf_read (tag, rid)) - & PCI_MAP_MEMORY_ADDRESS_MASK); - pci_conf_write (tag, rid, 0xfffffffful); - l = pci_conf_read (tag, rid); - pci_conf_write (tag, rid, p); - - /* - ** check the type - */ - - if (!((l & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_32BIT_1M - && ((u_long)sc->ha_Base & ~0xfffff) == 0) - && ((l & PCI_MAP_MEMORY_TYPE_MASK) != PCI_MAP_MEMORY_TYPE_32BIT)) { - debug_asr_printf ( - "asr_pci_map_mem failed: bad memory type=0x%x\n", - (unsigned) l); - return (0); - }; - - /* - ** get the size. - */ - - psize = -(l & PCI_MAP_MEMORY_ADDRESS_MASK); - if (psize > MAX_MAP) { - psize = MAX_MAP; - } - /* - * The 2005S Zero Channel RAID solution is not a perfect PCI - * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once - * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to - * BAR0+2MB and sets it's size to 2MB. The IOP registers are - * accessible via BAR0, the messaging registers are accessible - * via BAR1. If the subdevice code is 50 to 59 decimal. - */ - s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s)); - if (s != 0xA5111044) { - s = pci_conf_read (tag, PCIR_SUBVEND_0) - if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0) - && (ADPTDOMINATOR_SUB_ID_START <= s) - && (s <= ADPTDOMINATOR_SUB_ID_END)) { - psize = MAX_MAP; - } - } - - if ((sc->ha_Base == (void *)NULL) - || (sc->ha_Base == (void *)PCI_MAP_MEMORY_ADDRESS_MASK)) { - debug_asr_printf ("asr_pci_map_mem: not configured by bios.\n"); - return (0); - }; - - /* - ** Truncate sc->ha_Base to page boundary. - ** (Or does pmap_mapdev the job?) - */ - - poffs = (u_long)sc->ha_Base - trunc_page ((u_long)sc->ha_Base); - sc->ha_Virt = (i2oRegs_t *)pmap_mapdev ((u_long)sc->ha_Base - poffs, - psize + poffs); - - if (sc->ha_Virt == (i2oRegs_t *)NULL) { - return (0); - } - - sc->ha_Virt = (i2oRegs_t *)((u_long)sc->ha_Virt + poffs); - if (s == 0xA5111044) { - if ((rid += sizeof(u_int32_t)) - >= (PCI_MAP_REG_START + 4 * sizeof(u_int32_t))) { - return (0); - } - - /* - ** save old mapping, get size and type of memory - ** - ** type is in the lowest four bits. - ** If device requires 2^n bytes, the next - ** n-4 bits are read as 0. - */ - - if ((((p = pci_conf_read (tag, rid)) - & PCI_MAP_MEMORY_ADDRESS_MASK) == 0L) - || ((p & PCI_MAP_MEMORY_ADDRESS_MASK) - == PCI_MAP_MEMORY_ADDRESS_MASK)) { - debug_asr_printf ("asr_pci_map_mem: not configured by bios.\n"); - } - pci_conf_write (tag, rid, 0xfffffffful); - l = pci_conf_read (tag, rid); - pci_conf_write (tag, rid, p); - p &= PCI_MAP_MEMORY_TYPE_MASK; - - /* - ** check the type - */ - - if (!((l & PCI_MAP_MEMORY_TYPE_MASK) - == PCI_MAP_MEMORY_TYPE_32BIT_1M - && (p & ~0xfffff) == 0) - && ((l & PCI_MAP_MEMORY_TYPE_MASK) - != PCI_MAP_MEMORY_TYPE_32BIT)) { - debug_asr_printf ( - "asr_pci_map_mem failed: bad memory type=0x%x\n", - (unsigned) l); - return (0); - }; - - /* - ** get the size. - */ - - psize = -(l & PCI_MAP_MEMORY_ADDRESS_MASK); - if (psize > MAX_MAP) { - psize = MAX_MAP; - } - - /* - ** Truncate p to page boundary. - ** (Or does pmap_mapdev the job?) - */ - - poffs = p - trunc_page (p); - sc->ha_Fvirt = (U8 *)pmap_mapdev (p - poffs, psize + poffs); - - if (sc->ha_Fvirt == (U8 *)NULL) { - return (0); - } - - sc->ha_Fvirt = (U8 *)((u_long)sc->ha_Fvirt + poffs); - } else { - sc->ha_Fvirt = (U8 *)(sc->ha_Virt); - } + vm_size_t psize, poffs; + + /* + * I2O specification says we must find first *memory* mapped BAR + */ + for (rid = PCI_MAP_REG_START; + rid < (PCI_MAP_REG_START + 4 * sizeof(u_int32_t)); + rid += sizeof(u_int32_t)) { + p = pci_conf_read (tag, rid); + if ((p & 1) == 0) { + break; + } + } + if (rid >= (PCI_MAP_REG_START + 4 * sizeof(u_int32_t))) { + rid = PCI_MAP_REG_START; + } + /* + ** save old mapping, get size and type of memory + ** + ** type is in the lowest four bits. + ** If device requires 2^n bytes, the next + ** n-4 bits are read as 0. + */ + + sc->ha_Base = (void *)((p = pci_conf_read (tag, rid)) + & PCI_MAP_MEMORY_ADDRESS_MASK); + pci_conf_write (tag, rid, 0xfffffffful); + l = pci_conf_read (tag, rid); + pci_conf_write (tag, rid, p); + + /* + ** check the type + */ + + if (!((l & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_32BIT_1M + && ((u_long)sc->ha_Base & ~0xfffff) == 0) + && ((l & PCI_MAP_MEMORY_TYPE_MASK) != PCI_MAP_MEMORY_TYPE_32BIT)) { + debug_asr_printf ( + "asr_pci_map_mem failed: bad memory type=0x%x\n", + (unsigned) l); + return (0); + }; + + /* + ** get the size. + */ + + psize = -(l & PCI_MAP_MEMORY_ADDRESS_MASK); + if (psize > MAX_MAP) { + psize = MAX_MAP; + } + /* + * The 2005S Zero Channel RAID solution is not a perfect PCI + * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once + * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to + * BAR0+2MB and sets it's size to 2MB. The IOP registers are + * accessible via BAR0, the messaging registers are accessible + * via BAR1. If the subdevice code is 50 to 59 decimal. + */ + s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s)); + if (s != 0xA5111044) { + s = pci_conf_read (tag, PCIR_SUBVEND_0) + if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0) + && (ADPTDOMINATOR_SUB_ID_START <= s) + && (s <= ADPTDOMINATOR_SUB_ID_END)) { + psize = MAX_MAP; + } + } + + if ((sc->ha_Base == (void *)NULL) + || (sc->ha_Base == (void *)PCI_MAP_MEMORY_ADDRESS_MASK)) { + debug_asr_printf ("asr_pci_map_mem: not configured by bios.\n"); + return (0); + }; + + /* + ** Truncate sc->ha_Base to page boundary. + ** (Or does pmap_mapdev the job?) + */ + + poffs = (u_long)sc->ha_Base - trunc_page ((u_long)sc->ha_Base); + sc->ha_Virt = (i2oRegs_t *)pmap_mapdev ((u_long)sc->ha_Base - poffs, + psize + poffs); + + if (sc->ha_Virt == (i2oRegs_t *)NULL) { + return (0); + } + + sc->ha_Virt = (i2oRegs_t *)((u_long)sc->ha_Virt + poffs); + if (s == 0xA5111044) { + if ((rid += sizeof(u_int32_t)) + >= (PCI_MAP_REG_START + 4 * sizeof(u_int32_t))) { + return (0); + } + + /* + ** save old mapping, get size and type of memory + ** + ** type is in the lowest four bits. + ** If device requires 2^n bytes, the next + ** n-4 bits are read as 0. + */ + + if ((((p = pci_conf_read (tag, rid)) + & PCI_MAP_MEMORY_ADDRESS_MASK) == 0L) + || ((p & PCI_MAP_MEMORY_ADDRESS_MASK) + == PCI_MAP_MEMORY_ADDRESS_MASK)) { + debug_asr_printf ("asr_pci_map_mem: not configured by bios.\n"); + } + pci_conf_write (tag, rid, 0xfffffffful); + l = pci_conf_read (tag, rid); + pci_conf_write (tag, rid, p); + p &= PCI_MAP_MEMORY_TYPE_MASK; + + /* + ** check the type + */ + + if (!((l & PCI_MAP_MEMORY_TYPE_MASK) + == PCI_MAP_MEMORY_TYPE_32BIT_1M + && (p & ~0xfffff) == 0) + && ((l & PCI_MAP_MEMORY_TYPE_MASK) + != PCI_MAP_MEMORY_TYPE_32BIT)) { + debug_asr_printf ( + "asr_pci_map_mem failed: bad memory type=0x%x\n", + (unsigned) l); + return (0); + }; + + /* + ** get the size. + */ + + psize = -(l & PCI_MAP_MEMORY_ADDRESS_MASK); + if (psize > MAX_MAP) { + psize = MAX_MAP; + } + + /* + ** Truncate p to page boundary. + ** (Or does pmap_mapdev the job?) + */ + + poffs = p - trunc_page (p); + sc->ha_Fvirt = (U8 *)pmap_mapdev (p - poffs, psize + poffs); + + if (sc->ha_Fvirt == (U8 *)NULL) { + return (0); + } + + sc->ha_Fvirt = (U8 *)((u_long)sc->ha_Fvirt + poffs); + } else { + sc->ha_Fvirt = (U8 *)(sc->ha_Virt); + } #endif - return (1); + return (1); } /* asr_pci_map_mem */ /* - * A simplified copy of the real pci_map_int with additional + * A simplified copy of the real pci_map_int with additional * registration requirements. */ STATIC int asr_pci_map_int ( #if __FreeBSD_version >= 400000 - IN device_t tag, + IN device_t tag, #else - IN pcici_t tag, + IN pcici_t tag, #endif - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { #if __FreeBSD_version >= 400000 - int rid = 0; - - sc->ha_irq_res = bus_alloc_resource(tag, SYS_RES_IRQ, &rid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (sc->ha_irq_res == (struct resource *)NULL) { - return (0); - } - if (bus_setup_intr(tag, sc->ha_irq_res, INTR_TYPE_CAM | INTR_ENTROPY, - (driver_intr_t *)asr_intr, (void *)sc, &(sc->ha_intr))) { - return (0); - } - sc->ha_irq = pci_read_config(tag, PCIR_INTLINE, sizeof(char)); + int rid = 0; + + sc->ha_irq_res = bus_alloc_resource(tag, SYS_RES_IRQ, &rid, + 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (sc->ha_irq_res == (struct resource *)NULL) { + return (0); + } + if (bus_setup_intr(tag, sc->ha_irq_res, INTR_TYPE_CAM | INTR_ENTROPY, + (driver_intr_t *)asr_intr, (void *)sc, &(sc->ha_intr))) { + return (0); + } + sc->ha_irq = pci_read_config(tag, PCIR_INTLINE, sizeof(char)); #else - if (!pci_map_int(tag, (pci_inthand_t *)asr_intr, - (void *)sc, &cam_imask)) { - return (0); - } - sc->ha_irq = pci_conf_read(tag, PCIR_INTLINE); + if (!pci_map_int(tag, (pci_inthand_t *)asr_intr, + (void *)sc, &cam_imask)) { + return (0); + } + sc->ha_irq = pci_conf_read(tag, PCIR_INTLINE); #endif - return (1); + return (1); } /* asr_pci_map_int */ /* - * Attach the devices, and virtual devices to the driver list. + * Attach the devices, and virtual devices to the driver list. */ STATIC ATTACH_RET asr_attach (ATTACH_ARGS) { - Asr_softc_t * sc; - struct scsi_inquiry_data * iq; - ATTACH_SET(); + Asr_softc_t * sc; + struct scsi_inquiry_data * iq; + ATTACH_SET(); - if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == + if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == (Asr_softc_t *)NULL) - { - ATTACH_RETURN(ENOMEM); - } - if (Asr_softc == (Asr_softc_t *)NULL) { - /* - * Fixup the OS revision as saved in the dptsig for the - * engine (dptioctl.h) to pick up. - */ - bcopy (osrelease, &ASR_sig.dsDescription[16], 5); - printf ("asr%d: major=%d\n", unit, asr_cdevsw.d_maj); - } - /* - * Initialize the software structure - */ - LIST_INIT(&(sc->ha_ccb)); -# ifdef ASR_MEASURE_PERFORMANCE - { - u_int32_t i; - - /* initialize free list for timeQ */ - sc->ha_timeQFreeHead = 0; - sc->ha_timeQFreeTail = MAX_TIMEQ_SIZE - 1; - for (i = 0; i < MAX_TIMEQ_SIZE; i++) { - sc->ha_timeQFreeList[i] = i; - } - } -# endif - /* Link us into the HA list */ - { - Asr_softc_t **ha; - - for (ha = &Asr_softc; *ha; ha = &((*ha)->ha_next)); - *(ha) = sc; - } - { - PI2O_EXEC_STATUS_GET_REPLY status; - int size; - - /* - * This is the real McCoy! - */ - if (!asr_pci_map_mem(tag, sc)) { - printf ("asr%d: could not map memory\n", unit); - ATTACH_RETURN(ENXIO); - } - /* Enable if not formerly enabled */ + { + ATTACH_RETURN(ENOMEM); + } + if (Asr_softc == (Asr_softc_t *)NULL) { + /* + * Fixup the OS revision as saved in the dptsig for the + * engine (dptioctl.h) to pick up. + */ + bcopy (osrelease, &ASR_sig.dsDescription[16], 5); + printf ("asr%d: major=%d\n", unit, asr_cdevsw.d_maj); + } + /* + * Initialize the software structure + */ + LIST_INIT(&(sc->ha_ccb)); +# ifdef ASR_MEASURE_PERFORMANCE + { + u_int32_t i; + + /* initialize free list for timeQ */ + sc->ha_timeQFreeHead = 0; + sc->ha_timeQFreeTail = MAX_TIMEQ_SIZE - 1; + for (i = 0; i < MAX_TIMEQ_SIZE; i++) { + sc->ha_timeQFreeList[i] = i; + } + } +# endif + /* Link us into the HA list */ + { + Asr_softc_t **ha; + + for (ha = &Asr_softc; *ha; ha = &((*ha)->ha_next)); + *(ha) = sc; + } + { + PI2O_EXEC_STATUS_GET_REPLY status; + int size; + + /* + * This is the real McCoy! + */ + if (!asr_pci_map_mem(tag, sc)) { + printf ("asr%d: could not map memory\n", unit); + ATTACH_RETURN(ENXIO); + } + /* Enable if not formerly enabled */ #if __FreeBSD_version >= 400000 - pci_write_config (tag, PCIR_COMMAND, - pci_read_config (tag, PCIR_COMMAND, sizeof(char)) - | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN, sizeof(char)); - /* Knowledge is power, responsibility is direct */ - { - struct pci_devinfo { - STAILQ_ENTRY(pci_devinfo) pci_links; - struct resource_list resources; - pcicfgregs cfg; - } * dinfo = device_get_ivars(tag); - sc->ha_pciBusNum = dinfo->cfg.bus; - sc->ha_pciDeviceNum = (dinfo->cfg.slot << 3) - | dinfo->cfg.func; - } + pci_write_config (tag, PCIR_COMMAND, + pci_read_config (tag, PCIR_COMMAND, sizeof(char)) + | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN, sizeof(char)); + /* Knowledge is power, responsibility is direct */ + { + struct pci_devinfo { + STAILQ_ENTRY(pci_devinfo) pci_links; + struct resource_list resources; + pcicfgregs cfg; + } * dinfo = device_get_ivars(tag); + sc->ha_pciBusNum = dinfo->cfg.bus; + sc->ha_pciDeviceNum = (dinfo->cfg.slot << 3) + | dinfo->cfg.func; + } #else - pci_conf_write (tag, PCIR_COMMAND, - pci_conf_read (tag, PCIR_COMMAND) - | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - /* Knowledge is power, responsibility is direct */ - switch (pci_mechanism) { - - case 1: - sc->ha_pciBusNum = tag.cfg1 >> 16; - sc->ha_pciDeviceNum = tag.cfg1 >> 8; - - case 2: - sc->ha_pciBusNum = tag.cfg2.forward; - sc->ha_pciDeviceNum = ((tag.cfg2.enable >> 1) & 7) - | (tag.cfg2.port >> 5); - } + pci_conf_write (tag, PCIR_COMMAND, + pci_conf_read (tag, PCIR_COMMAND) + | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); + /* Knowledge is power, responsibility is direct */ + switch (pci_mechanism) { + + case 1: + sc->ha_pciBusNum = tag.cfg1 >> 16; + sc->ha_pciDeviceNum = tag.cfg1 >> 8; + + case 2: + sc->ha_pciBusNum = tag.cfg2.forward; + sc->ha_pciDeviceNum = ((tag.cfg2.enable >> 1) & 7) + | (tag.cfg2.port >> 5); + } #endif - /* Check if the device is there? */ - if ((ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt) == 0) - || ((status = (PI2O_EXEC_STATUS_GET_REPLY)malloc ( - sizeof(I2O_EXEC_STATUS_GET_REPLY), M_TEMP, M_WAITOK)) - == (PI2O_EXEC_STATUS_GET_REPLY)NULL) - || (ASR_getStatus(sc->ha_Virt, sc->ha_Fvirt, status) == NULL)) { - printf ("asr%d: could not initialize hardware\n", unit); - ATTACH_RETURN(ENODEV); /* Get next, maybe better luck */ - } - sc->ha_SystemTable.OrganizationID = status->OrganizationID; - sc->ha_SystemTable.IOP_ID = status->IOP_ID; - sc->ha_SystemTable.I2oVersion = status->I2oVersion; - sc->ha_SystemTable.IopState = status->IopState; - sc->ha_SystemTable.MessengerType = status->MessengerType; - sc->ha_SystemTable.InboundMessageFrameSize - = status->InboundMFrameSize; - sc->ha_SystemTable.MessengerInfo.InboundMessagePortAddressLow - = (U32)(sc->ha_Base) + (U32)(&(((i2oRegs_t *)NULL)->ToFIFO)); - - if (!asr_pci_map_int(tag, (void *)sc)) { - printf ("asr%d: could not map interrupt\n", unit); - ATTACH_RETURN(ENXIO); - } - - /* Adjust the maximim inbound count */ - if (((sc->ha_QueueSize - = I2O_EXEC_STATUS_GET_REPLY_getMaxInboundMFrames(status)) - > MAX_INBOUND) - || (sc->ha_QueueSize == 0)) { - sc->ha_QueueSize = MAX_INBOUND; - } - - /* Adjust the maximum outbound count */ - if (((sc->ha_Msgs_Count - = I2O_EXEC_STATUS_GET_REPLY_getMaxOutboundMFrames(status)) - > MAX_OUTBOUND) - || (sc->ha_Msgs_Count == 0)) { - sc->ha_Msgs_Count = MAX_OUTBOUND; - } - if (sc->ha_Msgs_Count > sc->ha_QueueSize) { - sc->ha_Msgs_Count = sc->ha_QueueSize; - } - - /* Adjust the maximum SG size to adapter */ - if ((size = (I2O_EXEC_STATUS_GET_REPLY_getInboundMFrameSize( - status) << 2)) > MAX_INBOUND_SIZE) { - size = MAX_INBOUND_SIZE; - } - free (status, M_TEMP); - sc->ha_SgSize = (size - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - + sizeof(I2O_SG_ELEMENT)) / sizeof(I2O_SGE_SIMPLE_ELEMENT); - } - - /* - * Only do a bus/HBA reset on the first time through. On this - * first time through, we do not send a flush to the devices. - */ - if (ASR_init(sc) == 0) { - struct BufferInfo { - I2O_PARAM_RESULTS_LIST_HEADER Header; - I2O_PARAM_READ_OPERATION_RESULT Read; - I2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info; - }; - defAlignLong (struct BufferInfo, Buffer); - PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info; -# define FW_DEBUG_BLED_OFFSET 8 - - if ((Info = (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR) - ASR_getParams(sc, 0, - I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO, - Buffer, sizeof(struct BufferInfo))) - != (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)NULL) { - sc->ha_blinkLED = sc->ha_Fvirt - + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR_getSerialOutputOffset(Info) - + FW_DEBUG_BLED_OFFSET; - } - if (ASR_acquireLct(sc) == 0) { - (void)ASR_acquireHrt(sc); - } - } else { - printf ("asr%d: failed to initialize\n", unit); - ATTACH_RETURN(ENXIO); - } - /* - * Add in additional probe responses for more channels. We - * are reusing the variable `target' for a channel loop counter. - * Done here because of we need both the acquireLct and - * acquireHrt data. - */ - { PI2O_LCT_ENTRY Device; - - for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) - (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); - ++Device) { - if (Device->le_type == I2O_UNKNOWN) { - continue; - } - if (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF) { - if (Device->le_target > sc->ha_MaxId) { - sc->ha_MaxId = Device->le_target; - } - if (Device->le_lun > sc->ha_MaxLun) { - sc->ha_MaxLun = Device->le_lun; - } - } - if (((Device->le_type & I2O_PORT) != 0) - && (Device->le_bus <= MAX_CHANNEL)) { - /* Do not increase MaxId for efficiency */ - sc->ha_adapter_target[Device->le_bus] - = Device->le_target; - } - } - } - - - /* - * Print the HBA model number as inquired from the card. - */ - - printf ("asr%d:", unit); - - if ((iq = (struct scsi_inquiry_data *)malloc ( - sizeof(struct scsi_inquiry_data), M_TEMP, M_WAITOK | M_ZERO)) - != (struct scsi_inquiry_data *)NULL) { - defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message); - PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr; - int posted = 0; - - bzero (Message_Ptr - = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message), - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)); - - I2O_MESSAGE_FRAME_setVersionOffset( - (PI2O_MESSAGE_FRAME)Message_Ptr, - I2O_VERSION_11 - | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT)) - / sizeof(U32)) << 4)); - I2O_MESSAGE_FRAME_setMessageSize( - (PI2O_MESSAGE_FRAME)Message_Ptr, - (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)) - / sizeof(U32)); - I2O_MESSAGE_FRAME_setInitiatorAddress ( - (PI2O_MESSAGE_FRAME)Message_Ptr, 1); - I2O_MESSAGE_FRAME_setFunction( - (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE); - I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( - (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, - I2O_SCSI_SCB_EXEC); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, - I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(Message_Ptr, 1); - I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( - (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, - DPT_ORGANIZATION_ID); - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6); - Message_Ptr->CDB[0] = INQUIRY; - Message_Ptr->CDB[4] = (unsigned char)sizeof(struct scsi_inquiry_data); - if (Message_Ptr->CDB[4] == 0) { - Message_Ptr->CDB[4] = 255; - } - - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, - (I2O_SCB_FLAG_XFER_FROM_DEVICE - | I2O_SCB_FLAG_ENABLE_DISCONNECT - | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG - | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); - - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, - sizeof(struct scsi_inquiry_data)); - SG(&(Message_Ptr->SGL), 0, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - iq, sizeof(struct scsi_inquiry_data)); - (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - - if (iq->vendor[0] && (iq->vendor[0] != ' ')) { - printf (" "); - ASR_prstring (iq->vendor, 8); - ++posted; - } - if (iq->product[0] && (iq->product[0] != ' ')) { - printf (" "); - ASR_prstring (iq->product, 16); - ++posted; - } - if (iq->revision[0] && (iq->revision[0] != ' ')) { - printf (" FW Rev. "); - ASR_prstring (iq->revision, 4); - ++posted; - } - free ((caddr_t)iq, M_TEMP); - if (posted) { - printf (","); - } - } - printf (" %d channel, %d CCBs, Protocol I2O\n", sc->ha_MaxBus + 1, - (sc->ha_QueueSize > MAX_INBOUND) ? MAX_INBOUND : sc->ha_QueueSize); - - /* - * fill in the prototype cam_path. - */ - { - int bus; - union asr_ccb * ccb; - - if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { - printf ("asr%d: CAM could not be notified of asynchronous callback parameters\n", unit); - ATTACH_RETURN(ENOMEM); - } - for (bus = 0; bus <= sc->ha_MaxBus; ++bus) { - struct cam_devq * devq; - int QueueSize = sc->ha_QueueSize; - - if (QueueSize > MAX_INBOUND) { - QueueSize = MAX_INBOUND; - } - - /* - * Create the device queue for our SIM(s). - */ - if ((devq = cam_simq_alloc(QueueSize)) == NULL) { - continue; - } - - /* - * Construct our first channel SIM entry - */ - sc->ha_sim[bus] = cam_sim_alloc( - asr_action, asr_poll, "asr", sc, - unit, 1, QueueSize, devq); - if (sc->ha_sim[bus] == NULL) { - continue; - } - - if (xpt_bus_register(sc->ha_sim[bus], bus) - != CAM_SUCCESS) { - cam_sim_free(sc->ha_sim[bus], - /*free_devq*/TRUE); - sc->ha_sim[bus] = NULL; - continue; - } - - if (xpt_create_path(&(sc->ha_path[bus]), /*periph*/NULL, - cam_sim_path(sc->ha_sim[bus]), CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - xpt_bus_deregister( - cam_sim_path(sc->ha_sim[bus])); - cam_sim_free(sc->ha_sim[bus], - /*free_devq*/TRUE); - sc->ha_sim[bus] = NULL; - continue; - } - } - asr_free_ccb (ccb); - } - /* - * Generate the device node information - */ - (void)make_dev(&asr_cdevsw, unit, 0, 0, S_IRWXU, "rasr%d", unit); - ATTACH_RETURN(0); + /* Check if the device is there? */ + if ((ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt) == 0) + || ((status = (PI2O_EXEC_STATUS_GET_REPLY)malloc ( + sizeof(I2O_EXEC_STATUS_GET_REPLY), M_TEMP, M_WAITOK)) + == (PI2O_EXEC_STATUS_GET_REPLY)NULL) + || (ASR_getStatus(sc->ha_Virt, sc->ha_Fvirt, status) == NULL)) { + printf ("asr%d: could not initialize hardware\n", unit); + ATTACH_RETURN(ENODEV); /* Get next, maybe better luck */ + } + sc->ha_SystemTable.OrganizationID = status->OrganizationID; + sc->ha_SystemTable.IOP_ID = status->IOP_ID; + sc->ha_SystemTable.I2oVersion = status->I2oVersion; + sc->ha_SystemTable.IopState = status->IopState; + sc->ha_SystemTable.MessengerType = status->MessengerType; + sc->ha_SystemTable.InboundMessageFrameSize + = status->InboundMFrameSize; + sc->ha_SystemTable.MessengerInfo.InboundMessagePortAddressLow + = (U32)(sc->ha_Base) + (U32)(&(((i2oRegs_t *)NULL)->ToFIFO)); + + if (!asr_pci_map_int(tag, (void *)sc)) { + printf ("asr%d: could not map interrupt\n", unit); + ATTACH_RETURN(ENXIO); + } + + /* Adjust the maximim inbound count */ + if (((sc->ha_QueueSize + = I2O_EXEC_STATUS_GET_REPLY_getMaxInboundMFrames(status)) + > MAX_INBOUND) + || (sc->ha_QueueSize == 0)) { + sc->ha_QueueSize = MAX_INBOUND; + } + + /* Adjust the maximum outbound count */ + if (((sc->ha_Msgs_Count + = I2O_EXEC_STATUS_GET_REPLY_getMaxOutboundMFrames(status)) + > MAX_OUTBOUND) + || (sc->ha_Msgs_Count == 0)) { + sc->ha_Msgs_Count = MAX_OUTBOUND; + } + if (sc->ha_Msgs_Count > sc->ha_QueueSize) { + sc->ha_Msgs_Count = sc->ha_QueueSize; + } + + /* Adjust the maximum SG size to adapter */ + if ((size = (I2O_EXEC_STATUS_GET_REPLY_getInboundMFrameSize( + status) << 2)) > MAX_INBOUND_SIZE) { + size = MAX_INBOUND_SIZE; + } + free (status, M_TEMP); + sc->ha_SgSize = (size - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + + sizeof(I2O_SG_ELEMENT)) / sizeof(I2O_SGE_SIMPLE_ELEMENT); + } + + /* + * Only do a bus/HBA reset on the first time through. On this + * first time through, we do not send a flush to the devices. + */ + if (ASR_init(sc) == 0) { + struct BufferInfo { + I2O_PARAM_RESULTS_LIST_HEADER Header; + I2O_PARAM_READ_OPERATION_RESULT Read; + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info; + }; + defAlignLong (struct BufferInfo, Buffer); + PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info; +# define FW_DEBUG_BLED_OFFSET 8 + + if ((Info = (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR) + ASR_getParams(sc, 0, + I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO, + Buffer, sizeof(struct BufferInfo))) + != (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)NULL) { + sc->ha_blinkLED = sc->ha_Fvirt + + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR_getSerialOutputOffset(Info) + + FW_DEBUG_BLED_OFFSET; + } + if (ASR_acquireLct(sc) == 0) { + (void)ASR_acquireHrt(sc); + } + } else { + printf ("asr%d: failed to initialize\n", unit); + ATTACH_RETURN(ENXIO); + } + /* + * Add in additional probe responses for more channels. We + * are reusing the variable `target' for a channel loop counter. + * Done here because of we need both the acquireLct and + * acquireHrt data. + */ + { PI2O_LCT_ENTRY Device; + + for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) + (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); + ++Device) { + if (Device->le_type == I2O_UNKNOWN) { + continue; + } + if (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF) { + if (Device->le_target > sc->ha_MaxId) { + sc->ha_MaxId = Device->le_target; + } + if (Device->le_lun > sc->ha_MaxLun) { + sc->ha_MaxLun = Device->le_lun; + } + } + if (((Device->le_type & I2O_PORT) != 0) + && (Device->le_bus <= MAX_CHANNEL)) { + /* Do not increase MaxId for efficiency */ + sc->ha_adapter_target[Device->le_bus] + = Device->le_target; + } + } + } + + + /* + * Print the HBA model number as inquired from the card. + */ + + printf ("asr%d:", unit); + + if ((iq = (struct scsi_inquiry_data *)malloc ( + sizeof(struct scsi_inquiry_data), M_TEMP, M_WAITOK | M_ZERO)) + != (struct scsi_inquiry_data *)NULL) { + defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message); + PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr; + int posted = 0; + + bzero (Message_Ptr + = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message), + sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)); + + I2O_MESSAGE_FRAME_setVersionOffset( + (PI2O_MESSAGE_FRAME)Message_Ptr, + I2O_VERSION_11 + | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT)) + / sizeof(U32)) << 4)); + I2O_MESSAGE_FRAME_setMessageSize( + (PI2O_MESSAGE_FRAME)Message_Ptr, + (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) + - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)) + / sizeof(U32)); + I2O_MESSAGE_FRAME_setInitiatorAddress ( + (PI2O_MESSAGE_FRAME)Message_Ptr, 1); + I2O_MESSAGE_FRAME_setFunction( + (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE); + I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( + (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, + I2O_SCSI_SCB_EXEC); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, + I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(Message_Ptr, 1); + I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( + (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, + DPT_ORGANIZATION_ID); + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6); + Message_Ptr->CDB[0] = INQUIRY; + Message_Ptr->CDB[4] = (unsigned char)sizeof(struct scsi_inquiry_data); + if (Message_Ptr->CDB[4] == 0) { + Message_Ptr->CDB[4] = 255; + } + + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, + (I2O_SCB_FLAG_XFER_FROM_DEVICE + | I2O_SCB_FLAG_ENABLE_DISCONNECT + | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG + | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); + + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, + sizeof(struct scsi_inquiry_data)); + SG(&(Message_Ptr->SGL), 0, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + iq, sizeof(struct scsi_inquiry_data)); + (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + + if (iq->vendor[0] && (iq->vendor[0] != ' ')) { + printf (" "); + ASR_prstring (iq->vendor, 8); + ++posted; + } + if (iq->product[0] && (iq->product[0] != ' ')) { + printf (" "); + ASR_prstring (iq->product, 16); + ++posted; + } + if (iq->revision[0] && (iq->revision[0] != ' ')) { + printf (" FW Rev. "); + ASR_prstring (iq->revision, 4); + ++posted; + } + free ((caddr_t)iq, M_TEMP); + if (posted) { + printf (","); + } + } + printf (" %d channel, %d CCBs, Protocol I2O\n", sc->ha_MaxBus + 1, + (sc->ha_QueueSize > MAX_INBOUND) ? MAX_INBOUND : sc->ha_QueueSize); + + /* + * fill in the prototype cam_path. + */ + { + int bus; + union asr_ccb * ccb; + + if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { + printf ("asr%d: CAM could not be notified of asynchronous callback parameters\n", unit); + ATTACH_RETURN(ENOMEM); + } + for (bus = 0; bus <= sc->ha_MaxBus; ++bus) { + struct cam_devq * devq; + int QueueSize = sc->ha_QueueSize; + + if (QueueSize > MAX_INBOUND) { + QueueSize = MAX_INBOUND; + } + + /* + * Create the device queue for our SIM(s). + */ + if ((devq = cam_simq_alloc(QueueSize)) == NULL) { + continue; + } + + /* + * Construct our first channel SIM entry + */ + sc->ha_sim[bus] = cam_sim_alloc( + asr_action, asr_poll, "asr", sc, + unit, 1, QueueSize, devq); + if (sc->ha_sim[bus] == NULL) { + continue; + } + + if (xpt_bus_register(sc->ha_sim[bus], bus) + != CAM_SUCCESS) { + cam_sim_free(sc->ha_sim[bus], + /*free_devq*/TRUE); + sc->ha_sim[bus] = NULL; + continue; + } + + if (xpt_create_path(&(sc->ha_path[bus]), /*periph*/NULL, + cam_sim_path(sc->ha_sim[bus]), CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_bus_deregister( + cam_sim_path(sc->ha_sim[bus])); + cam_sim_free(sc->ha_sim[bus], + /*free_devq*/TRUE); + sc->ha_sim[bus] = NULL; + continue; + } + } + asr_free_ccb (ccb); + } + /* + * Generate the device node information + */ + (void)make_dev(&asr_cdevsw, unit, 0, 0, S_IRWXU, "rasr%d", unit); + ATTACH_RETURN(0); } /* asr_attach */ STATIC void asr_poll( - IN struct cam_sim *sim) + IN struct cam_sim *sim) { - asr_intr(cam_sim_softc(sim)); + asr_intr(cam_sim_softc(sim)); } /* asr_poll */ STATIC void asr_action( - IN struct cam_sim * sim, - IN union ccb * ccb) + IN struct cam_sim * sim, + IN union ccb * ccb) { - struct Asr_softc * sc; - - debug_asr_printf ("asr_action(%lx,%lx{%x})\n", - (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code); - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("asr_action\n")); - - ccb->ccb_h.spriv_ptr0 = sc = (struct Asr_softc *)cam_sim_softc(sim); - - switch (ccb->ccb_h.func_code) { - - /* Common cases first */ - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - { - struct Message { - char M[MAX_INBOUND_SIZE]; - }; - defAlignLong(struct Message,Message); - PI2O_MESSAGE_FRAME Message_Ptr; - - /* Reject incoming commands while we are resetting the card */ - if (sc->ha_in_reset != HA_OPERATIONAL) { - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - if (sc->ha_in_reset >= HA_OFF_LINE) { - /* HBA is now off-line */ - ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR; - } else { - /* HBA currently resetting, try again later. */ - ccb->ccb_h.status |= CAM_REQUEUE_REQ; - } - debug_asr_cmd_printf (" e\n"); - xpt_done(ccb); - debug_asr_cmd_printf (" q\n"); - break; - } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { - printf( - "asr%d WARNING: scsi_cmd(%x) already done on b%dt%du%d\n", - cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), - ccb->csio.cdb_io.cdb_bytes[0], - cam_sim_bus(sim), - ccb->ccb_h.target_id, - ccb->ccb_h.target_lun); - } - debug_asr_cmd_printf ("(%d,%d,%d,%d)", - cam_sim_unit(sim), - cam_sim_bus(sim), - ccb->ccb_h.target_id, - ccb->ccb_h.target_lun); - debug_asr_cmd_dump_ccb(ccb); - - if ((Message_Ptr = ASR_init_message ((union asr_ccb *)ccb, - (PI2O_MESSAGE_FRAME)Message)) != (PI2O_MESSAGE_FRAME)NULL) { - debug_asr_cmd2_printf ("TID=%x:\n", - PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getTID( - (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)); - debug_asr_cmd2_dump_message(Message_Ptr); - debug_asr_cmd1_printf (" q"); - - if (ASR_queue (sc, Message_Ptr) == EMPTY_QUEUE) { + struct Asr_softc * sc; + + debug_asr_printf ("asr_action(%lx,%lx{%x})\n", + (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code); + + CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("asr_action\n")); + + ccb->ccb_h.spriv_ptr0 = sc = (struct Asr_softc *)cam_sim_softc(sim); + + switch (ccb->ccb_h.func_code) { + + /* Common cases first */ + case XPT_SCSI_IO: /* Execute the requested I/O operation */ + { + struct Message { + char M[MAX_INBOUND_SIZE]; + }; + defAlignLong(struct Message,Message); + PI2O_MESSAGE_FRAME Message_Ptr; + + /* Reject incoming commands while we are resetting the card */ + if (sc->ha_in_reset != HA_OPERATIONAL) { + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + if (sc->ha_in_reset >= HA_OFF_LINE) { + /* HBA is now off-line */ + ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR; + } else { + /* HBA currently resetting, try again later. */ + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + } + debug_asr_cmd_printf (" e\n"); + xpt_done(ccb); + debug_asr_cmd_printf (" q\n"); + break; + } + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { + printf( + "asr%d WARNING: scsi_cmd(%x) already done on b%dt%du%d\n", + cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), + ccb->csio.cdb_io.cdb_bytes[0], + cam_sim_bus(sim), + ccb->ccb_h.target_id, + ccb->ccb_h.target_lun); + } + debug_asr_cmd_printf ("(%d,%d,%d,%d)", + cam_sim_unit(sim), + cam_sim_bus(sim), + ccb->ccb_h.target_id, + ccb->ccb_h.target_lun); + debug_asr_cmd_dump_ccb(ccb); + + if ((Message_Ptr = ASR_init_message ((union asr_ccb *)ccb, + (PI2O_MESSAGE_FRAME)Message)) != (PI2O_MESSAGE_FRAME)NULL) { + debug_asr_cmd2_printf ("TID=%x:\n", + PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getTID( + (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)); + debug_asr_cmd2_dump_message(Message_Ptr); + debug_asr_cmd1_printf (" q"); + + if (ASR_queue (sc, Message_Ptr) == EMPTY_QUEUE) { #ifdef ASR_MEASURE_PERFORMANCE - ++sc->ha_performance.command_too_busy; + ++sc->ha_performance.command_too_busy; #endif - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_REQUEUE_REQ; - debug_asr_cmd_printf (" E\n"); - xpt_done(ccb); - } - debug_asr_cmd_printf (" Q\n"); - break; - } - /* - * We will get here if there is no valid TID for the device - * referenced in the scsi command packet. - */ - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_SEL_TIMEOUT; - debug_asr_cmd_printf (" B\n"); - xpt_done(ccb); - break; - } - - case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ - /* Rese HBA device ... */ - asr_hbareset (sc); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - -# if (defined(REPORT_LUNS)) - case REPORT_LUNS: -# endif - case XPT_ABORT: /* Abort the specified CCB */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - - case XPT_SET_TRAN_SETTINGS: - /* XXX Implement */ - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - break; - - case XPT_GET_TRAN_SETTINGS: - /* Get default/user set transfer settings for the target */ - { - struct ccb_trans_settings *cts; - u_int target_mask; - - cts = &(ccb->cts); - target_mask = 0x01 << ccb->ccb_h.target_id; - if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { - cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB; - cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; - cts->sync_period = 6; /* 40MHz */ - cts->sync_offset = 15; - - cts->valid = CCB_TRANS_SYNC_RATE_VALID - | CCB_TRANS_SYNC_OFFSET_VALID - | CCB_TRANS_BUS_WIDTH_VALID - | CCB_TRANS_DISC_VALID - | CCB_TRANS_TQ_VALID; - ccb->ccb_h.status = CAM_REQ_CMP; - } else { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - } - xpt_done(ccb); - break; - } - - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - u_int32_t size_mb; - u_int32_t secs_per_cylinder; - - ccg = &(ccb->ccg); - size_mb = ccg->volume_size - / ((1024L * 1024L) / ccg->block_size); - - if (size_mb > 4096) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else if (size_mb > 2048) { - ccg->heads = 128; - ccg->secs_per_track = 63; - } else if (size_mb > 1024) { - ccg->heads = 65; - ccg->secs_per_track = 63; - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - - case XPT_RESET_BUS: /* Reset the specified SCSI bus */ - ASR_resetBus (sc, cam_sim_bus(sim)); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - - case XPT_TERM_IO: /* Terminate the I/O process */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - - case XPT_PATH_INQ: /* Path routing inquiry */ - { - struct ccb_pathinq *cpi = &(ccb->cpi); - - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; - cpi->target_sprt = 0; - /* Not necessary to reset bus, done by HDM initialization */ - cpi->hba_misc = PIM_NOBUSRESET; - cpi->hba_eng_cnt = 0; - cpi->max_target = sc->ha_MaxId; - cpi->max_lun = sc->ha_MaxLun; - cpi->initiator_id = sc->ha_adapter_target[cam_sim_bus(sim)]; - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); - strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - default: - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + debug_asr_cmd_printf (" E\n"); + xpt_done(ccb); + } + debug_asr_cmd_printf (" Q\n"); + break; + } + /* + * We will get here if there is no valid TID for the device + * referenced in the scsi command packet. + */ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_SEL_TIMEOUT; + debug_asr_cmd_printf (" B\n"); + xpt_done(ccb); + break; + } + + case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ + /* Rese HBA device ... */ + asr_hbareset (sc); + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + +# if (defined(REPORT_LUNS)) + case REPORT_LUNS: +# endif + case XPT_ABORT: /* Abort the specified CCB */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + + case XPT_SET_TRAN_SETTINGS: + /* XXX Implement */ + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + xpt_done(ccb); + break; + + case XPT_GET_TRAN_SETTINGS: + /* Get default/user set transfer settings for the target */ + { + struct ccb_trans_settings *cts; + u_int target_mask; + + cts = &(ccb->cts); + target_mask = 0x01 << ccb->ccb_h.target_id; + if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { + cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB; + cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + cts->sync_period = 6; /* 40MHz */ + cts->sync_offset = 15; + + cts->valid = CCB_TRANS_SYNC_RATE_VALID + | CCB_TRANS_SYNC_OFFSET_VALID + | CCB_TRANS_BUS_WIDTH_VALID + | CCB_TRANS_DISC_VALID + | CCB_TRANS_TQ_VALID; + ccb->ccb_h.status = CAM_REQ_CMP; + } else { + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + } + xpt_done(ccb); + break; + } + + case XPT_CALC_GEOMETRY: + { + struct ccb_calc_geometry *ccg; + u_int32_t size_mb; + u_int32_t secs_per_cylinder; + + ccg = &(ccb->ccg); + size_mb = ccg->volume_size + / ((1024L * 1024L) / ccg->block_size); + + if (size_mb > 4096) { + ccg->heads = 255; + ccg->secs_per_track = 63; + } else if (size_mb > 2048) { + ccg->heads = 128; + ccg->secs_per_track = 63; + } else if (size_mb > 1024) { + ccg->heads = 65; + ccg->secs_per_track = 63; + } else { + ccg->heads = 64; + ccg->secs_per_track = 32; + } + secs_per_cylinder = ccg->heads * ccg->secs_per_track; + ccg->cylinders = ccg->volume_size / secs_per_cylinder; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + + case XPT_RESET_BUS: /* Reset the specified SCSI bus */ + ASR_resetBus (sc, cam_sim_bus(sim)); + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + + case XPT_TERM_IO: /* Terminate the I/O process */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + + case XPT_PATH_INQ: /* Path routing inquiry */ + { + struct ccb_pathinq *cpi = &(ccb->cpi); + + cpi->version_num = 1; /* XXX??? */ + cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; + cpi->target_sprt = 0; + /* Not necessary to reset bus, done by HDM initialization */ + cpi->hba_misc = PIM_NOBUSRESET; + cpi->hba_eng_cnt = 0; + cpi->max_target = sc->ha_MaxId; + cpi->max_lun = sc->ha_MaxLun; + cpi->initiator_id = sc->ha_adapter_target[cam_sim_bus(sim)]; + cpi->bus_id = cam_sim_bus(sim); + cpi->base_transfer_speed = 3300; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } } /* asr_action */ #ifdef ASR_MEASURE_PERFORMANCE -#define WRITE_OP 1 -#define READ_OP 2 -#define min_submitR sc->ha_performance.read_by_size_min_time[index] -#define max_submitR sc->ha_performance.read_by_size_max_time[index] -#define min_submitW sc->ha_performance.write_by_size_min_time[index] -#define max_submitW sc->ha_performance.write_by_size_max_time[index] +#define WRITE_OP 1 +#define READ_OP 2 +#define min_submitR sc->ha_performance.read_by_size_min_time[index] +#define max_submitR sc->ha_performance.read_by_size_max_time[index] +#define min_submitW sc->ha_performance.write_by_size_min_time[index] +#define max_submitW sc->ha_performance.write_by_size_max_time[index] STATIC INLINE void asr_IObySize( - IN Asr_softc_t * sc, - IN u_int32_t submitted_time, - IN int op, - IN int index) + IN Asr_softc_t * sc, + IN u_int32_t submitted_time, + IN int op, + IN int index) { - struct timeval submitted_timeval; - - submitted_timeval.tv_sec = 0; - submitted_timeval.tv_usec = submitted_time; - - if ( op == READ_OP ) { - ++sc->ha_performance.read_by_size_count[index]; - - if ( submitted_time != 0xffffffff ) { - timevaladd( - &(sc->ha_performance.read_by_size_total_time[index]), - &submitted_timeval); - if ( (min_submitR == 0) - || (submitted_time < min_submitR) ) { - min_submitR = submitted_time; - } - - if ( submitted_time > max_submitR ) { - max_submitR = submitted_time; - } - } - } else { - ++sc->ha_performance.write_by_size_count[index]; - if ( submitted_time != 0xffffffff ) { - timevaladd( - &(sc->ha_performance.write_by_size_total_time[index]), - &submitted_timeval); - if ( (submitted_time < min_submitW) - || (min_submitW == 0) ) { - min_submitW = submitted_time; - } - - if ( submitted_time > max_submitW ) { - max_submitW = submitted_time; - } - } - } + struct timeval submitted_timeval; + + submitted_timeval.tv_sec = 0; + submitted_timeval.tv_usec = submitted_time; + + if ( op == READ_OP ) { + ++sc->ha_performance.read_by_size_count[index]; + + if ( submitted_time != 0xffffffff ) { + timevaladd( + &(sc->ha_performance.read_by_size_total_time[index]), + &submitted_timeval); + if ( (min_submitR == 0) + || (submitted_time < min_submitR) ) { + min_submitR = submitted_time; + } + + if ( submitted_time > max_submitR ) { + max_submitR = submitted_time; + } + } + } else { + ++sc->ha_performance.write_by_size_count[index]; + if ( submitted_time != 0xffffffff ) { + timevaladd( + &(sc->ha_performance.write_by_size_total_time[index]), + &submitted_timeval); + if ( (submitted_time < min_submitW) + || (min_submitW == 0) ) { + min_submitW = submitted_time; + } + + if ( submitted_time > max_submitW ) { + max_submitW = submitted_time; + } + } + } } /* asr_IObySize */ #endif @@ -3457,403 +3457,403 @@ asr_IObySize( */ STATIC int asr_intr ( - IN Asr_softc_t * sc) + IN Asr_softc_t * sc) { - OUT int processed; + OUT int processed; #ifdef ASR_MEASURE_PERFORMANCE - struct timeval junk; + struct timeval junk; - microtime(&junk); - sc->ha_performance.intr_started = junk; + microtime(&junk); + sc->ha_performance.intr_started = junk; #endif - for (processed = 0; - sc->ha_Virt->Status & Mask_InterruptsDisabled; - processed = 1) { - union asr_ccb * ccb; - U32 ReplyOffset; - PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply; - - if (((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE) - && ((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)) { - break; - } - Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)(ReplyOffset - - sc->ha_Msgs_Phys + (char *)(sc->ha_Msgs)); - /* - * We do not need any (optional byteswapping) method access to - * the Initiator context field. - */ - ccb = (union asr_ccb *)(long) - I2O_MESSAGE_FRAME_getInitiatorContext64( - &(Reply->StdReplyFrame.StdMessageFrame)); - if (I2O_MESSAGE_FRAME_getMsgFlags( - &(Reply->StdReplyFrame.StdMessageFrame)) - & I2O_MESSAGE_FLAGS_FAIL) { - defAlignLong(I2O_UTIL_NOP_MESSAGE,Message); - PI2O_UTIL_NOP_MESSAGE Message_Ptr; - U32 MessageOffset; - - MessageOffset = (u_long) - I2O_FAILURE_REPLY_MESSAGE_FRAME_getPreservedMFA( - (PI2O_FAILURE_REPLY_MESSAGE_FRAME)Reply); - /* - * Get the Original Message Frame's address, and get - * it's Transaction Context into our space. (Currently - * unused at original authorship, but better to be - * safe than sorry). Straight copy means that we - * need not concern ourselves with the (optional - * byteswapping) method access. - */ - Reply->StdReplyFrame.TransactionContext - = ((PI2O_SINGLE_REPLY_MESSAGE_FRAME) - (sc->ha_Fvirt + MessageOffset))->TransactionContext; - /* - * For 64 bit machines, we need to reconstruct the - * 64 bit context. - */ - ccb = (union asr_ccb *)(long) - I2O_MESSAGE_FRAME_getInitiatorContext64( - &(Reply->StdReplyFrame.StdMessageFrame)); - /* - * Unique error code for command failure. - */ - I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( - &(Reply->StdReplyFrame), (u_int16_t)-2); - /* - * Modify the message frame to contain a NOP and - * re-issue it to the controller. - */ - Message_Ptr = (PI2O_UTIL_NOP_MESSAGE)ASR_fillMessage( - Message, sizeof(I2O_UTIL_NOP_MESSAGE)); -# if (I2O_UTIL_NOP != 0) - I2O_MESSAGE_FRAME_setFunction ( - &(Message_Ptr->StdMessageFrame), - I2O_UTIL_NOP); -# endif - /* - * Copy the packet out to the Original Message - */ - bcopy ((caddr_t)Message_Ptr, - sc->ha_Fvirt + MessageOffset, - sizeof(I2O_UTIL_NOP_MESSAGE)); - /* - * Issue the NOP - */ - sc->ha_Virt->ToFIFO = MessageOffset; - } - - /* - * Asynchronous command with no return requirements, - * and a generic handler for immunity against odd error - * returns from the adapter. - */ - if (ccb == (union asr_ccb *)NULL) { - /* - * Return Reply so that it can be used for the - * next command - */ - sc->ha_Virt->FromFIFO = ReplyOffset; - continue; - } - - /* Welease Wadjah! (and stop timeouts) */ - ASR_ccbRemove (sc, ccb); - - switch ( - I2O_SINGLE_REPLY_MESSAGE_FRAME_getDetailedStatusCode( - &(Reply->StdReplyFrame))) { - - case I2O_SCSI_DSC_SUCCESS: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_REQ_CMP; - break; - - case I2O_SCSI_DSC_CHECK_CONDITION: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_REQ_CMP|CAM_AUTOSNS_VALID; - break; - - case I2O_SCSI_DSC_BUSY: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_ADAPTER_BUSY: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_BUS_BUSY: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_SCSI_BUSY; - break; - - case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_SEL_TIMEOUT; - break; - - case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_LUN_INVALID: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_CMD_TIMEOUT; - break; - - case I2O_SCSI_HBA_DSC_DATA_OVERRUN: - /* FALLTHRU */ - case I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_DATA_RUN_ERR; - break; - - default: - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_REQUEUE_REQ; - break; - } - if ((ccb->csio.resid = ccb->csio.dxfer_len) != 0) { - ccb->csio.resid -= - I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getTransferCount( - Reply); - } + for (processed = 0; + sc->ha_Virt->Status & Mask_InterruptsDisabled; + processed = 1) { + union asr_ccb * ccb; + U32 ReplyOffset; + PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply; + + if (((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE) + && ((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)) { + break; + } + Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)(ReplyOffset + - sc->ha_Msgs_Phys + (char *)(sc->ha_Msgs)); + /* + * We do not need any (optional byteswapping) method access to + * the Initiator context field. + */ + ccb = (union asr_ccb *)(long) + I2O_MESSAGE_FRAME_getInitiatorContext64( + &(Reply->StdReplyFrame.StdMessageFrame)); + if (I2O_MESSAGE_FRAME_getMsgFlags( + &(Reply->StdReplyFrame.StdMessageFrame)) + & I2O_MESSAGE_FLAGS_FAIL) { + defAlignLong(I2O_UTIL_NOP_MESSAGE,Message); + PI2O_UTIL_NOP_MESSAGE Message_Ptr; + U32 MessageOffset; + + MessageOffset = (u_long) + I2O_FAILURE_REPLY_MESSAGE_FRAME_getPreservedMFA( + (PI2O_FAILURE_REPLY_MESSAGE_FRAME)Reply); + /* + * Get the Original Message Frame's address, and get + * it's Transaction Context into our space. (Currently + * unused at original authorship, but better to be + * safe than sorry). Straight copy means that we + * need not concern ourselves with the (optional + * byteswapping) method access. + */ + Reply->StdReplyFrame.TransactionContext + = ((PI2O_SINGLE_REPLY_MESSAGE_FRAME) + (sc->ha_Fvirt + MessageOffset))->TransactionContext; + /* + * For 64 bit machines, we need to reconstruct the + * 64 bit context. + */ + ccb = (union asr_ccb *)(long) + I2O_MESSAGE_FRAME_getInitiatorContext64( + &(Reply->StdReplyFrame.StdMessageFrame)); + /* + * Unique error code for command failure. + */ + I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( + &(Reply->StdReplyFrame), (u_int16_t)-2); + /* + * Modify the message frame to contain a NOP and + * re-issue it to the controller. + */ + Message_Ptr = (PI2O_UTIL_NOP_MESSAGE)ASR_fillMessage( + Message, sizeof(I2O_UTIL_NOP_MESSAGE)); +# if (I2O_UTIL_NOP != 0) + I2O_MESSAGE_FRAME_setFunction ( + &(Message_Ptr->StdMessageFrame), + I2O_UTIL_NOP); +# endif + /* + * Copy the packet out to the Original Message + */ + bcopy ((caddr_t)Message_Ptr, + sc->ha_Fvirt + MessageOffset, + sizeof(I2O_UTIL_NOP_MESSAGE)); + /* + * Issue the NOP + */ + sc->ha_Virt->ToFIFO = MessageOffset; + } + + /* + * Asynchronous command with no return requirements, + * and a generic handler for immunity against odd error + * returns from the adapter. + */ + if (ccb == (union asr_ccb *)NULL) { + /* + * Return Reply so that it can be used for the + * next command + */ + sc->ha_Virt->FromFIFO = ReplyOffset; + continue; + } + + /* Welease Wadjah! (and stop timeouts) */ + ASR_ccbRemove (sc, ccb); + + switch ( + I2O_SINGLE_REPLY_MESSAGE_FRAME_getDetailedStatusCode( + &(Reply->StdReplyFrame))) { + + case I2O_SCSI_DSC_SUCCESS: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_REQ_CMP; + break; + + case I2O_SCSI_DSC_CHECK_CONDITION: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_REQ_CMP|CAM_AUTOSNS_VALID; + break; + + case I2O_SCSI_DSC_BUSY: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_ADAPTER_BUSY: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_BUS_BUSY: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_SCSI_BUSY; + break; + + case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_SEL_TIMEOUT; + break; + + case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_LUN_INVALID: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_CMD_TIMEOUT; + break; + + case I2O_SCSI_HBA_DSC_DATA_OVERRUN: + /* FALLTHRU */ + case I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_DATA_RUN_ERR; + break; + + default: + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + break; + } + if ((ccb->csio.resid = ccb->csio.dxfer_len) != 0) { + ccb->csio.resid -= + I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getTransferCount( + Reply); + } #ifdef ASR_MEASURE_PERFORMANCE - { - struct timeval endTime; - u_int32_t submitted_time; - u_int32_t size; - int op_type; - int startTimeIndex; - - --sc->ha_submitted_ccbs_count; - startTimeIndex - = (int)Reply->StdReplyFrame.TransactionContext; - if (-1 != startTimeIndex) { - /* Compute the time spent in device/adapter */ - microtime(&endTime); - submitted_time = asr_time_delta(sc->ha_timeQ[ - startTimeIndex], endTime); - /* put the startTimeIndex back on free list */ - ENQ_TIMEQ_FREE_LIST(startTimeIndex, - sc->ha_timeQFreeList, - sc->ha_timeQFreeHead, - sc->ha_timeQFreeTail); - } else { - submitted_time = 0xffffffff; - } - -#define maxctime sc->ha_performance.max_command_time[ccb->csio.cdb_io.cdb_bytes[0]] -#define minctime sc->ha_performance.min_command_time[ccb->csio.cdb_io.cdb_bytes[0]] - if (submitted_time != 0xffffffff) { - if ( maxctime < submitted_time ) { - maxctime = submitted_time; - } - if ( (minctime == 0) - || (minctime > submitted_time) ) { - minctime = submitted_time; - } - - if ( sc->ha_performance.max_submit_time - < submitted_time ) { - sc->ha_performance.max_submit_time - = submitted_time; - } - if ( sc->ha_performance.min_submit_time == 0 - || sc->ha_performance.min_submit_time - > submitted_time) { - sc->ha_performance.min_submit_time - = submitted_time; - } - - switch ( ccb->csio.cdb_io.cdb_bytes[0] ) { - - case 0xa8: /* 12-byte READ */ - /* FALLTHRU */ - case 0x08: /* 6-byte READ */ - /* FALLTHRU */ - case 0x28: /* 10-byte READ */ - op_type = READ_OP; - break; - - case 0x0a: /* 6-byte WRITE */ - /* FALLTHRU */ - case 0xaa: /* 12-byte WRITE */ - /* FALLTHRU */ - case 0x2a: /* 10-byte WRITE */ - op_type = WRITE_OP; - break; - - default: - op_type = 0; - break; - } - - if ( op_type != 0 ) { - struct scsi_rw_big * cmd; - - cmd = (struct scsi_rw_big *) - &(ccb->csio.cdb_io); - - size = (((u_int32_t) cmd->length2 << 8) - | ((u_int32_t) cmd->length1)) << 9; - - switch ( size ) { - - case 512: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_512); - break; - - case 1024: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_1K); - break; - - case 2048: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_2K); - break; - - case 4096: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_4K); - break; - - case 8192: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_8K); - break; - - case 16384: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_16K); - break; - - case 32768: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_32K); - break; - - case 65536: - asr_IObySize(sc, - submitted_time, op_type, - SIZE_64K); - break; - - default: - if ( size > (1 << 16) ) { - asr_IObySize(sc, - submitted_time, - op_type, - SIZE_BIGGER); - } else { - asr_IObySize(sc, - submitted_time, - op_type, - SIZE_OTHER); - } - break; - } - } - } - } + { + struct timeval endTime; + u_int32_t submitted_time; + u_int32_t size; + int op_type; + int startTimeIndex; + + --sc->ha_submitted_ccbs_count; + startTimeIndex + = (int)Reply->StdReplyFrame.TransactionContext; + if (-1 != startTimeIndex) { + /* Compute the time spent in device/adapter */ + microtime(&endTime); + submitted_time = asr_time_delta(sc->ha_timeQ[ + startTimeIndex], endTime); + /* put the startTimeIndex back on free list */ + ENQ_TIMEQ_FREE_LIST(startTimeIndex, + sc->ha_timeQFreeList, + sc->ha_timeQFreeHead, + sc->ha_timeQFreeTail); + } else { + submitted_time = 0xffffffff; + } + +#define maxctime sc->ha_performance.max_command_time[ccb->csio.cdb_io.cdb_bytes[0]] +#define minctime sc->ha_performance.min_command_time[ccb->csio.cdb_io.cdb_bytes[0]] + if (submitted_time != 0xffffffff) { + if ( maxctime < submitted_time ) { + maxctime = submitted_time; + } + if ( (minctime == 0) + || (minctime > submitted_time) ) { + minctime = submitted_time; + } + + if ( sc->ha_performance.max_submit_time + < submitted_time ) { + sc->ha_performance.max_submit_time + = submitted_time; + } + if ( sc->ha_performance.min_submit_time == 0 + || sc->ha_performance.min_submit_time + > submitted_time) { + sc->ha_performance.min_submit_time + = submitted_time; + } + + switch ( ccb->csio.cdb_io.cdb_bytes[0] ) { + + case 0xa8: /* 12-byte READ */ + /* FALLTHRU */ + case 0x08: /* 6-byte READ */ + /* FALLTHRU */ + case 0x28: /* 10-byte READ */ + op_type = READ_OP; + break; + + case 0x0a: /* 6-byte WRITE */ + /* FALLTHRU */ + case 0xaa: /* 12-byte WRITE */ + /* FALLTHRU */ + case 0x2a: /* 10-byte WRITE */ + op_type = WRITE_OP; + break; + + default: + op_type = 0; + break; + } + + if ( op_type != 0 ) { + struct scsi_rw_big * cmd; + + cmd = (struct scsi_rw_big *) + &(ccb->csio.cdb_io); + + size = (((u_int32_t) cmd->length2 << 8) + | ((u_int32_t) cmd->length1)) << 9; + + switch ( size ) { + + case 512: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_512); + break; + + case 1024: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_1K); + break; + + case 2048: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_2K); + break; + + case 4096: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_4K); + break; + + case 8192: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_8K); + break; + + case 16384: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_16K); + break; + + case 32768: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_32K); + break; + + case 65536: + asr_IObySize(sc, + submitted_time, op_type, + SIZE_64K); + break; + + default: + if ( size > (1 << 16) ) { + asr_IObySize(sc, + submitted_time, + op_type, + SIZE_BIGGER); + } else { + asr_IObySize(sc, + submitted_time, + op_type, + SIZE_OTHER); + } + break; + } + } + } + } #endif - /* Sense data in reply packet */ - if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) { - u_int16_t size = I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getAutoSenseTransferCount(Reply); - - if (size) { - if (size > sizeof(ccb->csio.sense_data)) { - size = sizeof(ccb->csio.sense_data); - } - if (size > I2O_SCSI_SENSE_DATA_SZ) { - size = I2O_SCSI_SENSE_DATA_SZ; - } - if ((ccb->csio.sense_len) - && (size > ccb->csio.sense_len)) { - size = ccb->csio.sense_len; - } - bcopy ((caddr_t)Reply->SenseData, - (caddr_t)&(ccb->csio.sense_data), size); - } - } - - /* - * Return Reply so that it can be used for the next command - * since we have no more need for it now - */ - sc->ha_Virt->FromFIFO = ReplyOffset; - - if (ccb->ccb_h.path) { - xpt_done ((union ccb *)ccb); - } else { - wakeup ((caddr_t)ccb); - } - } + /* Sense data in reply packet */ + if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) { + u_int16_t size = I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getAutoSenseTransferCount(Reply); + + if (size) { + if (size > sizeof(ccb->csio.sense_data)) { + size = sizeof(ccb->csio.sense_data); + } + if (size > I2O_SCSI_SENSE_DATA_SZ) { + size = I2O_SCSI_SENSE_DATA_SZ; + } + if ((ccb->csio.sense_len) + && (size > ccb->csio.sense_len)) { + size = ccb->csio.sense_len; + } + bcopy ((caddr_t)Reply->SenseData, + (caddr_t)&(ccb->csio.sense_data), size); + } + } + + /* + * Return Reply so that it can be used for the next command + * since we have no more need for it now + */ + sc->ha_Virt->FromFIFO = ReplyOffset; + + if (ccb->ccb_h.path) { + xpt_done ((union ccb *)ccb); + } else { + wakeup ((caddr_t)ccb); + } + } #ifdef ASR_MEASURE_PERFORMANCE - { - u_int32_t result; - - microtime(&junk); - result = asr_time_delta(sc->ha_performance.intr_started, junk); - - if (result != 0xffffffff) { - if ( sc->ha_performance.max_intr_time < result ) { - sc->ha_performance.max_intr_time = result; - } - - if ( (sc->ha_performance.min_intr_time == 0) - || (sc->ha_performance.min_intr_time > result) ) { - sc->ha_performance.min_intr_time = result; - } - } - } + { + u_int32_t result; + + microtime(&junk); + result = asr_time_delta(sc->ha_performance.intr_started, junk); + + if (result != 0xffffffff) { + if ( sc->ha_performance.max_intr_time < result ) { + sc->ha_performance.max_intr_time = result; + } + + if ( (sc->ha_performance.min_intr_time == 0) + || (sc->ha_performance.min_intr_time > result) ) { + sc->ha_performance.min_intr_time = result; + } + } + } #endif - return (processed); + return (processed); } /* asr_intr */ -#undef QueueSize /* Grrrr */ -#undef SG_Size /* Grrrr */ +#undef QueueSize /* Grrrr */ +#undef SG_Size /* Grrrr */ /* - * Meant to be included at the bottom of asr.c !!! + * Meant to be included at the bottom of asr.c !!! */ /* - * Included here as hard coded. Done because other necessary include - * files utilize C++ comment structures which make them a nuisance to - * included here just to pick up these three typedefs. + * Included here as hard coded. Done because other necessary include + * files utilize C++ comment structures which make them a nuisance to + * included here just to pick up these three typedefs. */ typedef U32 DPT_TAG_T; typedef U32 DPT_MSG_T; typedef U32 DPT_RTN_T; -#undef SCSI_RESET /* Conflicts with "scsi/scsiconf.h" defintion */ -#include "dev/asr/osd_unix.h" +#undef SCSI_RESET /* Conflicts with "scsi/scsiconf.h" defintion */ +#include "dev/asr/osd_unix.h" -#define asr_unit(dev) minor(dev) +#define asr_unit(dev) minor(dev) STATIC INLINE Asr_softc_t * ASR_get_sc ( - IN dev_t dev) + IN dev_t dev) { - int unit = asr_unit(dev); - OUT Asr_softc_t * sc = Asr_softc; + int unit = asr_unit(dev); + OUT Asr_softc_t * sc = Asr_softc; - while (sc && sc->ha_sim[0] && (cam_sim_unit(sc->ha_sim[0]) != unit)) { - sc = sc->ha_next; - } - return (sc); + while (sc && sc->ha_sim[0] && (cam_sim_unit(sc->ha_sim[0]) != unit)) { + sc = sc->ha_next; + } + return (sc); } /* ASR_get_sc */ STATIC u_int8_t ASR_ctlr_held; @@ -3863,800 +3863,800 @@ STATIC u_int8_t ASR_ctlr_held; STATIC int asr_open( - IN dev_t dev, - int32_t flags, - int32_t ifmt, - IN struct thread * td) + IN dev_t dev, + int32_t flags, + int32_t ifmt, + IN struct thread * td) { - int s; - OUT int error; - UNREFERENCED_PARAMETER(flags); - UNREFERENCED_PARAMETER(ifmt); - - if (ASR_get_sc (dev) == (Asr_softc_t *)NULL) { - return (ENODEV); - } - s = splcam (); - if (ASR_ctlr_held) { - error = EBUSY; - } else if ((error = suser(td)) == 0) { - ++ASR_ctlr_held; - } - splx(s); - return (error); + int s; + OUT int error; + UNREFERENCED_PARAMETER(flags); + UNREFERENCED_PARAMETER(ifmt); + + if (ASR_get_sc (dev) == (Asr_softc_t *)NULL) { + return (ENODEV); + } + s = splcam (); + if (ASR_ctlr_held) { + error = EBUSY; + } else if ((error = suser(td)) == 0) { + ++ASR_ctlr_held; + } + splx(s); + return (error); } /* asr_open */ STATIC int asr_close( - dev_t dev, - int flags, - int ifmt, - struct thread * td) + dev_t dev, + int flags, + int ifmt, + struct thread * td) { - UNREFERENCED_PARAMETER(dev); - UNREFERENCED_PARAMETER(flags); - UNREFERENCED_PARAMETER(ifmt); - UNREFERENCED_PARAMETER(td); + UNREFERENCED_PARAMETER(dev); + UNREFERENCED_PARAMETER(flags); + UNREFERENCED_PARAMETER(ifmt); + UNREFERENCED_PARAMETER(td); - ASR_ctlr_held = 0; - return (0); + ASR_ctlr_held = 0; + return (0); } /* asr_close */ /*-------------------------------------------------------------------------*/ -/* Function ASR_queue_i */ +/* Function ASR_queue_i */ /*-------------------------------------------------------------------------*/ -/* The Parameters Passed To This Function Are : */ -/* Asr_softc_t * : HBA miniport driver's adapter data storage. */ -/* PI2O_MESSAGE_FRAME : Msg Structure Pointer For This Command */ -/* I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME following the Msg Structure */ -/* */ -/* This Function Will Take The User Request Packet And Convert It To An */ -/* I2O MSG And Send It Off To The Adapter. */ -/* */ -/* Return : 0 For OK, Error Code Otherwise */ +/* The Parameters Passed To This Function Are : */ +/* Asr_softc_t * : HBA miniport driver's adapter data storage. */ +/* PI2O_MESSAGE_FRAME : Msg Structure Pointer For This Command */ +/* I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME following the Msg Structure */ +/* */ +/* This Function Will Take The User Request Packet And Convert It To An */ +/* I2O MSG And Send It Off To The Adapter. */ +/* */ +/* Return : 0 For OK, Error Code Otherwise */ /*-------------------------------------------------------------------------*/ STATIC INLINE int ASR_queue_i( - IN Asr_softc_t * sc, - INOUT PI2O_MESSAGE_FRAME Packet) + IN Asr_softc_t * sc, + INOUT PI2O_MESSAGE_FRAME Packet) { - union asr_ccb * ccb; - PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply; - PI2O_MESSAGE_FRAME Message_Ptr; - PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply_Ptr; - int MessageSizeInBytes; - int ReplySizeInBytes; - int error; - int s; - /* Scatter Gather buffer list */ - struct ioctlSgList_S { - SLIST_ENTRY(ioctlSgList_S) link; - caddr_t UserSpace; - I2O_FLAGS_COUNT FlagsCount; - char KernelSpace[sizeof(long)]; - } * elm; - /* Generates a `first' entry */ - SLIST_HEAD(ioctlSgListHead_S, ioctlSgList_S) sgList; - - if (ASR_getBlinkLedCode(sc)) { - debug_usr_cmd_printf ("Adapter currently in BlinkLed %x\n", - ASR_getBlinkLedCode(sc)); - return (EIO); - } - /* Copy in the message into a local allocation */ - if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc ( - sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK)) - == (PI2O_MESSAGE_FRAME)NULL) { - debug_usr_cmd_printf ( - "Failed to acquire I2O_MESSAGE_FRAME memory\n"); - return (ENOMEM); - } - if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr, - sizeof(I2O_MESSAGE_FRAME))) != 0) { - free (Message_Ptr, M_TEMP); - debug_usr_cmd_printf ("Can't copy in packet errno=%d\n", error); - return (error); - } - /* Acquire information to determine type of packet */ - MessageSizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)<<2); - /* The offset of the reply information within the user packet */ - Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)((char *)Packet - + MessageSizeInBytes); - - /* Check if the message is a synchronous initialization command */ - s = I2O_MESSAGE_FRAME_getFunction(Message_Ptr); - free (Message_Ptr, M_TEMP); - switch (s) { - - case I2O_EXEC_IOP_RESET: - { U32 status; - - status = ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt); - ReplySizeInBytes = sizeof(status); - debug_usr_cmd_printf ("resetIOP done\n"); - return (copyout ((caddr_t)&status, (caddr_t)Reply, - ReplySizeInBytes)); - } - - case I2O_EXEC_STATUS_GET: - { I2O_EXEC_STATUS_GET_REPLY status; - - if (ASR_getStatus (sc->ha_Virt, sc->ha_Fvirt, &status) - == (PI2O_EXEC_STATUS_GET_REPLY)NULL) { - debug_usr_cmd_printf ("getStatus failed\n"); - return (ENXIO); - } - ReplySizeInBytes = sizeof(status); - debug_usr_cmd_printf ("getStatus done\n"); - return (copyout ((caddr_t)&status, (caddr_t)Reply, - ReplySizeInBytes)); - } - - case I2O_EXEC_OUTBOUND_INIT: - { U32 status; - - status = ASR_initOutBound(sc); - ReplySizeInBytes = sizeof(status); - debug_usr_cmd_printf ("intOutBound done\n"); - return (copyout ((caddr_t)&status, (caddr_t)Reply, - ReplySizeInBytes)); - } - } - - /* Determine if the message size is valid */ - if ((MessageSizeInBytes < sizeof(I2O_MESSAGE_FRAME)) - || (MAX_INBOUND_SIZE < MessageSizeInBytes)) { - debug_usr_cmd_printf ("Packet size %d incorrect\n", - MessageSizeInBytes); - return (EINVAL); - } - - if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc (MessageSizeInBytes, - M_TEMP, M_WAITOK)) == (PI2O_MESSAGE_FRAME)NULL) { - debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n", - MessageSizeInBytes); - return (ENOMEM); - } - if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr, - MessageSizeInBytes)) != 0) { - free (Message_Ptr, M_TEMP); - debug_usr_cmd_printf ("Can't copy in packet[%d] errno=%d\n", - MessageSizeInBytes, error); - return (error); - } - - /* Check the size of the reply frame, and start constructing */ - - if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc ( - sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK)) - == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { - free (Message_Ptr, M_TEMP); - debug_usr_cmd_printf ( - "Failed to acquire I2O_MESSAGE_FRAME memory\n"); - return (ENOMEM); - } - if ((error = copyin ((caddr_t)Reply, (caddr_t)Reply_Ptr, - sizeof(I2O_MESSAGE_FRAME))) != 0) { - free (Reply_Ptr, M_TEMP); - free (Message_Ptr, M_TEMP); - debug_usr_cmd_printf ( - "Failed to copy in reply frame, errno=%d\n", - error); - return (error); - } - ReplySizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize( - &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) << 2); - free (Reply_Ptr, M_TEMP); - if (ReplySizeInBytes < sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)) { - free (Message_Ptr, M_TEMP); - debug_usr_cmd_printf ( - "Failed to copy in reply frame[%d], errno=%d\n", - ReplySizeInBytes, error); - return (EINVAL); - } - - if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc ( - ((ReplySizeInBytes > sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)) - ? ReplySizeInBytes - : sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)), - M_TEMP, M_WAITOK)) == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { - free (Message_Ptr, M_TEMP); - debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n", - ReplySizeInBytes); - return (ENOMEM); - } - (void)ASR_fillMessage ((char *)Reply_Ptr, ReplySizeInBytes); - Reply_Ptr->StdReplyFrame.StdMessageFrame.InitiatorContext - = Message_Ptr->InitiatorContext; - Reply_Ptr->StdReplyFrame.TransactionContext - = ((PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr)->TransactionContext; - I2O_MESSAGE_FRAME_setMsgFlags( - &(Reply_Ptr->StdReplyFrame.StdMessageFrame), - I2O_MESSAGE_FRAME_getMsgFlags( - &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) - | I2O_MESSAGE_FLAGS_REPLY); - - /* Check if the message is a special case command */ - switch (I2O_MESSAGE_FRAME_getFunction(Message_Ptr)) { - case I2O_EXEC_SYS_TAB_SET: /* Special Case of empty Scatter Gather */ - if (MessageSizeInBytes == ((I2O_MESSAGE_FRAME_getVersionOffset( - Message_Ptr) & 0xF0) >> 2)) { - free (Message_Ptr, M_TEMP); - I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( - &(Reply_Ptr->StdReplyFrame), - (ASR_setSysTab(sc) != CAM_REQ_CMP)); - I2O_MESSAGE_FRAME_setMessageSize( - &(Reply_Ptr->StdReplyFrame.StdMessageFrame), - sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)); - error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply, - ReplySizeInBytes); - free (Reply_Ptr, M_TEMP); - return (error); - } - } - - /* Deal in the general case */ - /* First allocate and optionally copy in each scatter gather element */ - SLIST_INIT(&sgList); - if ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) != 0) { - PI2O_SGE_SIMPLE_ELEMENT sg; - - /* - * since this code is reused in several systems, code - * efficiency is greater by using a shift operation rather - * than a divide by sizeof(u_int32_t). - */ - sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr - + ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) - >> 2)); - while (sg < (PI2O_SGE_SIMPLE_ELEMENT)(((caddr_t)Message_Ptr) - + MessageSizeInBytes)) { - caddr_t v; - int len; - - if ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount)) - & I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT) == 0) { - error = EINVAL; - break; - } - len = I2O_FLAGS_COUNT_getCount(&(sg->FlagsCount)); - debug_usr_cmd_printf ("SG[%d] = %x[%d]\n", - sg - (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr - + ((I2O_MESSAGE_FRAME_getVersionOffset( - Message_Ptr) & 0xF0) >> 2)), - I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), len); - - if ((elm = (struct ioctlSgList_S *)malloc ( - sizeof(*elm) - sizeof(elm->KernelSpace) + len, - M_TEMP, M_WAITOK)) - == (struct ioctlSgList_S *)NULL) { - debug_usr_cmd_printf ( - "Failed to allocate SG[%d]\n", len); - error = ENOMEM; - break; - } - SLIST_INSERT_HEAD(&sgList, elm, link); - elm->FlagsCount = sg->FlagsCount; - elm->UserSpace = (caddr_t) - (I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg)); - v = elm->KernelSpace; - /* Copy in outgoing data (DIR bit could be invalid) */ - if ((error = copyin (elm->UserSpace, (caddr_t)v, len)) - != 0) { - break; - } - /* - * If the buffer is not contiguous, lets - * break up the scatter/gather entries. - */ - while ((len > 0) - && (sg < (PI2O_SGE_SIMPLE_ELEMENT) - (((caddr_t)Message_Ptr) + MAX_INBOUND_SIZE))) { - int next, base, span; - - span = 0; - next = base = KVTOPHYS(v); - I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, - base); - - /* How far can we go physically contiguously */ - while ((len > 0) && (base == next)) { - int size; - - next = trunc_page(base) + PAGE_SIZE; - size = next - base; - if (size > len) { - size = len; - } - span += size; - v += size; - len -= size; - base = KVTOPHYS(v); - } - - /* Construct the Flags */ - I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), - span); - { - int flags = I2O_FLAGS_COUNT_getFlags( - &(elm->FlagsCount)); - /* Any remaining length? */ - if (len > 0) { - flags &= - ~(I2O_SGL_FLAGS_END_OF_BUFFER - | I2O_SGL_FLAGS_LAST_ELEMENT); - } - I2O_FLAGS_COUNT_setFlags( - &(sg->FlagsCount), flags); - } - - debug_usr_cmd_printf ("sg[%d] = %x[%d]\n", - sg - (PI2O_SGE_SIMPLE_ELEMENT) - ((char *)Message_Ptr - + ((I2O_MESSAGE_FRAME_getVersionOffset( - Message_Ptr) & 0xF0) >> 2)), - I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), - span); - if (len <= 0) { - break; - } - - /* - * Incrementing requires resizing of the - * packet, and moving up the existing SG - * elements. - */ - ++sg; - MessageSizeInBytes += sizeof(*sg); - I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, - I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr) - + (sizeof(*sg) / sizeof(U32))); - { - PI2O_MESSAGE_FRAME NewMessage_Ptr; - - if ((NewMessage_Ptr - = (PI2O_MESSAGE_FRAME) - malloc (MessageSizeInBytes, - M_TEMP, M_WAITOK)) - == (PI2O_MESSAGE_FRAME)NULL) { - debug_usr_cmd_printf ( - "Failed to acquire frame[%d] memory\n", - MessageSizeInBytes); - error = ENOMEM; - break; - } - span = ((caddr_t)sg) - - (caddr_t)Message_Ptr; - bcopy ((caddr_t)Message_Ptr, - (caddr_t)NewMessage_Ptr, span); - bcopy ((caddr_t)(sg-1), - ((caddr_t)NewMessage_Ptr) + span, - MessageSizeInBytes - span); - free (Message_Ptr, M_TEMP); - sg = (PI2O_SGE_SIMPLE_ELEMENT) - (((caddr_t)NewMessage_Ptr) + span); - Message_Ptr = NewMessage_Ptr; - } - } - if ((error) - || ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount)) - & I2O_SGL_FLAGS_LAST_ELEMENT) != 0)) { - break; - } - ++sg; - } - if (error) { - while ((elm = SLIST_FIRST(&sgList)) - != (struct ioctlSgList_S *)NULL) { - SLIST_REMOVE_HEAD(&sgList, link); - free (elm, M_TEMP); - } - free (Reply_Ptr, M_TEMP); - free (Message_Ptr, M_TEMP); - return (error); - } - } - - debug_usr_cmd_printf ("Inbound: "); - debug_usr_cmd_dump_message(Message_Ptr); - - /* Send the command */ - if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { - /* Free up in-kernel buffers */ - while ((elm = SLIST_FIRST(&sgList)) - != (struct ioctlSgList_S *)NULL) { - SLIST_REMOVE_HEAD(&sgList, link); - free (elm, M_TEMP); - } - free (Reply_Ptr, M_TEMP); - free (Message_Ptr, M_TEMP); - return (ENOMEM); - } - - /* - * We do not need any (optional byteswapping) method access to - * the Initiator context field. - */ - I2O_MESSAGE_FRAME_setInitiatorContext64( - (PI2O_MESSAGE_FRAME)Message_Ptr, (long)ccb); - - (void)ASR_queue (sc, (PI2O_MESSAGE_FRAME)Message_Ptr); - - free (Message_Ptr, M_TEMP); - - /* - * Wait for the board to report a finished instruction. - */ - s = splcam(); - while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { - if (ASR_getBlinkLedCode(sc)) { - /* Reset Adapter */ - printf ("asr%d: Blink LED 0x%x resetting adapter\n", - cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), - ASR_getBlinkLedCode(sc)); - if (ASR_reset (sc) == ENXIO) { - /* Command Cleanup */ - ASR_ccbRemove(sc, ccb); - } - splx(s); - /* Free up in-kernel buffers */ - while ((elm = SLIST_FIRST(&sgList)) - != (struct ioctlSgList_S *)NULL) { - SLIST_REMOVE_HEAD(&sgList, link); - free (elm, M_TEMP); - } - free (Reply_Ptr, M_TEMP); - asr_free_ccb(ccb); - return (EIO); - } - /* Check every second for BlinkLed */ - /* There is no PRICAM, but outwardly PRIBIO is functional */ - tsleep((caddr_t)ccb, PRIBIO, "asr", hz); - } - splx(s); - - debug_usr_cmd_printf ("Outbound: "); - debug_usr_cmd_dump_message(Reply_Ptr); - - I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( - &(Reply_Ptr->StdReplyFrame), - (ccb->ccb_h.status != CAM_REQ_CMP)); - - if (ReplySizeInBytes >= (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) - - I2O_SCSI_SENSE_DATA_SZ - sizeof(U32))) { - I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setTransferCount(Reply_Ptr, - ccb->csio.dxfer_len - ccb->csio.resid); - } - if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) && (ReplySizeInBytes - > (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) - - I2O_SCSI_SENSE_DATA_SZ))) { - int size = ReplySizeInBytes - - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) - - I2O_SCSI_SENSE_DATA_SZ; - - if (size > sizeof(ccb->csio.sense_data)) { - size = sizeof(ccb->csio.sense_data); - } - bcopy ((caddr_t)&(ccb->csio.sense_data), (caddr_t)Reply_Ptr->SenseData, - size); - I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setAutoSenseTransferCount( - Reply_Ptr, size); - } - - /* Free up in-kernel buffers */ - while ((elm = SLIST_FIRST(&sgList)) != (struct ioctlSgList_S *)NULL) { - /* Copy out as necessary */ - if ((error == 0) - /* DIR bit considered `valid', error due to ignorance works */ - && ((I2O_FLAGS_COUNT_getFlags(&(elm->FlagsCount)) - & I2O_SGL_FLAGS_DIR) == 0)) { - error = copyout ((caddr_t)(elm->KernelSpace), - elm->UserSpace, - I2O_FLAGS_COUNT_getCount(&(elm->FlagsCount))); - } - SLIST_REMOVE_HEAD(&sgList, link); - free (elm, M_TEMP); - } - if (error == 0) { - /* Copy reply frame to user space */ - error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply, - ReplySizeInBytes); - } - free (Reply_Ptr, M_TEMP); - asr_free_ccb(ccb); - - return (error); + union asr_ccb * ccb; + PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply; + PI2O_MESSAGE_FRAME Message_Ptr; + PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply_Ptr; + int MessageSizeInBytes; + int ReplySizeInBytes; + int error; + int s; + /* Scatter Gather buffer list */ + struct ioctlSgList_S { + SLIST_ENTRY(ioctlSgList_S) link; + caddr_t UserSpace; + I2O_FLAGS_COUNT FlagsCount; + char KernelSpace[sizeof(long)]; + } * elm; + /* Generates a `first' entry */ + SLIST_HEAD(ioctlSgListHead_S, ioctlSgList_S) sgList; + + if (ASR_getBlinkLedCode(sc)) { + debug_usr_cmd_printf ("Adapter currently in BlinkLed %x\n", + ASR_getBlinkLedCode(sc)); + return (EIO); + } + /* Copy in the message into a local allocation */ + if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc ( + sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK)) + == (PI2O_MESSAGE_FRAME)NULL) { + debug_usr_cmd_printf ( + "Failed to acquire I2O_MESSAGE_FRAME memory\n"); + return (ENOMEM); + } + if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr, + sizeof(I2O_MESSAGE_FRAME))) != 0) { + free (Message_Ptr, M_TEMP); + debug_usr_cmd_printf ("Can't copy in packet errno=%d\n", error); + return (error); + } + /* Acquire information to determine type of packet */ + MessageSizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)<<2); + /* The offset of the reply information within the user packet */ + Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)((char *)Packet + + MessageSizeInBytes); + + /* Check if the message is a synchronous initialization command */ + s = I2O_MESSAGE_FRAME_getFunction(Message_Ptr); + free (Message_Ptr, M_TEMP); + switch (s) { + + case I2O_EXEC_IOP_RESET: + { U32 status; + + status = ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt); + ReplySizeInBytes = sizeof(status); + debug_usr_cmd_printf ("resetIOP done\n"); + return (copyout ((caddr_t)&status, (caddr_t)Reply, + ReplySizeInBytes)); + } + + case I2O_EXEC_STATUS_GET: + { I2O_EXEC_STATUS_GET_REPLY status; + + if (ASR_getStatus (sc->ha_Virt, sc->ha_Fvirt, &status) + == (PI2O_EXEC_STATUS_GET_REPLY)NULL) { + debug_usr_cmd_printf ("getStatus failed\n"); + return (ENXIO); + } + ReplySizeInBytes = sizeof(status); + debug_usr_cmd_printf ("getStatus done\n"); + return (copyout ((caddr_t)&status, (caddr_t)Reply, + ReplySizeInBytes)); + } + + case I2O_EXEC_OUTBOUND_INIT: + { U32 status; + + status = ASR_initOutBound(sc); + ReplySizeInBytes = sizeof(status); + debug_usr_cmd_printf ("intOutBound done\n"); + return (copyout ((caddr_t)&status, (caddr_t)Reply, + ReplySizeInBytes)); + } + } + + /* Determine if the message size is valid */ + if ((MessageSizeInBytes < sizeof(I2O_MESSAGE_FRAME)) + || (MAX_INBOUND_SIZE < MessageSizeInBytes)) { + debug_usr_cmd_printf ("Packet size %d incorrect\n", + MessageSizeInBytes); + return (EINVAL); + } + + if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc (MessageSizeInBytes, + M_TEMP, M_WAITOK)) == (PI2O_MESSAGE_FRAME)NULL) { + debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n", + MessageSizeInBytes); + return (ENOMEM); + } + if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr, + MessageSizeInBytes)) != 0) { + free (Message_Ptr, M_TEMP); + debug_usr_cmd_printf ("Can't copy in packet[%d] errno=%d\n", + MessageSizeInBytes, error); + return (error); + } + + /* Check the size of the reply frame, and start constructing */ + + if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc ( + sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK)) + == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { + free (Message_Ptr, M_TEMP); + debug_usr_cmd_printf ( + "Failed to acquire I2O_MESSAGE_FRAME memory\n"); + return (ENOMEM); + } + if ((error = copyin ((caddr_t)Reply, (caddr_t)Reply_Ptr, + sizeof(I2O_MESSAGE_FRAME))) != 0) { + free (Reply_Ptr, M_TEMP); + free (Message_Ptr, M_TEMP); + debug_usr_cmd_printf ( + "Failed to copy in reply frame, errno=%d\n", + error); + return (error); + } + ReplySizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize( + &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) << 2); + free (Reply_Ptr, M_TEMP); + if (ReplySizeInBytes < sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)) { + free (Message_Ptr, M_TEMP); + debug_usr_cmd_printf ( + "Failed to copy in reply frame[%d], errno=%d\n", + ReplySizeInBytes, error); + return (EINVAL); + } + + if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc ( + ((ReplySizeInBytes > sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)) + ? ReplySizeInBytes + : sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)), + M_TEMP, M_WAITOK)) == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { + free (Message_Ptr, M_TEMP); + debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n", + ReplySizeInBytes); + return (ENOMEM); + } + (void)ASR_fillMessage ((char *)Reply_Ptr, ReplySizeInBytes); + Reply_Ptr->StdReplyFrame.StdMessageFrame.InitiatorContext + = Message_Ptr->InitiatorContext; + Reply_Ptr->StdReplyFrame.TransactionContext + = ((PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr)->TransactionContext; + I2O_MESSAGE_FRAME_setMsgFlags( + &(Reply_Ptr->StdReplyFrame.StdMessageFrame), + I2O_MESSAGE_FRAME_getMsgFlags( + &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) + | I2O_MESSAGE_FLAGS_REPLY); + + /* Check if the message is a special case command */ + switch (I2O_MESSAGE_FRAME_getFunction(Message_Ptr)) { + case I2O_EXEC_SYS_TAB_SET: /* Special Case of empty Scatter Gather */ + if (MessageSizeInBytes == ((I2O_MESSAGE_FRAME_getVersionOffset( + Message_Ptr) & 0xF0) >> 2)) { + free (Message_Ptr, M_TEMP); + I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( + &(Reply_Ptr->StdReplyFrame), + (ASR_setSysTab(sc) != CAM_REQ_CMP)); + I2O_MESSAGE_FRAME_setMessageSize( + &(Reply_Ptr->StdReplyFrame.StdMessageFrame), + sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)); + error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply, + ReplySizeInBytes); + free (Reply_Ptr, M_TEMP); + return (error); + } + } + + /* Deal in the general case */ + /* First allocate and optionally copy in each scatter gather element */ + SLIST_INIT(&sgList); + if ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) != 0) { + PI2O_SGE_SIMPLE_ELEMENT sg; + + /* + * since this code is reused in several systems, code + * efficiency is greater by using a shift operation rather + * than a divide by sizeof(u_int32_t). + */ + sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr + + ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) + >> 2)); + while (sg < (PI2O_SGE_SIMPLE_ELEMENT)(((caddr_t)Message_Ptr) + + MessageSizeInBytes)) { + caddr_t v; + int len; + + if ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount)) + & I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT) == 0) { + error = EINVAL; + break; + } + len = I2O_FLAGS_COUNT_getCount(&(sg->FlagsCount)); + debug_usr_cmd_printf ("SG[%d] = %x[%d]\n", + sg - (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr + + ((I2O_MESSAGE_FRAME_getVersionOffset( + Message_Ptr) & 0xF0) >> 2)), + I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), len); + + if ((elm = (struct ioctlSgList_S *)malloc ( + sizeof(*elm) - sizeof(elm->KernelSpace) + len, + M_TEMP, M_WAITOK)) + == (struct ioctlSgList_S *)NULL) { + debug_usr_cmd_printf ( + "Failed to allocate SG[%d]\n", len); + error = ENOMEM; + break; + } + SLIST_INSERT_HEAD(&sgList, elm, link); + elm->FlagsCount = sg->FlagsCount; + elm->UserSpace = (caddr_t) + (I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg)); + v = elm->KernelSpace; + /* Copy in outgoing data (DIR bit could be invalid) */ + if ((error = copyin (elm->UserSpace, (caddr_t)v, len)) + != 0) { + break; + } + /* + * If the buffer is not contiguous, lets + * break up the scatter/gather entries. + */ + while ((len > 0) + && (sg < (PI2O_SGE_SIMPLE_ELEMENT) + (((caddr_t)Message_Ptr) + MAX_INBOUND_SIZE))) { + int next, base, span; + + span = 0; + next = base = KVTOPHYS(v); + I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, + base); + + /* How far can we go physically contiguously */ + while ((len > 0) && (base == next)) { + int size; + + next = trunc_page(base) + PAGE_SIZE; + size = next - base; + if (size > len) { + size = len; + } + span += size; + v += size; + len -= size; + base = KVTOPHYS(v); + } + + /* Construct the Flags */ + I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), + span); + { + int flags = I2O_FLAGS_COUNT_getFlags( + &(elm->FlagsCount)); + /* Any remaining length? */ + if (len > 0) { + flags &= + ~(I2O_SGL_FLAGS_END_OF_BUFFER + | I2O_SGL_FLAGS_LAST_ELEMENT); + } + I2O_FLAGS_COUNT_setFlags( + &(sg->FlagsCount), flags); + } + + debug_usr_cmd_printf ("sg[%d] = %x[%d]\n", + sg - (PI2O_SGE_SIMPLE_ELEMENT) + ((char *)Message_Ptr + + ((I2O_MESSAGE_FRAME_getVersionOffset( + Message_Ptr) & 0xF0) >> 2)), + I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), + span); + if (len <= 0) { + break; + } + + /* + * Incrementing requires resizing of the + * packet, and moving up the existing SG + * elements. + */ + ++sg; + MessageSizeInBytes += sizeof(*sg); + I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, + I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr) + + (sizeof(*sg) / sizeof(U32))); + { + PI2O_MESSAGE_FRAME NewMessage_Ptr; + + if ((NewMessage_Ptr + = (PI2O_MESSAGE_FRAME) + malloc (MessageSizeInBytes, + M_TEMP, M_WAITOK)) + == (PI2O_MESSAGE_FRAME)NULL) { + debug_usr_cmd_printf ( + "Failed to acquire frame[%d] memory\n", + MessageSizeInBytes); + error = ENOMEM; + break; + } + span = ((caddr_t)sg) + - (caddr_t)Message_Ptr; + bcopy ((caddr_t)Message_Ptr, + (caddr_t)NewMessage_Ptr, span); + bcopy ((caddr_t)(sg-1), + ((caddr_t)NewMessage_Ptr) + span, + MessageSizeInBytes - span); + free (Message_Ptr, M_TEMP); + sg = (PI2O_SGE_SIMPLE_ELEMENT) + (((caddr_t)NewMessage_Ptr) + span); + Message_Ptr = NewMessage_Ptr; + } + } + if ((error) + || ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount)) + & I2O_SGL_FLAGS_LAST_ELEMENT) != 0)) { + break; + } + ++sg; + } + if (error) { + while ((elm = SLIST_FIRST(&sgList)) + != (struct ioctlSgList_S *)NULL) { + SLIST_REMOVE_HEAD(&sgList, link); + free (elm, M_TEMP); + } + free (Reply_Ptr, M_TEMP); + free (Message_Ptr, M_TEMP); + return (error); + } + } + + debug_usr_cmd_printf ("Inbound: "); + debug_usr_cmd_dump_message(Message_Ptr); + + /* Send the command */ + if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { + /* Free up in-kernel buffers */ + while ((elm = SLIST_FIRST(&sgList)) + != (struct ioctlSgList_S *)NULL) { + SLIST_REMOVE_HEAD(&sgList, link); + free (elm, M_TEMP); + } + free (Reply_Ptr, M_TEMP); + free (Message_Ptr, M_TEMP); + return (ENOMEM); + } + + /* + * We do not need any (optional byteswapping) method access to + * the Initiator context field. + */ + I2O_MESSAGE_FRAME_setInitiatorContext64( + (PI2O_MESSAGE_FRAME)Message_Ptr, (long)ccb); + + (void)ASR_queue (sc, (PI2O_MESSAGE_FRAME)Message_Ptr); + + free (Message_Ptr, M_TEMP); + + /* + * Wait for the board to report a finished instruction. + */ + s = splcam(); + while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + if (ASR_getBlinkLedCode(sc)) { + /* Reset Adapter */ + printf ("asr%d: Blink LED 0x%x resetting adapter\n", + cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), + ASR_getBlinkLedCode(sc)); + if (ASR_reset (sc) == ENXIO) { + /* Command Cleanup */ + ASR_ccbRemove(sc, ccb); + } + splx(s); + /* Free up in-kernel buffers */ + while ((elm = SLIST_FIRST(&sgList)) + != (struct ioctlSgList_S *)NULL) { + SLIST_REMOVE_HEAD(&sgList, link); + free (elm, M_TEMP); + } + free (Reply_Ptr, M_TEMP); + asr_free_ccb(ccb); + return (EIO); + } + /* Check every second for BlinkLed */ + /* There is no PRICAM, but outwardly PRIBIO is functional */ + tsleep((caddr_t)ccb, PRIBIO, "asr", hz); + } + splx(s); + + debug_usr_cmd_printf ("Outbound: "); + debug_usr_cmd_dump_message(Reply_Ptr); + + I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( + &(Reply_Ptr->StdReplyFrame), + (ccb->ccb_h.status != CAM_REQ_CMP)); + + if (ReplySizeInBytes >= (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) + - I2O_SCSI_SENSE_DATA_SZ - sizeof(U32))) { + I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setTransferCount(Reply_Ptr, + ccb->csio.dxfer_len - ccb->csio.resid); + } + if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) && (ReplySizeInBytes + > (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) + - I2O_SCSI_SENSE_DATA_SZ))) { + int size = ReplySizeInBytes + - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) + - I2O_SCSI_SENSE_DATA_SZ; + + if (size > sizeof(ccb->csio.sense_data)) { + size = sizeof(ccb->csio.sense_data); + } + bcopy ((caddr_t)&(ccb->csio.sense_data), (caddr_t)Reply_Ptr->SenseData, + size); + I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setAutoSenseTransferCount( + Reply_Ptr, size); + } + + /* Free up in-kernel buffers */ + while ((elm = SLIST_FIRST(&sgList)) != (struct ioctlSgList_S *)NULL) { + /* Copy out as necessary */ + if ((error == 0) + /* DIR bit considered `valid', error due to ignorance works */ + && ((I2O_FLAGS_COUNT_getFlags(&(elm->FlagsCount)) + & I2O_SGL_FLAGS_DIR) == 0)) { + error = copyout ((caddr_t)(elm->KernelSpace), + elm->UserSpace, + I2O_FLAGS_COUNT_getCount(&(elm->FlagsCount))); + } + SLIST_REMOVE_HEAD(&sgList, link); + free (elm, M_TEMP); + } + if (error == 0) { + /* Copy reply frame to user space */ + error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply, + ReplySizeInBytes); + } + free (Reply_Ptr, M_TEMP); + asr_free_ccb(ccb); + + return (error); } /* ASR_queue_i */ /*----------------------------------------------------------------------*/ -/* Function asr_ioctl */ +/* Function asr_ioctl */ /*----------------------------------------------------------------------*/ -/* The parameters passed to this function are : */ -/* dev : Device number. */ -/* cmd : Ioctl Command */ -/* data : User Argument Passed In. */ -/* flag : Mode Parameter */ -/* proc : Process Parameter */ -/* */ -/* This function is the user interface into this adapter driver */ -/* */ -/* Return : zero if OK, error code if not */ +/* The parameters passed to this function are : */ +/* dev : Device number. */ +/* cmd : Ioctl Command */ +/* data : User Argument Passed In. */ +/* flag : Mode Parameter */ +/* proc : Process Parameter */ +/* */ +/* This function is the user interface into this adapter driver */ +/* */ +/* Return : zero if OK, error code if not */ /*----------------------------------------------------------------------*/ STATIC int asr_ioctl( - IN dev_t dev, - IN u_long cmd, - INOUT caddr_t data, - int flag, - struct thread * td) + IN dev_t dev, + IN u_long cmd, + INOUT caddr_t data, + int flag, + struct thread * td) { - int i, j; - OUT int error = 0; - Asr_softc_t * sc = ASR_get_sc (dev); - UNREFERENCED_PARAMETER(flag); - UNREFERENCED_PARAMETER(td); - - if (sc != (Asr_softc_t *)NULL) - switch(cmd) { - - case DPT_SIGNATURE: -# if (dsDescription_size != 50) - case DPT_SIGNATURE + ((50 - dsDescription_size) << 16): -# endif - if (cmd & 0xFFFF0000) { - (void)bcopy ((caddr_t)(&ASR_sig), data, - sizeof(dpt_sig_S)); - return (0); - } - /* Traditional version of the ioctl interface */ - case DPT_SIGNATURE & 0x0000FFFF: - return (copyout ((caddr_t)(&ASR_sig), *((caddr_t *)data), - sizeof(dpt_sig_S))); - - /* Traditional version of the ioctl interface */ - case DPT_CTRLINFO & 0x0000FFFF: - case DPT_CTRLINFO: { - struct { - u_int16_t length; - u_int16_t drvrHBAnum; - u_int32_t baseAddr; - u_int16_t blinkState; - u_int8_t pciBusNum; - u_int8_t pciDeviceNum; - u_int16_t hbaFlags; - u_int16_t Interrupt; - u_int32_t reserved1; - u_int32_t reserved2; - u_int32_t reserved3; - } CtlrInfo; - - bzero (&CtlrInfo, sizeof(CtlrInfo)); - CtlrInfo.length = sizeof(CtlrInfo) - sizeof(u_int16_t); - CtlrInfo.drvrHBAnum = asr_unit(dev); - CtlrInfo.baseAddr = (u_long)sc->ha_Base; - i = ASR_getBlinkLedCode (sc); - if (i == -1) { - i = 0; - } - CtlrInfo.blinkState = i; - CtlrInfo.pciBusNum = sc->ha_pciBusNum; - CtlrInfo.pciDeviceNum = sc->ha_pciDeviceNum; -#define FLG_OSD_PCI_VALID 0x0001 -#define FLG_OSD_DMA 0x0002 -#define FLG_OSD_I2O 0x0004 - CtlrInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O; - CtlrInfo.Interrupt = sc->ha_irq; - if (cmd & 0xFFFF0000) { - bcopy (&CtlrInfo, data, sizeof(CtlrInfo)); - } else { - error = copyout (&CtlrInfo, *(caddr_t *)data, sizeof(CtlrInfo)); - } - } return (error); - - /* Traditional version of the ioctl interface */ - case DPT_SYSINFO & 0x0000FFFF: - case DPT_SYSINFO: { - sysInfo_S Info; - char * cp; - /* Kernel Specific ptok `hack' */ -# define ptok(a) ((char *)(a) + KERNBASE) - - bzero (&Info, sizeof(Info)); - - /* Appears I am the only person in the Kernel doing this */ - outb (0x70, 0x12); - i = inb(0x71); - j = i >> 4; - if (i == 0x0f) { - outb (0x70, 0x19); - j = inb (0x71); - } - Info.drive0CMOS = j; - - j = i & 0x0f; - if (i == 0x0f) { - outb (0x70, 0x1a); - j = inb (0x71); - } - Info.drive1CMOS = j; - - Info.numDrives = *((char *)ptok(0x475)); - - Info.processorFamily = ASR_sig.dsProcessorFamily; + int i, j; + OUT int error = 0; + Asr_softc_t * sc = ASR_get_sc (dev); + UNREFERENCED_PARAMETER(flag); + UNREFERENCED_PARAMETER(td); + + if (sc != (Asr_softc_t *)NULL) + switch(cmd) { + + case DPT_SIGNATURE: +# if (dsDescription_size != 50) + case DPT_SIGNATURE + ((50 - dsDescription_size) << 16): +# endif + if (cmd & 0xFFFF0000) { + (void)bcopy ((caddr_t)(&ASR_sig), data, + sizeof(dpt_sig_S)); + return (0); + } + /* Traditional version of the ioctl interface */ + case DPT_SIGNATURE & 0x0000FFFF: + return (copyout ((caddr_t)(&ASR_sig), *((caddr_t *)data), + sizeof(dpt_sig_S))); + + /* Traditional version of the ioctl interface */ + case DPT_CTRLINFO & 0x0000FFFF: + case DPT_CTRLINFO: { + struct { + u_int16_t length; + u_int16_t drvrHBAnum; + u_int32_t baseAddr; + u_int16_t blinkState; + u_int8_t pciBusNum; + u_int8_t pciDeviceNum; + u_int16_t hbaFlags; + u_int16_t Interrupt; + u_int32_t reserved1; + u_int32_t reserved2; + u_int32_t reserved3; + } CtlrInfo; + + bzero (&CtlrInfo, sizeof(CtlrInfo)); + CtlrInfo.length = sizeof(CtlrInfo) - sizeof(u_int16_t); + CtlrInfo.drvrHBAnum = asr_unit(dev); + CtlrInfo.baseAddr = (u_long)sc->ha_Base; + i = ASR_getBlinkLedCode (sc); + if (i == -1) { + i = 0; + } + CtlrInfo.blinkState = i; + CtlrInfo.pciBusNum = sc->ha_pciBusNum; + CtlrInfo.pciDeviceNum = sc->ha_pciDeviceNum; +#define FLG_OSD_PCI_VALID 0x0001 +#define FLG_OSD_DMA 0x0002 +#define FLG_OSD_I2O 0x0004 + CtlrInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O; + CtlrInfo.Interrupt = sc->ha_irq; + if (cmd & 0xFFFF0000) { + bcopy (&CtlrInfo, data, sizeof(CtlrInfo)); + } else { + error = copyout (&CtlrInfo, *(caddr_t *)data, sizeof(CtlrInfo)); + } + } return (error); + + /* Traditional version of the ioctl interface */ + case DPT_SYSINFO & 0x0000FFFF: + case DPT_SYSINFO: { + sysInfo_S Info; + char * cp; + /* Kernel Specific ptok `hack' */ +# define ptok(a) ((char *)(a) + KERNBASE) + + bzero (&Info, sizeof(Info)); + + /* Appears I am the only person in the Kernel doing this */ + outb (0x70, 0x12); + i = inb(0x71); + j = i >> 4; + if (i == 0x0f) { + outb (0x70, 0x19); + j = inb (0x71); + } + Info.drive0CMOS = j; + + j = i & 0x0f; + if (i == 0x0f) { + outb (0x70, 0x1a); + j = inb (0x71); + } + Info.drive1CMOS = j; + + Info.numDrives = *((char *)ptok(0x475)); + + Info.processorFamily = ASR_sig.dsProcessorFamily; #if defined (__i386__) - switch (cpu) { - case CPU_386SX: case CPU_386: - Info.processorType = PROC_386; break; - case CPU_486SX: case CPU_486: - Info.processorType = PROC_486; break; - case CPU_586: - Info.processorType = PROC_PENTIUM; break; - case CPU_686: - Info.processorType = PROC_SEXIUM; break; - } + switch (cpu) { + case CPU_386SX: case CPU_386: + Info.processorType = PROC_386; break; + case CPU_486SX: case CPU_486: + Info.processorType = PROC_486; break; + case CPU_586: + Info.processorType = PROC_PENTIUM; break; + case CPU_686: + Info.processorType = PROC_SEXIUM; break; + } #elif defined (__alpha__) Info.processorType = PROC_ALPHA; #endif - Info.osType = OS_BSDI_UNIX; - Info.osMajorVersion = osrelease[0] - '0'; - Info.osMinorVersion = osrelease[2] - '0'; - /* Info.osRevision = 0; */ - /* Info.osSubRevision = 0; */ - Info.busType = SI_PCI_BUS; - Info.flags = SI_CMOS_Valid | SI_NumDrivesValid - | SI_OSversionValid | SI_BusTypeValid | SI_NO_SmartROM; - - /* Go Out And Look For I2O SmartROM */ - for(j = 0xC8000; j < 0xE0000; j += 2048) { - int k; - - cp = ptok(j); - if (*((unsigned short *)cp) != 0xAA55) { - continue; - } - j += (cp[2] * 512) - 2048; - if ((*((u_long *)(cp + 6)) - != ('S' + (' ' * 256) + (' ' * 65536L))) - || (*((u_long *)(cp + 10)) - != ('I' + ('2' * 256) + ('0' * 65536L)))) { - continue; - } - cp += 0x24; - for (k = 0; k < 64; ++k) { - if (*((unsigned short *)cp) - == (' ' + ('v' * 256))) { - break; - } - } - if (k < 64) { - Info.smartROMMajorVersion - = *((unsigned char *)(cp += 4)) - '0'; - Info.smartROMMinorVersion - = *((unsigned char *)(cp += 2)); - Info.smartROMRevision - = *((unsigned char *)(++cp)); - Info.flags |= SI_SmartROMverValid; - Info.flags &= ~SI_NO_SmartROM; - break; - } - } - /* Get The Conventional Memory Size From CMOS */ - outb (0x70, 0x16); - j = inb (0x71); - j <<= 8; - outb (0x70, 0x15); - j |= inb(0x71); - Info.conventionalMemSize = j; - - /* Get The Extended Memory Found At Power On From CMOS */ - outb (0x70, 0x31); - j = inb (0x71); - j <<= 8; - outb (0x70, 0x30); - j |= inb(0x71); - Info.extendedMemSize = j; - Info.flags |= SI_MemorySizeValid; - -# if (defined(THIS_IS_BROKEN)) - /* If There Is 1 or 2 Drives Found, Set Up Drive Parameters */ - if (Info.numDrives > 0) { - /* - * Get The Pointer From Int 41 For The First - * Drive Parameters - */ - j = ((unsigned)(*((unsigned short *)ptok(0x104+2))) << 4) - + (unsigned)(*((unsigned short *)ptok(0x104+0))); - /* - * It appears that SmartROM's Int41/Int46 pointers - * use memory that gets stepped on by the kernel - * loading. We no longer have access to this - * geometry information but try anyways (!?) - */ - Info.drives[0].cylinders = *((unsigned char *)ptok(j)); - ++j; - Info.drives[0].cylinders += ((int)*((unsigned char *) - ptok(j))) << 8; - ++j; - Info.drives[0].heads = *((unsigned char *)ptok(j)); - j += 12; - Info.drives[0].sectors = *((unsigned char *)ptok(j)); - Info.flags |= SI_DriveParamsValid; - if ((Info.drives[0].cylinders == 0) - || (Info.drives[0].heads == 0) - || (Info.drives[0].sectors == 0)) { - Info.flags &= ~SI_DriveParamsValid; - } - if (Info.numDrives > 1) { - /* - * Get The Pointer From Int 46 For The - * Second Drive Parameters - */ - j = ((unsigned)(*((unsigned short *)ptok(0x118+2))) << 4) - + (unsigned)(*((unsigned short *)ptok(0x118+0))); - Info.drives[1].cylinders = *((unsigned char *) - ptok(j)); - ++j; - Info.drives[1].cylinders += ((int) - *((unsigned char *)ptok(j))) << 8; - ++j; - Info.drives[1].heads = *((unsigned char *) - ptok(j)); - j += 12; - Info.drives[1].sectors = *((unsigned char *) - ptok(j)); - if ((Info.drives[1].cylinders == 0) - || (Info.drives[1].heads == 0) - || (Info.drives[1].sectors == 0)) { - Info.flags &= ~SI_DriveParamsValid; - } - } - } -# endif - /* Copy Out The Info Structure To The User */ - if (cmd & 0xFFFF0000) { - bcopy (&Info, data, sizeof(Info)); - } else { - error = copyout (&Info, *(caddr_t *)data, sizeof(Info)); - } - return (error); } - - /* Get The BlinkLED State */ - case DPT_BLINKLED: - i = ASR_getBlinkLedCode (sc); - if (i == -1) { - i = 0; - } - if (cmd & 0xFFFF0000) { - bcopy ((caddr_t)(&i), data, sizeof(i)); - } else { - error = copyout (&i, *(caddr_t *)data, sizeof(i)); - } - break; - - /* Get performance metrics */ + Info.osType = OS_BSDI_UNIX; + Info.osMajorVersion = osrelease[0] - '0'; + Info.osMinorVersion = osrelease[2] - '0'; + /* Info.osRevision = 0; */ + /* Info.osSubRevision = 0; */ + Info.busType = SI_PCI_BUS; + Info.flags = SI_CMOS_Valid | SI_NumDrivesValid + | SI_OSversionValid | SI_BusTypeValid | SI_NO_SmartROM; + + /* Go Out And Look For I2O SmartROM */ + for(j = 0xC8000; j < 0xE0000; j += 2048) { + int k; + + cp = ptok(j); + if (*((unsigned short *)cp) != 0xAA55) { + continue; + } + j += (cp[2] * 512) - 2048; + if ((*((u_long *)(cp + 6)) + != ('S' + (' ' * 256) + (' ' * 65536L))) + || (*((u_long *)(cp + 10)) + != ('I' + ('2' * 256) + ('0' * 65536L)))) { + continue; + } + cp += 0x24; + for (k = 0; k < 64; ++k) { + if (*((unsigned short *)cp) + == (' ' + ('v' * 256))) { + break; + } + } + if (k < 64) { + Info.smartROMMajorVersion + = *((unsigned char *)(cp += 4)) - '0'; + Info.smartROMMinorVersion + = *((unsigned char *)(cp += 2)); + Info.smartROMRevision + = *((unsigned char *)(++cp)); + Info.flags |= SI_SmartROMverValid; + Info.flags &= ~SI_NO_SmartROM; + break; + } + } + /* Get The Conventional Memory Size From CMOS */ + outb (0x70, 0x16); + j = inb (0x71); + j <<= 8; + outb (0x70, 0x15); + j |= inb(0x71); + Info.conventionalMemSize = j; + + /* Get The Extended Memory Found At Power On From CMOS */ + outb (0x70, 0x31); + j = inb (0x71); + j <<= 8; + outb (0x70, 0x30); + j |= inb(0x71); + Info.extendedMemSize = j; + Info.flags |= SI_MemorySizeValid; + +# if (defined(THIS_IS_BROKEN)) + /* If There Is 1 or 2 Drives Found, Set Up Drive Parameters */ + if (Info.numDrives > 0) { + /* + * Get The Pointer From Int 41 For The First + * Drive Parameters + */ + j = ((unsigned)(*((unsigned short *)ptok(0x104+2))) << 4) + + (unsigned)(*((unsigned short *)ptok(0x104+0))); + /* + * It appears that SmartROM's Int41/Int46 pointers + * use memory that gets stepped on by the kernel + * loading. We no longer have access to this + * geometry information but try anyways (!?) + */ + Info.drives[0].cylinders = *((unsigned char *)ptok(j)); + ++j; + Info.drives[0].cylinders += ((int)*((unsigned char *) + ptok(j))) << 8; + ++j; + Info.drives[0].heads = *((unsigned char *)ptok(j)); + j += 12; + Info.drives[0].sectors = *((unsigned char *)ptok(j)); + Info.flags |= SI_DriveParamsValid; + if ((Info.drives[0].cylinders == 0) + || (Info.drives[0].heads == 0) + || (Info.drives[0].sectors == 0)) { + Info.flags &= ~SI_DriveParamsValid; + } + if (Info.numDrives > 1) { + /* + * Get The Pointer From Int 46 For The + * Second Drive Parameters + */ + j = ((unsigned)(*((unsigned short *)ptok(0x118+2))) << 4) + + (unsigned)(*((unsigned short *)ptok(0x118+0))); + Info.drives[1].cylinders = *((unsigned char *) + ptok(j)); + ++j; + Info.drives[1].cylinders += ((int) + *((unsigned char *)ptok(j))) << 8; + ++j; + Info.drives[1].heads = *((unsigned char *) + ptok(j)); + j += 12; + Info.drives[1].sectors = *((unsigned char *) + ptok(j)); + if ((Info.drives[1].cylinders == 0) + || (Info.drives[1].heads == 0) + || (Info.drives[1].sectors == 0)) { + Info.flags &= ~SI_DriveParamsValid; + } + } + } +# endif + /* Copy Out The Info Structure To The User */ + if (cmd & 0xFFFF0000) { + bcopy (&Info, data, sizeof(Info)); + } else { + error = copyout (&Info, *(caddr_t *)data, sizeof(Info)); + } + return (error); } + + /* Get The BlinkLED State */ + case DPT_BLINKLED: + i = ASR_getBlinkLedCode (sc); + if (i == -1) { + i = 0; + } + if (cmd & 0xFFFF0000) { + bcopy ((caddr_t)(&i), data, sizeof(i)); + } else { + error = copyout (&i, *(caddr_t *)data, sizeof(i)); + } + break; + + /* Get performance metrics */ #ifdef ASR_MEASURE_PERFORMANCE - case DPT_PERF_INFO: - bcopy((caddr_t) &(sc->ha_performance), data, - sizeof(sc->ha_performance)); - return (0); + case DPT_PERF_INFO: + bcopy((caddr_t) &(sc->ha_performance), data, + sizeof(sc->ha_performance)); + return (0); #endif - /* Send an I2O command */ - case I2OUSRCMD: - return (ASR_queue_i (sc, *((PI2O_MESSAGE_FRAME *)data))); + /* Send an I2O command */ + case I2OUSRCMD: + return (ASR_queue_i (sc, *((PI2O_MESSAGE_FRAME *)data))); - /* Reset and re-initialize the adapter */ - case I2ORESETCMD: - return (ASR_reset (sc)); + /* Reset and re-initialize the adapter */ + case I2ORESETCMD: + return (ASR_reset (sc)); - /* Rescan the LCT table and resynchronize the information */ - case I2ORESCANCMD: - return (ASR_rescan (sc)); - } - return (EINVAL); + /* Rescan the LCT table and resynchronize the information */ + case I2ORESCANCMD: + return (ASR_rescan (sc)); + } + return (EINVAL); } /* asr_ioctl */ #ifdef ASR_MEASURE_PERFORMANCE @@ -4669,26 +4669,26 @@ asr_ioctl( STATIC u_int32_t asr_time_delta( - IN struct timeval start, - IN struct timeval end) + IN struct timeval start, + IN struct timeval end) { - OUT u_int32_t result; - - if (start.tv_sec > end.tv_sec) { - result = 0xffffffff; - } - else { - if (start.tv_sec == end.tv_sec) { - if (start.tv_usec > end.tv_usec) { - result = 0xffffffff; - } else { - return (end.tv_usec - start.tv_usec); - } - } else { - return (end.tv_sec - start.tv_sec) * 1000000 + - end.tv_usec + (1000000 - start.tv_usec); - } - } - return(result); + OUT u_int32_t result; + + if (start.tv_sec > end.tv_sec) { + result = 0xffffffff; + } + else { + if (start.tv_sec == end.tv_sec) { + if (start.tv_usec > end.tv_usec) { + result = 0xffffffff; + } else { + return (end.tv_usec - start.tv_usec); + } + } else { + return (end.tv_sec - start.tv_sec) * 1000000 + + end.tv_usec + (1000000 - start.tv_usec); + } + } + return(result); } /* asr_time_delta */ #endif |