diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 5ac37c701ba7..380fa18c90b8 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -132,7 +132,6 @@ MAN= aac.4 \ disc.4 \ divert.4 \ ${_dpms.4} \ - dpt.4 \ ds1307.4 \ ds3231.4 \ ${_dtrace_provs} \ diff --git a/share/man/man4/dpt.4 b/share/man/man4/dpt.4 deleted file mode 100644 index c687d185c014..000000000000 --- a/share/man/man4/dpt.4 +++ /dev/null @@ -1,109 +0,0 @@ -.\" -.\" Copyright (c) 1998 Justin T. Gibbs -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd November 13, 2014 -.Dt DPT 4 -.Os -.Sh NAME -.Nm dpt -.Nd DPT RAID Controller SCSI driver -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device scbus" -.Cd "device dpt" -.Pp -For one or more PCI cards: -.Cd "device pci" -.Pp -To allow PCI adapters to use memory mapped I/O if enabled: -.Cd options DPT_ALLOW_MEMIO -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -dpt_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver supports DPT RAID SCSI controllers. -.Pp -SmartRAID (PM3???) are "Enterprise" class cards, -and SmartCache (PM2???) cards are in the "Workstation" class. -The Gen 4 Smart Cache IV products were a re-issue of the Gen 3 utilizing -upgraded (and cheaper to produce) silicon. -The PM3334 (Smart RAID III) was not revamped as there was no upgraded silicon -(68040 processor) and it was using the best DPT made. -Note there has been customer confusion over the faster enterprise class card -supported by this driver being an older generation. -The Gen5 cards are supported by the -.Xr asr 4 -driver. -.Sh HARDWARE -The -.Nm -driver provides support for the following RAID adapters: -.Pp -.Bl -bullet -compact -.It -DPT Smart Cache Plus -.It -Smart Cache II (PM2?2?, PM2024/PM2124 [PCI]) (Gen2) -.It -Smart RAID II (PM3?2?, PM3021, PM3222) -.It -Smart Cache III (PM2?3?) -.It -Smart RAID III (PM3?3?, PM3334UW [PCI]) (Gen3) -.It -Smart Cache IV (PM2?4?, PM2044/PM2144 [PCI]) (Gen4) -.It -Smart RAID IV -.El -.Sh SEE ALSO -.Xr asr 4 , -.Xr cd 4 , -.Xr ch 4 , -.Xr da 4 , -.Xr sa 4 , -.Xr scsi 4 -.Sh HISTORY -The -.Nm -driver first appeared in -.Fx 2.2.6 . -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An Simon Shapiro -and ported to the CAM SCSI system by -.An Justin T. Gibbs . diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 0a49fa89a001..7f59214f1039 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -159,7 +159,6 @@ device ses # Enclosure Services (SES and SAF-TE) device amr # AMI MegaRAID device arcmsr # Areca SATA II RAID device ciss # Compaq Smart RAID 5* -device dpt # DPT Smartcache III, IV - See NOTES for options device hptmv # Highpoint RocketRAID 182x device hptnr # Highpoint DC7280, R750 device hptrr # Highpoint RocketRAID 17xx, 22xx, 23xx, 25xx diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 3ea1eeef1256..820308a4b53f 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1663,27 +1663,6 @@ options ISP_DEFAULT_ROLES=0 #options SYM_SETUP_MAX_LUN #-Number of LUNs supported # default:8, range:[1..64] -# The 'dpt' driver provides support for old DPT controllers (http://www.dpt.com/). -# These have hardware RAID-{0,1,5} support, and do multi-initiator I/O. -# The DPT controllers are commonly re-licensed under other brand-names - -# some controllers by Olivetti, Dec, HP, AT&T, SNI, AST, Alphatronic, NEC and -# Compaq are actually DPT controllers. -# -# See src/sys/dev/dpt for debugging and other subtle options. -# DPT_MEASURE_PERFORMANCE Enables a set of (semi)invasive metrics. Various -# instruments are enabled. The tools in -# /usr/sbin/dpt_* assume these to be enabled. -# DPT_DEBUG_xxxx These are controllable from sys/dev/dpt/dpt.h -# DPT_RESET_HBA Make "reset" actually reset the controller -# instead of fudging it. Only enable this if you -# are 100% certain you need it. - -device dpt - -# DPT options -#!CAM# options DPT_MEASURE_PERFORMANCE -options DPT_RESET_HBA - # # Compaq "CISS" RAID controllers (SmartRAID 5* series) # These controllers have a SCSI-like interface, and require the diff --git a/sys/conf/files b/sys/conf/files index 63e1abdf3f16..3097278f84d3 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1537,8 +1537,6 @@ dev/dcons/dcons_crom.c optional dcons_crom dev/dcons/dcons_os.c optional dcons dev/de/if_de.c optional de pci dev/dme/if_dme.c optional dme -dev/dpt/dpt_pci.c optional dpt pci -dev/dpt/dpt_scsi.c optional dpt dev/drm/ati_pcigart.c optional drm dev/drm/drm_agpsupport.c optional drm dev/drm/drm_auth.c optional drm diff --git a/sys/conf/options b/sys/conf/options index 4a7d4f6197a0..5e89f3931e10 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -566,10 +566,6 @@ DRM_DEBUG opt_drm.h TI_SF_BUF_JUMBO opt_ti.h TI_JUMBO_HDRSPLIT opt_ti.h -# DPT driver debug flags -DPT_MEASURE_PERFORMANCE opt_dpt.h -DPT_RESET_HBA opt_dpt.h - # Misc debug flags. Most of these should probably be replaced with # 'DEBUG', and then let people recompile just the interesting modules # with 'make CC="cc -DDEBUG"'. diff --git a/sys/dev/dpt/dpt.h b/sys/dev/dpt/dpt.h deleted file mode 100644 index cc0f0528b869..000000000000 --- a/sys/dev/dpt/dpt.h +++ /dev/null @@ -1,1298 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1997 by Simon Shapiro - * All Rights Reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* - * - * dpt.h: Definitions and constants used by the SCSI side of the DPT - * - * credits: Mike Neuffer; DPT low level code and in other areas as well. - * Mark Salyzyn; Many vital bits of info and diagnostics. - * Justin Gibbs; FreeBSD API, debugging and style - * Ron McDaniels; SCSI Software Interrupts - * FreeBSD.ORG; Great O/S to work on and for. - */ - -#ifndef _DPT_H -#define _DPT_H - -#include - - -#undef DPT_USE_DLM_SWI - -#define DPT_RELEASE 1 -#define DPT_VERSION 4 -#define DPT_PATCH 5 -#define DPT_MONTH 8 -#define DPT_DAY 3 -#define DPT_YEAR 18 /* 1998 - 1980 */ - -#define DPT_CTL_RELEASE 1 -#define DPT_CTL_VERSION 0 -#define DPT_CTL_PATCH 6 - -#ifndef PAGESIZ -#define PAGESIZ 4096 -#endif - -#ifndef physaddr -typedef void *physaddr; -#endif - -#undef DPT_INQUIRE_DEVICES /* We have no buyers for this function */ -#define DPT_SUPPORT_POLLING /* Use polled mode at boot (must be ON!) */ -#define DPT_OPENNINGS 8 /* Commands-in-progress per device */ - -#define DPT_RETRIES 5 /* Times to retry failed commands */ -#undef DPT_DISABLE_SG -#define DPT_HAS_OPEN - -/* Arguments to dpt_run_queue() can be: */ - -#define DPT_MAX_TARGET_MODE_BUFFER_SIZE 8192 -#define DPT_FREE_LIST_INCREMENT 64 -#define DPT_CMD_LEN 12 - -/* - * How many segments do we want in a Scatter/Gather list? - * Some HBA's can do 16, Some 8192. Since we pre-allocate - * them in fixed increments, we need to put a practical limit on - * these. A passed parameter (from kernel boot or lkm) would help - */ -#define DPT_MAX_SEGS 32 - -/* Debug levels */ - -#undef DPT_DEBUG_PCI -#undef DPT_DEBUG_INIT -#undef DPT_DEBUG_SETUP -#undef DPT_DEBUG_STATES -#undef DPT_DEBUG_CONFIG -#undef DPT_DEBUG_QUEUES -#undef DPT_DEBUG_SCSI_CMD -#undef DPT_DEBUG_SOFTINTR -#undef DPT_DEBUG_HARDINTR -#undef DPT_DEBUG_HEX_DUMPS -#undef DPT_DEBUG_POLLING -#undef DPT_DEBUG_INQUIRE -#undef DPT_DEBUG_COMPLETION -#undef DPT_DEBUG_COMPLETION_ERRORS -#define DPT_DEBUG_MINPHYS -#undef DPT_DEBUG_SG -#undef DPT_DEBUG_SG_SHOW_DATA -#undef DPT_DEBUG_SCSI_CMD_NAME -#undef DPT_DEBUG_CONTROL -#undef DPT_DEBUG_TIMEOUTS -#undef DPT_DEBUG_SHUTDOWN -#define DPT_DEBUG_USER_CMD - -/* - * Misc. definitions - */ -#undef TRUE -#undef FALSE -#define TRUE 1 -#define FALSE 0 - -#define MAX_CHANNELS 3 -#define MAX_TARGETS 16 -#define MAX_LUNS 8 - -/* Map minor numbers to device identity */ -#define TARGET_MASK 0x000f -#define BUS_MASK 0x0030 -#define HBA_MASK 0x01c0 -#define LUN_MASK 0x0e00 - -#define minor2target(minor) ( minor & TARGET_MASK ) -#define minor2bus(minor) ( (minor & BUS_MASK) >> 4 ) -#define minor2hba(minor) ( (minor & HBA_MASK) >> 6 ) -#define minor2lun(minor) ( (minor & LUN_MASK) >> 9 ) - -/* - * Valid values for cache_type - */ -#define DPT_NO_CACHE 0 -#define DPT_CACHE_WRITETHROUGH 1 -#define DPT_CACHE_WRITEBACK 2 - -#define min(a,b) ((ahost->hostdata)) -#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble)) -#define SD(host) ((hostdata *)&(host->hostdata)) - -/* - * EATA Command & Register definitions - */ - -#define PCI_REG_DPTconfig 0x40 -#define PCI_REG_PumpModeAddress 0x44 -#define PCI_REG_PumpModeData 0x48 -#define PCI_REG_ConfigParam1 0x50 -#define PCI_REG_ConfigParam2 0x54 - -#define EATA_CMD_RESET 0xf9 -#define EATA_COLD_BOOT 0x06 /* Last resort only! */ - -#define EATA_CMD_IMMEDIATE 0xfa - -#define EATA_CMD_DMA_READ_CONFIG 0xfd -#define EATA_CMD_DMA_SET_CONFIG 0xfe -#define EATA_CMD_DMA_SEND_CP 0xff - -#define ECS_EMULATE_SENSE 0xd4 - -/* - * Immediate Commands - * Beware of this enumeration. Not all commands are in sequence! - */ - -enum dpt_immediate_cmd { - EATA_GENERIC_ABORT, - EATA_SPECIFIC_RESET, - EATA_BUS_RESET, - EATA_SPECIFIC_ABORT, - EATA_QUIET_INTR, - EATA_SMART_ROM_DL_EN, - EATA_COLD_BOOT_HBA, /* Only as a last resort */ - EATA_FORCE_IO, - EATA_SCSI_BUS_OFFLINE, - EATA_RESET_MASKED_BUS, - EATA_POWER_OFF_WARN -}; - -#define HA_CTRLREG 0x206 /* control register for HBA */ -#define HA_CTRL_DISINT 0x02 /* CTRLREG: disable interrupts */ -#define HA_CTRL_RESCPU 0x04 /* CTRLREG: reset processo */ -#define HA_CTRL_8HEADS 0x08 /* - * CTRLREG: set for drives with - * >=8 heads - * (WD1003 rudimentary :-) - */ - -#define HA_WCOMMAND 0x07 /* command register offset */ -#define HA_WIFC 0x06 /* immediate command offset */ -#define HA_WCODE 0x05 -#define HA_WCODE2 0x04 -#define HA_WDMAADDR 0x02 /* DMA address LSB offset */ -#define HA_RERROR 0x01 /* Error Register, offset 1 from base */ -#define HA_RAUXSTAT 0x08 /* aux status register offset */ -#define HA_RSTATUS 0x07 /* status register offset */ -#define HA_RDATA 0x00 /* data register (16bit) */ -#define HA_WDATA 0x00 /* data register (16bit) */ - -#define HA_ABUSY 0x01 /* aux busy bit */ -#define HA_AIRQ 0x02 /* aux IRQ pending bit */ -#define HA_SERROR 0x01 /* pr. command ended in error */ -#define HA_SMORE 0x02 /* more data soon to come */ -#define HA_SCORR 0x04 /* datio_addra corrected */ -#define HA_SDRQ 0x08 /* data request active */ -#define HA_SSC 0x10 /* seek complete */ -#define HA_SFAULT 0x20 /* write fault */ -#define HA_SREADY 0x40 /* drive ready */ -#define HA_SBUSY 0x80 /* drive busy */ -#define HA_SDRDY (HA_SSC|HA_SREADY|HA_SDRQ) - -/* - * Message definitions - */ - -enum dpt_message { - HA_NO_ERROR, /* No Error */ - HA_ERR_SEL_TO, /* Selection Timeout */ - HA_ERR_CMD_TO, /* Command Timeout */ - HA_SCSIBUS_RESET, - HA_HBA_POWER_UP, /* Initial Controller Power-up */ - HA_UNX_BUSPHASE, /* Unexpected Bus Phase */ - HA_UNX_BUS_FREE, /* Unexpected Bus Free */ - HA_BUS_PARITY, /* Bus Parity Error */ - HA_SCSI_HUNG, /* SCSI Hung */ - HA_UNX_MSGRJCT, /* Unexpected Message Rejected */ - HA_RESET_STUCK, /* SCSI Bus Reset Stuck */ - HA_RSENSE_FAIL, /* Auto Request-Sense Failed */ - HA_PARITY_ERR, /* Controller Ram Parity Error */ - HA_CP_ABORT_NA, /* Abort Message sent to non-active cmd */ - HA_CP_ABORTED, /* Abort Message sent to active cmd */ - HA_CP_RESET_NA, /* Reset Message sent to non-active cmd */ - HA_CP_RESET, /* Reset Message sent to active cmd */ - HA_ECC_ERR, /* Controller Ram ECC Error */ - HA_PCI_PARITY, /* PCI Parity Error */ - HA_PCI_MABORT, /* PCI Master Abort */ - HA_PCI_TABORT, /* PCI Target Abort */ - HA_PCI_STABORT /* PCI Signaled Target Abort */ -}; - -#define HA_STATUS_MASK 0x7F -#define HA_IDENTIFY_MSG 0x80 -#define HA_DISCO_RECO 0x40 /* Disconnect/Reconnect */ - -#define DPT_RW_BUFF_HEART 0X00 -#define DPT_RW_BUFF_DLM 0x02 -#define DPT_RW_BUFF_ACCESS 0x03 - -#define HA_INTR_OFF 1 -#define HA_INTR_ON 0 - -/* This is really a one-time shot through some black magic */ -#define DPT_EATA_REVA 0x1c -#define DPT_EATA_REVB 0x1e -#define DPT_EATA_REVC 0x22 -#define DPT_EATA_REVZ 0x24 - - -/* IOCTL List */ - -#define DPT_RW_CMD_LEN 32 -#define DPT_RW_CMD_DUMP_SOFTC "dump softc" -#define DPT_RW_CMD_DUMP_SYSINFO "dump sysinfo" -#define DPT_RW_CMD_DUMP_METRICS "dump metrics" -#define DPT_RW_CMD_CLEAR_METRICS "clear metrics" -#define DPT_RW_CMD_SHOW_LED "show LED" - -#define DPT_IOCTL_INTERNAL_METRICS _IOR('D', 1, dpt_perf_t) -#define DPT_IOCTL_SOFTC _IOR('D', 2, dpt_user_softc_t) -#define DPT_IOCTL_SEND _IOWR('D', 3, eata_pt_t) -#define SDI_SEND 0x40044444 /* Observed from dptmgr */ - -/* - * Other definitions - */ - -#define DPT_HCP_LENGTH(page) (ntohs(*(int16_t *)(void *)(&page[2]))+4) -#define DPT_HCP_FIRST(page) (&page[4]) -#define DPT_HCP_NEXT(param) (¶m[3 + param[3] + 1]) -#define DPT_HCP_CODE(param) (ntohs(*(int16_t *)(void *)param)) - - -/* Possible return values from dpt_register_buffer() */ - -#define SCSI_TM_READ_BUFFER 0x3c -#define SCSI_TM_WRITE_BUFFER 0x3b - -#define SCSI_TM_MODE_MASK 0x07 /* Strip off reserved and LUN */ -#define SCSI_TM_LUN_MASK 0xe0 /* Strip off reserved and LUN */ - -typedef enum { - SUCCESSFULLY_REGISTERED, - DRIVER_DOWN, - ALREADY_REGISTERED, - REGISTERED_TO_ANOTHER, - NOT_REGISTERED, - INVALID_UNIT, - INVALID_SENDER, - INVALID_CALLBACK, - NO_RESOURCES -} dpt_rb_t; - -typedef enum { - REGISTER_BUFFER, - RELEASE_BUFFER -} dpt_rb_op_t; - -/* - * New way for completion routines to reliably copmplete processing. - * Should take properly typed dpt_softc_t and dpt_ccb_t, - * but interdependencies preclude that. - */ -typedef void (*ccb_callback)(void *dpt, int bus, void *ccb); - -typedef void (*buff_wr_done)(int unit, u_int8_t channel, u_int8_t target, - u_int8_t lun, u_int16_t offset, u_int16_t length, - int result); - -typedef void (*dpt_rec_buff)(int unit, u_int8_t channel, u_int8_t target, - u_int8_t lun, void *buffer, u_int16_t offset, - u_int16_t length); - -/* HBA's Status port (register) bitmap */ -typedef struct reg_bit { /* reading this one will clear the interrupt */ - u_int8_t error :1, /* previous command ended in an error */ - more :1, /* More DATA coming soon Poll BSY & DRQ (PIO) */ - corr :1, /* data read was successfully corrected with ECC */ - drq :1, /* data request active */ - sc :1, /* seek complete */ - fault :1, /* write fault */ - ready :1, /* drive ready */ - busy :1; /* controller busy */ -} dpt_status_reg_t; - -/* HBA's Auxiliary status port (register) bitmap */ -typedef struct reg_abit { /* reading this won't clear the interrupt */ - u_int8_t abusy :1, /* auxiliary busy */ - irq :1, /* set when drive interrupt is asserted */ - :6; -} dpt_aux_status_t; - -/* The EATA Register Set as a structure */ -typedef struct eata_register { - u_int8_t data_reg[2]; /* R, couldn't figure this one out */ - u_int8_t cp_addr[4]; /* W, CP address register */ - union { - u_int8_t command; /* - * W, command code: - * [read|set] conf, send CP - */ - struct reg_bit status; /* R, see register_bit1 */ - u_int8_t statusbyte; - } ovr; - struct reg_abit aux_stat; /* R, see register_bit2 */ -} eata_reg_t; - -/* - * Holds the results of a READ_CONFIGURATION command - * Beware of data items which are larger than 1 byte. - * these come from the DPT in network order. - * On an Intel ``CPU'' they will be upside down and backwards! - * The dpt_get_conf function is normally responsible for flipping - * Everything back. - */ -typedef struct get_conf { /* Read Configuration Array */ - union { - struct { - u_int8_t foo_DevType; - u_int8_t foo_PageCode; - u_int8_t foo_Reserved0; - u_int8_t foo_len; - } foo; - u_int32_t foo_length; /* Should return 0x22, 0x24, etc */ - } bar; -#define gcs_length bar.foo_length -#define gcs_PageCode bar.foo.foo_DevType -#define gcs_reserved0 bar.foo.foo_Reserved0 -#define gcs_len bar.foo.foo_len - - u_int32_t signature; /* Signature MUST be "EATA". ntohl()`ed */ - - u_int8_t version2 :4, - version :4; /* EATA Version level */ - - u_int8_t OCS_enabled :1, /* Overlap Command Support enabled */ - TAR_support :1, /* SCSI Target Mode supported */ - TRNXFR :1, /* Truncate Transfer Cmd Used in PIO Mode */ - MORE_support:1, /* MORE supported (PIO Mode Only) */ - DMA_support :1, /* DMA supported */ - DMA_valid :1, /* DRQ value in Byte 30 is valid */ - ATA :1, /* ATA device connected (not supported) */ - HAA_valid :1; /* Hostadapter Address is valid */ - - u_int16_t cppadlen; /* - * Number of pad bytes send after CD data set - * to zero for DMA commands. Ntohl()`ed - */ - u_int8_t scsi_idS; /* SCSI ID of controller 2-0 Byte 0 res. */ - u_int8_t scsi_id2; /* If not, zero is returned */ - u_int8_t scsi_id1; - u_int8_t scsi_id0; - u_int32_t cplen; /* CP length: number of valid cp bytes */ - - u_int32_t splen; /* Returned bytes for a received SP command */ - u_int16_t queuesiz; /* max number of queueable CPs */ - - u_int16_t dummy; - u_int16_t SGsiz; /* max number of SG table entrie */ - - u_int8_t IRQ :4,/* IRQ used this HBA */ - IRQ_TR :1,/* IRQ Trigger: 0=edge, 1=level */ - SECOND :1,/* This is a secondary controller */ - DMA_channel:2;/* DRQ index, DRQ is 2comp of DRQX */ - - u_int8_t sync; /* 0-7 sync active bitmask (deprecated) */ - u_int8_t DSBLE :1, /* ISA i/o addressing is disabled */ - FORCADR :1, /* i/o address has been forced */ - SG_64K :1, - SG_UAE :1, - :4; - - u_int8_t MAX_ID :5, /* Max number of SCSI target IDs */ - MAX_CHAN :3; /* Number of SCSI busses on HBA */ - - u_int8_t MAX_LUN; /* Max number of LUNs */ - u_int8_t :3, - AUTOTRM :1, - M1_inst :1, - ID_qest :1, /* Raidnum ID is questionable */ - is_PCI :1, /* HBA is PCI */ - is_EISA :1; /* HBA is EISA */ - - u_int8_t RAIDNUM; /* unique HBA identifier */ - u_int8_t unused[4]; /* When doing PIO, you GET 512 bytes */ - - /* >>------>> End of The DPT structure <<------<< */ - - u_int32_t length; /* True length, after ntohl conversion */ -} dpt_conf_t; - -/* Scatter-Gather list entry */ -typedef struct dpt_sg_segment { - u_int32_t seg_addr; /* All fields in network byte order */ - u_int32_t seg_len; -} dpt_sg_t; - - -/* Status Packet */ -typedef struct eata_sp { - u_int8_t hba_stat :7, /* HBA status */ - EOC :1; /* True if command finished */ - - u_int8_t scsi_stat; /* Target SCSI status */ - - u_int8_t reserved[2]; - - u_int32_t residue_len; /* Number of bytes not transferred */ - - u_int32_t ccb_busaddr; - - u_int8_t sp_ID_Message; - u_int8_t sp_Que_Message; - u_int8_t sp_Tag_Message; - u_int8_t msg[9]; -} dpt_sp_t; - -/* - * A strange collection of O/S-Hardware releated bits and pieces. - * Used by the dpt_ioctl() entry point to return DPT_SYSINFO command. - */ -typedef struct dpt_drive_parameters { - u_int16_t cylinders; /* Up to 1024 */ - u_int8_t heads; /* Up to 255 */ - u_int8_t sectors; /* Up to 63 */ -} dpt_drive_t; - -typedef struct driveParam_S driveParam_T; - -#define SI_CMOS_Valid 0x0001 -#define SI_NumDrivesValid 0x0002 -#define SI_ProcessorValid 0x0004 -#define SI_MemorySizeValid 0x0008 -#define SI_DriveParamsValid 0x0010 -#define SI_SmartROMverValid 0x0020 -#define SI_OSversionValid 0x0040 -#define SI_OSspecificValid 0x0080 -#define SI_BusTypeValid 0x0100 - -#define SI_ALL_VALID 0x0FFF -#define SI_NO_SmartROM 0x8000 - -#define SI_ISA_BUS 0x00 -#define SI_PCI_BUS 0x04 - -#define HBA_BUS_ISA 0x00 -#define HBA_BUS_PCI 0x02 - -typedef struct dpt_sysinfo { - u_int8_t drive0CMOS; /* CMOS Drive 0 Type */ - u_int8_t drive1CMOS; /* CMOS Drive 1 Type */ - u_int8_t numDrives; /* 0040:0075 contents */ - u_int8_t processorFamily; /* Same as DPTSIG definition */ - u_int8_t processorType; /* Same as DPTSIG definition */ - u_int8_t smartROMMajorVersion; - u_int8_t smartROMMinorVersion; /* SmartROM version */ - u_int8_t smartROMRevision; - u_int16_t flags; /* See bit definitions above */ - u_int16_t conventionalMemSize; /* in KB */ - u_int32_t extendedMemSize; /* in KB */ - u_int32_t osType; /* Same as DPTSIG definition */ - u_int8_t osMajorVersion; - u_int8_t osMinorVersion; /* The OS version */ - u_int8_t osRevision; - u_int8_t osSubRevision; - u_int8_t busType; /* See defininitions above */ - u_int8_t pad[3]; /* For alignment */ - dpt_drive_t drives[16]; /* SmartROM Logical Drives */ -} dpt_sysinfo_t; - -/* SEND_COMMAND packet structure */ -typedef struct eata_ccb { - u_int8_t SCSI_Reset :1, /* Cause a SCSI Bus reset on the cmd */ - HBA_Init :1, /* Cause Controller to reinitialize */ - Auto_Req_Sen :1, /* Do Auto Request Sense on errors */ - scatter :1, /* Data Ptr points to a SG Packet */ - Quick :1, /* Set this one for NO Status PAcket */ - Interpret :1, /* Interpret the SCSI cdb for own use */ - DataOut :1, /* Data Out phase with command */ - DataIn :1; /* Data In phase with command */ - - u_int8_t reqlen; /* Request Sense Length, if Auto_Req_Sen=1 */ - u_int8_t unused[3]; - u_int8_t FWNEST :1, /* send cmd to phys RAID component */ - unused2 :7; - - u_int8_t Phsunit :1, /* physical unit on mirrored pair */ - I_AT :1, /* inhibit address translation */ - Disable_Cache :1, /* HBA inhibit caching */ - :5; - - u_int8_t cp_id :5, /* SCSI Device ID of target */ - cp_channel :3; /* SCSI Channel # of HBA */ - - u_int8_t cp_LUN :5, - cp_luntar :1, /* CP is for target ROUTINE */ - cp_dispri :1, /* Grant disconnect privilege */ - cp_identify :1; /* Always TRUE */ - - u_int8_t cp_msg[3]; /* Message bytes 0-3 */ - - union { - struct { - u_int8_t x_scsi_cmd; /* Partial SCSI CDB def */ - - u_int8_t x_extent :1, - x_bytchk :1, - x_reladr :1, - x_cmplst :1, - x_fmtdata :1, - x_lun :3; - - u_int8_t x_page; - u_int8_t reserved4; - u_int8_t x_len; - u_int8_t x_link :1; - u_int8_t x_flag :1; - u_int8_t reserved5 :4; - u_int8_t x_vendor :2; - } x; - u_int8_t z[12]; /* Command Descriptor Block (= 12) */ - } cp_w; - -#define cp_cdb cp_w.z -#define cp_scsi_cmd cp_w.x.x_scsi_cmd -#define cp_extent cp_w.x.x_extent -#define cp_lun cp_w.x.x_lun -#define cp_page cp_w.x.x_page -#define cp_len cp_w.x.x_len - -#define MULTIFUNCTION_CMD 0x0e /* SCSI Multi Function Cmd */ -#define BUS_QUIET 0x04 /* Quite Scsi Bus Code */ -#define BUS_UNQUIET 0x05 /* Un Quiet Scsi Bus Code */ - - u_int32_t cp_datalen; /* - * Data Transfer Length. If scatter=1 len (IN - * BYTES!) of the S/G array - */ - - u_int32_t cp_busaddr; /* Unique identifier. Busaddr works well */ - u_int32_t cp_dataDMA; /* - * Data Address, if scatter=1 then it is the - * address of scatter packet - */ - u_int32_t cp_statDMA; /* address for Status Packet */ - u_int32_t cp_reqDMA; /* - * Request Sense Address, used if CP command - * ends with error - */ - u_int8_t CP_OpCode; - -} eata_ccb_t; - -/* - * DPT Signature Structure. - * Used by /dev/dpt to directly pass commands to the HBA - * We have more information here than we care for... - */ - -/* Current Signature Version - sigBYTE dsSigVersion; */ -#define SIG_VERSION 1 - -/* - * Processor Family - sigBYTE dsProcessorFamily; DISTINCT VALUE - * - * What type of processor the file is meant to run on. - * This will let us know whether to read sigWORDs as high/low or low/high. - */ -#define PROC_INTEL 0x00 /* Intel 80x86 */ -#define PROC_MOTOROLA 0x01 /* Motorola 68K */ -#define PROC_MIPS4000 0x02 /* MIPS RISC 4000 */ -#define PROC_ALPHA 0x03 /* DEC Alpha */ - -/* - * Specific Minimim Processor - sigBYTE dsProcessor; FLAG BITS - * - * Different bit definitions dependent on processor_family - */ - -/* PROC_INTEL: */ -#define PROC_8086 0x01 /* Intel 8086 */ -#define PROC_286 0x02 /* Intel 80286 */ -#define PROC_386 0x04 /* Intel 80386 */ -#define PROC_486 0x08 /* Intel 80486 */ -#define PROC_PENTIUM 0x10 /* Intel 586 aka P5 aka Pentium */ -#define PROC_P6 0x20 /* Intel 686 aka P6 */ - -/* PROC_MOTOROLA: */ -#define PROC_68000 0x01 /* Motorola 68000 */ -#define PROC_68020 0x02 /* Motorola 68020 */ -#define PROC_68030 0x04 /* Motorola 68030 */ -#define PROC_68040 0x08 /* Motorola 68040 */ - -/* Filetype - sigBYTE dsFiletype; DISTINCT VALUES */ -#define FT_EXECUTABLE 0 /* Executable Program */ -#define FT_SCRIPT 1 /* Script/Batch File??? */ -#define FT_HBADRVR 2 /* HBA Driver */ -#define FT_OTHERDRVR 3 /* Other Driver */ -#define FT_IFS 4 /* Installable Filesystem Driver */ -#define FT_ENGINE 5 /* DPT Engine */ -#define FT_COMPDRVR 6 /* Compressed Driver Disk */ -#define FT_LANGUAGE 7 /* Foreign Language file */ -#define FT_FIRMWARE 8 /* Downloadable or actual Firmware */ -#define FT_COMMMODL 9 /* Communications Module */ -#define FT_INT13 10 /* INT 13 style HBA Driver */ -#define FT_HELPFILE 11 /* Help file */ -#define FT_LOGGER 12 /* Event Logger */ -#define FT_INSTALL 13 /* An Install Program */ -#define FT_LIBRARY 14 /* Storage Manager Real-Mode Calls */ -#define FT_RESOURCE 15 /* Storage Manager Resource File */ -#define FT_MODEM_DB 16 /* Storage Manager Modem Database */ - -/* Filetype flags - sigBYTE dsFiletypeFlags; FLAG BITS */ -#define FTF_DLL 0x01 /* Dynamic Link Library */ -#define FTF_NLM 0x02 /* Netware Loadable Module */ -#define FTF_OVERLAYS 0x04 /* Uses overlays */ -#define FTF_DEBUG 0x08 /* Debug version */ -#define FTF_TSR 0x10 /* TSR */ -#define FTF_SYS 0x20 /* DOS Lodable driver */ -#define FTF_PROTECTED 0x40 /* Runs in protected mode */ -#define FTF_APP_SPEC 0x80 /* Application Specific */ - -/* OEM - sigBYTE dsOEM; DISTINCT VALUES */ -#define OEM_DPT 0 /* DPT */ -#define OEM_ATT 1 /* ATT */ -#define OEM_NEC 2 /* NEC */ -#define OEM_ALPHA 3 /* Alphatronix */ -#define OEM_AST 4 /* AST */ -#define OEM_OLIVETTI 5 /* Olivetti */ -#define OEM_SNI 6 /* Siemens/Nixdorf */ - -/* Operating System - sigLONG dsOS; FLAG BITS */ -#define OS_DOS 0x00000001 /* PC/MS-DOS */ -#define OS_WINDOWS 0x00000002 /* Microsoft Windows 3.x */ -#define OS_WINDOWS_NT 0x00000004 /* Microsoft Windows NT */ -#define OS_OS2M 0x00000008 /* OS/2 1.2.x,MS 1.3.0,IBM 1.3.x */ -#define OS_OS2L 0x00000010 /* Microsoft OS/2 1.301 - LADDR */ -#define OS_OS22x 0x00000020 /* IBM OS/2 2.x */ -#define OS_NW286 0x00000040 /* Novell NetWare 286 */ -#define OS_NW386 0x00000080 /* Novell NetWare 386 */ -#define OS_GEN_UNIX 0x00000100 /* Generic Unix */ -#define OS_SCO_UNIX 0x00000200 /* SCO Unix */ -#define OS_ATT_UNIX 0x00000400 /* ATT Unix */ -#define OS_UNIXWARE 0x00000800 /* UnixWare Unix */ -#define OS_INT_UNIX 0x00001000 /* Interactive Unix */ -#define OS_SOLARIS 0x00002000 /* SunSoft Solaris */ -#define OS_QN 0x00004000 /* QNX for Tom Moch */ -#define OS_NEXTSTEP 0x00008000 /* NeXTSTEP */ -#define OS_BANYAN 0x00010000 /* Banyan Vines */ -#define OS_OLIVETTI_UNIX 0x00020000 /* Olivetti Unix */ -#define OS_FREEBSD 0x00040000 /* FreeBSD 2.2 and later */ -#define OS_OTHER 0x80000000 /* Other */ - -/* Capabilities - sigWORD dsCapabilities; FLAG BITS */ -#define CAP_RAID0 0x0001 /* RAID-0 */ -#define CAP_RAID1 0x0002 /* RAID-1 */ -#define CAP_RAID3 0x0004 /* RAID-3 */ -#define CAP_RAID5 0x0008 /* RAID-5 */ -#define CAP_SPAN 0x0010 /* Spanning */ -#define CAP_PASS 0x0020 /* Provides passthrough */ -#define CAP_OVERLAP 0x0040 /* Passthrough supports overlapped commands */ -#define CAP_ASPI 0x0080 /* Supports ASPI Command Requests */ -#define CAP_ABOVE16MB 0x0100 /* ISA Driver supports greater than 16MB */ -#define CAP_EXTEND 0x8000 /* Extended info appears after description */ - -/* Devices Supported - sigWORD dsDeviceSupp; FLAG BITS */ -#define DEV_DASD 0x0001 /* DASD (hard drives) */ -#define DEV_TAPE 0x0002 /* Tape drives */ -#define DEV_PRINTER 0x0004 /* Printers */ -#define DEV_PROC 0x0008 /* Processors */ -#define DEV_WORM 0x0010 /* WORM drives */ -#define DEV_CDROM 0x0020 /* CD-ROM drives */ -#define DEV_SCANNER 0x0040 /* Scanners */ -#define DEV_OPTICAL 0x0080 /* Optical Drives */ -#define DEV_JUKEBOX 0x0100 /* Jukebox */ -#define DEV_COMM 0x0200 /* Communications Devices */ -#define DEV_OTHER 0x0400 /* Other Devices */ -#define DEV_ALL 0xFFFF /* All SCSI Devices */ - -/* Adapters Families Supported - sigWORD dsAdapterSupp; FLAG BITS */ -#define ADF_2001 0x0001 /* PM2001 */ -#define ADF_2012A 0x0002 /* PM2012A */ -#define ADF_PLUS_ISA 0x0004 /* PM2011,PM2021 */ -#define ADF_SC3_ISA 0x0010 /* PM2021 */ -#define ADF_SC3_PCI 0x0040 /* SmartCache III PCI */ -#define ADF_SC4_ISA 0x0080 /* SmartCache IV ISA */ -#define ADF_SC4_PCI 0x0200 /* SmartCache IV PCI */ -#define ADF_ALL_MASTER 0xFFFE /* All bus mastering */ -#define ADF_ALL_CACHE 0xFFFC /* All caching */ -#define ADF_ALL 0xFFFF /* ALL DPT adapters */ - -/* Application - sigWORD dsApplication; FLAG BITS */ -#define APP_DPTMGR 0x0001 /* DPT Storage Manager */ -#define APP_ENGINE 0x0002 /* DPT Engine */ -#define APP_SYTOS 0x0004 /* Sytron Sytos Plus */ -#define APP_CHEYENNE 0x0008 /* Cheyenne ARCServe + ARCSolo */ -#define APP_MSCDEX 0x0010 /* Microsoft CD-ROM extensions */ -#define APP_NOVABACK 0x0020 /* NovaStor Novaback */ -#define APP_AIM 0x0040 /* Archive Information Manager */ - -/* Requirements - sigBYTE dsRequirements; FLAG BITS */ -#define REQ_SMARTROM 0x01 /* Requires SmartROM to be present */ -#define REQ_DPTDDL 0x02 /* Requires DPTDDL.SYS to be loaded */ -#define REQ_HBA_DRIVER 0x04 /* Requires an HBA driver to be loaded */ -#define REQ_ASPI_TRAN 0x08 /* Requires an ASPI Transport Modules */ -#define REQ_ENGINE 0x10 /* Requires a DPT Engine to be loaded */ -#define REQ_COMM_ENG 0x20 /* Requires a DPT Communications Engine */ - -typedef struct dpt_sig { - char dsSignature[6]; /* ALWAYS "dPtSiG" */ - u_int8_t SigVersion; /* signature version (currently 1) */ - u_int8_t ProcessorFamily; /* what type of processor */ - u_int8_t Processor; /* precise processor */ - u_int8_t Filetype; /* type of file */ - u_int8_t FiletypeFlags; /* flags to specify load type, etc. */ - u_int8_t OEM; /* OEM file was created for */ - u_int32_t OS; /* which Operating systems */ - u_int16_t Capabilities; /* RAID levels, etc. */ - u_int16_t DeviceSupp; /* Types of SCSI devices supported */ - u_int16_t AdapterSupp; /* DPT adapter families supported */ - u_int16_t Application; /* applications file is for */ - u_int8_t Requirements; /* Other driver dependencies */ - u_int8_t Version; /* 1 */ - u_int8_t Revision; /* 'J' */ - u_int8_t SubRevision; /* '9', ' ' if N/A */ - u_int8_t Month; /* creation month */ - u_int8_t Day; /* creation day */ - u_int8_t Year; /* creation year since 1980 */ - char *Description; /* description (NULL terminated) */ -} dpt_sig_t; - -/* 32 bytes minimum - with no description. Put NULL at description[0] */ -/* 81 bytes maximum - with 49 character description plus NULL. */ - -/* This line added at Roycroft's request */ -/* Microsoft's NT compiler gets confused if you do a pack and don't */ -/* restore it. */ -typedef struct eata_pass_through { - u_int8_t eataID[4]; - u_int32_t command; - -#define EATAUSRCMD (('D'<<8)|65) /* EATA PassThrough Command */ -#define DPT_SIGNATURE (('D'<<8)|67) /* Get Signature Structure */ -#define DPT_NUMCTRLS (('D'<<8)|68) /* Get Number Of DPT Adapters */ -#define DPT_CTRLINFO (('D'<<8)|69) /* Get Adapter Info Structure */ -#define DPT_SYSINFO (('D'<<8)|72) /* Get System Info Structure */ -#define DPT_BLINKLED (('D'<<8)|75) /* Get The BlinkLED Status */ - - u_int8_t *command_buffer; - eata_ccb_t command_packet; - u_int32_t timeout; - u_int8_t host_status; - u_int8_t target_status; - u_int8_t retries; -} eata_pt_t; - -typedef enum { - DCCB_FREE = 0x00, - DCCB_ACTIVE = 0x01, - DCCB_RELEASE_SIMQ = 0x02 -} dccb_state; - -typedef struct dpt_ccb { - eata_ccb_t eata_ccb; - bus_dmamap_t dmamap; - struct callout timer; - dpt_sg_t *sg_list; - u_int32_t sg_busaddr; - dccb_state state; - union ccb *ccb; - struct scsi_sense_data sense_data; - u_int8_t tag; - u_int8_t retries; - u_int8_t status; /* status of this queueslot */ - u_int8_t *cmd; /* address of cmd */ - - u_int32_t transaction_id; - u_int32_t result; - caddr_t data; - SLIST_ENTRY(dpt_ccb) links; - -#ifdef DPT_MEASURE_PERFORMANCE - u_int32_t submitted_time; - struct timeval command_started; - struct timeval command_ended; -#endif -} dpt_ccb_t; - -/* - * This is provided for compatibility with UnixWare only. - * Some of the fields may be bogus. - * Others may have a totally different meaning. - */ -typedef struct dpt_scsi_ha { - u_int32_t ha_state; /* Operational state */ - u_int8_t ha_id[MAX_CHANNELS]; /* Host adapter SCSI ids */ - int32_t ha_base; /* Base I/O address */ - int ha_max_jobs; /* Max number of Active Jobs */ - int ha_cache:2; /* Cache parameters */ - int ha_cachesize:30; /* In meg, only if cache present*/ - int ha_nbus; /* Number Of Busses on HBA */ - int ha_ntargets; /* Number Of Targets Supported */ - int ha_nluns; /* Number Of LUNs Supported */ - int ha_tshift; /* Shift value for target */ - int ha_bshift; /* Shift value for bus */ - int ha_npend; /* # of jobs sent to HBA */ - int ha_active_jobs; /* Number Of Active Jobs */ - char ha_fw_version[4]; /* Firmware Revision Level */ - void *ha_ccb; /* Controller command blocks */ - void *ha_cblist; /* Command block free list */ - void *ha_dev; /* Logical unit queues */ - void *ha_StPkt_lock; /* Status Packet Lock */ - void *ha_ccb_lock; /* CCB Lock */ - void *ha_LuQWaiting; /* Lu Queue Waiting List */ - void *ha_QWait_lock; /* Device Que Waiting Lock */ - int ha_QWait_opri; /* Saved Priority Level */ -#ifdef DPT_TARGET_MODE - dpt_ccb_t *target_ccb[MAX_CHANNELS]; /* Command block waiting writebuf */ -#endif -} dpt_compat_ha_t; - -/* - * Describe the Inquiry Data returned on Page 0 from the Adapter. The - * Page C1 Inquiry Data is described in the DptConfig_t structure above. - */ -typedef struct { - u_int8_t deviceType; - u_int8_t rm_dtq; - u_int8_t otherData[6]; - u_int8_t vendor[8]; - u_int8_t modelNum[16]; - u_int8_t firmware[4]; - u_int8_t protocol[4]; -} dpt_inq_t; - -/* - * sp_EOC is not `safe', so I will check sp_Messages[0] instead! - */ -#define DptStat_BUSY(x) ((x)->sp_ID_Message) -#define DptStat_Reset_BUSY(x) \ - ((x)->msg[0] = 0xA5, (x)->EOC = 0, \ - (x)->ccb_busaddr = ~0) - -#ifdef DPT_MEASURE_PERFORMANCE -#define BIG_ENOUGH 0x8fffffff -typedef struct dpt_metrics { - u_int32_t command_count[256]; /* We assume MAX 256 SCSI commands */ - u_int32_t max_command_time[256]; - u_int32_t min_command_time[256]; - - u_int32_t min_intr_time; - u_int32_t max_intr_time; - u_int32_t aborted_interrupts; - u_int32_t spurious_interrupts; - - u_int32_t max_waiting_count; - u_int32_t max_submit_count; - u_int32_t max_complete_count; - - u_int32_t min_waiting_time; - u_int32_t min_submit_time; - u_int32_t min_complete_time; - - u_int32_t max_waiting_time; - u_int32_t max_submit_time; - u_int32_t max_complete_time; - - u_int32_t command_collisions; - u_int32_t command_too_busy; - u_int32_t max_eata_tries; - u_int32_t min_eata_tries; - - u_int32_t read_by_size_count[10]; - u_int32_t write_by_size_count[10]; - u_int32_t read_by_size_min_time[10]; - u_int32_t read_by_size_max_time[10]; - u_int32_t write_by_size_min_time[10]; - u_int32_t write_by_size_max_time[10]; - -#define SIZE_512 0 -#define SIZE_1K 1 -#define SIZE_2K 2 -#define SIZE_4K 3 -#define SIZE_8K 4 -#define SIZE_16K 5 -#define SIZE_32K 6 -#define SIZE_64K 7 -#define SIZE_BIGGER 8 -#define SIZE_OTHER 9 - - struct timeval intr_started; - - u_int32_t warm_starts; - u_int32_t cold_boots; -} dpt_perf_t; -#endif - -struct sg_map_node { - bus_dmamap_t sg_dmamap; - bus_addr_t sg_physaddr; - dpt_sg_t* sg_vaddr; - SLIST_ENTRY(sg_map_node) links; -}; - -/* Main state machine and interface structure */ -typedef struct dpt_softc { - device_t dev; - struct mtx lock; - - struct resource * io_res; - int io_rid; - int io_type; - int io_offset; - - struct resource * irq_res; - int irq_rid; - void * ih; - - struct resource * drq_res; - int drq_rid; - - bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */ - dpt_ccb_t *dpt_dccbs; /* Array of dpt ccbs */ - bus_addr_t dpt_ccb_busbase; /* phys base address of array */ - bus_addr_t dpt_ccb_busend; /* phys end address of array */ - - u_int32_t handle_interrupts :1, /* Are we ready for real work? */ - target_mode_enabled :1, - resource_shortage :1, - cache_type :2, - spare :28; - - int total_dccbs; - int free_dccbs; - int pending_ccbs; - int completed_ccbs; - - SLIST_HEAD(, dpt_ccb) free_dccb_list; - LIST_HEAD(, ccb_hdr) pending_ccb_list; - - bus_dma_tag_t parent_dmat; - bus_dma_tag_t dccb_dmat; /* dmat for our ccb array */ - bus_dmamap_t dccb_dmamap; - bus_dma_tag_t sg_dmat; /* dmat for our sg maps */ - SLIST_HEAD(, sg_map_node) sg_maps; - - struct cam_sim *sims[MAX_CHANNELS]; - struct cam_path *paths[MAX_CHANNELS]; - u_int32_t commands_processed; - u_int32_t lost_interrupts; - - /* - * These three parameters can be used to allow for wide scsi, and - * for host adapters that support multiple busses. The first two - * should be set to 1 more than the actual max id or lun (i.e. 8 for - * normal systems). - * - * There is a FAT assumption here; We assume that these will never - * exceed MAX_CHANNELS, MAX_TARGETS, MAX_LUNS - */ - u_int channels; /* # of avail scsi chan. */ - u_int32_t max_id; - u_int32_t max_lun; - - u_int8_t irq; - u_int8_t dma_channel; - - TAILQ_ENTRY(dpt_softc) links; - int init_level; - - /* - * Every object on a unit can have a receiver, if it treats - * us as a target. We do that so that separate and independent - * clients can consume received buffers. - */ - -#define DPT_RW_BUFFER_SIZE (8 * 1024) - dpt_ccb_t *target_ccb[MAX_CHANNELS][MAX_TARGETS][MAX_LUNS]; - u_int8_t *rw_buffer[MAX_CHANNELS][MAX_TARGETS][MAX_LUNS]; - dpt_rec_buff buffer_receiver[MAX_CHANNELS][MAX_TARGETS][MAX_LUNS]; - - dpt_inq_t board_data; - u_int8_t EATA_revision; - u_int8_t bustype; /* bustype of HBA */ - u_int32_t state; /* state of HBA */ - -#define DPT_HA_FREE 0x00000000 -#define DPT_HA_OK 0x00000000 -#define DPT_HA_NO_TIMEOUT 0x00000000 -#define DPT_HA_BUSY 0x00000001 -#define DPT_HA_TIMEOUT 0x00000002 -#define DPT_HA_RESET 0x00000004 -#define DPT_HA_LOCKED 0x00000008 -#define DPT_HA_ABORTED 0x00000010 -#define DPT_HA_CONTROL_ACTIVE 0x00000020 -#define DPT_HA_SHUTDOWN_ACTIVE 0x00000040 -#define DPT_HA_COMMAND_ACTIVE 0x00000080 -#define DPT_HA_QUIET 0x00000100 - - u_int8_t primary; /* true if primary */ - - u_int8_t more_support :1, /* HBA supports MORE flag */ - immediate_support :1, /* HBA supports IMMEDIATE */ - spare2 :6; - - u_int8_t resetlevel[MAX_CHANNELS]; - u_int32_t last_ccb; /* Last used ccb */ - u_int32_t cplen; /* size of CP in words */ - u_int16_t cppadlen; /* pad length of cp */ - u_int16_t max_dccbs; - u_int16_t sgsize; /* Entries in the SG list */ - u_int8_t hostid[MAX_CHANNELS]; /* SCSI ID of HBA */ - u_int32_t cache_size; - - volatile dpt_sp_t *sp; /* status packet */ - /* Copied from the status packet during interrupt handler */ - u_int8_t hba_stat; - u_int8_t scsi_stat; /* Target SCSI status */ - u_int32_t residue_len; /* Number of bytes not transferred */ - bus_addr_t sp_physaddr; /* phys address of status packet */ - - /* - * We put ALL conditional elements at the tail for the structure. - * If we do not, then userland code will crash or trash based on which - * kernel it is running with. - * This isi most visible with usr/sbin/dpt_softc(8) - */ - -#ifdef DPT_MEASURE_PERFORMANCE - dpt_perf_t performance; -#endif - -#ifdef DPT_RESET_HBA - struct timeval last_contact; -#endif -} dpt_softc_t; - -/* - * This structure is used to pass dpt_softc contents to userland via the - * ioctl DPT_IOCTL_SOFTC. The reason for this maddness, is that FreeBSD - * (all BSDs ?) chose to actually assign a nasty meaning to the IOCTL word, - * encoding 13 bits of it as size. As dpt_softc_t is somewhere between - * 8,594 and 8,600 (depends on options), we have to copy the data to - * something less than 4KB long. This siliness also solves the problem of - * varying definition of dpt_softc_t, As the variants are exluded from - * dpt_user_softc. - * - * See dpt_softc_t above for enumerations, comments and such. - */ -typedef struct dpt_user_softc { - int unit; - u_int32_t handle_interrupts :1, /* Are we ready for real work? */ - target_mode_enabled :1, - spare :30; - - int total_ccbs_count; - int free_ccbs_count; - int waiting_ccbs_count; - int submitted_ccbs_count; - int completed_ccbs_count; - - u_int32_t queue_status; - u_int32_t free_lock; - u_int32_t waiting_lock; - u_int32_t submitted_lock; - u_int32_t completed_lock; - - u_int32_t commands_processed; - u_int32_t lost_interrupts; - - u_int8_t channels; - u_int32_t max_id; - u_int32_t max_lun; - - u_int16_t io_base; - u_int8_t *v_membase; - u_int8_t *p_membase; - - u_int8_t irq; - u_int8_t dma_channel; - - dpt_inq_t board_data; - u_int8_t EATA_revision; - u_int8_t bustype; - u_int32_t state; - - u_int8_t primary; - u_int8_t more_support :1, - immediate_support :1, - spare2 :6; - - u_int8_t resetlevel[MAX_CHANNELS]; - u_int32_t last_ccb; - u_int32_t cplen; - u_int16_t cppadlen; - u_int16_t queuesize; - u_int16_t sgsize; - u_int8_t hostid[MAX_CHANNELS]; - u_int32_t cache_type :2, - cache_size :30; -} dpt_user_softc_t; - -/* - * Externals: - * These all come from dpt_scsi.c - * - */ -#ifdef _KERNEL -/* This function gets the current hi-res time and returns it to the caller */ -static __inline struct timeval -dpt_time_now(void) -{ - struct timeval now; - - microtime(&now); - return(now); -} - -/* - * Given a minor device number, get its SCSI Unit. - */ -static __inline int -dpt_minor2unit(int minor) -{ - return(minor2hba(minor)); -} - -dpt_softc_t *dpt_minor2softc(int minor_no); - -#endif /* _KERNEL */ - -/* - * This function subtracts one timval structure from another, - * Returning the result in usec. - * It assumes that less than 4 billion usecs passed form start to end. - * If times are sensless, ~0 is returned. - */ -static __inline u_int32_t -dpt_time_delta(struct timeval start, - struct timeval end) -{ - if (start.tv_sec > end.tv_sec) - return(~0); - - if ( (start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec) ) - return(~0); - - return ( (end.tv_sec - start.tv_sec) * 1000000 + - (end.tv_usec - start.tv_usec) ); -} - -extern devclass_t dpt_devclass; - -#ifdef _KERNEL -void dpt_alloc(device_t); -int dpt_detach(device_t); -int dpt_alloc_resources(device_t); -void dpt_release_resources(device_t); -#endif -void dpt_free(struct dpt_softc *dpt); -int dpt_init(struct dpt_softc *dpt); -int dpt_attach(dpt_softc_t * dpt); -void dpt_intr(void *arg); - -#if 0 -extern void hex_dump(u_char * data, int length, - char *name, int no); -extern char *i2bin(unsigned int no, int length); -extern char *scsi_cmd_name(u_int8_t cmd); - -extern dpt_conf_t *dpt_get_conf(dpt_softc_t *dpt, u_int8_t page, - u_int8_t target, u_int8_t size, - int extent); - -extern int dpt_setup(dpt_softc_t * dpt, dpt_conf_t * conf); -extern int dpt_attach(dpt_softc_t * dpt); -extern void dpt_shutdown(int howto, dpt_softc_t *dpt); -extern void dpt_detect_cache(dpt_softc_t *dpt); - -extern int dpt_user_cmd(dpt_softc_t *dpt, eata_pt_t *user_cmd, - caddr_t cmdarg, int minor_no); - -extern u_int8_t dpt_blinking_led(dpt_softc_t *dpt); - -extern dpt_rb_t dpt_register_buffer(int unit, u_int8_t channel, u_int8_t target, - u_int8_t lun, u_int8_t mode, - u_int16_t length, u_int16_t offset, - dpt_rec_buff callback, dpt_rb_op_t op); - -extern int dpt_send_buffer(int unit, u_int8_t channel, u_int8_t target, - u_int8_t lun, u_int8_t mode, u_int16_t length, - u_int16_t offset, void *data, - buff_wr_done callback); - - - -void dpt_reset_performance(dpt_softc_t *dpt); -#endif - -#endif /* _DPT_H */ diff --git a/sys/dev/dpt/dpt_pci.c b/sys/dev/dpt/dpt_pci.c deleted file mode 100644 index 5d4b21345c3b..000000000000 --- a/sys/dev/dpt/dpt_pci.c +++ /dev/null @@ -1,189 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000 Matthew N. Dodd - * All rights reserved. - * - * Copyright (c) 1997 Simon Shapiro - * All Rights Reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include - -#define DPT_VENDOR_ID 0x1044 -#define DPT_DEVICE_ID 0xa400 - -#define DPT_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ -#define DPT_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ - -#define ISA_PRIMARY_WD_ADDRESS 0x1f8 - -static int dpt_pci_probe (device_t); -static int dpt_pci_attach (device_t); - -static int -dpt_pci_probe (device_t dev) -{ - if ((pci_get_vendor(dev) == DPT_VENDOR_ID) && - (pci_get_device(dev) == DPT_DEVICE_ID)) { - device_set_desc(dev, "DPT Caching SCSI RAID Controller"); - return (BUS_PROBE_DEFAULT); - } - return (ENXIO); -} - -static int -dpt_pci_attach (device_t dev) -{ - dpt_softc_t * dpt; - int error = 0; - - dpt = device_get_softc(dev); - dpt->dev = dev; - dpt_alloc(dev); - -#ifdef DPT_ALLOW_MMIO - dpt->io_rid = DPT_PCI_MEMADDR; - dpt->io_type = SYS_RES_MEMORY; - dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, - &dpt->io_rid, RF_ACTIVE); -#endif - if (dpt->io_res == NULL) { - dpt->io_rid = DPT_PCI_IOADDR; - dpt->io_type = SYS_RES_IOPORT; - dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, - &dpt->io_rid, RF_ACTIVE); - } - - if (dpt->io_res == NULL) { - device_printf(dev, "can't allocate register resources\n"); - error = ENOMEM; - goto bad; - } - dpt->io_offset = 0x10; - - dpt->irq_rid = 0; - dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid, - RF_ACTIVE | RF_SHAREABLE); - if (dpt->irq_res == NULL) { - device_printf(dev, "No irq?!\n"); - error = ENOMEM; - goto bad; - } - - /* Ensure busmastering is enabled */ - pci_enable_busmaster(dev); - - if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) { -#ifdef DPT_DEBUG_WARN - device_printf(dev, "Mapped as an IDE controller. " - "Disabling SCSI setup\n"); -#endif - error = ENXIO; - goto bad; - } - - /* Allocate a dmatag representing the capabilities of this attachment */ - if (bus_dma_tag_create( /* PCI parent */ bus_get_dma_tag(dev), - /* alignemnt */ 1, - /* boundary */ 0, - /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, - /* highaddr */ BUS_SPACE_MAXADDR, - /* filter */ NULL, - /* filterarg */ NULL, - /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, - /* nsegments */ ~0, - /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, - /* flags */ 0, - /* lockfunc */ NULL, - /* lockarg */ NULL, - &dpt->parent_dmat) != 0) { - error = ENXIO; - goto bad; - } - - if (dpt_init(dpt) != 0) { - error = ENXIO; - goto bad; - } - - /* Register with the XPT */ - dpt_attach(dpt); - - if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY | - INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) { - device_printf(dev, "Unable to register interrupt handler\n"); - error = ENXIO; - goto bad; - } - gone_in_dev(dev, 12, "dpt(4) driver"); - - return (error); - -bad: - dpt_release_resources(dev); - - dpt_free(dpt); - - return (error); -} - -static device_method_t dpt_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, dpt_pci_probe), - DEVMETHOD(device_attach, dpt_pci_attach), - DEVMETHOD(device_detach, dpt_detach), - - { 0, 0 } -}; - -static driver_t dpt_pci_driver = { - "dpt", - dpt_pci_methods, - sizeof(dpt_softc_t), -}; - -DRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0); -MODULE_DEPEND(dpt, pci, 1, 1, 1); -MODULE_DEPEND(dpt, cam, 1, 1, 1); diff --git a/sys/dev/dpt/dpt_scsi.c b/sys/dev/dpt/dpt_scsi.c deleted file mode 100644 index 168764d80279..000000000000 --- a/sys/dev/dpt/dpt_scsi.c +++ /dev/null @@ -1,2411 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1997 by Simon Shapiro - * All Rights Reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * dpt_scsi.c: SCSI dependent code for the DPT driver - * - * credits: Assisted by Mike Neuffer in the early low level DPT code - * Thanx to Mark Salyzyn of DPT for his assistance. - * Special thanx to Justin Gibbs for invaluable help in - * making this driver look and work like a FreeBSD component. - * Last but not least, many thanx to UCB and the FreeBSD - * team for creating and maintaining such a wonderful O/S. - * - * TODO: * Add ISA probe code. - * * Add driver-level RAID-0. This will allow interoperability with - * NiceTry, M$-Doze, Win-Dog, Slowlaris, etc., in recognizing RAID - * arrays that span controllers (Wow!). - */ - -#define _DPT_C_ - -#include "opt_dpt.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -/* dpt_isa.c, and dpt_pci.c need this in a central place */ -devclass_t dpt_devclass; - -#define microtime_now dpt_time_now() - -#define dpt_inl(dpt, port) \ - bus_read_4((dpt)->io_res, (dpt)->io_offset + port) -#define dpt_inb(dpt, port) \ - bus_read_1((dpt)->io_res, (dpt)->io_offset + port) -#define dpt_outl(dpt, port, value) \ - bus_write_4((dpt)->io_res, (dpt)->io_offset + port, value) -#define dpt_outb(dpt, port, value) \ - bus_write_1((dpt)->io_res, (dpt)->io_offset + port, value) - -/* - * These will have to be setup by parameters passed at boot/load time. For - * performance reasons, we make them constants for the time being. - */ -#define dpt_min_segs DPT_MAX_SEGS -#define dpt_max_segs DPT_MAX_SEGS - -/* Definitions for our use of the SIM private CCB area */ -#define ccb_dccb_ptr spriv_ptr0 -#define ccb_dpt_ptr spriv_ptr1 - -/* ================= Private Inline Function declarations ===================*/ -static __inline int dpt_just_reset(dpt_softc_t * dpt); -static __inline int dpt_raid_busy(dpt_softc_t * dpt); -static __inline int dpt_wait(dpt_softc_t *dpt, u_int bits, - u_int state); -static __inline struct dpt_ccb* dptgetccb(struct dpt_softc *dpt); -static __inline void dptfreeccb(struct dpt_softc *dpt, - struct dpt_ccb *dccb); -static __inline bus_addr_t dptccbvtop(struct dpt_softc *dpt, - struct dpt_ccb *dccb); - -static __inline int dpt_send_immediate(dpt_softc_t *dpt, - eata_ccb_t *cmd_block, - u_int32_t cmd_busaddr, - u_int retries, - u_int ifc, u_int code, - u_int code2); - -/* ==================== Private Function declarations =======================*/ -static void dptmapmem(void *arg, bus_dma_segment_t *segs, - int nseg, int error); - -static struct sg_map_node* - dptallocsgmap(struct dpt_softc *dpt); - -static int dptallocccbs(dpt_softc_t *dpt); - -static int dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, - u_int32_t dccb_busaddr, u_int size, - u_int page, u_int target, int extent); -static void dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, - u_int32_t dccb_busaddr, - u_int8_t *buff); - -static void dpt_poll(struct cam_sim *sim); -static void dpt_intr_locked(dpt_softc_t *dpt); - -static void dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, - int nseg, int error); - -static void dpt_action(struct cam_sim *sim, union ccb *ccb); - -static int dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd, - u_int32_t cmd_busaddr, - u_int command, u_int retries, - u_int ifc, u_int code, - u_int code2); -static void dptprocesserror(dpt_softc_t *dpt, dpt_ccb_t *dccb, - union ccb *ccb, u_int hba_stat, - u_int scsi_stat, u_int32_t resid); - -static void dpttimeout(void *arg); -static void dptshutdown(void *arg, int howto); - -/* ================= Private Inline Function definitions ====================*/ -static __inline int -dpt_just_reset(dpt_softc_t * dpt) -{ - if ((dpt_inb(dpt, 2) == 'D') - && (dpt_inb(dpt, 3) == 'P') - && (dpt_inb(dpt, 4) == 'T') - && (dpt_inb(dpt, 5) == 'H')) - return (1); - else - return (0); -} - -static __inline int -dpt_raid_busy(dpt_softc_t * dpt) -{ - if ((dpt_inb(dpt, 0) == 'D') - && (dpt_inb(dpt, 1) == 'P') - && (dpt_inb(dpt, 2) == 'T')) - return (1); - else - return (0); -} - -static __inline int -dpt_wait(dpt_softc_t *dpt, u_int bits, u_int state) -{ - int i; - u_int c; - - for (i = 0; i < 20000; i++) { /* wait 20ms for not busy */ - c = dpt_inb(dpt, HA_RSTATUS) & bits; - if (c == state) - return (0); - else - DELAY(50); - } - return (-1); -} - -static __inline struct dpt_ccb* -dptgetccb(struct dpt_softc *dpt) -{ - struct dpt_ccb* dccb; - - if (!dumping) - mtx_assert(&dpt->lock, MA_OWNED); - if ((dccb = SLIST_FIRST(&dpt->free_dccb_list)) != NULL) { - SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links); - dpt->free_dccbs--; - } else if (dpt->total_dccbs < dpt->max_dccbs) { - dptallocccbs(dpt); - dccb = SLIST_FIRST(&dpt->free_dccb_list); - if (dccb == NULL) - device_printf(dpt->dev, "Can't malloc DCCB\n"); - else { - SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links); - dpt->free_dccbs--; - } - } - - return (dccb); -} - -static __inline void -dptfreeccb(struct dpt_softc *dpt, struct dpt_ccb *dccb) -{ - - if (!dumping) - mtx_assert(&dpt->lock, MA_OWNED); - if ((dccb->state & DCCB_ACTIVE) != 0) - LIST_REMOVE(&dccb->ccb->ccb_h, sim_links.le); - if ((dccb->state & DCCB_RELEASE_SIMQ) != 0) - dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - else if (dpt->resource_shortage != 0 - && (dccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { - dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - dpt->resource_shortage = FALSE; - } - dccb->state = DCCB_FREE; - SLIST_INSERT_HEAD(&dpt->free_dccb_list, dccb, links); - ++dpt->free_dccbs; -} - -static __inline bus_addr_t -dptccbvtop(struct dpt_softc *dpt, struct dpt_ccb *dccb) -{ - return (dpt->dpt_ccb_busbase - + (u_int32_t)((caddr_t)dccb - (caddr_t)dpt->dpt_dccbs)); -} - -static __inline struct dpt_ccb * -dptccbptov(struct dpt_softc *dpt, bus_addr_t busaddr) -{ - return (dpt->dpt_dccbs - + ((struct dpt_ccb *)busaddr - - (struct dpt_ccb *)dpt->dpt_ccb_busbase)); -} - -/* - * Send a command for immediate execution by the DPT - * See above function for IMPORTANT notes. - */ -static __inline int -dpt_send_immediate(dpt_softc_t *dpt, eata_ccb_t *cmd_block, - u_int32_t cmd_busaddr, u_int retries, - u_int ifc, u_int code, u_int code2) -{ - return (dpt_send_eata_command(dpt, cmd_block, cmd_busaddr, - EATA_CMD_IMMEDIATE, retries, ifc, - code, code2)); -} - - -/* ===================== Private Function definitions =======================*/ -static void -dptmapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - bus_addr_t *busaddrp; - - busaddrp = (bus_addr_t *)arg; - *busaddrp = segs->ds_addr; -} - -static struct sg_map_node * -dptallocsgmap(struct dpt_softc *dpt) -{ - struct sg_map_node *sg_map; - - sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); - - if (sg_map == NULL) - return (NULL); - - /* Allocate S/G space for the next batch of CCBS */ - if (bus_dmamem_alloc(dpt->sg_dmat, (void **)&sg_map->sg_vaddr, - BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { - free(sg_map, M_DEVBUF); - return (NULL); - } - - (void)bus_dmamap_load(dpt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, - PAGE_SIZE, dptmapmem, &sg_map->sg_physaddr, - /*flags*/0); - - SLIST_INSERT_HEAD(&dpt->sg_maps, sg_map, links); - - return (sg_map); -} - -/* - * Allocate another chunk of CCB's. Return count of entries added. - */ -static int -dptallocccbs(dpt_softc_t *dpt) -{ - struct dpt_ccb *next_ccb; - struct sg_map_node *sg_map; - bus_addr_t physaddr; - dpt_sg_t *segs; - int newcount; - int i; - - if (!dumping) - mtx_assert(&dpt->lock, MA_OWNED); - next_ccb = &dpt->dpt_dccbs[dpt->total_dccbs]; - - if (next_ccb == dpt->dpt_dccbs) { - /* - * First time through. Re-use the S/G - * space we allocated for initialization - * CCBS. - */ - sg_map = SLIST_FIRST(&dpt->sg_maps); - } else { - sg_map = dptallocsgmap(dpt); - } - - if (sg_map == NULL) - return (0); - - segs = sg_map->sg_vaddr; - physaddr = sg_map->sg_physaddr; - - newcount = (PAGE_SIZE / (dpt->sgsize * sizeof(dpt_sg_t))); - for (i = 0; dpt->total_dccbs < dpt->max_dccbs && i < newcount; i++) { - int error; - - error = bus_dmamap_create(dpt->buffer_dmat, /*flags*/0, - &next_ccb->dmamap); - if (error != 0) - break; - callout_init_mtx(&next_ccb->timer, &dpt->lock, 0); - next_ccb->sg_list = segs; - next_ccb->sg_busaddr = htonl(physaddr); - next_ccb->eata_ccb.cp_dataDMA = htonl(physaddr); - next_ccb->eata_ccb.cp_statDMA = htonl(dpt->sp_physaddr); - next_ccb->eata_ccb.cp_reqDMA = - htonl(dptccbvtop(dpt, next_ccb) - + offsetof(struct dpt_ccb, sense_data)); - next_ccb->eata_ccb.cp_busaddr = dpt->dpt_ccb_busend; - next_ccb->state = DCCB_FREE; - next_ccb->tag = dpt->total_dccbs; - SLIST_INSERT_HEAD(&dpt->free_dccb_list, next_ccb, links); - segs += dpt->sgsize; - physaddr += (dpt->sgsize * sizeof(dpt_sg_t)); - dpt->dpt_ccb_busend += sizeof(*next_ccb); - next_ccb++; - dpt->total_dccbs++; - } - return (i); -} - -/* - * Read a configuration page into the supplied dpt_cont_t buffer. - */ -static int -dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr, - u_int size, u_int page, u_int target, int extent) -{ - eata_ccb_t *cp; - - u_int8_t status; - - int ndx; - int result; - - mtx_assert(&dpt->lock, MA_OWNED); - cp = &dccb->eata_ccb; - bzero((void *)(uintptr_t)(volatile void *)dpt->sp, sizeof(*dpt->sp)); - - cp->Interpret = 1; - cp->DataIn = 1; - cp->Auto_Req_Sen = 1; - cp->reqlen = sizeof(struct scsi_sense_data); - - cp->cp_id = target; - cp->cp_LUN = 0; /* In the EATA packet */ - cp->cp_lun = 0; /* In the SCSI command */ - - cp->cp_scsi_cmd = INQUIRY; - cp->cp_len = size; - - cp->cp_extent = extent; - - cp->cp_page = page; - cp->cp_channel = 0; /* DNC, Interpret mode is set */ - cp->cp_identify = 1; - cp->cp_datalen = htonl(size); - - /* - * This could be a simple for loop, but we suspected the compiler To - * have optimized it a bit too much. Wait for the controller to - * become ready - */ - while (((status = dpt_inb(dpt, HA_RSTATUS)) != (HA_SREADY | HA_SSC) - && (status != (HA_SREADY | HA_SSC | HA_SERROR)) - && (status != (HA_SDRDY | HA_SERROR | HA_SDRQ))) - || (dpt_wait(dpt, HA_SBUSY, 0))) { - - /* - * RAID Drives still Spinning up? (This should only occur if - * the DPT controller is in a NON PC (PCI?) platform). - */ - if (dpt_raid_busy(dpt)) { - device_printf(dpt->dev, - "WARNING: Get_conf() RSUS failed.\n"); - return (0); - } - } - - DptStat_Reset_BUSY(dpt->sp); - - /* - * XXXX We might want to do something more clever than aborting at - * this point, like resetting (rebooting) the controller and trying - * again. - */ - if ((result = dpt_send_eata_command(dpt, cp, dccb_busaddr, - EATA_CMD_DMA_SEND_CP, - 10000, 0, 0, 0)) != 0) { - device_printf(dpt->dev, - "WARNING: Get_conf() failed (%d) to send " - "EATA_CMD_DMA_READ_CONFIG\n", - result); - return (0); - } - /* Wait for two seconds for a response. This can be slow */ - for (ndx = 0; - (ndx < 20000) - && !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ); - ndx++) { - DELAY(50); - } - - /* Grab the status and clear interrupts */ - status = dpt_inb(dpt, HA_RSTATUS); - - /* - * Check the status carefully. Return only if the - * command was successful. - */ - if (((status & HA_SERROR) == 0) - && (dpt->sp->hba_stat == 0) - && (dpt->sp->scsi_stat == 0) - && (dpt->sp->residue_len == 0)) - return (0); - - if (dpt->sp->scsi_stat == SCSI_STATUS_CHECK_COND) - return (0); - - return (1); -} - -/* Detect Cache parameters and size */ -static void -dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr, - u_int8_t *buff) -{ - eata_ccb_t *cp; - u_int8_t *param; - int bytes; - int result; - int ndx; - u_int8_t status; - - mtx_assert(&dpt->lock, MA_OWNED); - - /* - * Default setting, for best performance.. - * This is what virtually all cards default to.. - */ - dpt->cache_type = DPT_CACHE_WRITEBACK; - dpt->cache_size = 0; - - cp = &dccb->eata_ccb; - bzero((void *)(uintptr_t)(volatile void *)dpt->sp, sizeof(dpt->sp)); - bzero(buff, 512); - - /* Setup the command structure */ - cp->Interpret = 1; - cp->DataIn = 1; - cp->Auto_Req_Sen = 1; - cp->reqlen = sizeof(struct scsi_sense_data); - - cp->cp_id = 0; /* who cares? The HBA will interpret.. */ - cp->cp_LUN = 0; /* In the EATA packet */ - cp->cp_lun = 0; /* In the SCSI command */ - cp->cp_channel = 0; - - cp->cp_scsi_cmd = EATA_CMD_DMA_SEND_CP; - cp->cp_len = 56; - - cp->cp_extent = 0; - cp->cp_page = 0; - cp->cp_identify = 1; - cp->cp_dispri = 1; - - /* - * Build the EATA Command Packet structure - * for a Log Sense Command. - */ - cp->cp_cdb[0] = 0x4d; - cp->cp_cdb[1] = 0x0; - cp->cp_cdb[2] = 0x40 | 0x33; - cp->cp_cdb[7] = 1; - - cp->cp_datalen = htonl(512); - - result = dpt_send_eata_command(dpt, cp, dccb_busaddr, - EATA_CMD_DMA_SEND_CP, - 10000, 0, 0, 0); - if (result != 0) { - device_printf(dpt->dev, - "WARNING: detect_cache() failed (%d) to send " - "EATA_CMD_DMA_SEND_CP\n", result); - return; - } - /* Wait for two seconds for a response. This can be slow... */ - for (ndx = 0; - (ndx < 20000) && - !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ); - ndx++) { - DELAY(50); - } - - /* Grab the status and clear interrupts */ - status = dpt_inb(dpt, HA_RSTATUS); - - /* - * Sanity check - */ - if (buff[0] != 0x33) { - return; - } - bytes = DPT_HCP_LENGTH(buff); - param = DPT_HCP_FIRST(buff); - - if (DPT_HCP_CODE(param) != 1) { - /* - * DPT Log Page layout error - */ - device_printf(dpt->dev, "NOTICE: Log Page (1) layout error\n"); - return; - } - if (!(param[4] & 0x4)) { - dpt->cache_type = DPT_NO_CACHE; - return; - } - while (DPT_HCP_CODE(param) != 6) { - param = DPT_HCP_NEXT(param); - if ((param < buff) - || (param >= &buff[bytes])) { - return; - } - } - - if (param[4] & 0x2) { - /* - * Cache disabled - */ - dpt->cache_type = DPT_NO_CACHE; - return; - } - - if (param[4] & 0x4) { - dpt->cache_type = DPT_CACHE_WRITETHROUGH; - } - - /* XXX This isn't correct. This log parameter only has two bytes.... */ -#if 0 - dpt->cache_size = param[5] - | (param[6] << 8) - | (param[7] << 16) - | (param[8] << 24); -#endif -} - -static void -dpt_poll(struct cam_sim *sim) -{ - dpt_intr_locked(cam_sim_softc(sim)); -} - -static void -dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) -{ - struct dpt_ccb *dccb; - union ccb *ccb; - struct dpt_softc *dpt; - - dccb = (struct dpt_ccb *)arg; - ccb = dccb->ccb; - dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr; - if (!dumping) - mtx_assert(&dpt->lock, MA_OWNED); - - if (error != 0) { - if (error != EFBIG) - device_printf(dpt->dev, - "Unexepected error 0x%x returned from " - "bus_dmamap_load\n", error); - if (ccb->ccb_h.status == CAM_REQ_INPROG) { - xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); - ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; - } - dptfreeccb(dpt, dccb); - xpt_done(ccb); - return; - } - - if (nseg != 0) { - dpt_sg_t *sg; - bus_dma_segment_t *end_seg; - bus_dmasync_op_t op; - - end_seg = dm_segs + nseg; - - /* Copy the segments into our SG list */ - sg = dccb->sg_list; - while (dm_segs < end_seg) { - sg->seg_len = htonl(dm_segs->ds_len); - sg->seg_addr = htonl(dm_segs->ds_addr); - sg++; - dm_segs++; - } - - if (nseg > 1) { - dccb->eata_ccb.scatter = 1; - dccb->eata_ccb.cp_dataDMA = dccb->sg_busaddr; - dccb->eata_ccb.cp_datalen = - htonl(nseg * sizeof(dpt_sg_t)); - } else { - dccb->eata_ccb.cp_dataDMA = dccb->sg_list[0].seg_addr; - dccb->eata_ccb.cp_datalen = dccb->sg_list[0].seg_len; - } - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - op = BUS_DMASYNC_PREREAD; - else - op = BUS_DMASYNC_PREWRITE; - - bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op); - - } else { - dccb->eata_ccb.cp_dataDMA = 0; - dccb->eata_ccb.cp_datalen = 0; - } - - /* - * Last time we need to check if this CCB needs to - * be aborted. - */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { - if (nseg != 0) - bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); - dptfreeccb(dpt, dccb); - xpt_done(ccb); - return; - } - - dccb->state |= DCCB_ACTIVE; - ccb->ccb_h.status |= CAM_SIM_QUEUED; - LIST_INSERT_HEAD(&dpt->pending_ccb_list, &ccb->ccb_h, sim_links.le); - callout_reset_sbt(&dccb->timer, SBT_1MS * ccb->ccb_h.timeout, 0, - dpttimeout, dccb, 0); - if (dpt_send_eata_command(dpt, &dccb->eata_ccb, - dccb->eata_ccb.cp_busaddr, - EATA_CMD_DMA_SEND_CP, 0, 0, 0, 0) != 0) { - ccb->ccb_h.status = CAM_NO_HBA; /* HBA dead or just busy?? */ - if (nseg != 0) - bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); - dptfreeccb(dpt, dccb); - xpt_done(ccb); - } -} - -static void -dpt_action(struct cam_sim *sim, union ccb *ccb) -{ - struct dpt_softc *dpt; - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("dpt_action\n")); - - dpt = (struct dpt_softc *)cam_sim_softc(sim); - mtx_assert(&dpt->lock, MA_OWNED); - - if ((dpt->state & DPT_HA_SHUTDOWN_ACTIVE) != 0) { - xpt_print_path(ccb->ccb_h.path); - printf("controller is shutdown. Aborting CCB.\n"); - ccb->ccb_h.status = CAM_NO_HBA; - xpt_done(ccb); - return; - } - - switch (ccb->ccb_h.func_code) { - /* Common cases first */ - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - { - struct ccb_scsiio *csio; - struct ccb_hdr *ccbh; - struct dpt_ccb *dccb; - struct eata_ccb *eccb; - - csio = &ccb->csio; - ccbh = &ccb->ccb_h; - /* Max CDB length is 12 bytes */ - if (csio->cdb_len > 12) { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - return; - } - if ((dccb = dptgetccb(dpt)) == NULL) { - dpt->resource_shortage = 1; - xpt_freeze_simq(sim, /*count*/1); - ccb->ccb_h.status = CAM_REQUEUE_REQ; - xpt_done(ccb); - return; - } - eccb = &dccb->eata_ccb; - - /* Link dccb and ccb so we can find one from the other */ - dccb->ccb = ccb; - ccb->ccb_h.ccb_dccb_ptr = dccb; - ccb->ccb_h.ccb_dpt_ptr = dpt; - - /* - * Explicitly set all flags so that the compiler can - * be smart about setting them. - */ - eccb->SCSI_Reset = 0; - eccb->HBA_Init = 0; - eccb->Auto_Req_Sen = (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) - ? 0 : 1; - eccb->scatter = 0; - eccb->Quick = 0; - eccb->Interpret = - ccb->ccb_h.target_id == dpt->hostid[cam_sim_bus(sim)] - ? 1 : 0; - eccb->DataOut = (ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0; - eccb->DataIn = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0; - eccb->reqlen = csio->sense_len; - eccb->cp_id = ccb->ccb_h.target_id; - eccb->cp_channel = cam_sim_bus(sim); - eccb->cp_LUN = ccb->ccb_h.target_lun; - eccb->cp_luntar = 0; - eccb->cp_dispri = (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) - ? 0 : 1; - eccb->cp_identify = 1; - - if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0 - && csio->tag_action != CAM_TAG_ACTION_NONE) { - eccb->cp_msg[0] = csio->tag_action; - eccb->cp_msg[1] = dccb->tag; - } else { - eccb->cp_msg[0] = 0; - eccb->cp_msg[1] = 0; - } - eccb->cp_msg[2] = 0; - - if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { - if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { - bcopy(csio->cdb_io.cdb_ptr, - eccb->cp_cdb, csio->cdb_len); - } else { - /* I guess I could map it in... */ - ccb->ccb_h.status = CAM_REQ_INVALID; - dptfreeccb(dpt, dccb); - xpt_done(ccb); - return; - } - } else { - bcopy(csio->cdb_io.cdb_bytes, - eccb->cp_cdb, csio->cdb_len); - } - /* - * If we have any data to send with this command, - * map it into bus space. - */ - /* Only use S/G if there is a transfer */ - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - int error; - - error = bus_dmamap_load_ccb(dpt->buffer_dmat, - dccb->dmamap, - ccb, - dptexecuteccb, - dccb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(sim, 1); - dccb->state |= CAM_RELEASE_SIMQ; - } - } else { - /* - * XXX JGibbs. - * Does it want them both on or both off? - * CAM_DIR_NONE is both on, so this code can - * be removed if this is also what the DPT - * exptects. - */ - eccb->DataOut = 0; - eccb->DataIn = 0; - dptexecuteccb(dccb, NULL, 0, 0); - } - break; - } - case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ - 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: - { - 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 = &ccb->cts; - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - if (cts->type == CTS_TYPE_USER_SETTINGS) { - spi->flags = CTS_SPI_FLAGS_DISC_ENB; - spi->bus_width = (dpt->max_id > 7) - ? MSG_EXT_WDTR_BUS_8_BIT - : MSG_EXT_WDTR_BUS_16_BIT; - spi->sync_period = 25; /* 10MHz */ - if (spi->sync_period != 0) - spi->sync_offset = 15; - scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - - spi->valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET - | CTS_SPI_VALID_BUS_WIDTH - | CTS_SPI_VALID_DISC; - scsi->valid = CTS_SCSI_VALID_TQ; - ccb->ccb_h.status = CAM_REQ_CMP; - } else { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - } - xpt_done(ccb); - break; - } - case XPT_CALC_GEOMETRY: - { - /* - * XXX Use Adaptec translation until I find out how to - * get this information from the card. - */ - cam_calc_geometry(&ccb->ccg, /*extended*/1); - xpt_done(ccb); - break; - } - case XPT_RESET_BUS: /* Reset the specified SCSI bus */ - { - /* XXX Implement */ - 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; - cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; - if (dpt->max_id > 7) - cpi->hba_inquiry |= PI_WIDE_16; - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->hba_eng_cnt = 0; - cpi->max_target = dpt->max_id; - cpi->max_lun = dpt->max_lun; - cpi->initiator_id = dpt->hostid[cam_sim_bus(sim)]; - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strlcpy(cpi->hba_vid, "DPT", HBA_IDLEN); - strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->transport = XPORT_SPI; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - default: - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } -} - -/* - * This routine will try to send an EATA command to the DPT HBA. - * It will, by default, try 20,000 times, waiting 50us between tries. - * It returns 0 on success and 1 on failure. - */ -static int -dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd_block, - u_int32_t cmd_busaddr, u_int command, u_int retries, - u_int ifc, u_int code, u_int code2) -{ - u_int loop; - - if (!retries) - retries = 20000; - - /* - * I hate this polling nonsense. Wish there was a way to tell the DPT - * to go get commands at its own pace, or to interrupt when ready. - * In the mean time we will measure how many itterations it really - * takes. - */ - for (loop = 0; loop < retries; loop++) { - if ((dpt_inb(dpt, HA_RAUXSTAT) & HA_ABUSY) == 0) - break; - else - DELAY(50); - } - - if (loop < retries) { -#ifdef DPT_MEASURE_PERFORMANCE - if (loop > dpt->performance.max_eata_tries) - dpt->performance.max_eata_tries = loop; - - if (loop < dpt->performance.min_eata_tries) - dpt->performance.min_eata_tries = loop; -#endif - } else { -#ifdef DPT_MEASURE_PERFORMANCE - ++dpt->performance.command_too_busy; -#endif - return (1); - } - - /* The controller is alive, advance the wedge timer */ -#ifdef DPT_RESET_HBA - dpt->last_contact = microtime_now; -#endif - - if (cmd_block == NULL) - cmd_busaddr = 0; -#if (BYTE_ORDER == BIG_ENDIAN) - else { - cmd_busaddr = ((cmd_busaddr >> 24) & 0xFF) - | ((cmd_busaddr >> 16) & 0xFF) - | ((cmd_busaddr >> 8) & 0xFF) - | (cmd_busaddr & 0xFF); - } -#endif - /* And now the address */ - dpt_outl(dpt, HA_WDMAADDR, cmd_busaddr); - - if (command == EATA_CMD_IMMEDIATE) { - if (cmd_block == NULL) { - dpt_outb(dpt, HA_WCODE2, code2); - dpt_outb(dpt, HA_WCODE, code); - } - dpt_outb(dpt, HA_WIFC, ifc); - } - dpt_outb(dpt, HA_WCOMMAND, command); - - return (0); -} - - -/* ==================== Exported Function definitions =======================*/ -void -dpt_alloc(device_t dev) -{ - dpt_softc_t *dpt = device_get_softc(dev); - int i; - - mtx_init(&dpt->lock, "dpt", NULL, MTX_DEF); - SLIST_INIT(&dpt->free_dccb_list); - LIST_INIT(&dpt->pending_ccb_list); - for (i = 0; i < MAX_CHANNELS; i++) - dpt->resetlevel[i] = DPT_HA_OK; - -#ifdef DPT_MEASURE_PERFORMANCE - dpt_reset_performance(dpt); -#endif /* DPT_MEASURE_PERFORMANCE */ - return; -} - -void -dpt_free(struct dpt_softc *dpt) -{ - switch (dpt->init_level) { - default: - case 5: - bus_dmamap_unload(dpt->dccb_dmat, dpt->dccb_dmamap); - case 4: - bus_dmamem_free(dpt->dccb_dmat, dpt->dpt_dccbs, - dpt->dccb_dmamap); - case 3: - bus_dma_tag_destroy(dpt->dccb_dmat); - case 2: - bus_dma_tag_destroy(dpt->buffer_dmat); - case 1: - { - struct sg_map_node *sg_map; - - while ((sg_map = SLIST_FIRST(&dpt->sg_maps)) != NULL) { - SLIST_REMOVE_HEAD(&dpt->sg_maps, links); - bus_dmamap_unload(dpt->sg_dmat, - sg_map->sg_dmamap); - bus_dmamem_free(dpt->sg_dmat, sg_map->sg_vaddr, - sg_map->sg_dmamap); - free(sg_map, M_DEVBUF); - } - bus_dma_tag_destroy(dpt->sg_dmat); - } - case 0: - break; - } - mtx_destroy(&dpt->lock); -} - -int -dpt_alloc_resources (device_t dev) -{ - dpt_softc_t * dpt; - int error; - - dpt = device_get_softc(dev); - - dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, &dpt->io_rid, - RF_ACTIVE); - if (dpt->io_res == NULL) { - device_printf(dev, "No I/O space?!\n"); - error = ENOMEM; - goto bad; - } - - dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid, - RF_ACTIVE); - if (dpt->irq_res == NULL) { - device_printf(dev, "No IRQ!\n"); - error = ENOMEM; - goto bad; - } - - return (0); -bad: - return(error); -} - - -void -dpt_release_resources (device_t dev) -{ - struct dpt_softc * dpt; - - dpt = device_get_softc(dev); - - if (dpt->ih) - bus_teardown_intr(dev, dpt->irq_res, dpt->ih); - if (dpt->io_res) - bus_release_resource(dev, dpt->io_type, dpt->io_rid, dpt->io_res); - if (dpt->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, dpt->irq_rid, dpt->irq_res); - if (dpt->drq_res) - bus_release_resource(dev, SYS_RES_DRQ, dpt->drq_rid, dpt->drq_res); - - return; -} - -static u_int8_t string_sizes[] = -{ - sizeof(((dpt_inq_t*)NULL)->vendor), - sizeof(((dpt_inq_t*)NULL)->modelNum), - sizeof(((dpt_inq_t*)NULL)->firmware), - sizeof(((dpt_inq_t*)NULL)->protocol), -}; - -int -dpt_init(struct dpt_softc *dpt) -{ - dpt_conf_t conf; - struct sg_map_node *sg_map; - dpt_ccb_t *dccb; - u_int8_t *strp; - int index; - int i; - int retval; - - dpt->init_level = 0; - SLIST_INIT(&dpt->sg_maps); - mtx_lock(&dpt->lock); - -#ifdef DPT_RESET_BOARD - device_printf(dpt->dev, "resetting HBA\n"); - dpt_outb(dpt, HA_WCOMMAND, EATA_CMD_RESET); - DELAY(750000); - /* XXX Shouldn't we poll a status register or something??? */ -#endif - /* DMA tag for our S/G structures. We allocate in page sized chunks */ - if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, - /* alignment */ 1, - /* boundary */ 0, - /* lowaddr */ BUS_SPACE_MAXADDR, - /* highaddr */ BUS_SPACE_MAXADDR, - /* filter */ NULL, - /* filterarg */ NULL, - /* maxsize */ PAGE_SIZE, - /* nsegments */ 1, - /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, - /* flags */ 0, - /* lockfunc */ NULL, - /* lockarg */ NULL, - &dpt->sg_dmat) != 0) { - goto error_exit; - } - - dpt->init_level++; - - /* - * We allocate our DPT ccbs as a contiguous array of bus dma'able - * memory. To get the allocation size, we need to know how many - * ccbs the card supports. This requires a ccb. We solve this - * chicken and egg problem by allocating some re-usable S/G space - * up front, and treating it as our status packet, CCB, and target - * memory space for these commands. - */ - sg_map = dptallocsgmap(dpt); - if (sg_map == NULL) - goto error_exit; - - dpt->sp = (volatile dpt_sp_t *)sg_map->sg_vaddr; - dccb = (struct dpt_ccb *)(uintptr_t)(volatile void *)&dpt->sp[1]; - bzero(dccb, sizeof(*dccb)); - dpt->sp_physaddr = sg_map->sg_physaddr; - dccb->eata_ccb.cp_dataDMA = - htonl(sg_map->sg_physaddr + sizeof(dpt_sp_t) + sizeof(*dccb)); - dccb->eata_ccb.cp_busaddr = ~0; - dccb->eata_ccb.cp_statDMA = htonl(dpt->sp_physaddr); - dccb->eata_ccb.cp_reqDMA = htonl(dpt->sp_physaddr + sizeof(*dccb) - + offsetof(struct dpt_ccb, sense_data)); - - /* Okay. Fetch our config */ - bzero(&dccb[1], sizeof(conf)); /* data area */ - retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), - sizeof(conf), 0xc1, 7, 1); - - if (retval != 0) { - device_printf(dpt->dev, "Failed to get board configuration\n"); - goto error_exit; - } - bcopy(&dccb[1], &conf, sizeof(conf)); - - bzero(&dccb[1], sizeof(dpt->board_data)); - retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), - sizeof(dpt->board_data), 0, conf.scsi_id0, 0); - if (retval != 0) { - device_printf(dpt->dev, "Failed to get inquiry information\n"); - goto error_exit; - } - bcopy(&dccb[1], &dpt->board_data, sizeof(dpt->board_data)); - - dpt_detect_cache(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), - (u_int8_t *)&dccb[1]); - - switch (ntohl(conf.splen)) { - case DPT_EATA_REVA: - dpt->EATA_revision = 'a'; - break; - case DPT_EATA_REVB: - dpt->EATA_revision = 'b'; - break; - case DPT_EATA_REVC: - dpt->EATA_revision = 'c'; - break; - case DPT_EATA_REVZ: - dpt->EATA_revision = 'z'; - break; - default: - dpt->EATA_revision = '?'; - } - - dpt->max_id = conf.MAX_ID; - dpt->max_lun = conf.MAX_LUN; - dpt->irq = conf.IRQ; - dpt->dma_channel = (8 - conf.DMA_channel) & 7; - dpt->channels = conf.MAX_CHAN + 1; - dpt->state |= DPT_HA_OK; - if (conf.SECOND) - dpt->primary = FALSE; - else - dpt->primary = TRUE; - - dpt->more_support = conf.MORE_support; - - if (strncmp(dpt->board_data.firmware, "07G0", 4) >= 0) - dpt->immediate_support = 1; - else - dpt->immediate_support = 0; - - dpt->cplen = ntohl(conf.cplen); - dpt->cppadlen = ntohs(conf.cppadlen); - dpt->max_dccbs = ntohs(conf.queuesiz); - - if (dpt->max_dccbs > 256) { - device_printf(dpt->dev, "Max CCBs reduced from %d to " - "256 due to tag algorithm\n", dpt->max_dccbs); - dpt->max_dccbs = 256; - } - - dpt->hostid[0] = conf.scsi_id0; - dpt->hostid[1] = conf.scsi_id1; - dpt->hostid[2] = conf.scsi_id2; - - if (conf.SG_64K) - dpt->sgsize = 8192; - else - dpt->sgsize = ntohs(conf.SGsiz); - - /* We can only get 64k buffers, so don't bother to waste space. */ - if (dpt->sgsize < 17 || dpt->sgsize > 32) - dpt->sgsize = 32; - - if (dpt->sgsize > dpt_max_segs) - dpt->sgsize = dpt_max_segs; - - /* DMA tag for mapping buffers into device visible space. */ - if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, - /* alignment */ 1, - /* boundary */ 0, - /* lowaddr */ BUS_SPACE_MAXADDR, - /* highaddr */ BUS_SPACE_MAXADDR, - /* filter */ NULL, - /* filterarg */ NULL, - /* maxsize */ DFLTPHYS, - /* nsegments */ dpt->sgsize, - /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, - /* flags */ BUS_DMA_ALLOCNOW, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &dpt->lock, - &dpt->buffer_dmat) != 0) { - device_printf(dpt->dev, - "bus_dma_tag_create(...,dpt->buffer_dmat) failed\n"); - goto error_exit; - } - - dpt->init_level++; - - /* DMA tag for our ccb structures and interrupt status packet */ - if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, - /* alignment */ 1, - /* boundary */ 0, - /* lowaddr */ BUS_SPACE_MAXADDR, - /* highaddr */ BUS_SPACE_MAXADDR, - /* filter */ NULL, - /* filterarg */ NULL, - /* maxsize */ (dpt->max_dccbs * - sizeof(struct dpt_ccb)) + - sizeof(dpt_sp_t), - /* nsegments */ 1, - /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, - /* flags */ 0, - /* lockfunc */ NULL, - /* lockarg */ NULL, - &dpt->dccb_dmat) != 0) { - device_printf(dpt->dev, - "bus_dma_tag_create(...,dpt->dccb_dmat) failed\n"); - goto error_exit; - } - - dpt->init_level++; - - /* Allocation for our ccbs and interrupt status packet */ - if (bus_dmamem_alloc(dpt->dccb_dmat, (void **)&dpt->dpt_dccbs, - BUS_DMA_NOWAIT, &dpt->dccb_dmamap) != 0) { - device_printf(dpt->dev, - "bus_dmamem_alloc(dpt->dccb_dmat,...) failed\n"); - goto error_exit; - } - - dpt->init_level++; - - /* And permanently map them */ - bus_dmamap_load(dpt->dccb_dmat, dpt->dccb_dmamap, - dpt->dpt_dccbs, - (dpt->max_dccbs * sizeof(struct dpt_ccb)) - + sizeof(dpt_sp_t), - dptmapmem, &dpt->dpt_ccb_busbase, /*flags*/0); - - /* Clear them out. */ - bzero(dpt->dpt_dccbs, - (dpt->max_dccbs * sizeof(struct dpt_ccb)) + sizeof(dpt_sp_t)); - - dpt->dpt_ccb_busend = dpt->dpt_ccb_busbase; - - dpt->sp = (dpt_sp_t*)&dpt->dpt_dccbs[dpt->max_dccbs]; - dpt->sp_physaddr = dpt->dpt_ccb_busbase - + (dpt->max_dccbs * sizeof(dpt_ccb_t)); - dpt->init_level++; - - /* Allocate our first batch of ccbs */ - if (dptallocccbs(dpt) == 0) { - device_printf(dpt->dev, "dptallocccbs(dpt) == 0\n"); - mtx_unlock(&dpt->lock); - return (2); - } - - /* Prepare for Target Mode */ - dpt->target_mode_enabled = 1; - - /* Nuke excess spaces from inquiry information */ - strp = dpt->board_data.vendor; - for (i = 0; i < sizeof(string_sizes); i++) { - index = string_sizes[i] - 1; - while (index && (strp[index] == ' ')) - strp[index--] = '\0'; - strp += string_sizes[i]; - } - - device_printf(dpt->dev, "%.8s %.16s FW Rev. %.4s, ", - dpt->board_data.vendor, - dpt->board_data.modelNum, dpt->board_data.firmware); - - printf("%d channel%s, ", dpt->channels, dpt->channels > 1 ? "s" : ""); - - if (dpt->cache_type != DPT_NO_CACHE - && dpt->cache_size != 0) { - printf("%s Cache, ", - dpt->cache_type == DPT_CACHE_WRITETHROUGH - ? "Write-Through" : "Write-Back"); - } - - printf("%d CCBs\n", dpt->max_dccbs); - mtx_unlock(&dpt->lock); - return (0); - -error_exit: - mtx_unlock(&dpt->lock); - return (1); -} - -int -dpt_attach(dpt_softc_t *dpt) -{ - struct cam_devq *devq; - int i; - - /* - * Create the device queue for our SIM. - */ - devq = cam_simq_alloc(dpt->max_dccbs); - if (devq == NULL) - return (0); - - mtx_lock(&dpt->lock); - for (i = 0; i < dpt->channels; i++) { - /* - * Construct our SIM entry - */ - dpt->sims[i] = cam_sim_alloc(dpt_action, dpt_poll, "dpt", - dpt, device_get_unit(dpt->dev), &dpt->lock, - /*untagged*/2, - /*tagged*/dpt->max_dccbs, devq); - if (dpt->sims[i] == NULL) { - if (i == 0) - cam_simq_free(devq); - else - printf( "%s(): Unable to attach bus %d " - "due to resource shortage\n", - __func__, i); - break; - } - - if (xpt_bus_register(dpt->sims[i], dpt->dev, i) != CAM_SUCCESS){ - cam_sim_free(dpt->sims[i], /*free_devq*/i == 0); - dpt->sims[i] = NULL; - break; - } - - if (xpt_create_path(&dpt->paths[i], /*periph*/NULL, - cam_sim_path(dpt->sims[i]), - CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - xpt_bus_deregister(cam_sim_path(dpt->sims[i])); - cam_sim_free(dpt->sims[i], /*free_devq*/i == 0); - dpt->sims[i] = NULL; - break; - } - - } - mtx_unlock(&dpt->lock); - if (i > 0) - EVENTHANDLER_REGISTER(shutdown_final, dptshutdown, - dpt, SHUTDOWN_PRI_DEFAULT); - return (i); -} - -int -dpt_detach (device_t dev) -{ - struct dpt_softc * dpt; - int i; - - dpt = device_get_softc(dev); - - mtx_lock(&dpt->lock); - for (i = 0; i < dpt->channels; i++) { -#if 0 - xpt_async(AC_LOST_DEVICE, dpt->paths[i], NULL); -#endif - xpt_free_path(dpt->paths[i]); - xpt_bus_deregister(cam_sim_path(dpt->sims[i])); - cam_sim_free(dpt->sims[i], /*free_devq*/TRUE); - } - mtx_unlock(&dpt->lock); - - dptshutdown((void *)dpt, SHUTDOWN_PRI_DEFAULT); - - dpt_release_resources(dev); - - dpt_free(dpt); - - return (0); -} - -/* - * This is the interrupt handler for the DPT driver. - */ -void -dpt_intr(void *arg) -{ - dpt_softc_t *dpt; - - dpt = arg; - mtx_lock(&dpt->lock); - dpt_intr_locked(dpt); - mtx_unlock(&dpt->lock); -} - -void -dpt_intr_locked(dpt_softc_t *dpt) -{ - dpt_ccb_t *dccb; - union ccb *ccb; - u_int status; - u_int aux_status; - u_int hba_stat; - u_int scsi_stat; - u_int32_t residue_len; /* Number of bytes not transferred */ - - /* First order of business is to check if this interrupt is for us */ - while (((aux_status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ) != 0) { - - /* - * What we want to do now, is to capture the status, all of it, - * move it where it belongs, wake up whoever sleeps waiting to - * process this result, and get out of here. - */ - if (dpt->sp->ccb_busaddr < dpt->dpt_ccb_busbase - || dpt->sp->ccb_busaddr >= dpt->dpt_ccb_busend) { - device_printf(dpt->dev, - "Encountered bogus status packet\n"); - status = dpt_inb(dpt, HA_RSTATUS); - return; - } - - dccb = dptccbptov(dpt, dpt->sp->ccb_busaddr); - - dpt->sp->ccb_busaddr = ~0; - - /* Ignore status packets with EOC not set */ - if (dpt->sp->EOC == 0) { - device_printf(dpt->dev, - "ERROR: Request %d received with " - "clear EOC.\n Marking as LOST.\n", - dccb->transaction_id); - - /* This CLEARS the interrupt! */ - status = dpt_inb(dpt, HA_RSTATUS); - continue; - } - dpt->sp->EOC = 0; - - /* - * Double buffer the status information so the hardware can - * work on updating the status packet while we decifer the - * one we were just interrupted for. - * According to Mark Salyzyn, we only need few pieces of it. - */ - hba_stat = dpt->sp->hba_stat; - scsi_stat = dpt->sp->scsi_stat; - residue_len = dpt->sp->residue_len; - - /* Clear interrupts, check for error */ - if ((status = dpt_inb(dpt, HA_RSTATUS)) & HA_SERROR) { - /* - * Error Condition. Check for magic cookie. Exit - * this test on earliest sign of non-reset condition - */ - - /* Check that this is not a board reset interrupt */ - if (dpt_just_reset(dpt)) { - device_printf(dpt->dev, "HBA rebooted.\n" - " All transactions should be " - "resubmitted\n"); - - device_printf(dpt->dev, - ">>---->> This is incomplete, " - "fix me.... <<----<<"); - panic("DPT Rebooted"); - - } - } - /* Process CCB */ - ccb = dccb->ccb; - callout_stop(&dccb->timer); - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - bus_dmasync_op_t op; - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - op = BUS_DMASYNC_POSTREAD; - else - op = BUS_DMASYNC_POSTWRITE; - bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op); - bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); - } - - /* Common Case inline... */ - if (hba_stat == HA_NO_ERROR) { - ccb->csio.scsi_status = scsi_stat; - ccb->ccb_h.status = 0; - switch (scsi_stat) { - case SCSI_STATUS_OK: - ccb->ccb_h.status |= CAM_REQ_CMP; - break; - case SCSI_STATUS_CHECK_COND: - case SCSI_STATUS_CMD_TERMINATED: - bcopy(&dccb->sense_data, &ccb->csio.sense_data, - ccb->csio.sense_len); - ccb->ccb_h.status |= CAM_AUTOSNS_VALID; - /* FALLTHROUGH */ - default: - ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; - /* XXX Freeze DevQ */ - break; - } - ccb->csio.resid = residue_len; - dptfreeccb(dpt, dccb); - xpt_done(ccb); - } else { - dptprocesserror(dpt, dccb, ccb, hba_stat, scsi_stat, - residue_len); - } - } -} - -static void -dptprocesserror(dpt_softc_t *dpt, dpt_ccb_t *dccb, union ccb *ccb, - u_int hba_stat, u_int scsi_stat, u_int32_t resid) -{ - ccb->csio.resid = resid; - switch (hba_stat) { - case HA_ERR_SEL_TO: - ccb->ccb_h.status = CAM_SEL_TIMEOUT; - break; - case HA_ERR_CMD_TO: - ccb->ccb_h.status = CAM_CMD_TIMEOUT; - break; - case HA_SCSIBUS_RESET: - case HA_HBA_POWER_UP: /* Similar effect to a bus reset??? */ - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; - break; - case HA_CP_ABORTED: - case HA_CP_RESET: /* XXX ??? */ - case HA_CP_ABORT_NA: /* XXX ??? */ - case HA_CP_RESET_NA: /* XXX ??? */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) - ccb->ccb_h.status = CAM_REQ_ABORTED; - break; - case HA_PCI_PARITY: - case HA_PCI_MABORT: - case HA_PCI_TABORT: - case HA_PCI_STABORT: - case HA_BUS_PARITY: - case HA_PARITY_ERR: - case HA_ECC_ERR: - ccb->ccb_h.status = CAM_UNCOR_PARITY; - break; - case HA_UNX_MSGRJCT: - ccb->ccb_h.status = CAM_MSG_REJECT_REC; - break; - case HA_UNX_BUSPHASE: - ccb->ccb_h.status = CAM_SEQUENCE_FAIL; - break; - case HA_UNX_BUS_FREE: - ccb->ccb_h.status = CAM_UNEXP_BUSFREE; - break; - case HA_SCSI_HUNG: - case HA_RESET_STUCK: - /* - * Dead??? Can the controller get unstuck - * from these conditions - */ - ccb->ccb_h.status = CAM_NO_HBA; - break; - case HA_RSENSE_FAIL: - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; - break; - default: - device_printf(dpt->dev, "Undocumented Error %x\n", hba_stat); - printf("Please mail this message to shimon@simon-shapiro.org\n"); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - break; - } - dptfreeccb(dpt, dccb); - xpt_done(ccb); -} - -static void -dpttimeout(void *arg) -{ - struct dpt_ccb *dccb; - union ccb *ccb; - struct dpt_softc *dpt; - - dccb = (struct dpt_ccb *)arg; - ccb = dccb->ccb; - dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr; - mtx_assert(&dpt->lock, MA_OWNED); - xpt_print_path(ccb->ccb_h.path); - printf("CCB %p - timed out\n", (void *)dccb); - - /* - * Try to clear any pending jobs. FreeBSD will lose interrupts, - * leaving the controller suspended, and commands timed-out. - * By calling the interrupt handler, any command thus stuck will be - * completed. - */ - dpt_intr_locked(dpt); - - if ((dccb->state & DCCB_ACTIVE) == 0) { - xpt_print_path(ccb->ccb_h.path); - printf("CCB %p - timed out CCB already completed\n", - (void *)dccb); - return; - } - - /* Abort this particular command. Leave all others running */ - dpt_send_immediate(dpt, &dccb->eata_ccb, dccb->eata_ccb.cp_busaddr, - /*retries*/20000, EATA_SPECIFIC_ABORT, 0, 0); - ccb->ccb_h.status = CAM_CMD_TIMEOUT; -} - -/* - * Shutdown the controller and ensure that the cache is completely flushed. - * Called from the shutdown_final event after all disk access has completed. - */ -static void -dptshutdown(void *arg, int howto) -{ - dpt_softc_t *dpt; - - dpt = (dpt_softc_t *)arg; - - device_printf(dpt->dev, - "Shutting down (mode %x) HBA. Please wait...\n", howto); - - /* - * What we do for a shutdown, is give the DPT early power loss warning - */ - mtx_lock(&dpt->lock); - dpt_send_immediate(dpt, NULL, 0, EATA_POWER_OFF_WARN, 0, 0, 0); - mtx_unlock(&dpt->lock); - DELAY(1000 * 1000 * 5); - device_printf(dpt->dev, "Controller was warned of shutdown and is now " - "disabled\n"); -} - -/*============================================================================*/ - -#if 0 -#ifdef DPT_RESET_HBA - -/* -** Function name : dpt_reset_hba -** -** Description : Reset the HBA and properly discard all pending work -** Input : Softc -** Output : Nothing -*/ -static void -dpt_reset_hba(dpt_softc_t *dpt) -{ - eata_ccb_t *ccb; - dpt_ccb_t dccb, *dccbp; - int result; - struct scsi_xfer *xs; - - mtx_assert(&dpt->lock, MA_OWNED); - - /* Prepare a control block. The SCSI command part is immaterial */ - dccb.xs = NULL; - dccb.flags = 0; - dccb.state = DPT_CCB_STATE_NEW; - dccb.std_callback = NULL; - dccb.wrbuff_callback = NULL; - - ccb = &dccb.eata_ccb; - ccb->CP_OpCode = EATA_CMD_RESET; - ccb->SCSI_Reset = 0; - ccb->HBA_Init = 1; - ccb->Auto_Req_Sen = 1; - ccb->cp_id = 0; /* Should be ignored */ - ccb->DataIn = 1; - ccb->DataOut = 0; - ccb->Interpret = 1; - ccb->reqlen = htonl(sizeof(struct scsi_sense_data)); - ccb->cp_statDMA = htonl(vtophys(&ccb->cp_statDMA)); - ccb->cp_reqDMA = htonl(vtophys(&ccb->cp_reqDMA)); - ccb->cp_viraddr = (u_int32_t) & ccb; - - ccb->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO; - ccb->cp_scsi_cmd = 0; /* Should be ignored */ - - /* Lock up the submitted queue. We are very persistent here */ - while (dpt->queue_status & DPT_SUBMITTED_QUEUE_ACTIVE) { - DELAY(100); - } - - dpt->queue_status |= DPT_SUBMITTED_QUEUE_ACTIVE; - - /* Send the RESET message */ - if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb, - EATA_CMD_RESET, 0, 0, 0, 0)) != 0) { - device_printf(dpt->dev, "Failed to send the RESET message.\n" - " Trying cold boot (ouch!)\n"); - - - if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb, - EATA_COLD_BOOT, 0, 0, - 0, 0)) != 0) { - panic("%s: Faild to cold boot the HBA\n", - device_get_nameunit(dpt->dev)); - } -#ifdef DPT_MEASURE_PERFORMANCE - dpt->performance.cold_boots++; -#endif /* DPT_MEASURE_PERFORMANCE */ - } - -#ifdef DPT_MEASURE_PERFORMANCE - dpt->performance.warm_starts++; -#endif /* DPT_MEASURE_PERFORMANCE */ - - device_printf(dpt->dev, - "Aborting pending requests. O/S should re-submit\n"); - - while ((dccbp = TAILQ_FIRST(&dpt->completed_ccbs)) != NULL) { - struct scsi_xfer *xs = dccbp->xs; - - /* Not all transactions have xs structs */ - if (xs != NULL) { - /* Tell the kernel proper this did not complete well */ - xs->error |= XS_SELTIMEOUT; - xs->flags |= SCSI_ITSDONE; - scsi_done(xs); - } - - dpt_Qremove_submitted(dpt, dccbp); - - /* Remember, Callbacks are NOT in the standard queue */ - if (dccbp->std_callback != NULL) { - (dccbp->std_callback)(dpt, dccbp->eata_ccb.cp_channel, - dccbp); - } else { - dpt_Qpush_free(dpt, dccbp); - } - } - - device_printf(dpt->dev, "reset done aborting all pending commands\n"); - dpt->queue_status &= ~DPT_SUBMITTED_QUEUE_ACTIVE; -} - -#endif /* DPT_RESET_HBA */ - -/* - * Build a Command Block for target mode READ/WRITE BUFFER, - * with the ``sync'' bit ON. - * - * Although the length and offset are 24 bit fields in the command, they cannot - * exceed 8192 bytes, so we take them as short integers andcheck their range. - * If they are sensless, we round them to zero offset, maximum length and - * complain. - */ - -static void -dpt_target_ccb(dpt_softc_t * dpt, int bus, u_int8_t target, u_int8_t lun, - dpt_ccb_t * ccb, int mode, u_int8_t command, - u_int16_t length, u_int16_t offset) -{ - eata_ccb_t *cp; - - mtx_assert(&dpt->lock, MA_OWNED); - if ((length + offset) > DPT_MAX_TARGET_MODE_BUFFER_SIZE) { - device_printf(dpt->dev, - "Length of %d, and offset of %d are wrong\n", - length, offset); - length = DPT_MAX_TARGET_MODE_BUFFER_SIZE; - offset = 0; - } - ccb->xs = NULL; - ccb->flags = 0; - ccb->state = DPT_CCB_STATE_NEW; - ccb->std_callback = (ccb_callback) dpt_target_done; - ccb->wrbuff_callback = NULL; - - cp = &ccb->eata_ccb; - cp->CP_OpCode = EATA_CMD_DMA_SEND_CP; - cp->SCSI_Reset = 0; - cp->HBA_Init = 0; - cp->Auto_Req_Sen = 1; - cp->cp_id = target; - cp->DataIn = 1; - cp->DataOut = 0; - cp->Interpret = 0; - cp->reqlen = htonl(sizeof(struct scsi_sense_data)); - cp->cp_statDMA = htonl(vtophys(&cp->cp_statDMA)); - cp->cp_reqDMA = htonl(vtophys(&cp->cp_reqDMA)); - cp->cp_viraddr = (u_int32_t) & ccb; - - cp->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO; - - cp->cp_scsi_cmd = command; - cp->cp_cdb[1] = (u_int8_t) (mode & SCSI_TM_MODE_MASK); - cp->cp_lun = lun; /* Order is important here! */ - cp->cp_cdb[2] = 0x00; /* Buffer Id, only 1 :-( */ - cp->cp_cdb[3] = (length >> 16) & 0xFF; /* Buffer offset MSB */ - cp->cp_cdb[4] = (length >> 8) & 0xFF; - cp->cp_cdb[5] = length & 0xFF; - cp->cp_cdb[6] = (length >> 16) & 0xFF; /* Length MSB */ - cp->cp_cdb[7] = (length >> 8) & 0xFF; - cp->cp_cdb[8] = length & 0xFF; /* Length LSB */ - cp->cp_cdb[9] = 0; /* No sync, no match bits */ - - /* - * This could be optimized to live in dpt_register_buffer. - * We keep it here, just in case the kernel decides to reallocate pages - */ - if (dpt_scatter_gather(dpt, ccb, DPT_RW_BUFFER_SIZE, - dpt->rw_buffer[bus][target][lun])) { - device_printf(dpt->dev, "Failed to setup Scatter/Gather for " - "Target-Mode buffer\n"); - } -} - -/* Setup a target mode READ command */ - -static void -dpt_set_target(int redo, dpt_softc_t * dpt, - u_int8_t bus, u_int8_t target, u_int8_t lun, int mode, - u_int16_t length, u_int16_t offset, dpt_ccb_t * ccb) -{ - - mtx_assert(&dpt->lock, MA_OWNED); - if (dpt->target_mode_enabled) { - if (!redo) - dpt_target_ccb(dpt, bus, target, lun, ccb, mode, - SCSI_TM_READ_BUFFER, length, offset); - - ccb->transaction_id = ++dpt->commands_processed; - -#ifdef DPT_MEASURE_PERFORMANCE - dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++; - ccb->command_started = microtime_now; -#endif - dpt_Qadd_waiting(dpt, ccb); - dpt_sched_queue(dpt); - } else { - device_printf(dpt->dev, - "Target Mode Request, but Target Mode is OFF\n"); - } -} - -/* - * Schedule a buffer to be sent to another target. - * The work will be scheduled and the callback provided will be called when - * the work is actually done. - * - * Please NOTE: ``Anyone'' can send a buffer, but only registered clients - * get notified of receipt of buffers. - */ - -int -dpt_send_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun, - u_int8_t mode, u_int16_t length, u_int16_t offset, void *data, - buff_wr_done callback) -{ - dpt_softc_t *dpt; - dpt_ccb_t *ccb = NULL; - - /* This is an external call. Be a bit paranoid */ - dpt = devclass_get_device(dpt_devclass, unit); - if (dpt == NULL) - return (INVALID_UNIT); - - mtx_lock(&dpt->lock); - if (dpt->target_mode_enabled) { - if ((channel >= dpt->channels) || (target > dpt->max_id) || - (lun > dpt->max_lun)) { - mtx_unlock(&dpt->lock); - return (INVALID_SENDER); - } - if ((dpt->rw_buffer[channel][target][lun] == NULL) || - (dpt->buffer_receiver[channel][target][lun] == NULL)) { - mtx_unlock(&dpt->lock); - return (NOT_REGISTERED); - } - - /* Process the free list */ - if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { - device_printf(dpt->dev, - "ERROR: Cannot allocate any more free CCB's.\n" - " Please try later\n"); - mtx_unlock(&dpt->lock); - return (NO_RESOURCES); - } - /* Now grab the newest CCB */ - if ((ccb = dpt_Qpop_free(dpt)) == NULL) { - mtx_unlock(&dpt->lock); - panic("%s: Got a NULL CCB from pop_free()\n", - device_get_nameunit(dpt->dev)); - } - - bcopy(dpt->rw_buffer[channel][target][lun] + offset, data, length); - dpt_target_ccb(dpt, channel, target, lun, ccb, mode, - SCSI_TM_WRITE_BUFFER, - length, offset); - ccb->std_callback = (ccb_callback) callback; /* Potential trouble */ - - ccb->transaction_id = ++dpt->commands_processed; - -#ifdef DPT_MEASURE_PERFORMANCE - dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++; - ccb->command_started = microtime_now; -#endif - dpt_Qadd_waiting(dpt, ccb); - dpt_sched_queue(dpt); - - mtx_unlock(&dpt->lock); - return (0); - } - mtx_unlock(&dpt->lock); - return (DRIVER_DOWN); -} - -static void -dpt_target_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb) -{ - eata_ccb_t *cp; - - cp = &ccb->eata_ccb; - - /* - * Remove the CCB from the waiting queue. - * We do NOT put it back on the free, etc., queues as it is a special - * ccb, owned by the dpt_softc of this unit. - */ - dpt_Qremove_completed(dpt, ccb); - -#define br_channel (ccb->eata_ccb.cp_channel) -#define br_target (ccb->eata_ccb.cp_id) -#define br_lun (ccb->eata_ccb.cp_LUN) -#define br_index [br_channel][br_target][br_lun] -#define read_buffer_callback (dpt->buffer_receiver br_index ) -#define read_buffer (dpt->rw_buffer[br_channel][br_target][br_lun]) -#define cb(offset) (ccb->eata_ccb.cp_cdb[offset]) -#define br_offset ((cb(3) << 16) | (cb(4) << 8) | cb(5)) -#define br_length ((cb(6) << 16) | (cb(7) << 8) | cb(8)) - - /* Different reasons for being here, you know... */ - switch (ccb->eata_ccb.cp_scsi_cmd) { - case SCSI_TM_READ_BUFFER: - if (read_buffer_callback != NULL) { - /* This is a buffer generated by a kernel process */ - read_buffer_callback(device_get_unit(dpt->dev), - br_channel, br_target, br_lun, - read_buffer, - br_offset, br_length); - } else { - /* - * This is a buffer waited for by a user (sleeping) - * command - */ - wakeup(ccb); - } - - /* We ALWAYS re-issue the same command; args are don't-care */ - dpt_set_target(1, 0, 0, 0, 0, 0, 0, 0, 0); - break; - - case SCSI_TM_WRITE_BUFFER: - (ccb->wrbuff_callback) (device_get_unit(dpt->dev), br_channel, - br_target, br_offset, br_length, - br_lun, ccb->status_packet.hba_stat); - break; - default: - device_printf(dpt->dev, - "%s is an unsupported command for target mode\n", - scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd)); - } - dpt->target_ccb[br_channel][br_target][br_lun] = NULL; - dpt_Qpush_free(dpt, ccb); -} - - -/* - * Use this function to register a client for a buffer read target operation. - * The function you register will be called every time a buffer is received - * by the target mode code. - */ -dpt_rb_t -dpt_register_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun, - u_int8_t mode, u_int16_t length, u_int16_t offset, - dpt_rec_buff callback, dpt_rb_op_t op) -{ - dpt_softc_t *dpt; - dpt_ccb_t *ccb = NULL; - int ospl; - - dpt = devclass_get_device(dpt_devclass, unit); - if (dpt == NULL) - return (INVALID_UNIT); - mtx_lock(&dpt->lock); - - if (dpt->state & DPT_HA_SHUTDOWN_ACTIVE) { - mtx_unlock(&dpt->lock); - return (DRIVER_DOWN); - } - - if ((channel > (dpt->channels - 1)) || (target > (dpt->max_id - 1)) || - (lun > (dpt->max_lun - 1))) { - mtx_unlock(&dpt->lock); - return (INVALID_SENDER); - } - - if (dpt->buffer_receiver[channel][target][lun] == NULL) { - if (op == REGISTER_BUFFER) { - /* Assign the requested callback */ - dpt->buffer_receiver[channel][target][lun] = callback; - /* Get a CCB */ - - /* Process the free list */ - if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { - device_printf(dpt->dev, - "ERROR: Cannot allocate any more free CCB's.\n" - " Please try later\n"); - mtx_unlock(&dpt->lock); - return (NO_RESOURCES); - } - /* Now grab the newest CCB */ - if ((ccb = dpt_Qpop_free(dpt)) == NULL) { - mtx_unlock(&dpt->lock); - panic("%s: Got a NULL CCB from pop_free()\n", - device_get_nameunit(dpt->dev)); - } - - /* Clean up the leftover of the previous tenant */ - ccb->status = DPT_CCB_STATE_NEW; - dpt->target_ccb[channel][target][lun] = ccb; - - dpt->rw_buffer[channel][target][lun] = - malloc(DPT_RW_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); - if (dpt->rw_buffer[channel][target][lun] == NULL) { - device_printf(dpt->dev, "Failed to allocate " - "Target-Mode buffer\n"); - dpt_Qpush_free(dpt, ccb); - mtx_unlock(&dpt->lock); - return (NO_RESOURCES); - } - dpt_set_target(0, dpt, channel, target, lun, mode, - length, offset, ccb); - mtx_unlock(&dpt->lock); - return (SUCCESSFULLY_REGISTERED); - } else { - mtx_unlock(&dpt->lock); - return (NOT_REGISTERED); - } - } else { - if (op == REGISTER_BUFFER) { - if (dpt->buffer_receiver[channel][target][lun] == callback) { - mtx_unlock(&dpt->lock); - return (ALREADY_REGISTERED); - } else { - mtx_unlock(&dpt->lock); - return (REGISTERED_TO_ANOTHER); - } - } else { - if (dpt->buffer_receiver[channel][target][lun] == callback) { - dpt->buffer_receiver[channel][target][lun] = NULL; - dpt_Qpush_free(dpt, ccb); - free(dpt->rw_buffer[channel][target][lun], M_DEVBUF); - mtx_unlock(&dpt->lock); - return (SUCCESSFULLY_REGISTERED); - } else { - mtx_unlock(&dpt->lock); - return (INVALID_CALLBACK); - } - } - - } - mtx_unlock(&dpt->lock); -} - -/* Return the state of the blinking DPT LED's */ -u_int8_t -dpt_blinking_led(dpt_softc_t * dpt) -{ - int ndx; - u_int32_t state; - u_int32_t previous; - u_int8_t result; - - mtx_assert(&dpt->lock, MA_OWNED); - result = 0; - - for (ndx = 0, state = 0, previous = 0; - (ndx < 10) && (state != previous); - ndx++) { - previous = state; - state = dpt_inl(dpt, 1); - } - - if ((state == previous) && (state == DPT_BLINK_INDICATOR)) - result = dpt_inb(dpt, 5); - - return (result); -} - -/* - * Execute a command which did not come from the kernel's SCSI layer. - * The only way to map user commands to bus and target is to comply with the - * standard DPT wire-down scheme: - */ -int -dpt_user_cmd(dpt_softc_t * dpt, eata_pt_t * user_cmd, - caddr_t cmdarg, int minor_no) -{ - dpt_ccb_t *ccb; - void *data; - int channel, target, lun; - int huh; - int result; - int submitted; - - mtx_assert(&dpt->lock, MA_OWNED); - data = NULL; - channel = minor2hba(minor_no); - target = minor2target(minor_no); - lun = minor2lun(minor_no); - - if ((channel > (dpt->channels - 1)) - || (target > dpt->max_id) - || (lun > dpt->max_lun)) - return (ENXIO); - - if (target == dpt->sc_scsi_link[channel].adapter_targ) { - /* This one is for the controller itself */ - if ((user_cmd->eataID[0] != 'E') - || (user_cmd->eataID[1] != 'A') - || (user_cmd->eataID[2] != 'T') - || (user_cmd->eataID[3] != 'A')) { - return (ENXIO); - } - } - /* Get a DPT CCB, so we can prepare a command */ - - /* Process the free list */ - if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { - device_printf(dpt->dev, - "ERROR: Cannot allocate any more free CCB's.\n" - " Please try later\n"); - return (EFAULT); - } - /* Now grab the newest CCB */ - if ((ccb = dpt_Qpop_free(dpt)) == NULL) { - panic("%s: Got a NULL CCB from pop_free()\n", - device_get_nameunit(dpt->dev)); - } else { - /* Clean up the leftover of the previous tenant */ - ccb->status = DPT_CCB_STATE_NEW; - } - - bcopy((caddr_t) & user_cmd->command_packet, (caddr_t) & ccb->eata_ccb, - sizeof(eata_ccb_t)); - - /* We do not want to do user specified scatter/gather. Why?? */ - if (ccb->eata_ccb.scatter == 1) - return (EINVAL); - - ccb->eata_ccb.Auto_Req_Sen = 1; - ccb->eata_ccb.reqlen = htonl(sizeof(struct scsi_sense_data)); - ccb->eata_ccb.cp_datalen = htonl(sizeof(ccb->eata_ccb.cp_datalen)); - ccb->eata_ccb.cp_dataDMA = htonl(vtophys(ccb->eata_ccb.cp_dataDMA)); - ccb->eata_ccb.cp_statDMA = htonl(vtophys(&ccb->eata_ccb.cp_statDMA)); - ccb->eata_ccb.cp_reqDMA = htonl(vtophys(&ccb->eata_ccb.cp_reqDMA)); - ccb->eata_ccb.cp_viraddr = (u_int32_t) & ccb; - - if (ccb->eata_ccb.DataIn || ccb->eata_ccb.DataOut) { - /* Data I/O is involved in this command. Alocate buffer */ - if (ccb->eata_ccb.cp_datalen > PAGE_SIZE) { - data = contigmalloc(ccb->eata_ccb.cp_datalen, - M_TEMP, M_WAITOK, 0, ~0, - ccb->eata_ccb.cp_datalen, - 0x10000); - } else { - data = malloc(ccb->eata_ccb.cp_datalen, M_TEMP, - M_WAITOK); - } - - if (data == NULL) { - device_printf(dpt->dev, "Cannot allocate %d bytes " - "for EATA command\n", - ccb->eata_ccb.cp_datalen); - return (EFAULT); - } -#define usr_cmd_DMA (caddr_t)user_cmd->command_packet.cp_dataDMA - if (ccb->eata_ccb.DataIn == 1) { - if (copyin(usr_cmd_DMA, - data, ccb->eata_ccb.cp_datalen) == -1) - return (EFAULT); - } - } else { - /* No data I/O involved here. Make sure the DPT knows that */ - ccb->eata_ccb.cp_datalen = 0; - data = NULL; - } - - if (ccb->eata_ccb.FWNEST == 1) - ccb->eata_ccb.FWNEST = 0; - - if (ccb->eata_ccb.cp_datalen != 0) { - if (dpt_scatter_gather(dpt, ccb, ccb->eata_ccb.cp_datalen, - data) != 0) { - if (data != NULL) - free(data, M_TEMP); - return (EFAULT); - } - } - /** - * We are required to quiet a SCSI bus. - * since we do not queue comands on a bus basis, - * we wait for ALL commands on a controller to complete. - * In the mean time, sched_queue() will not schedule new commands. - */ - if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD) - && (ccb->eata_ccb.cp_cdb[2] == BUS_QUIET)) { - /* We wait for ALL traffic for this HBa to subside */ - dpt->state |= DPT_HA_QUIET; - - while ((submitted = dpt->submitted_ccbs_count) != 0) { - huh = mtx_sleep((void *) dpt, &dpt->lock, - PCATCH | PRIBIO, "dptqt", 100 * hz); - switch (huh) { - case 0: - /* Wakeup call received */ - break; - case EWOULDBLOCK: - /* Timer Expired */ - break; - default: - /* anything else */ - break; - } - } - } - /* Resume normal operation */ - if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD) - && (ccb->eata_ccb.cp_cdb[2] == BUS_UNQUIET)) { - dpt->state &= ~DPT_HA_QUIET; - } - /** - * Schedule the command and submit it. - * We bypass dpt_sched_queue, as it will block on DPT_HA_QUIET - */ - ccb->xs = NULL; - ccb->flags = 0; - ccb->eata_ccb.Auto_Req_Sen = 1; /* We always want this feature */ - - ccb->transaction_id = ++dpt->commands_processed; - ccb->std_callback = (ccb_callback) dpt_user_cmd_done; - ccb->result = (u_int32_t) & cmdarg; - ccb->data = data; - -#ifdef DPT_MEASURE_PERFORMANCE - ++dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]; - ccb->command_started = microtime_now; -#endif - dpt_Qadd_waiting(dpt, ccb); - - dpt_sched_queue(dpt); - - /* Wait for the command to complete */ - (void) mtx_sleep((void *) ccb, &dpt->lock, PCATCH | PRIBIO, "dptucw", - 100 * hz); - - /* Free allocated memory */ - if (data != NULL) - free(data, M_TEMP); - - return (0); -} - -static void -dpt_user_cmd_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb) -{ - u_int32_t result; - caddr_t cmd_arg; - - mtx_unlock(&dpt->lock); - - /** - * If Auto Request Sense is on, copyout the sense struct - */ -#define usr_pckt_DMA (caddr_t)(intptr_t)ntohl(ccb->eata_ccb.cp_reqDMA) -#define usr_pckt_len ntohl(ccb->eata_ccb.cp_datalen) - if (ccb->eata_ccb.Auto_Req_Sen == 1) { - if (copyout((caddr_t) & ccb->sense_data, usr_pckt_DMA, - sizeof(struct scsi_sense_data))) { - mtx_lock(&dpt->lock); - ccb->result = EFAULT; - dpt_Qpush_free(dpt, ccb); - wakeup(ccb); - return; - } - } - /* If DataIn is on, copyout the data */ - if ((ccb->eata_ccb.DataIn == 1) - && (ccb->status_packet.hba_stat == HA_NO_ERROR)) { - if (copyout(ccb->data, usr_pckt_DMA, usr_pckt_len)) { - mtx_lock(&dpt->lock); - dpt_Qpush_free(dpt, ccb); - ccb->result = EFAULT; - - wakeup(ccb); - return; - } - } - /* Copyout the status */ - result = ccb->status_packet.hba_stat; - cmd_arg = (caddr_t) ccb->result; - - if (copyout((caddr_t) & result, cmd_arg, sizeof(result))) { - mtx_lock(&dpt->lock); - dpt_Qpush_free(dpt, ccb); - ccb->result = EFAULT; - wakeup(ccb); - return; - } - mtx_lock(&dpt->lock); - /* Put the CCB back in the freelist */ - ccb->state |= DPT_CCB_STATE_COMPLETED; - dpt_Qpush_free(dpt, ccb); - - /* Free allocated memory */ - return; -} - -#endif diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 636897576a2d..1e8172ad5b8a 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -151,7 +151,6 @@ device ses # Enclosure Services (SES and SAF-TE) device amr # AMI MegaRAID device arcmsr # Areca SATA II RAID device ciss # Compaq Smart RAID 5* -device dpt # DPT Smartcache III, IV - See NOTES for options device hptmv # Highpoint RocketRAID 182x device hptnr # Highpoint DC7280, R750 device hptrr # Highpoint RocketRAID 17xx, 22xx, 23xx, 25xx diff --git a/sys/kern/Make.tags.inc b/sys/kern/Make.tags.inc index bd963967984f..50aed68dbf40 100644 --- a/sys/kern/Make.tags.inc +++ b/sys/kern/Make.tags.inc @@ -12,7 +12,6 @@ SYS?= ${.CURDIR}/.. COMM= ${SYS}/sys/vnode.h \ ${SYS}/dev/alc/*.[ch] \ - ${SYS}/dev/dpt/*.[ch] \ ${SYS}/dev/en/*.[ch] \ ${SYS}/dev/iicbus/*.[ch] \ ${SYS}/dev/isp/*.[ch] \ @@ -66,7 +65,6 @@ COMMDIR1= ${SYS}/conf \ ${SYS}/sys COMMDIR2= ${SYS}/dev/alc \ - ${SYS}/dev/dpt \ ${SYS}/dev/en \ ${SYS}/dev/iicbus \ ${SYS}/dev/isp \ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index f27a0579b25f..19a37fe57430 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -110,7 +110,6 @@ SUBDIR= \ dcons_crom \ de \ ${_dpms} \ - ${_dpt} \ ${_drm} \ ${_drm2} \ dummynet \ @@ -767,7 +766,6 @@ _stg= stg .if ${MK_SOURCELESS_UCODE} != "no" _ctau= ctau .endif -_dpt= dpt _ex= ex .endif diff --git a/sys/modules/dpt/Makefile b/sys/modules/dpt/Makefile deleted file mode 100644 index d01f1704db34..000000000000 --- a/sys/modules/dpt/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $FreeBSD$ - -SYSDIR?=${SRCTOP}/sys -.include "${SYSDIR}/conf/kern.opts.mk" - -.PATH: ${SYSDIR}/dev/dpt -KMOD= dpt -SRCS= dpt_scsi.c dpt.h \ - dpt_pci.c pci_if.h \ - opt_dpt.h \ - opt_cam.h opt_scsi.h \ - device_if.h bus_if.h - -.include