bt.c revision 256893
1139749Simp/*- 239223Sgibbs * Generic driver for the BusLogic MultiMaster SCSI host adapters 339223Sgibbs * Product specific probe and attach routines can be found in: 452052Smdodd * sys/dev/buslogic/bt_isa.c BT-54X, BT-445 cards 552052Smdodd * sys/dev/buslogic/bt_mca.c BT-64X, SDC3211B, SDC3211F 652052Smdodd * sys/dev/buslogic/bt_eisa.c BT-74X, BT-75x cards, SDC3222F 752052Smdodd * sys/dev/buslogic/bt_pci.c BT-946, BT-948, BT-956, BT-958 cards 839223Sgibbs * 944581Sgibbs * Copyright (c) 1998, 1999 Justin T. Gibbs. 1039223Sgibbs * All rights reserved. 1139223Sgibbs * 1239223Sgibbs * Redistribution and use in source and binary forms, with or without 1339223Sgibbs * modification, are permitted provided that the following conditions 1439223Sgibbs * are met: 1539223Sgibbs * 1. Redistributions of source code must retain the above copyright 1639223Sgibbs * notice, this list of conditions, and the following disclaimer, 1739223Sgibbs * without modification, immediately at the beginning of the file. 1839223Sgibbs * 2. The name of the author may not be used to endorse or promote products 1939223Sgibbs * derived from this software without specific prior written permission. 2039223Sgibbs * 2139223Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2239223Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2339223Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2439223Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2539223Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2639223Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2739223Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2839223Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2939223Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3039223Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3139223Sgibbs * SUCH DAMAGE. 3239223Sgibbs */ 3339223Sgibbs 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/buslogic/bt.c 256893 2013-10-22 13:52:20Z mav $"); 36119418Sobrien 3739223Sgibbs /* 3839223Sgibbs * Special thanks to Leonard N. Zubkoff for writing such a complete and 3939223Sgibbs * well documented Mylex/BusLogic MultiMaster driver for Linux. Support 4039223Sgibbs * in this driver for the wide range of MultiMaster controllers and 4139223Sgibbs * firmware revisions, with their otherwise undocumented quirks, would not 4239223Sgibbs * have been possible without his efforts. 4339223Sgibbs */ 4439223Sgibbs 4539223Sgibbs#include <sys/param.h> 46241592Sjhb#include <sys/conf.h> 4739223Sgibbs#include <sys/systm.h> 4839223Sgibbs#include <sys/malloc.h> 4939223Sgibbs#include <sys/kernel.h> 50117126Sscottl#include <sys/lock.h> 51165102Smjacob#include <sys/module.h> 52117126Sscottl#include <sys/mutex.h> 5339223Sgibbs#include <sys/sysctl.h> 5445791Speter#include <sys/bus.h> 5539223Sgibbs 5639223Sgibbs#include <machine/bus.h> 5745791Speter#include <sys/rman.h> 5839223Sgibbs 5939223Sgibbs#include <cam/cam.h> 6039223Sgibbs#include <cam/cam_ccb.h> 6139223Sgibbs#include <cam/cam_sim.h> 6239223Sgibbs#include <cam/cam_xpt_sim.h> 6339223Sgibbs#include <cam/cam_debug.h> 6439223Sgibbs 6539223Sgibbs#include <cam/scsi/scsi_message.h> 6639223Sgibbs 6739223Sgibbs#include <vm/vm.h> 6839223Sgibbs#include <vm/pmap.h> 6939223Sgibbs 7039223Sgibbs#include <dev/buslogic/btreg.h> 7139223Sgibbs 7239223Sgibbs/* MailBox Management functions */ 7339223Sgibbsstatic __inline void btnextinbox(struct bt_softc *bt); 7439223Sgibbsstatic __inline void btnextoutbox(struct bt_softc *bt); 7539223Sgibbs 7639223Sgibbsstatic __inline void 7739223Sgibbsbtnextinbox(struct bt_softc *bt) 7839223Sgibbs{ 7939223Sgibbs if (bt->cur_inbox == bt->last_inbox) 8039223Sgibbs bt->cur_inbox = bt->in_boxes; 8139223Sgibbs else 8239223Sgibbs bt->cur_inbox++; 8339223Sgibbs} 8439223Sgibbs 8539223Sgibbsstatic __inline void 8639223Sgibbsbtnextoutbox(struct bt_softc *bt) 8739223Sgibbs{ 8839223Sgibbs if (bt->cur_outbox == bt->last_outbox) 8939223Sgibbs bt->cur_outbox = bt->out_boxes; 9039223Sgibbs else 9139223Sgibbs bt->cur_outbox++; 9239223Sgibbs} 9339223Sgibbs 9439223Sgibbs/* CCB Mangement functions */ 9539223Sgibbsstatic __inline u_int32_t btccbvtop(struct bt_softc *bt, 9639223Sgibbs struct bt_ccb *bccb); 9739223Sgibbsstatic __inline struct bt_ccb* btccbptov(struct bt_softc *bt, 9839223Sgibbs u_int32_t ccb_addr); 9939223Sgibbsstatic __inline u_int32_t btsensepaddr(struct bt_softc *bt, 10039223Sgibbs struct bt_ccb *bccb); 10139223Sgibbsstatic __inline struct scsi_sense_data* btsensevaddr(struct bt_softc *bt, 10239223Sgibbs struct bt_ccb *bccb); 10339223Sgibbs 10439223Sgibbsstatic __inline u_int32_t 10539223Sgibbsbtccbvtop(struct bt_softc *bt, struct bt_ccb *bccb) 10639223Sgibbs{ 10739223Sgibbs return (bt->bt_ccb_physbase 10839223Sgibbs + (u_int32_t)((caddr_t)bccb - (caddr_t)bt->bt_ccb_array)); 10939223Sgibbs} 11039223Sgibbs 11139223Sgibbsstatic __inline struct bt_ccb * 11239223Sgibbsbtccbptov(struct bt_softc *bt, u_int32_t ccb_addr) 11339223Sgibbs{ 11439223Sgibbs return (bt->bt_ccb_array + 115106521Sjhb ((struct bt_ccb*)(uintptr_t)ccb_addr - (struct bt_ccb*)(uintptr_t)bt->bt_ccb_physbase)); 11639223Sgibbs} 11739223Sgibbs 11839223Sgibbsstatic __inline u_int32_t 11939223Sgibbsbtsensepaddr(struct bt_softc *bt, struct bt_ccb *bccb) 12039223Sgibbs{ 12139223Sgibbs u_int index; 12239223Sgibbs 12339223Sgibbs index = (u_int)(bccb - bt->bt_ccb_array); 12439223Sgibbs return (bt->sense_buffers_physbase 12539223Sgibbs + (index * sizeof(struct scsi_sense_data))); 12639223Sgibbs} 12739223Sgibbs 12839223Sgibbsstatic __inline struct scsi_sense_data * 12939223Sgibbsbtsensevaddr(struct bt_softc *bt, struct bt_ccb *bccb) 13039223Sgibbs{ 13139223Sgibbs u_int index; 13239223Sgibbs 13339223Sgibbs index = (u_int)(bccb - bt->bt_ccb_array); 13439223Sgibbs return (bt->sense_buffers + index); 13539223Sgibbs} 13639223Sgibbs 13739223Sgibbsstatic __inline struct bt_ccb* btgetccb(struct bt_softc *bt); 13839223Sgibbsstatic __inline void btfreeccb(struct bt_softc *bt, 13939223Sgibbs struct bt_ccb *bccb); 14039223Sgibbsstatic void btallocccbs(struct bt_softc *bt); 14139223Sgibbsstatic bus_dmamap_callback_t btexecuteccb; 14239223Sgibbsstatic void btdone(struct bt_softc *bt, struct bt_ccb *bccb, 14339223Sgibbs bt_mbi_comp_code_t comp_code); 144241592Sjhbstatic void bt_intr_locked(struct bt_softc *bt); 14539223Sgibbs 14639223Sgibbs/* Host adapter command functions */ 14739223Sgibbsstatic int btreset(struct bt_softc* bt, int hard_reset); 14839223Sgibbs 14939223Sgibbs/* Initialization functions */ 15039223Sgibbsstatic int btinitmboxes(struct bt_softc *bt); 15139223Sgibbsstatic bus_dmamap_callback_t btmapmboxes; 15239223Sgibbsstatic bus_dmamap_callback_t btmapccbs; 15339223Sgibbsstatic bus_dmamap_callback_t btmapsgs; 15439223Sgibbs 15539223Sgibbs/* Transfer Negotiation Functions */ 15639223Sgibbsstatic void btfetchtransinfo(struct bt_softc *bt, 15739223Sgibbs struct ccb_trans_settings *cts); 15839223Sgibbs 15939223Sgibbs/* CAM SIM entry points */ 16039223Sgibbs#define ccb_bccb_ptr spriv_ptr0 16139223Sgibbs#define ccb_bt_ptr spriv_ptr1 16239223Sgibbsstatic void btaction(struct cam_sim *sim, union ccb *ccb); 16339223Sgibbsstatic void btpoll(struct cam_sim *sim); 16439223Sgibbs 16539223Sgibbs/* Our timeout handler */ 166241592Sjhbstatic void bttimeout(void *arg); 16739223Sgibbs 16839223Sgibbs/* 16939223Sgibbs * XXX 17039223Sgibbs * Do our own re-probe protection until a configuration 17139223Sgibbs * manager can do it for us. This ensures that we don't 17239223Sgibbs * reprobe a card already found by the EISA or PCI probes. 17339223Sgibbs */ 17439223Sgibbsstruct bt_isa_port bt_isa_ports[] = 17539223Sgibbs{ 17641048Sgibbs { 0x130, 0, 4 }, 17741048Sgibbs { 0x134, 0, 5 }, 17841048Sgibbs { 0x230, 0, 2 }, 17941048Sgibbs { 0x234, 0, 3 }, 18041048Sgibbs { 0x330, 0, 0 }, 18141048Sgibbs { 0x334, 0, 1 } 18239223Sgibbs}; 18339223Sgibbs 18441048Sgibbs/* 18541048Sgibbs * I/O ports listed in the order enumerated by the 18641048Sgibbs * card for certain op codes. 18741048Sgibbs */ 18841048Sgibbsu_int16_t bt_board_ports[] = 18941048Sgibbs{ 19041048Sgibbs 0x330, 19141048Sgibbs 0x334, 19241048Sgibbs 0x230, 19341048Sgibbs 0x234, 19441048Sgibbs 0x130, 19541048Sgibbs 0x134 19641048Sgibbs}; 19741048Sgibbs 19839223Sgibbs/* Exported functions */ 19945791Spetervoid 20045791Speterbt_init_softc(device_t dev, struct resource *port, 20145791Speter struct resource *irq, struct resource *drq) 20239223Sgibbs{ 20345791Speter struct bt_softc *bt = device_get_softc(dev); 20439223Sgibbs 20539223Sgibbs SLIST_INIT(&bt->free_bt_ccbs); 20639223Sgibbs LIST_INIT(&bt->pending_ccbs); 20739223Sgibbs SLIST_INIT(&bt->sg_maps); 20845791Speter bt->dev = dev; 20945791Speter bt->port = port; 21045791Speter bt->irq = irq; 21145791Speter bt->drq = drq; 212241592Sjhb mtx_init(&bt->lock, "bt", NULL, MTX_DEF); 21339223Sgibbs} 21439223Sgibbs 21539223Sgibbsvoid 21645791Speterbt_free_softc(device_t dev) 21739223Sgibbs{ 21845791Speter struct bt_softc *bt = device_get_softc(dev); 21945791Speter 22039223Sgibbs switch (bt->init_level) { 22139223Sgibbs default: 22239223Sgibbs case 11: 22339223Sgibbs bus_dmamap_unload(bt->sense_dmat, bt->sense_dmamap); 22439223Sgibbs case 10: 22539223Sgibbs bus_dmamem_free(bt->sense_dmat, bt->sense_buffers, 22639223Sgibbs bt->sense_dmamap); 22739223Sgibbs case 9: 22839223Sgibbs bus_dma_tag_destroy(bt->sense_dmat); 22939223Sgibbs case 8: 23039223Sgibbs { 23139223Sgibbs struct sg_map_node *sg_map; 23239223Sgibbs 23339223Sgibbs while ((sg_map = SLIST_FIRST(&bt->sg_maps))!= NULL) { 23439223Sgibbs SLIST_REMOVE_HEAD(&bt->sg_maps, links); 23539223Sgibbs bus_dmamap_unload(bt->sg_dmat, 23639223Sgibbs sg_map->sg_dmamap); 23739223Sgibbs bus_dmamem_free(bt->sg_dmat, sg_map->sg_vaddr, 23839223Sgibbs sg_map->sg_dmamap); 23939223Sgibbs free(sg_map, M_DEVBUF); 24039223Sgibbs } 24139223Sgibbs bus_dma_tag_destroy(bt->sg_dmat); 24239223Sgibbs } 24339223Sgibbs case 7: 24439223Sgibbs bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap); 245115555Sphk /* FALLTHROUGH */ 24639223Sgibbs case 6: 24739223Sgibbs bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array, 24839223Sgibbs bt->ccb_dmamap); 24939223Sgibbs bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap); 250115555Sphk /* FALLTHROUGH */ 25139223Sgibbs case 5: 25239223Sgibbs bus_dma_tag_destroy(bt->ccb_dmat); 253115555Sphk /* FALLTHROUGH */ 25439223Sgibbs case 4: 25539223Sgibbs bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap); 256115555Sphk /* FALLTHROUGH */ 25739223Sgibbs case 3: 25839223Sgibbs bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes, 25939223Sgibbs bt->mailbox_dmamap); 26039223Sgibbs bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap); 261115555Sphk /* FALLTHROUGH */ 26239223Sgibbs case 2: 26339223Sgibbs bus_dma_tag_destroy(bt->buffer_dmat); 264115555Sphk /* FALLTHROUGH */ 26539223Sgibbs case 1: 26639223Sgibbs bus_dma_tag_destroy(bt->mailbox_dmat); 267115555Sphk /* FALLTHROUGH */ 26839223Sgibbs case 0: 26939223Sgibbs break; 27039223Sgibbs } 271241592Sjhb mtx_destroy(&bt->lock); 27239223Sgibbs} 27339223Sgibbs 27444581Sgibbsint 27545791Speterbt_port_probe(device_t dev, struct bt_probe_info *info) 27644581Sgibbs{ 27745791Speter struct bt_softc *bt = device_get_softc(dev); 27844581Sgibbs config_data_t config_data; 27944581Sgibbs int error; 28044581Sgibbs 28144581Sgibbs /* See if there is really a card present */ 28245791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev)) 28344581Sgibbs return(1); 28444581Sgibbs 28544581Sgibbs /* 28644581Sgibbs * Determine our IRQ, and DMA settings and 28744581Sgibbs * export them to the configuration system. 28844581Sgibbs */ 289241592Sjhb mtx_lock(&bt->lock); 29044581Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 29144581Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 29244581Sgibbs DEFAULT_CMD_TIMEOUT); 293241592Sjhb mtx_unlock(&bt->lock); 29444581Sgibbs if (error != 0) { 29544581Sgibbs printf("bt_port_probe: Could not determine IRQ or DMA " 29644581Sgibbs "settings for adapter.\n"); 29744581Sgibbs return (1); 29844581Sgibbs } 29944581Sgibbs 30044581Sgibbs if (bt->model[0] == '5') { 30144581Sgibbs /* DMA settings only make sense for ISA cards */ 30244581Sgibbs switch (config_data.dma_chan) { 30344581Sgibbs case DMA_CHAN_5: 30444581Sgibbs info->drq = 5; 30544581Sgibbs break; 30644581Sgibbs case DMA_CHAN_6: 30744581Sgibbs info->drq = 6; 30844581Sgibbs break; 30944581Sgibbs case DMA_CHAN_7: 31044581Sgibbs info->drq = 7; 31144581Sgibbs break; 31244581Sgibbs default: 31344581Sgibbs printf("bt_port_probe: Invalid DMA setting " 31444581Sgibbs "detected for adapter.\n"); 31544581Sgibbs return (1); 31644581Sgibbs } 31744581Sgibbs } else { 31844581Sgibbs /* VL/EISA/PCI DMA */ 31944581Sgibbs info->drq = -1; 32044581Sgibbs } 32144581Sgibbs switch (config_data.irq) { 32244581Sgibbs case IRQ_9: 32344581Sgibbs case IRQ_10: 32444581Sgibbs case IRQ_11: 32544581Sgibbs case IRQ_12: 32644581Sgibbs case IRQ_14: 32744581Sgibbs case IRQ_15: 32844581Sgibbs info->irq = ffs(config_data.irq) + 8; 32944581Sgibbs break; 33044581Sgibbs default: 33144581Sgibbs printf("bt_port_probe: Invalid IRQ setting %x" 33244581Sgibbs "detected for adapter.\n", config_data.irq); 33344581Sgibbs return (1); 33444581Sgibbs } 33544581Sgibbs return (0); 33644581Sgibbs} 33744581Sgibbs 33839223Sgibbs/* 33939223Sgibbs * Probe the adapter and verify that the card is a BusLogic. 34039223Sgibbs */ 34139223Sgibbsint 34245791Speterbt_probe(device_t dev) 34339223Sgibbs{ 34445791Speter struct bt_softc *bt = device_get_softc(dev); 34539223Sgibbs esetup_info_data_t esetup_info; 34639223Sgibbs u_int status; 34739223Sgibbs u_int intstat; 34839223Sgibbs u_int geometry; 34939223Sgibbs int error; 35039223Sgibbs u_int8_t param; 35139223Sgibbs 35239223Sgibbs /* 35339223Sgibbs * See if the three I/O ports look reasonable. 35439223Sgibbs * Touch the minimal number of registers in the 35539223Sgibbs * failure case. 35639223Sgibbs */ 35739223Sgibbs status = bt_inb(bt, STATUS_REG); 35839223Sgibbs if ((status == 0) 35939223Sgibbs || (status & (DIAG_ACTIVE|CMD_REG_BUSY| 36039223Sgibbs STATUS_REG_RSVD|CMD_INVALID)) != 0) { 36139223Sgibbs if (bootverbose) 36245791Speter device_printf(dev, "Failed Status Reg Test - %x\n", 36339223Sgibbs status); 36439223Sgibbs return (ENXIO); 36539223Sgibbs } 36639223Sgibbs 36739223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 36839223Sgibbs if ((intstat & INTSTAT_REG_RSVD) != 0) { 36945791Speter device_printf(dev, "Failed Intstat Reg Test\n"); 37039223Sgibbs return (ENXIO); 37139223Sgibbs } 37239223Sgibbs 37339223Sgibbs geometry = bt_inb(bt, GEOMETRY_REG); 37439223Sgibbs if (geometry == 0xFF) { 37539223Sgibbs if (bootverbose) 37645791Speter device_printf(dev, "Failed Geometry Reg Test\n"); 37739223Sgibbs return (ENXIO); 37839223Sgibbs } 37939223Sgibbs 38039223Sgibbs /* 38139223Sgibbs * Looking good so far. Final test is to reset the 38239223Sgibbs * adapter and attempt to fetch the extended setup 38339223Sgibbs * information. This should filter out all 1542 cards. 38439223Sgibbs */ 385241592Sjhb mtx_lock(&bt->lock); 38639223Sgibbs if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) { 387241592Sjhb mtx_unlock(&bt->lock); 38839223Sgibbs if (bootverbose) 38945791Speter device_printf(dev, "Failed Reset\n"); 39039223Sgibbs return (ENXIO); 39139223Sgibbs } 39239223Sgibbs 39339223Sgibbs param = sizeof(esetup_info); 39439223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, ¶m, /*parmlen*/1, 39539223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 39639223Sgibbs DEFAULT_CMD_TIMEOUT); 397241592Sjhb mtx_unlock(&bt->lock); 39839223Sgibbs if (error != 0) { 39939223Sgibbs return (ENXIO); 40039223Sgibbs } 40139223Sgibbs 40239223Sgibbs return (0); 40339223Sgibbs} 40439223Sgibbs 40539223Sgibbs/* 40639223Sgibbs * Pull the boards setup information and record it in our softc. 40739223Sgibbs */ 40839223Sgibbsint 40945791Speterbt_fetch_adapter_info(device_t dev) 41039223Sgibbs{ 41145791Speter struct bt_softc *bt = device_get_softc(dev); 41239223Sgibbs board_id_data_t board_id; 41339223Sgibbs esetup_info_data_t esetup_info; 41439223Sgibbs config_data_t config_data; 41539223Sgibbs int error; 41639223Sgibbs u_int8_t length_param; 41739223Sgibbs 41839223Sgibbs /* First record the firmware version */ 419241592Sjhb mtx_lock(&bt->lock); 42039223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0, 42139223Sgibbs (u_int8_t*)&board_id, sizeof(board_id), 42239223Sgibbs DEFAULT_CMD_TIMEOUT); 42339223Sgibbs if (error != 0) { 424241592Sjhb mtx_unlock(&bt->lock); 42545791Speter device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n"); 42639223Sgibbs return (error); 42739223Sgibbs } 42839223Sgibbs bt->firmware_ver[0] = board_id.firmware_rev_major; 42939223Sgibbs bt->firmware_ver[1] = '.'; 43039223Sgibbs bt->firmware_ver[2] = board_id.firmware_rev_minor; 43139223Sgibbs bt->firmware_ver[3] = '\0'; 43239223Sgibbs 43339223Sgibbs /* 43439223Sgibbs * Depending on the firmware major and minor version, 43539223Sgibbs * we may be able to fetch additional minor version info. 43639223Sgibbs */ 43739223Sgibbs if (bt->firmware_ver[0] > '0') { 43839223Sgibbs 43939223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0, 44039223Sgibbs (u_int8_t*)&bt->firmware_ver[3], 1, 44139223Sgibbs DEFAULT_CMD_TIMEOUT); 44239223Sgibbs if (error != 0) { 443241592Sjhb mtx_unlock(&bt->lock); 44445791Speter device_printf(dev, 44545791Speter "bt_fetch_adapter_info - Failed Get " 44645791Speter "Firmware 3rd Digit\n"); 44739223Sgibbs return (error); 44839223Sgibbs } 44939223Sgibbs if (bt->firmware_ver[3] == ' ') 45039223Sgibbs bt->firmware_ver[3] = '\0'; 45139223Sgibbs bt->firmware_ver[4] = '\0'; 45239223Sgibbs } 45339223Sgibbs 45439223Sgibbs if (strcmp(bt->firmware_ver, "3.3") >= 0) { 45539223Sgibbs 45639223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_4DIG, NULL, /*parmlen*/0, 45739223Sgibbs (u_int8_t*)&bt->firmware_ver[4], 1, 45839223Sgibbs DEFAULT_CMD_TIMEOUT); 45939223Sgibbs if (error != 0) { 460241592Sjhb mtx_unlock(&bt->lock); 46145791Speter device_printf(dev, 46245791Speter "bt_fetch_adapter_info - Failed Get " 46345791Speter "Firmware 4th Digit\n"); 46439223Sgibbs return (error); 46539223Sgibbs } 46639223Sgibbs if (bt->firmware_ver[4] == ' ') 46739223Sgibbs bt->firmware_ver[4] = '\0'; 46839223Sgibbs bt->firmware_ver[5] = '\0'; 46939223Sgibbs } 47039223Sgibbs 47139223Sgibbs /* 47239223Sgibbs * Some boards do not handle the "recently documented" 47339223Sgibbs * Inquire Board Model Number command correctly or do not give 47439223Sgibbs * exact information. Use the Firmware and Extended Setup 47539223Sgibbs * information in these cases to come up with the right answer. 47639223Sgibbs * The major firmware revision number indicates: 47739223Sgibbs * 47839223Sgibbs * 5.xx BusLogic "W" Series Host Adapters: 47939223Sgibbs * BT-948/958/958D 48039223Sgibbs * 4.xx BusLogic "C" Series Host Adapters: 48139223Sgibbs * BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF 48239223Sgibbs * 3.xx BusLogic "S" Series Host Adapters: 48339223Sgibbs * BT-747S/747D/757S/757D/445S/545S/542D 48439223Sgibbs * BT-542B/742A (revision H) 48539223Sgibbs * 2.xx BusLogic "A" Series Host Adapters: 48639223Sgibbs * BT-542B/742A (revision G and below) 48739223Sgibbs * 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter 48839223Sgibbs */ 48939223Sgibbs length_param = sizeof(esetup_info); 49039223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &length_param, /*parmlen*/1, 49139223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 49239223Sgibbs DEFAULT_CMD_TIMEOUT); 49339223Sgibbs if (error != 0) { 494241592Sjhb mtx_unlock(&bt->lock); 49539223Sgibbs return (error); 49639223Sgibbs } 49739223Sgibbs 49839223Sgibbs bt->bios_addr = esetup_info.bios_addr << 12; 49939223Sgibbs 50068661Sgibbs bt->mailbox_addrlimit = BUS_SPACE_MAXADDR; 50139223Sgibbs if (esetup_info.bus_type == 'A' 50239223Sgibbs && bt->firmware_ver[0] == '2') { 50341514Sarchie snprintf(bt->model, sizeof(bt->model), "542B"); 50439223Sgibbs } else if (esetup_info.bus_type == 'E' 50568661Sgibbs && bt->firmware_ver[0] == '2') { 50668661Sgibbs 50768661Sgibbs /* 50868661Sgibbs * The 742A seems to object if its mailboxes are 50968661Sgibbs * allocated above the 16MB mark. 51068661Sgibbs */ 51168661Sgibbs bt->mailbox_addrlimit = BUS_SPACE_MAXADDR_24BIT; 51241514Sarchie snprintf(bt->model, sizeof(bt->model), "742A"); 51339223Sgibbs } else if (esetup_info.bus_type == 'E' 51439223Sgibbs && bt->firmware_ver[0] == '0') { 51539223Sgibbs /* AMI FastDisk EISA Series 441 0.x */ 51641514Sarchie snprintf(bt->model, sizeof(bt->model), "747A"); 51739223Sgibbs } else { 51839223Sgibbs ha_model_data_t model_data; 51939223Sgibbs int i; 52039223Sgibbs 52139223Sgibbs length_param = sizeof(model_data); 52239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1, 52339223Sgibbs (u_int8_t*)&model_data, sizeof(model_data), 52439223Sgibbs DEFAULT_CMD_TIMEOUT); 52539223Sgibbs if (error != 0) { 526241592Sjhb mtx_unlock(&bt->lock); 52745791Speter device_printf(dev, 52845791Speter "bt_fetch_adapter_info - Failed Inquire " 52945791Speter "Model Number\n"); 53039223Sgibbs return (error); 53139223Sgibbs } 53239223Sgibbs for (i = 0; i < sizeof(model_data.ascii_model); i++) { 53339223Sgibbs bt->model[i] = model_data.ascii_model[i]; 53439223Sgibbs if (bt->model[i] == ' ') 53539223Sgibbs break; 53639223Sgibbs } 53739223Sgibbs bt->model[i] = '\0'; 53839223Sgibbs } 53939223Sgibbs 54044581Sgibbs bt->level_trigger_ints = esetup_info.level_trigger_ints ? 1 : 0; 54144581Sgibbs 54239223Sgibbs /* SG element limits */ 54339223Sgibbs bt->max_sg = esetup_info.max_sg; 54439223Sgibbs 54539223Sgibbs /* Set feature flags */ 54639223Sgibbs bt->wide_bus = esetup_info.wide_bus; 54739223Sgibbs bt->diff_bus = esetup_info.diff_bus; 54839223Sgibbs bt->ultra_scsi = esetup_info.ultra_scsi; 54939223Sgibbs 55039223Sgibbs if ((bt->firmware_ver[0] == '5') 55139223Sgibbs || (bt->firmware_ver[0] == '4' && bt->wide_bus)) 55239223Sgibbs bt->extended_lun = TRUE; 55339223Sgibbs 55439223Sgibbs bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0); 55539223Sgibbs 55639223Sgibbs bt->extended_trans = 55739223Sgibbs ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0); 55839223Sgibbs 55939223Sgibbs /* 56039223Sgibbs * Determine max CCB count and whether tagged queuing is 56139223Sgibbs * available based on controller type. Tagged queuing 56239223Sgibbs * only works on 'W' series adapters, 'C' series adapters 56339223Sgibbs * with firmware of rev 4.42 and higher, and 'S' series 56439223Sgibbs * adapters with firmware of rev 3.35 and higher. The 56539223Sgibbs * maximum CCB counts are as follows: 56639223Sgibbs * 56739223Sgibbs * 192 BT-948/958/958D 56839223Sgibbs * 100 BT-946C/956C/956CD/747C/757C/757CD/445C 56939223Sgibbs * 50 BT-545C/540CF 57039223Sgibbs * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A 57139223Sgibbs */ 57239223Sgibbs if (bt->firmware_ver[0] == '5') { 57339223Sgibbs bt->max_ccbs = 192; 57439223Sgibbs bt->tag_capable = TRUE; 57539223Sgibbs } else if (bt->firmware_ver[0] == '4') { 57639223Sgibbs if (bt->model[0] == '5') 57739223Sgibbs bt->max_ccbs = 50; 57839223Sgibbs else 57939223Sgibbs bt->max_ccbs = 100; 58039223Sgibbs bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0); 58139223Sgibbs } else { 58239223Sgibbs bt->max_ccbs = 30; 58339223Sgibbs if (bt->firmware_ver[0] == '3' 58439223Sgibbs && (strcmp(bt->firmware_ver, "3.35") >= 0)) 58539223Sgibbs bt->tag_capable = TRUE; 58639223Sgibbs else 58739223Sgibbs bt->tag_capable = FALSE; 58839223Sgibbs } 58939223Sgibbs 59039223Sgibbs if (bt->tag_capable != FALSE) 59139223Sgibbs bt->tags_permitted = ALL_TARGETS; 59239223Sgibbs 59339223Sgibbs /* Determine Sync/Wide/Disc settings */ 59439223Sgibbs if (bt->firmware_ver[0] >= '4') { 59539223Sgibbs auto_scsi_data_t auto_scsi_data; 59639223Sgibbs fetch_lram_params_t fetch_lram_params; 59739223Sgibbs int error; 59839223Sgibbs 59939223Sgibbs /* 60039223Sgibbs * These settings are stored in the 60139223Sgibbs * AutoSCSI data in LRAM of 'W' and 'C' 60239223Sgibbs * adapters. 60339223Sgibbs */ 60439223Sgibbs fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET; 60539223Sgibbs fetch_lram_params.response_len = sizeof(auto_scsi_data); 60639223Sgibbs error = bt_cmd(bt, BOP_FETCH_LRAM, 60739223Sgibbs (u_int8_t*)&fetch_lram_params, 60839223Sgibbs sizeof(fetch_lram_params), 60939223Sgibbs (u_int8_t*)&auto_scsi_data, 61039223Sgibbs sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT); 61139223Sgibbs 61239223Sgibbs if (error != 0) { 613241592Sjhb mtx_unlock(&bt->lock); 61445791Speter device_printf(dev, 61545791Speter "bt_fetch_adapter_info - Failed " 61645791Speter "Get Auto SCSI Info\n"); 61739223Sgibbs return (error); 61839223Sgibbs } 61939223Sgibbs 62039223Sgibbs bt->disc_permitted = auto_scsi_data.low_disc_permitted 62139223Sgibbs | (auto_scsi_data.high_disc_permitted << 8); 62239223Sgibbs bt->sync_permitted = auto_scsi_data.low_sync_permitted 62339223Sgibbs | (auto_scsi_data.high_sync_permitted << 8); 62439223Sgibbs bt->fast_permitted = auto_scsi_data.low_fast_permitted 62539223Sgibbs | (auto_scsi_data.high_fast_permitted << 8); 62639223Sgibbs bt->ultra_permitted = auto_scsi_data.low_ultra_permitted 62739223Sgibbs | (auto_scsi_data.high_ultra_permitted << 8); 62839223Sgibbs bt->wide_permitted = auto_scsi_data.low_wide_permitted 62939223Sgibbs | (auto_scsi_data.high_wide_permitted << 8); 63039223Sgibbs 63139223Sgibbs if (bt->ultra_scsi == FALSE) 63239223Sgibbs bt->ultra_permitted = 0; 63339223Sgibbs 63439223Sgibbs if (bt->wide_bus == FALSE) 63539223Sgibbs bt->wide_permitted = 0; 63639223Sgibbs } else { 63739223Sgibbs /* 63839223Sgibbs * 'S' and 'A' series have this information in the setup 63939223Sgibbs * information structure. 64039223Sgibbs */ 64139223Sgibbs setup_data_t setup_info; 64239223Sgibbs 64339223Sgibbs length_param = sizeof(setup_info); 64439223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param, 64539223Sgibbs /*paramlen*/1, (u_int8_t*)&setup_info, 64639223Sgibbs sizeof(setup_info), DEFAULT_CMD_TIMEOUT); 64739223Sgibbs 64839223Sgibbs if (error != 0) { 649241592Sjhb mtx_unlock(&bt->lock); 65045791Speter device_printf(dev, 65145791Speter "bt_fetch_adapter_info - Failed " 65245791Speter "Get Setup Info\n"); 65339223Sgibbs return (error); 65439223Sgibbs } 65539223Sgibbs 65639223Sgibbs if (setup_info.initiate_sync != 0) { 65739223Sgibbs bt->sync_permitted = ALL_TARGETS; 65839223Sgibbs 65939223Sgibbs if (bt->model[0] == '7') { 66039223Sgibbs if (esetup_info.sync_neg10MB != 0) 66139223Sgibbs bt->fast_permitted = ALL_TARGETS; 66239223Sgibbs if (strcmp(bt->model, "757") == 0) 66339223Sgibbs bt->wide_permitted = ALL_TARGETS; 66439223Sgibbs } 66539223Sgibbs } 66639223Sgibbs bt->disc_permitted = ALL_TARGETS; 66739223Sgibbs } 66839223Sgibbs 66939223Sgibbs /* We need as many mailboxes as we can have ccbs */ 67039223Sgibbs bt->num_boxes = bt->max_ccbs; 67139223Sgibbs 67239223Sgibbs /* Determine our SCSI ID */ 67339223Sgibbs 67439223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 67539223Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 67639223Sgibbs DEFAULT_CMD_TIMEOUT); 677241592Sjhb mtx_unlock(&bt->lock); 67839223Sgibbs if (error != 0) { 67945791Speter device_printf(dev, 68045791Speter "bt_fetch_adapter_info - Failed Get Config\n"); 68139223Sgibbs return (error); 68239223Sgibbs } 68339223Sgibbs bt->scsi_id = config_data.scsi_id; 68439223Sgibbs 68539223Sgibbs return (0); 68639223Sgibbs} 68739223Sgibbs 68839223Sgibbs/* 68939223Sgibbs * Start the board, ready for normal operation 69039223Sgibbs */ 69139223Sgibbsint 69245791Speterbt_init(device_t dev) 69339223Sgibbs{ 69445791Speter struct bt_softc *bt = device_get_softc(dev); 69545791Speter 69639223Sgibbs /* Announce the Adapter */ 69745791Speter device_printf(dev, "BT-%s FW Rev. %s ", bt->model, bt->firmware_ver); 69839223Sgibbs 69939223Sgibbs if (bt->ultra_scsi != 0) 70039223Sgibbs printf("Ultra "); 70139223Sgibbs 70239223Sgibbs if (bt->wide_bus != 0) 70339223Sgibbs printf("Wide "); 70439223Sgibbs else 70539223Sgibbs printf("Narrow "); 70639223Sgibbs 70739223Sgibbs if (bt->diff_bus != 0) 70839223Sgibbs printf("Diff "); 70939223Sgibbs 71039223Sgibbs printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id, 71139223Sgibbs bt->max_ccbs); 71239223Sgibbs 71339223Sgibbs /* 71439223Sgibbs * Create our DMA tags. These tags define the kinds of device 71561686Salex * accessible memory allocations and memory mappings we will 71639223Sgibbs * need to perform during normal operation. 71739223Sgibbs * 71839223Sgibbs * Unless we need to further restrict the allocation, we rely 71939223Sgibbs * on the restrictions of the parent dmat, hence the common 72039223Sgibbs * use of MAXADDR and MAXSIZE. 72139223Sgibbs */ 72239223Sgibbs 72339223Sgibbs /* DMA tag for mapping buffers into device visible space. */ 724112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 725112782Smdodd /* alignment */ 1, 726112782Smdodd /* boundary */ 0, 727112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 728112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 729112782Smdodd /* filter */ NULL, 730112782Smdodd /* filterarg */ NULL, 731112782Smdodd /* maxsize */ MAXBSIZE, 732112782Smdodd /* nsegments */ BT_NSEG, 733112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 734112782Smdodd /* flags */ BUS_DMA_ALLOCNOW, 735117126Sscottl /* lockfunc */ busdma_lock_mutex, 736241592Sjhb /* lockarg */ &bt->lock, 737112782Smdodd &bt->buffer_dmat) != 0) { 73839223Sgibbs goto error_exit; 73939223Sgibbs } 74039223Sgibbs 74139223Sgibbs bt->init_level++; 74239223Sgibbs /* DMA tag for our mailboxes */ 743112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 744112782Smdodd /* alignment */ 1, 745112782Smdodd /* boundary */ 0, 746112782Smdodd /* lowaddr */ bt->mailbox_addrlimit, 747112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 748112782Smdodd /* filter */ NULL, 749112782Smdodd /* filterarg */ NULL, 750112782Smdodd /* maxsize */ bt->num_boxes * 751112782Smdodd (sizeof(bt_mbox_in_t) + 752112782Smdodd sizeof(bt_mbox_out_t)), 753112782Smdodd /* nsegments */ 1, 754112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 755112782Smdodd /* flags */ 0, 756241592Sjhb /* lockfunc */ NULL, 757241592Sjhb /* lockarg */ NULL, 758112782Smdodd &bt->mailbox_dmat) != 0) { 75939223Sgibbs goto error_exit; 76039223Sgibbs } 76139223Sgibbs 76239223Sgibbs bt->init_level++; 76339223Sgibbs 76439223Sgibbs /* Allocation for our mailboxes */ 76539223Sgibbs if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes, 76639223Sgibbs BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) { 76739223Sgibbs goto error_exit; 76839223Sgibbs } 76939223Sgibbs 77039223Sgibbs bt->init_level++; 77139223Sgibbs 77239223Sgibbs /* And permanently map them */ 77339223Sgibbs bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap, 77439223Sgibbs bt->out_boxes, 77539223Sgibbs bt->num_boxes * (sizeof(bt_mbox_in_t) 77639223Sgibbs + sizeof(bt_mbox_out_t)), 77739223Sgibbs btmapmboxes, bt, /*flags*/0); 77839223Sgibbs 77939223Sgibbs bt->init_level++; 78039223Sgibbs 78139223Sgibbs bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes]; 78239223Sgibbs 783241592Sjhb mtx_lock(&bt->lock); 78439223Sgibbs btinitmboxes(bt); 785241592Sjhb mtx_unlock(&bt->lock); 78639223Sgibbs 78739223Sgibbs /* DMA tag for our ccb structures */ 788112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 789112782Smdodd /* alignment */ 1, 790112782Smdodd /* boundary */ 0, 791112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 792112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 793112782Smdodd /* filter */ NULL, 794112782Smdodd /* filterarg */ NULL, 795112782Smdodd /* maxsize */ bt->max_ccbs * 796112782Smdodd sizeof(struct bt_ccb), 797112782Smdodd /* nsegments */ 1, 798112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 799112782Smdodd /* flags */ 0, 800241592Sjhb /* lockfunc */ NULL, 801241592Sjhb /* lockarg */ NULL, 802112782Smdodd &bt->ccb_dmat) != 0) { 80339223Sgibbs goto error_exit; 80439223Sgibbs } 80539223Sgibbs 80639223Sgibbs bt->init_level++; 80739223Sgibbs 80839223Sgibbs /* Allocation for our ccbs */ 80939223Sgibbs if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array, 81039223Sgibbs BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) { 81139223Sgibbs goto error_exit; 81239223Sgibbs } 81339223Sgibbs 81439223Sgibbs bt->init_level++; 81539223Sgibbs 81639223Sgibbs /* And permanently map them */ 81739223Sgibbs bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap, 81839223Sgibbs bt->bt_ccb_array, 81939223Sgibbs bt->max_ccbs * sizeof(struct bt_ccb), 82039223Sgibbs btmapccbs, bt, /*flags*/0); 82139223Sgibbs 82239223Sgibbs bt->init_level++; 82339223Sgibbs 82439223Sgibbs /* DMA tag for our S/G structures. We allocate in page sized chunks */ 825112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 826112782Smdodd /* alignment */ 1, 827112782Smdodd /* boundary */ 0, 828112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 829112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 830112782Smdodd /* filter */ NULL, 831112782Smdodd /* filterarg */ NULL, 832112782Smdodd /* maxsize */ PAGE_SIZE, 833112782Smdodd /* nsegments */ 1, 834112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 835112782Smdodd /* flags */ 0, 836241592Sjhb /* lockfunc */ NULL, 837241592Sjhb /* lockarg */ NULL, 838112782Smdodd &bt->sg_dmat) != 0) { 83939223Sgibbs goto error_exit; 84039223Sgibbs } 84139223Sgibbs 84239223Sgibbs bt->init_level++; 84339223Sgibbs 84439223Sgibbs /* Perform initial CCB allocation */ 84539223Sgibbs bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb)); 84639223Sgibbs btallocccbs(bt); 84739223Sgibbs 84839223Sgibbs if (bt->num_ccbs == 0) { 84945791Speter device_printf(dev, 85045791Speter "bt_init - Unable to allocate initial ccbs\n"); 85139223Sgibbs goto error_exit; 85239223Sgibbs } 85339223Sgibbs 85439223Sgibbs /* 855241592Sjhb * Note that we are going and return (to attach) 85639223Sgibbs */ 85739223Sgibbs return 0; 85839223Sgibbs 85939223Sgibbserror_exit: 86039223Sgibbs 86139223Sgibbs return (ENXIO); 86239223Sgibbs} 86339223Sgibbs 86439223Sgibbsint 86545791Speterbt_attach(device_t dev) 86639223Sgibbs{ 86745791Speter struct bt_softc *bt = device_get_softc(dev); 86839223Sgibbs int tagged_dev_openings; 86939223Sgibbs struct cam_devq *devq; 87045795Speter int error; 87139223Sgibbs 87239223Sgibbs /* 87339223Sgibbs * We reserve 1 ccb for error recovery, so don't 87439223Sgibbs * tell the XPT about it. 87539223Sgibbs */ 87639223Sgibbs if (bt->tag_capable != 0) 87739223Sgibbs tagged_dev_openings = bt->max_ccbs - 1; 87839223Sgibbs else 87939223Sgibbs tagged_dev_openings = 0; 88039223Sgibbs 88139223Sgibbs /* 88239223Sgibbs * Create the device queue for our SIM. 88339223Sgibbs */ 88439223Sgibbs devq = cam_simq_alloc(bt->max_ccbs - 1); 88539223Sgibbs if (devq == NULL) 88639223Sgibbs return (ENOMEM); 88739223Sgibbs 88839223Sgibbs /* 88939223Sgibbs * Construct our SIM entry 89039223Sgibbs */ 891241592Sjhb bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, 892241592Sjhb device_get_unit(bt->dev), &bt->lock, 2, tagged_dev_openings, devq); 89339223Sgibbs if (bt->sim == NULL) { 89439223Sgibbs cam_simq_free(devq); 89539223Sgibbs return (ENOMEM); 89639223Sgibbs } 897241592Sjhb 898241592Sjhb mtx_lock(&bt->lock); 899170872Sscottl if (xpt_bus_register(bt->sim, dev, 0) != CAM_SUCCESS) { 90039223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 901241592Sjhb mtx_unlock(&bt->lock); 90239223Sgibbs return (ENXIO); 90339223Sgibbs } 90439223Sgibbs 90539223Sgibbs if (xpt_create_path(&bt->path, /*periph*/NULL, 90639223Sgibbs cam_sim_path(bt->sim), CAM_TARGET_WILDCARD, 90739223Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 90839223Sgibbs xpt_bus_deregister(cam_sim_path(bt->sim)); 90939223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 910241592Sjhb mtx_unlock(&bt->lock); 91139223Sgibbs return (ENXIO); 91239223Sgibbs } 913241592Sjhb mtx_unlock(&bt->lock); 91439223Sgibbs 91545791Speter /* 91645791Speter * Setup interrupt. 91745791Speter */ 918241592Sjhb error = bus_setup_intr(dev, bt->irq, INTR_TYPE_CAM | INTR_ENTROPY | 919241592Sjhb INTR_MPSAFE, NULL, bt_intr, bt, &bt->ih); 92045795Speter if (error) { 92145795Speter device_printf(dev, "bus_setup_intr() failed: %d\n", error); 92245795Speter return (error); 92345795Speter } 92445791Speter 92539223Sgibbs return (0); 92639223Sgibbs} 92739223Sgibbs 92839223Sgibbsint 92939223Sgibbsbt_check_probed_iop(u_int ioport) 93039223Sgibbs{ 93139223Sgibbs u_int i; 93239223Sgibbs 93341048Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 93439223Sgibbs if (bt_isa_ports[i].addr == ioport) { 93539223Sgibbs if (bt_isa_ports[i].probed != 0) 93639223Sgibbs return (1); 93739223Sgibbs else { 93839223Sgibbs return (0); 93939223Sgibbs } 94039223Sgibbs } 94139223Sgibbs } 94239223Sgibbs return (1); 94339223Sgibbs} 94439223Sgibbs 94539223Sgibbsvoid 94639223Sgibbsbt_mark_probed_bio(isa_compat_io_t port) 94739223Sgibbs{ 94839223Sgibbs if (port < BIO_DISABLED) 94941048Sgibbs bt_mark_probed_iop(bt_board_ports[port]); 95039223Sgibbs} 95139223Sgibbs 95239223Sgibbsvoid 95339223Sgibbsbt_mark_probed_iop(u_int ioport) 95439223Sgibbs{ 95539223Sgibbs u_int i; 95639223Sgibbs 95739223Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 95839223Sgibbs if (ioport == bt_isa_ports[i].addr) { 95939223Sgibbs bt_isa_ports[i].probed = 1; 96039223Sgibbs break; 96139223Sgibbs } 96239223Sgibbs } 96339223Sgibbs} 96439223Sgibbs 96541048Sgibbsvoid 96641048Sgibbsbt_find_probe_range(int ioport, int *port_index, int *max_port_index) 96741048Sgibbs{ 96841048Sgibbs if (ioport > 0) { 96941048Sgibbs int i; 97041048Sgibbs 97141048Sgibbs for (i = 0;i < BT_NUM_ISAPORTS; i++) 97241048Sgibbs if (ioport <= bt_isa_ports[i].addr) 97341048Sgibbs break; 97441048Sgibbs if ((i >= BT_NUM_ISAPORTS) 97541048Sgibbs || (ioport != bt_isa_ports[i].addr)) { 97687797Sjhb printf( 977118052Sbde"bt_find_probe_range: Invalid baseport of 0x%x specified.\n" 978118052Sbde"bt_find_probe_range: Nearest valid baseport is 0x%x.\n" 979118052Sbde"bt_find_probe_range: Failing probe.\n", 98041048Sgibbs ioport, 98141048Sgibbs (i < BT_NUM_ISAPORTS) 98241048Sgibbs ? bt_isa_ports[i].addr 98341048Sgibbs : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr); 98441048Sgibbs *port_index = *max_port_index = -1; 98541048Sgibbs return; 98641048Sgibbs } 98741048Sgibbs *port_index = *max_port_index = bt_isa_ports[i].bio; 98841048Sgibbs } else { 98941048Sgibbs *port_index = 0; 99041048Sgibbs *max_port_index = BT_NUM_ISAPORTS - 1; 99141048Sgibbs } 99241048Sgibbs} 99341048Sgibbs 99441048Sgibbsint 99541048Sgibbsbt_iop_from_bio(isa_compat_io_t bio_index) 99641048Sgibbs{ 997217538Sjhb if (bio_index < BT_NUM_ISAPORTS) 99841048Sgibbs return (bt_board_ports[bio_index]); 99941048Sgibbs return (-1); 100041048Sgibbs} 100141048Sgibbs 100241048Sgibbs 100339223Sgibbsstatic void 100439223Sgibbsbtallocccbs(struct bt_softc *bt) 100539223Sgibbs{ 100639223Sgibbs struct bt_ccb *next_ccb; 100739223Sgibbs struct sg_map_node *sg_map; 100839223Sgibbs bus_addr_t physaddr; 100939223Sgibbs bt_sg_t *segs; 101039223Sgibbs int newcount; 101139223Sgibbs int i; 101239223Sgibbs 101345966Sgibbs if (bt->num_ccbs >= bt->max_ccbs) 101445966Sgibbs /* Can't allocate any more */ 101545966Sgibbs return; 101645966Sgibbs 101739223Sgibbs next_ccb = &bt->bt_ccb_array[bt->num_ccbs]; 101839223Sgibbs 101939223Sgibbs sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 102039223Sgibbs 102139223Sgibbs if (sg_map == NULL) 102245966Sgibbs goto error_exit; 102339223Sgibbs 102439223Sgibbs /* Allocate S/G space for the next batch of CCBS */ 102539223Sgibbs if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr, 102639223Sgibbs BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { 102739223Sgibbs free(sg_map, M_DEVBUF); 102845966Sgibbs goto error_exit; 102939223Sgibbs } 103039223Sgibbs 103139223Sgibbs SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links); 103239223Sgibbs 103339223Sgibbs bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, 103439223Sgibbs PAGE_SIZE, btmapsgs, bt, /*flags*/0); 103539223Sgibbs 103639223Sgibbs segs = sg_map->sg_vaddr; 103739223Sgibbs physaddr = sg_map->sg_physaddr; 103839223Sgibbs 103939223Sgibbs newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t))); 104039223Sgibbs for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) { 104139223Sgibbs int error; 104239223Sgibbs 104339223Sgibbs next_ccb->sg_list = segs; 104439223Sgibbs next_ccb->sg_list_phys = physaddr; 104539223Sgibbs next_ccb->flags = BCCB_FREE; 1046241592Sjhb callout_init_mtx(&next_ccb->timer, &bt->lock, 0); 104739223Sgibbs error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0, 104839223Sgibbs &next_ccb->dmamap); 104939223Sgibbs if (error != 0) 105039223Sgibbs break; 105139223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links); 105239223Sgibbs segs += BT_NSEG; 105339223Sgibbs physaddr += (BT_NSEG * sizeof(bt_sg_t)); 105439223Sgibbs next_ccb++; 105539223Sgibbs bt->num_ccbs++; 105639223Sgibbs } 105739223Sgibbs 105839223Sgibbs /* Reserve a CCB for error recovery */ 105939223Sgibbs if (bt->recovery_bccb == NULL) { 106039223Sgibbs bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs); 106139223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 106239223Sgibbs } 106345966Sgibbs 106445966Sgibbs if (SLIST_FIRST(&bt->free_bt_ccbs) != NULL) 106545966Sgibbs return; 106645966Sgibbs 106745966Sgibbserror_exit: 106845966Sgibbs device_printf(bt->dev, "Can't malloc BCCBs\n"); 106939223Sgibbs} 107039223Sgibbs 107139223Sgibbsstatic __inline void 107239223Sgibbsbtfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) 107339223Sgibbs{ 107439223Sgibbs 1075241592Sjhb if (!dumping) 1076241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 107739223Sgibbs if ((bccb->flags & BCCB_ACTIVE) != 0) 107839223Sgibbs LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le); 107939223Sgibbs if (bt->resource_shortage != 0 108039223Sgibbs && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 108139223Sgibbs bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 108239223Sgibbs bt->resource_shortage = FALSE; 108339223Sgibbs } 108439223Sgibbs bccb->flags = BCCB_FREE; 108539223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links); 108641048Sgibbs bt->active_ccbs--; 108739223Sgibbs} 108839223Sgibbs 108939223Sgibbsstatic __inline struct bt_ccb* 109039223Sgibbsbtgetccb(struct bt_softc *bt) 109139223Sgibbs{ 109239223Sgibbs struct bt_ccb* bccb; 109339223Sgibbs 1094241592Sjhb if (!dumping) 1095241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 109639223Sgibbs if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) { 109739223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 109841048Sgibbs bt->active_ccbs++; 109945966Sgibbs } else { 110039223Sgibbs btallocccbs(bt); 110139223Sgibbs bccb = SLIST_FIRST(&bt->free_bt_ccbs); 110245966Sgibbs if (bccb != NULL) { 110339223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 110441048Sgibbs bt->active_ccbs++; 110541048Sgibbs } 110639223Sgibbs } 110739223Sgibbs 110839223Sgibbs return (bccb); 110939223Sgibbs} 111039223Sgibbs 111139223Sgibbsstatic void 111239223Sgibbsbtaction(struct cam_sim *sim, union ccb *ccb) 111339223Sgibbs{ 111439223Sgibbs struct bt_softc *bt; 111539223Sgibbs 111639223Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n")); 111739223Sgibbs 111839223Sgibbs bt = (struct bt_softc *)cam_sim_softc(sim); 1119241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 112039223Sgibbs 112139223Sgibbs switch (ccb->ccb_h.func_code) { 112239223Sgibbs /* Common cases first */ 112339223Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 112439223Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 112539223Sgibbs { 112639223Sgibbs struct bt_ccb *bccb; 112739223Sgibbs struct bt_hccb *hccb; 112839223Sgibbs 112939223Sgibbs /* 113039223Sgibbs * get a bccb to use. 113139223Sgibbs */ 113239223Sgibbs if ((bccb = btgetccb(bt)) == NULL) { 113339223Sgibbs 113439223Sgibbs bt->resource_shortage = TRUE; 113539223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 113639223Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 113739223Sgibbs xpt_done(ccb); 113839223Sgibbs return; 113939223Sgibbs } 114039223Sgibbs 114139223Sgibbs hccb = &bccb->hccb; 114239223Sgibbs 114339223Sgibbs /* 114439223Sgibbs * So we can find the BCCB when an abort is requested 114539223Sgibbs */ 114639223Sgibbs bccb->ccb = ccb; 114739223Sgibbs ccb->ccb_h.ccb_bccb_ptr = bccb; 114839223Sgibbs ccb->ccb_h.ccb_bt_ptr = bt; 114939223Sgibbs 115039223Sgibbs /* 115139223Sgibbs * Put all the arguments for the xfer in the bccb 115239223Sgibbs */ 115339223Sgibbs hccb->target_id = ccb->ccb_h.target_id; 115439223Sgibbs hccb->target_lun = ccb->ccb_h.target_lun; 115539223Sgibbs hccb->btstat = 0; 115639223Sgibbs hccb->sdstat = 0; 115739223Sgibbs 115839223Sgibbs if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 115939223Sgibbs struct ccb_scsiio *csio; 116039223Sgibbs struct ccb_hdr *ccbh; 1161246713Skib int error; 116239223Sgibbs 116339223Sgibbs csio = &ccb->csio; 116439223Sgibbs ccbh = &csio->ccb_h; 116539223Sgibbs hccb->opcode = INITIATOR_CCB_WRESID; 116641669Sgibbs hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0; 116741669Sgibbs hccb->dataout =(ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0; 116839223Sgibbs hccb->cmd_len = csio->cdb_len; 116939223Sgibbs if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) { 117039223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 117139223Sgibbs btfreeccb(bt, bccb); 117239223Sgibbs xpt_done(ccb); 117339223Sgibbs return; 117439223Sgibbs } 117539223Sgibbs hccb->sense_len = csio->sense_len; 117640418Sgibbs if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0 117740418Sgibbs && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) { 117839223Sgibbs hccb->tag_enable = TRUE; 117939223Sgibbs hccb->tag_type = (ccb->csio.tag_action & 0x3); 118039223Sgibbs } else { 118139223Sgibbs hccb->tag_enable = FALSE; 118239223Sgibbs hccb->tag_type = 0; 118339223Sgibbs } 118439223Sgibbs if ((ccbh->flags & CAM_CDB_POINTER) != 0) { 118539223Sgibbs if ((ccbh->flags & CAM_CDB_PHYS) == 0) { 118639223Sgibbs bcopy(csio->cdb_io.cdb_ptr, 118739223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 118839223Sgibbs } else { 118939223Sgibbs /* I guess I could map it in... */ 119039223Sgibbs ccbh->status = CAM_REQ_INVALID; 119139223Sgibbs btfreeccb(bt, bccb); 119239223Sgibbs xpt_done(ccb); 119339223Sgibbs return; 119439223Sgibbs } 119539223Sgibbs } else { 119639223Sgibbs bcopy(csio->cdb_io.cdb_bytes, 119739223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 119839223Sgibbs } 119939223Sgibbs /* If need be, bounce our sense buffer */ 120039223Sgibbs if (bt->sense_buffers != NULL) { 120139223Sgibbs hccb->sense_addr = btsensepaddr(bt, bccb); 120239223Sgibbs } else { 120339223Sgibbs hccb->sense_addr = vtophys(&csio->sense_data); 120439223Sgibbs } 120539223Sgibbs /* 120639223Sgibbs * If we have any data to send with this command, 120739223Sgibbs * map it into bus space. 120839223Sgibbs */ 1209246713Skib error = bus_dmamap_load_ccb( 1210246713Skib bt->buffer_dmat, 1211246713Skib bccb->dmamap, 1212246713Skib ccb, 1213246713Skib btexecuteccb, 1214246713Skib bccb, 1215246713Skib /*flags*/0); 1216246713Skib if (error == EINPROGRESS) { 1217246713Skib /* 1218246713Skib * So as to maintain ordering, freeze the 1219246713Skib * controller queue until our mapping is 1220246713Skib * returned. 1221246713Skib */ 1222246713Skib xpt_freeze_simq(bt->sim, 1); 1223246713Skib csio->ccb_h.status |= CAM_RELEASE_SIMQ; 122439223Sgibbs } 122539223Sgibbs } else { 122639223Sgibbs hccb->opcode = INITIATOR_BUS_DEV_RESET; 122739223Sgibbs /* No data transfer */ 122839223Sgibbs hccb->datain = TRUE; 122939223Sgibbs hccb->dataout = TRUE; 123039223Sgibbs hccb->cmd_len = 0; 123139223Sgibbs hccb->sense_len = 0; 123239223Sgibbs hccb->tag_enable = FALSE; 123339223Sgibbs hccb->tag_type = 0; 123439223Sgibbs btexecuteccb(bccb, NULL, 0, 0); 123539223Sgibbs } 123639223Sgibbs break; 123739223Sgibbs } 123839223Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 123939223Sgibbs case XPT_TARGET_IO: /* Execute target I/O request */ 124039223Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 124139223Sgibbs case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 124239223Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 124339223Sgibbs /* XXX Implement */ 124439223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 124539223Sgibbs xpt_done(ccb); 124639223Sgibbs break; 124739223Sgibbs case XPT_SET_TRAN_SETTINGS: 124839223Sgibbs { 124939223Sgibbs /* XXX Implement */ 125046581Sken ccb->ccb_h.status = CAM_PROVIDE_FAIL; 125139223Sgibbs xpt_done(ccb); 125239223Sgibbs break; 125339223Sgibbs } 125439223Sgibbs case XPT_GET_TRAN_SETTINGS: 125539223Sgibbs /* Get default/user set transfer settings for the target */ 125639223Sgibbs { 125739223Sgibbs struct ccb_trans_settings *cts; 125839223Sgibbs u_int target_mask; 125939223Sgibbs 126039223Sgibbs cts = &ccb->cts; 126139223Sgibbs target_mask = 0x01 << ccb->ccb_h.target_id; 126279175Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 126379175Smjacob struct ccb_trans_settings_scsi *scsi = 126479175Smjacob &cts->proto_specific.scsi; 126579175Smjacob struct ccb_trans_settings_spi *spi = 126679175Smjacob &cts->xport_specific.spi; 126779175Smjacob cts->protocol = PROTO_SCSI; 126879175Smjacob cts->protocol_version = SCSI_REV_2; 126979175Smjacob cts->transport = XPORT_SPI; 127079175Smjacob cts->transport_version = 2; 127179175Smjacob 127279175Smjacob scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 127379175Smjacob spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 127479175Smjacob 127579175Smjacob if ((bt->disc_permitted & target_mask) != 0) 127679175Smjacob spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 127779175Smjacob if ((bt->tags_permitted & target_mask) != 0) 127879175Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 127979175Smjacob 128079175Smjacob if ((bt->ultra_permitted & target_mask) != 0) 128179175Smjacob spi->sync_period = 12; 128279175Smjacob else if ((bt->fast_permitted & target_mask) != 0) 128379175Smjacob spi->sync_period = 25; 128479175Smjacob else if ((bt->sync_permitted & target_mask) != 0) 128579175Smjacob spi->sync_period = 50; 128679175Smjacob else 128779175Smjacob spi->sync_period = 0; 128879175Smjacob 128979175Smjacob if (spi->sync_period != 0) 129079175Smjacob spi->sync_offset = 15; 129179175Smjacob 129279175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_RATE; 129379175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 129479175Smjacob 129579175Smjacob spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 129679175Smjacob if ((bt->wide_permitted & target_mask) != 0) 129779175Smjacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 129879175Smjacob else 129979175Smjacob spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 130079175Smjacob 130179175Smjacob if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 130279175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 130379175Smjacob spi->valid |= CTS_SPI_VALID_DISC; 130479175Smjacob } else 130579175Smjacob scsi->valid = 0; 130679175Smjacob } else { 130739223Sgibbs btfetchtransinfo(bt, cts); 130839223Sgibbs } 130939223Sgibbs 131039223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 131139223Sgibbs xpt_done(ccb); 131239223Sgibbs break; 131339223Sgibbs } 131439223Sgibbs case XPT_CALC_GEOMETRY: 131539223Sgibbs { 131639223Sgibbs struct ccb_calc_geometry *ccg; 131739223Sgibbs u_int32_t size_mb; 131839223Sgibbs u_int32_t secs_per_cylinder; 131939223Sgibbs 132039223Sgibbs ccg = &ccb->ccg; 132139223Sgibbs size_mb = ccg->volume_size 132239223Sgibbs / ((1024L * 1024L) / ccg->block_size); 132339223Sgibbs 132439223Sgibbs if (size_mb >= 1024 && (bt->extended_trans != 0)) { 132539223Sgibbs if (size_mb >= 2048) { 132639223Sgibbs ccg->heads = 255; 132739223Sgibbs ccg->secs_per_track = 63; 132839223Sgibbs } else { 132939223Sgibbs ccg->heads = 128; 133039223Sgibbs ccg->secs_per_track = 32; 133139223Sgibbs } 133239223Sgibbs } else { 133339223Sgibbs ccg->heads = 64; 133439223Sgibbs ccg->secs_per_track = 32; 133539223Sgibbs } 133639223Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 133739223Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 133839223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 133939223Sgibbs xpt_done(ccb); 134039223Sgibbs break; 134139223Sgibbs } 134239223Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 134339223Sgibbs { 134439223Sgibbs btreset(bt, /*hardreset*/TRUE); 134539223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 134639223Sgibbs xpt_done(ccb); 134739223Sgibbs break; 134839223Sgibbs } 134939223Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 135039223Sgibbs /* XXX Implement */ 135139223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 135239223Sgibbs xpt_done(ccb); 135339223Sgibbs break; 135439223Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 135539223Sgibbs { 135639223Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 135739223Sgibbs 135839223Sgibbs cpi->version_num = 1; /* XXX??? */ 135939223Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE; 136039223Sgibbs if (bt->tag_capable != 0) 136139223Sgibbs cpi->hba_inquiry |= PI_TAG_ABLE; 136239223Sgibbs if (bt->wide_bus != 0) 136339223Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 136439223Sgibbs cpi->target_sprt = 0; 136539223Sgibbs cpi->hba_misc = 0; 136639223Sgibbs cpi->hba_eng_cnt = 0; 136739223Sgibbs cpi->max_target = bt->wide_bus ? 15 : 7; 136839223Sgibbs cpi->max_lun = 7; 136939223Sgibbs cpi->initiator_id = bt->scsi_id; 137039223Sgibbs cpi->bus_id = cam_sim_bus(sim); 137146581Sken cpi->base_transfer_speed = 3300; 137239223Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 137339223Sgibbs strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN); 137439223Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 137539223Sgibbs cpi->unit_number = cam_sim_unit(sim); 137639223Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 137779175Smjacob cpi->transport = XPORT_SPI; 137879175Smjacob cpi->transport_version = 2; 137979175Smjacob cpi->protocol = PROTO_SCSI; 138079175Smjacob cpi->protocol_version = SCSI_REV_2; 138139223Sgibbs xpt_done(ccb); 138239223Sgibbs break; 138339223Sgibbs } 138439223Sgibbs default: 138539223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 138639223Sgibbs xpt_done(ccb); 138739223Sgibbs break; 138839223Sgibbs } 138939223Sgibbs} 139039223Sgibbs 139139223Sgibbsstatic void 139239223Sgibbsbtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 139339223Sgibbs{ 139439223Sgibbs struct bt_ccb *bccb; 139539223Sgibbs union ccb *ccb; 139639223Sgibbs struct bt_softc *bt; 139739223Sgibbs 139839223Sgibbs bccb = (struct bt_ccb *)arg; 139939223Sgibbs ccb = bccb->ccb; 140039223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 140139223Sgibbs 140239223Sgibbs if (error != 0) { 140339223Sgibbs if (error != EFBIG) 140445791Speter device_printf(bt->dev, 140545791Speter "Unexepected error 0x%x returned from " 140645791Speter "bus_dmamap_load\n", error); 140739223Sgibbs if (ccb->ccb_h.status == CAM_REQ_INPROG) { 140839223Sgibbs xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 140939223Sgibbs ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 141039223Sgibbs } 141139223Sgibbs btfreeccb(bt, bccb); 141239223Sgibbs xpt_done(ccb); 141339223Sgibbs return; 141439223Sgibbs } 141539223Sgibbs 141639223Sgibbs if (nseg != 0) { 141739223Sgibbs bt_sg_t *sg; 141839223Sgibbs bus_dma_segment_t *end_seg; 1419115343Sscottl bus_dmasync_op_t op; 142039223Sgibbs 142139223Sgibbs end_seg = dm_segs + nseg; 142239223Sgibbs 142339223Sgibbs /* Copy the segments into our SG list */ 142439223Sgibbs sg = bccb->sg_list; 142539223Sgibbs while (dm_segs < end_seg) { 142639223Sgibbs sg->len = dm_segs->ds_len; 142739223Sgibbs sg->addr = dm_segs->ds_addr; 142839223Sgibbs sg++; 142939223Sgibbs dm_segs++; 143039223Sgibbs } 143139223Sgibbs 143239223Sgibbs if (nseg > 1) { 143339223Sgibbs bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID; 143439223Sgibbs bccb->hccb.data_len = sizeof(bt_sg_t) * nseg; 143539223Sgibbs bccb->hccb.data_addr = bccb->sg_list_phys; 143639223Sgibbs } else { 143739223Sgibbs bccb->hccb.data_len = bccb->sg_list->len; 143839223Sgibbs bccb->hccb.data_addr = bccb->sg_list->addr; 143939223Sgibbs } 144039223Sgibbs 144139223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 144239223Sgibbs op = BUS_DMASYNC_PREREAD; 144339223Sgibbs else 144439223Sgibbs op = BUS_DMASYNC_PREWRITE; 144539223Sgibbs 144639223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 144739223Sgibbs 144839223Sgibbs } else { 144941669Sgibbs bccb->hccb.opcode = INITIATOR_CCB; 145039223Sgibbs bccb->hccb.data_len = 0; 145139223Sgibbs bccb->hccb.data_addr = 0; 145239223Sgibbs } 145339223Sgibbs 145439223Sgibbs /* 145539223Sgibbs * Last time we need to check if this CCB needs to 145639223Sgibbs * be aborted. 145739223Sgibbs */ 145839223Sgibbs if (ccb->ccb_h.status != CAM_REQ_INPROG) { 145939223Sgibbs if (nseg != 0) 146039223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 146139223Sgibbs btfreeccb(bt, bccb); 146239223Sgibbs xpt_done(ccb); 146339223Sgibbs return; 146439223Sgibbs } 146539223Sgibbs 146639223Sgibbs bccb->flags = BCCB_ACTIVE; 146739223Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 146839223Sgibbs LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le); 146939223Sgibbs 1470241592Sjhb callout_reset(&bccb->timer, (ccb->ccb_h.timeout * hz) / 1000, 1471241592Sjhb bttimeout, bccb); 147239223Sgibbs 147339223Sgibbs /* Tell the adapter about this command */ 147439223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb); 147541048Sgibbs if (bt->cur_outbox->action_code != BMBO_FREE) { 147641048Sgibbs /* 147741048Sgibbs * We should never encounter a busy mailbox. 147841048Sgibbs * If we do, warn the user, and treat it as 147941048Sgibbs * a resource shortage. If the controller is 148041048Sgibbs * hung, one of the pending transactions will 148141048Sgibbs * timeout causing us to start recovery operations. 148241048Sgibbs */ 148345791Speter device_printf(bt->dev, 148445791Speter "Encountered busy mailbox with %d out of %d " 148545791Speter "commands active!!!\n", bt->active_ccbs, 148645791Speter bt->max_ccbs); 1487241592Sjhb callout_stop(&bccb->timer); 148841048Sgibbs if (nseg != 0) 148941048Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 149041048Sgibbs btfreeccb(bt, bccb); 149141048Sgibbs bt->resource_shortage = TRUE; 149241048Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 149341048Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 149441048Sgibbs xpt_done(ccb); 149541048Sgibbs return; 149641048Sgibbs } 149739223Sgibbs bt->cur_outbox->action_code = BMBO_START; 149839223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 149939223Sgibbs btnextoutbox(bt); 150039223Sgibbs} 150139223Sgibbs 150239223Sgibbsvoid 150339223Sgibbsbt_intr(void *arg) 150439223Sgibbs{ 150539223Sgibbs struct bt_softc *bt; 1506241592Sjhb 1507241592Sjhb bt = arg; 1508241592Sjhb mtx_lock(&bt->lock); 1509241592Sjhb bt_intr_locked(bt); 1510241592Sjhb mtx_unlock(&bt->lock); 1511241592Sjhb} 1512241592Sjhb 1513241592Sjhbvoid 1514241592Sjhbbt_intr_locked(struct bt_softc *bt) 1515241592Sjhb{ 151639223Sgibbs u_int intstat; 151739223Sgibbs 151839223Sgibbs while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) { 151939223Sgibbs 152039223Sgibbs if ((intstat & CMD_COMPLETE) != 0) { 152139223Sgibbs bt->latched_status = bt_inb(bt, STATUS_REG); 152239223Sgibbs bt->command_cmp = TRUE; 152339223Sgibbs } 152439223Sgibbs 152539223Sgibbs bt_outb(bt, CONTROL_REG, RESET_INTR); 152639223Sgibbs 152739223Sgibbs if ((intstat & IMB_LOADED) != 0) { 152839223Sgibbs while (bt->cur_inbox->comp_code != BMBI_FREE) { 152939223Sgibbs btdone(bt, 153039223Sgibbs btccbptov(bt, bt->cur_inbox->ccb_addr), 153139223Sgibbs bt->cur_inbox->comp_code); 153239223Sgibbs bt->cur_inbox->comp_code = BMBI_FREE; 153339223Sgibbs btnextinbox(bt); 153439223Sgibbs } 153539223Sgibbs } 153639223Sgibbs 153739223Sgibbs if ((intstat & SCSI_BUS_RESET) != 0) { 153839223Sgibbs btreset(bt, /*hardreset*/FALSE); 153939223Sgibbs } 154039223Sgibbs } 154139223Sgibbs} 154239223Sgibbs 154339223Sgibbsstatic void 154439223Sgibbsbtdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) 154539223Sgibbs{ 154639223Sgibbs union ccb *ccb; 154739223Sgibbs struct ccb_scsiio *csio; 154839223Sgibbs 154939223Sgibbs ccb = bccb->ccb; 155039223Sgibbs csio = &bccb->ccb->csio; 155139223Sgibbs 155239223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 155345791Speter device_printf(bt->dev, 155445791Speter "btdone - Attempt to free non-active BCCB %p\n", 155545791Speter (void *)bccb); 155639223Sgibbs return; 155739223Sgibbs } 155839223Sgibbs 155939223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1560115343Sscottl bus_dmasync_op_t op; 156139223Sgibbs 156239223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 156339223Sgibbs op = BUS_DMASYNC_POSTREAD; 156439223Sgibbs else 156539223Sgibbs op = BUS_DMASYNC_POSTWRITE; 156639223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 156739223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 156839223Sgibbs } 156939223Sgibbs 157039223Sgibbs if (bccb == bt->recovery_bccb) { 157139223Sgibbs /* 157239223Sgibbs * The recovery BCCB does not have a CCB associated 157339223Sgibbs * with it, so short circuit the normal error handling. 157439223Sgibbs * We now traverse our list of pending CCBs and process 157539223Sgibbs * any that were terminated by the recovery CCBs action. 157639223Sgibbs * We also reinstate timeouts for all remaining, pending, 157739223Sgibbs * CCBs. 157839223Sgibbs */ 157939223Sgibbs struct cam_path *path; 158039223Sgibbs struct ccb_hdr *ccb_h; 158139223Sgibbs cam_status error; 158239223Sgibbs 158339223Sgibbs /* Notify all clients that a BDR occured */ 158439223Sgibbs error = xpt_create_path(&path, /*periph*/NULL, 158539223Sgibbs cam_sim_path(bt->sim), 158639223Sgibbs bccb->hccb.target_id, 158739223Sgibbs CAM_LUN_WILDCARD); 158839223Sgibbs 1589256893Smav if (error == CAM_REQ_CMP) { 159039223Sgibbs xpt_async(AC_SENT_BDR, path, NULL); 1591256893Smav xpt_free_path(path); 1592256893Smav } 159339223Sgibbs 159439223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 159539223Sgibbs while (ccb_h != NULL) { 159639223Sgibbs struct bt_ccb *pending_bccb; 159739223Sgibbs 159839223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 159939223Sgibbs if (pending_bccb->hccb.target_id 160039223Sgibbs == bccb->hccb.target_id) { 160139223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_BDR; 160239223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 160339223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 160439223Sgibbs } else { 1605241592Sjhb callout_reset(&pending_bccb->timer, 1606241592Sjhb (ccb_h->timeout * hz) / 1000, 1607241592Sjhb bttimeout, pending_bccb); 160839223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 160939223Sgibbs } 161039223Sgibbs } 161145791Speter device_printf(bt->dev, "No longer in timeout\n"); 161239223Sgibbs return; 161339223Sgibbs } 161439223Sgibbs 1615241592Sjhb callout_stop(&bccb->timer); 161639223Sgibbs 161739223Sgibbs switch (comp_code) { 161839223Sgibbs case BMBI_FREE: 161945791Speter device_printf(bt->dev, 162045791Speter "btdone - CCB completed with free status!\n"); 162139223Sgibbs break; 162239223Sgibbs case BMBI_NOT_FOUND: 162345791Speter device_printf(bt->dev, 162445791Speter "btdone - CCB Abort failed to find CCB\n"); 162539223Sgibbs break; 162639223Sgibbs case BMBI_ABORT: 162739223Sgibbs case BMBI_ERROR: 162841133Sgibbs if (bootverbose) { 162941133Sgibbs printf("bt: ccb %p - error %x occured. " 163041133Sgibbs "btstat = %x, sdstat = %x\n", 163141133Sgibbs (void *)bccb, comp_code, bccb->hccb.btstat, 163241133Sgibbs bccb->hccb.sdstat); 163341133Sgibbs } 163439223Sgibbs /* An error occured */ 163539223Sgibbs switch(bccb->hccb.btstat) { 163639223Sgibbs case BTSTAT_DATARUN_ERROR: 163741048Sgibbs if (bccb->hccb.data_len == 0) { 163841048Sgibbs /* 163941048Sgibbs * At least firmware 4.22, does this 164041048Sgibbs * for a QUEUE FULL condition. 164141048Sgibbs */ 164241048Sgibbs bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL; 164341048Sgibbs } else if (bccb->hccb.data_len < 0) { 164439223Sgibbs csio->ccb_h.status = CAM_DATA_RUN_ERR; 164539223Sgibbs break; 164639223Sgibbs } 164739223Sgibbs /* FALLTHROUGH */ 164839223Sgibbs case BTSTAT_NOERROR: 164939223Sgibbs case BTSTAT_LINKED_CMD_COMPLETE: 165039223Sgibbs case BTSTAT_LINKED_CMD_FLAG_COMPLETE: 165139223Sgibbs case BTSTAT_DATAUNDERUN_ERROR: 165239223Sgibbs 165339223Sgibbs csio->scsi_status = bccb->hccb.sdstat; 165439223Sgibbs csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 165539223Sgibbs switch(csio->scsi_status) { 165639223Sgibbs case SCSI_STATUS_CHECK_COND: 165739223Sgibbs case SCSI_STATUS_CMD_TERMINATED: 165839223Sgibbs csio->ccb_h.status |= CAM_AUTOSNS_VALID; 165939223Sgibbs /* Bounce sense back if necessary */ 166039223Sgibbs if (bt->sense_buffers != NULL) { 166139223Sgibbs csio->sense_data = 166239223Sgibbs *btsensevaddr(bt, bccb); 166339223Sgibbs } 166439223Sgibbs break; 166539223Sgibbs default: 166639223Sgibbs break; 166739223Sgibbs case SCSI_STATUS_OK: 166839223Sgibbs csio->ccb_h.status = CAM_REQ_CMP; 166939223Sgibbs break; 167039223Sgibbs } 167139223Sgibbs csio->resid = bccb->hccb.data_len; 167239223Sgibbs break; 167339223Sgibbs case BTSTAT_SELTIMEOUT: 167439223Sgibbs csio->ccb_h.status = CAM_SEL_TIMEOUT; 167539223Sgibbs break; 167639223Sgibbs case BTSTAT_UNEXPECTED_BUSFREE: 167739223Sgibbs csio->ccb_h.status = CAM_UNEXP_BUSFREE; 167839223Sgibbs break; 167939223Sgibbs case BTSTAT_INVALID_PHASE: 168039223Sgibbs csio->ccb_h.status = CAM_SEQUENCE_FAIL; 168139223Sgibbs break; 168239223Sgibbs case BTSTAT_INVALID_ACTION_CODE: 168339223Sgibbs panic("%s: Inavlid Action code", bt_name(bt)); 168439223Sgibbs break; 168539223Sgibbs case BTSTAT_INVALID_OPCODE: 168639223Sgibbs panic("%s: Inavlid CCB Opcode code", bt_name(bt)); 168739223Sgibbs break; 168839223Sgibbs case BTSTAT_LINKED_CCB_LUN_MISMATCH: 168939223Sgibbs /* We don't even support linked commands... */ 169039223Sgibbs panic("%s: Linked CCB Lun Mismatch", bt_name(bt)); 169139223Sgibbs break; 169239223Sgibbs case BTSTAT_INVALID_CCB_OR_SG_PARAM: 169339223Sgibbs panic("%s: Invalid CCB or SG list", bt_name(bt)); 169439223Sgibbs break; 169539223Sgibbs case BTSTAT_AUTOSENSE_FAILED: 169639223Sgibbs csio->ccb_h.status = CAM_AUTOSENSE_FAIL; 169739223Sgibbs break; 169839223Sgibbs case BTSTAT_TAGGED_MSG_REJECTED: 169939223Sgibbs { 170039223Sgibbs struct ccb_trans_settings neg; 170179175Smjacob struct ccb_trans_settings_scsi *scsi = 170279175Smjacob &neg.proto_specific.scsi; 170379175Smjacob 170479175Smjacob neg.protocol = PROTO_SCSI; 170579175Smjacob neg.protocol_version = SCSI_REV_2; 170679175Smjacob neg.transport = XPORT_SPI; 170779175Smjacob neg.transport_version = 2; 170879175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 170979175Smjacob scsi->flags = 0; 171039223Sgibbs xpt_print_path(csio->ccb_h.path); 171139223Sgibbs printf("refuses tagged commands. Performing " 171239223Sgibbs "non-tagged I/O\n"); 171339223Sgibbs xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path, 171439223Sgibbs /*priority*/1); 171539223Sgibbs xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg); 171639223Sgibbs bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id); 171739223Sgibbs csio->ccb_h.status = CAM_MSG_REJECT_REC; 171839223Sgibbs break; 171939223Sgibbs } 172039223Sgibbs case BTSTAT_UNSUPPORTED_MSG_RECEIVED: 172139223Sgibbs /* 172239223Sgibbs * XXX You would think that this is 172339223Sgibbs * a recoverable error... Hmmm. 172439223Sgibbs */ 172539223Sgibbs csio->ccb_h.status = CAM_REQ_CMP_ERR; 172639223Sgibbs break; 172739223Sgibbs case BTSTAT_HA_SOFTWARE_ERROR: 172839223Sgibbs case BTSTAT_HA_WATCHDOG_ERROR: 172939223Sgibbs case BTSTAT_HARDWARE_FAILURE: 173039223Sgibbs /* Hardware reset ??? Can we recover ??? */ 173139223Sgibbs csio->ccb_h.status = CAM_NO_HBA; 173239223Sgibbs break; 173339223Sgibbs case BTSTAT_TARGET_IGNORED_ATN: 173439223Sgibbs case BTSTAT_OTHER_SCSI_BUS_RESET: 173539223Sgibbs case BTSTAT_HA_SCSI_BUS_RESET: 173639223Sgibbs if ((csio->ccb_h.status & CAM_STATUS_MASK) 173739223Sgibbs != CAM_CMD_TIMEOUT) 173839223Sgibbs csio->ccb_h.status = CAM_SCSI_BUS_RESET; 173939223Sgibbs break; 174039223Sgibbs case BTSTAT_HA_BDR: 174139223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) 174239223Sgibbs csio->ccb_h.status = CAM_BDR_SENT; 174339223Sgibbs else 174439223Sgibbs csio->ccb_h.status = CAM_CMD_TIMEOUT; 174539223Sgibbs break; 174639223Sgibbs case BTSTAT_INVALID_RECONNECT: 174739223Sgibbs case BTSTAT_ABORT_QUEUE_GENERATED: 174839223Sgibbs csio->ccb_h.status = CAM_REQ_TERMIO; 174939223Sgibbs break; 175039223Sgibbs case BTSTAT_SCSI_PERROR_DETECTED: 175139223Sgibbs csio->ccb_h.status = CAM_UNCOR_PARITY; 175239223Sgibbs break; 175339223Sgibbs } 175439223Sgibbs if (csio->ccb_h.status != CAM_REQ_CMP) { 175539223Sgibbs xpt_freeze_devq(csio->ccb_h.path, /*count*/1); 175639223Sgibbs csio->ccb_h.status |= CAM_DEV_QFRZN; 175739223Sgibbs } 175839223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 175939223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 176039223Sgibbs btfreeccb(bt, bccb); 176139223Sgibbs xpt_done(ccb); 176239223Sgibbs break; 176339223Sgibbs case BMBI_OK: 176439223Sgibbs /* All completed without incident */ 176539223Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 176639223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 176739223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 176839223Sgibbs btfreeccb(bt, bccb); 176939223Sgibbs xpt_done(ccb); 177039223Sgibbs break; 177139223Sgibbs } 177239223Sgibbs} 177339223Sgibbs 177439223Sgibbsstatic int 177539223Sgibbsbtreset(struct bt_softc* bt, int hard_reset) 177639223Sgibbs{ 177739223Sgibbs struct ccb_hdr *ccb_h; 177839223Sgibbs u_int status; 177939223Sgibbs u_int timeout; 178039223Sgibbs u_int8_t reset_type; 178139223Sgibbs 178239223Sgibbs if (hard_reset != 0) 178339223Sgibbs reset_type = HARD_RESET; 178439223Sgibbs else 178539223Sgibbs reset_type = SOFT_RESET; 178639223Sgibbs bt_outb(bt, CONTROL_REG, reset_type); 178739223Sgibbs 178839223Sgibbs /* Wait 5sec. for Diagnostic start */ 178939223Sgibbs timeout = 5 * 10000; 179039223Sgibbs while (--timeout) { 179139223Sgibbs status = bt_inb(bt, STATUS_REG); 179239223Sgibbs if ((status & DIAG_ACTIVE) != 0) 179339223Sgibbs break; 179439223Sgibbs DELAY(100); 179539223Sgibbs } 179639223Sgibbs if (timeout == 0) { 179739223Sgibbs if (bootverbose) 1798241592Sjhb device_printf(bt->dev, 1799241592Sjhb "btreset - Diagnostic Active failed to " 1800241592Sjhb "assert. status = 0x%x\n", status); 180139223Sgibbs return (ETIMEDOUT); 180239223Sgibbs } 180339223Sgibbs 180439223Sgibbs /* Wait 10sec. for Diagnostic end */ 180539223Sgibbs timeout = 10 * 10000; 180639223Sgibbs while (--timeout) { 180739223Sgibbs status = bt_inb(bt, STATUS_REG); 180839223Sgibbs if ((status & DIAG_ACTIVE) == 0) 180939223Sgibbs break; 181039223Sgibbs DELAY(100); 181139223Sgibbs } 181239223Sgibbs if (timeout == 0) { 181339223Sgibbs panic("%s: btreset - Diagnostic Active failed to drop. " 181439223Sgibbs "status = 0x%x\n", bt_name(bt), status); 181539223Sgibbs return (ETIMEDOUT); 181639223Sgibbs } 181739223Sgibbs 181839223Sgibbs /* Wait for the host adapter to become ready or report a failure */ 181939223Sgibbs timeout = 10000; 182039223Sgibbs while (--timeout) { 182139223Sgibbs status = bt_inb(bt, STATUS_REG); 182239223Sgibbs if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0) 182339223Sgibbs break; 182439223Sgibbs DELAY(100); 182539223Sgibbs } 182639223Sgibbs if (timeout == 0) { 1827241592Sjhb device_printf(bt->dev, 1828241592Sjhb "btreset - Host adapter failed to come ready. " 1829241592Sjhb "status = 0x%x\n", status); 183039223Sgibbs return (ETIMEDOUT); 183139223Sgibbs } 183239223Sgibbs 183339223Sgibbs /* If the diagnostics failed, tell the user */ 183439223Sgibbs if ((status & DIAG_FAIL) != 0 183539223Sgibbs || (status & HA_READY) == 0) { 1836241592Sjhb device_printf(bt->dev, 1837241592Sjhb "btreset - Adapter failed diagnostics\n"); 183839223Sgibbs 183939223Sgibbs if ((status & DATAIN_REG_READY) != 0) 1840241592Sjhb device_printf(bt->dev, 1841241592Sjhb "btreset - Host Adapter Error code = 0x%x\n", 1842241592Sjhb bt_inb(bt, DATAIN_REG)); 184339223Sgibbs return (ENXIO); 184439223Sgibbs } 184539223Sgibbs 184639223Sgibbs /* If we've allocated mailboxes, initialize them */ 184739223Sgibbs if (bt->init_level > 4) 184839223Sgibbs btinitmboxes(bt); 184939223Sgibbs 185039223Sgibbs /* If we've attached to the XPT, tell it about the event */ 185139223Sgibbs if (bt->path != NULL) 185239223Sgibbs xpt_async(AC_BUS_RESET, bt->path, NULL); 185339223Sgibbs 185439223Sgibbs /* 185539223Sgibbs * Perform completion processing for all outstanding CCBs. 185639223Sgibbs */ 185739223Sgibbs while ((ccb_h = LIST_FIRST(&bt->pending_ccbs)) != NULL) { 185839223Sgibbs struct bt_ccb *pending_bccb; 185939223Sgibbs 186039223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 186139223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_SCSI_BUS_RESET; 186239223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 186339223Sgibbs } 186439223Sgibbs 186539223Sgibbs return (0); 186639223Sgibbs} 186739223Sgibbs 186839223Sgibbs/* 186939223Sgibbs * Send a command to the adapter. 187039223Sgibbs */ 187139223Sgibbsint 187239223Sgibbsbt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, 187339223Sgibbs u_int8_t *reply_data, u_int reply_len, u_int cmd_timeout) 187439223Sgibbs{ 187539223Sgibbs u_int timeout; 187639223Sgibbs u_int status; 187745444Sgibbs u_int saved_status; 187839223Sgibbs u_int intstat; 187939223Sgibbs u_int reply_buf_size; 188041669Sgibbs int cmd_complete; 188145444Sgibbs int error; 188239223Sgibbs 188339223Sgibbs /* No data returned to start */ 188439223Sgibbs reply_buf_size = reply_len; 188539223Sgibbs reply_len = 0; 188639223Sgibbs intstat = 0; 188741669Sgibbs cmd_complete = 0; 188845444Sgibbs saved_status = 0; 188945444Sgibbs error = 0; 189039223Sgibbs 189139223Sgibbs bt->command_cmp = 0; 189239223Sgibbs /* 189345444Sgibbs * Wait up to 10 sec. for the adapter to become 189439223Sgibbs * ready to accept commands. 189539223Sgibbs */ 189645444Sgibbs timeout = 100000; 189739223Sgibbs while (--timeout) { 189839223Sgibbs status = bt_inb(bt, STATUS_REG); 189939223Sgibbs if ((status & HA_READY) != 0 190039223Sgibbs && (status & CMD_REG_BUSY) == 0) 190139223Sgibbs break; 190245444Sgibbs /* 190345444Sgibbs * Throw away any pending data which may be 190445444Sgibbs * left over from earlier commands that we 190545444Sgibbs * timedout on. 190645444Sgibbs */ 190745444Sgibbs if ((status & DATAIN_REG_READY) != 0) 190845444Sgibbs (void)bt_inb(bt, DATAIN_REG); 190939223Sgibbs DELAY(100); 191039223Sgibbs } 191139223Sgibbs if (timeout == 0) { 1912241592Sjhb device_printf(bt->dev, 1913241592Sjhb "bt_cmd: Timeout waiting for adapter ready, " 1914241592Sjhb "status = 0x%x\n", status); 191539223Sgibbs return (ETIMEDOUT); 191639223Sgibbs } 191739223Sgibbs 191839223Sgibbs /* 191939223Sgibbs * Send the opcode followed by any necessary parameter bytes. 192039223Sgibbs */ 192139223Sgibbs bt_outb(bt, COMMAND_REG, opcode); 192239223Sgibbs 192339223Sgibbs /* 1924240518Seadler * Wait for up to 1sec for each byte of the 192545444Sgibbs * parameter list sent to be sent. 192639223Sgibbs */ 192739223Sgibbs timeout = 10000; 192839223Sgibbs while (param_len && --timeout) { 192939223Sgibbs DELAY(100); 193039223Sgibbs status = bt_inb(bt, STATUS_REG); 193139223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 193247432Sgibbs 193339223Sgibbs if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 193441669Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 193545444Sgibbs saved_status = status; 193641669Sgibbs cmd_complete = 1; 193739223Sgibbs break; 193841669Sgibbs } 193939223Sgibbs if (bt->command_cmp != 0) { 194045444Sgibbs saved_status = bt->latched_status; 194141669Sgibbs cmd_complete = 1; 194239223Sgibbs break; 194339223Sgibbs } 194439223Sgibbs if ((status & DATAIN_REG_READY) != 0) 194539223Sgibbs break; 194639223Sgibbs if ((status & CMD_REG_BUSY) == 0) { 194739223Sgibbs bt_outb(bt, COMMAND_REG, *params++); 194839223Sgibbs param_len--; 194945444Sgibbs timeout = 10000; 195039223Sgibbs } 195139223Sgibbs } 195239223Sgibbs if (timeout == 0) { 1953241592Sjhb device_printf(bt->dev, "bt_cmd: Timeout sending parameters, " 1954241592Sjhb "status = 0x%x\n", status); 195545444Sgibbs cmd_complete = 1; 195645444Sgibbs saved_status = status; 195745444Sgibbs error = ETIMEDOUT; 195839223Sgibbs } 195939223Sgibbs 196039223Sgibbs /* 196145444Sgibbs * Wait for the command to complete. 196239223Sgibbs */ 196341669Sgibbs while (cmd_complete == 0 && --cmd_timeout) { 196439223Sgibbs 196539223Sgibbs status = bt_inb(bt, STATUS_REG); 196639223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 196747432Sgibbs /* 196847432Sgibbs * It may be that this command was issued with 196947432Sgibbs * controller interrupts disabled. We'll never 197047432Sgibbs * get to our command if an incoming mailbox 197147432Sgibbs * interrupt is pending, so take care of completed 197247432Sgibbs * mailbox commands by calling our interrupt handler. 197347432Sgibbs */ 197447432Sgibbs if ((intstat & (INTR_PENDING|IMB_LOADED)) 197547432Sgibbs == (INTR_PENDING|IMB_LOADED)) 1976241592Sjhb bt_intr_locked(bt); 197739223Sgibbs 197839223Sgibbs if (bt->command_cmp != 0) { 197945444Sgibbs /* 198045444Sgibbs * Our interrupt handler saw CMD_COMPLETE 198145444Sgibbs * status before we did. 198245444Sgibbs */ 198345444Sgibbs cmd_complete = 1; 198445444Sgibbs saved_status = bt->latched_status; 198545444Sgibbs } else if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 198645444Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 198745444Sgibbs /* 198845444Sgibbs * Our poll (in case interrupts are blocked) 198945444Sgibbs * saw the CMD_COMPLETE interrupt. 199045444Sgibbs */ 199145444Sgibbs cmd_complete = 1; 199245444Sgibbs saved_status = status; 199345444Sgibbs } else if (opcode == BOP_MODIFY_IO_ADDR 199445444Sgibbs && (status & CMD_REG_BUSY) == 0) { 199545444Sgibbs /* 199645444Sgibbs * The BOP_MODIFY_IO_ADDR does not issue a CMD_COMPLETE, 199745444Sgibbs * but it should update the status register. So, we 199845444Sgibbs * consider this command complete when the CMD_REG_BUSY 199945444Sgibbs * status clears. 200045444Sgibbs */ 200145444Sgibbs saved_status = status; 200245444Sgibbs cmd_complete = 1; 200345444Sgibbs } else if ((status & DATAIN_REG_READY) != 0) { 200439223Sgibbs u_int8_t data; 200539223Sgibbs 200639223Sgibbs data = bt_inb(bt, DATAIN_REG); 200739223Sgibbs if (reply_len < reply_buf_size) { 200839223Sgibbs *reply_data++ = data; 200939223Sgibbs } else { 2010241592Sjhb device_printf(bt->dev, 2011241592Sjhb "bt_cmd - Discarded reply data byte " 2012241592Sjhb "for opcode 0x%x\n", opcode); 201339223Sgibbs } 201445444Sgibbs /* 201545444Sgibbs * Reset timeout to ensure at least a second 201645444Sgibbs * between response bytes. 201745444Sgibbs */ 201845444Sgibbs cmd_timeout = MAX(cmd_timeout, 10000); 201939223Sgibbs reply_len++; 202045444Sgibbs 202145444Sgibbs } else if ((opcode == BOP_FETCH_LRAM) 202245444Sgibbs && (status & HA_READY) != 0) { 202345444Sgibbs saved_status = status; 202445444Sgibbs cmd_complete = 1; 202539223Sgibbs } 202639223Sgibbs DELAY(100); 202739223Sgibbs } 202845444Sgibbs if (cmd_timeout == 0) { 2029241592Sjhb device_printf(bt->dev, 2030241592Sjhb "bt_cmd: Timeout waiting for command (%x) " 2031241592Sjhb "to complete.\n", opcode); 2032241592Sjhb device_printf(bt->dev, "status = 0x%x, intstat = 0x%x, " 2033241592Sjhb "rlen %d\n", status, intstat, reply_len); 203445444Sgibbs error = (ETIMEDOUT); 203539223Sgibbs } 203639223Sgibbs 203739223Sgibbs /* 2038241592Sjhb * Clear any pending interrupts. 203939223Sgibbs */ 2040241592Sjhb bt_intr_locked(bt); 204139223Sgibbs 204245444Sgibbs if (error != 0) 204345444Sgibbs return (error); 204445444Sgibbs 204539223Sgibbs /* 204639223Sgibbs * If the command was rejected by the controller, tell the caller. 204739223Sgibbs */ 204845444Sgibbs if ((saved_status & CMD_INVALID) != 0) { 204939223Sgibbs /* 205039223Sgibbs * Some early adapters may not recover properly from 205139223Sgibbs * an invalid command. If it appears that the controller 205239223Sgibbs * has wedged (i.e. status was not cleared by our interrupt 205339223Sgibbs * reset above), perform a soft reset. 205439223Sgibbs */ 205539223Sgibbs if (bootverbose) 2056241592Sjhb device_printf(bt->dev, "Invalid Command 0x%x\n", 205739223Sgibbs opcode); 205839223Sgibbs DELAY(1000); 205939223Sgibbs status = bt_inb(bt, STATUS_REG); 206039223Sgibbs if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY| 206139223Sgibbs CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0 206239223Sgibbs || (status & (HA_READY|INIT_REQUIRED)) 206339223Sgibbs != (HA_READY|INIT_REQUIRED)) { 206439223Sgibbs btreset(bt, /*hard_reset*/FALSE); 206539223Sgibbs } 206639223Sgibbs return (EINVAL); 206739223Sgibbs } 206839223Sgibbs 206939223Sgibbs if (param_len > 0) { 207039223Sgibbs /* The controller did not accept the full argument list */ 207139223Sgibbs return (E2BIG); 207239223Sgibbs } 207339223Sgibbs 207439223Sgibbs if (reply_len != reply_buf_size) { 207539223Sgibbs /* Too much or too little data received */ 207639223Sgibbs return (EMSGSIZE); 207739223Sgibbs } 207839223Sgibbs 207939223Sgibbs /* We were successful */ 208039223Sgibbs return (0); 208139223Sgibbs} 208239223Sgibbs 208339223Sgibbsstatic int 208439223Sgibbsbtinitmboxes(struct bt_softc *bt) { 208539223Sgibbs init_32b_mbox_params_t init_mbox; 208639223Sgibbs int error; 208739223Sgibbs 208839223Sgibbs bzero(bt->in_boxes, sizeof(bt_mbox_in_t) * bt->num_boxes); 208939223Sgibbs bzero(bt->out_boxes, sizeof(bt_mbox_out_t) * bt->num_boxes); 209039223Sgibbs bt->cur_inbox = bt->in_boxes; 209139223Sgibbs bt->last_inbox = bt->in_boxes + bt->num_boxes - 1; 209239223Sgibbs bt->cur_outbox = bt->out_boxes; 209339223Sgibbs bt->last_outbox = bt->out_boxes + bt->num_boxes - 1; 209439223Sgibbs 209539223Sgibbs /* Tell the adapter about them */ 209639223Sgibbs init_mbox.num_boxes = bt->num_boxes; 209739223Sgibbs init_mbox.base_addr[0] = bt->mailbox_physbase & 0xFF; 209839223Sgibbs init_mbox.base_addr[1] = (bt->mailbox_physbase >> 8) & 0xFF; 209939223Sgibbs init_mbox.base_addr[2] = (bt->mailbox_physbase >> 16) & 0xFF; 210039223Sgibbs init_mbox.base_addr[3] = (bt->mailbox_physbase >> 24) & 0xFF; 210139223Sgibbs error = bt_cmd(bt, BOP_INITIALIZE_32BMBOX, (u_int8_t *)&init_mbox, 210239223Sgibbs /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL, 210339223Sgibbs /*reply_len*/0, DEFAULT_CMD_TIMEOUT); 210439223Sgibbs 210539223Sgibbs if (error != 0) 210639223Sgibbs printf("btinitmboxes: Initialization command failed\n"); 210739223Sgibbs else if (bt->strict_rr != 0) { 210839223Sgibbs /* 210939223Sgibbs * If the controller supports 211039223Sgibbs * strict round robin mode, 211139223Sgibbs * enable it 211239223Sgibbs */ 211339223Sgibbs u_int8_t param; 211439223Sgibbs 211539223Sgibbs param = 0; 211639223Sgibbs error = bt_cmd(bt, BOP_ENABLE_STRICT_RR, ¶m, 1, 211739223Sgibbs /*reply_buf*/NULL, /*reply_len*/0, 211839223Sgibbs DEFAULT_CMD_TIMEOUT); 211939223Sgibbs 212039223Sgibbs if (error != 0) { 212139223Sgibbs printf("btinitmboxes: Unable to enable strict RR\n"); 212239223Sgibbs error = 0; 212339223Sgibbs } else if (bootverbose) { 2124241592Sjhb device_printf(bt->dev, 2125241592Sjhb "Using Strict Round Robin Mailbox Mode\n"); 212639223Sgibbs } 212739223Sgibbs } 212839223Sgibbs 212939223Sgibbs return (error); 213039223Sgibbs} 213139223Sgibbs 213239223Sgibbs/* 213339223Sgibbs * Update the XPT's idea of the negotiated transfer 213439223Sgibbs * parameters for a particular target. 213539223Sgibbs */ 213639223Sgibbsstatic void 213779175Smjacobbtfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts) 213839223Sgibbs{ 213939223Sgibbs setup_data_t setup_info; 214039223Sgibbs u_int target; 214139223Sgibbs u_int targ_offset; 214239223Sgibbs u_int targ_mask; 214339223Sgibbs u_int sync_period; 214479175Smjacob u_int sync_offset; 214579175Smjacob u_int bus_width; 214639223Sgibbs int error; 214739223Sgibbs u_int8_t param; 214839223Sgibbs targ_syncinfo_t sync_info; 214979175Smjacob struct ccb_trans_settings_scsi *scsi = 215079175Smjacob &cts->proto_specific.scsi; 215179175Smjacob struct ccb_trans_settings_spi *spi = 215279175Smjacob &cts->xport_specific.spi; 215339223Sgibbs 215479175Smjacob spi->valid = 0; 215579175Smjacob scsi->valid = 0; 215679175Smjacob 215739223Sgibbs target = cts->ccb_h.target_id; 215839223Sgibbs targ_offset = (target & 0x7); 215939223Sgibbs targ_mask = (0x01 << targ_offset); 216039223Sgibbs 216139223Sgibbs /* 216239223Sgibbs * Inquire Setup Information. This command retreives the 216339223Sgibbs * Wide negotiation status for recent adapters as well as 216439223Sgibbs * the sync info for older models. 216539223Sgibbs */ 216639223Sgibbs param = sizeof(setup_info); 216739223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, ¶m, /*paramlen*/1, 216839223Sgibbs (u_int8_t*)&setup_info, sizeof(setup_info), 216939223Sgibbs DEFAULT_CMD_TIMEOUT); 217039223Sgibbs 217139223Sgibbs if (error != 0) { 2172241592Sjhb device_printf(bt->dev, 2173241592Sjhb "btfetchtransinfo - Inquire Setup Info Failed %x\n", 2174241592Sjhb error); 217539223Sgibbs return; 217639223Sgibbs } 217739223Sgibbs 217839223Sgibbs sync_info = (target < 8) ? setup_info.low_syncinfo[targ_offset] 217939223Sgibbs : setup_info.high_syncinfo[targ_offset]; 218039223Sgibbs 218139223Sgibbs if (sync_info.sync == 0) 218279175Smjacob sync_offset = 0; 218339223Sgibbs else 218479175Smjacob sync_offset = sync_info.offset; 218539223Sgibbs 218679175Smjacob 218779175Smjacob bus_width = MSG_EXT_WDTR_BUS_8_BIT; 218839223Sgibbs if (strcmp(bt->firmware_ver, "5.06L") >= 0) { 218939223Sgibbs u_int wide_active; 219039223Sgibbs 219139223Sgibbs wide_active = 219239223Sgibbs (target < 8) ? (setup_info.low_wide_active & targ_mask) 219339223Sgibbs : (setup_info.high_wide_active & targ_mask); 219439223Sgibbs 219539223Sgibbs if (wide_active) 219679175Smjacob bus_width = MSG_EXT_WDTR_BUS_16_BIT; 219739507Sgibbs } else if ((bt->wide_permitted & targ_mask) != 0) { 219839507Sgibbs struct ccb_getdev cgd; 219939507Sgibbs 220039507Sgibbs /* 220139507Sgibbs * Prior to rev 5.06L, wide status isn't provided, 220239507Sgibbs * so we "guess" that wide transfers are in effect 220339507Sgibbs * if the user settings allow for wide and the inquiry 220439507Sgibbs * data for the device indicates that it can handle 220539507Sgibbs * wide transfers. 220639507Sgibbs */ 220739507Sgibbs xpt_setup_ccb(&cgd.ccb_h, cts->ccb_h.path, /*priority*/1); 220839507Sgibbs cgd.ccb_h.func_code = XPT_GDEV_TYPE; 220939507Sgibbs xpt_action((union ccb *)&cgd); 221039507Sgibbs if ((cgd.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP 221139507Sgibbs && (cgd.inq_data.flags & SID_WBus16) != 0) 221279175Smjacob bus_width = MSG_EXT_WDTR_BUS_16_BIT; 221339223Sgibbs } 221439223Sgibbs 221544581Sgibbs if (bt->firmware_ver[0] >= '3') { 221639223Sgibbs /* 221739223Sgibbs * For adapters that can do fast or ultra speeds, 221839223Sgibbs * use the more exact Target Sync Information command. 221939223Sgibbs */ 222039223Sgibbs target_sync_info_data_t sync_info; 222139223Sgibbs 222239223Sgibbs param = sizeof(sync_info); 222339223Sgibbs error = bt_cmd(bt, BOP_TARG_SYNC_INFO, ¶m, /*paramlen*/1, 222439223Sgibbs (u_int8_t*)&sync_info, sizeof(sync_info), 222539223Sgibbs DEFAULT_CMD_TIMEOUT); 222639223Sgibbs 222739223Sgibbs if (error != 0) { 2228241592Sjhb device_printf(bt->dev, 2229241592Sjhb "btfetchtransinfo - Inquire Sync " 2230241592Sjhb "Info Failed 0x%x\n", error); 223139223Sgibbs return; 223239223Sgibbs } 223339223Sgibbs sync_period = sync_info.sync_rate[target] * 100; 223439223Sgibbs } else { 223539223Sgibbs sync_period = 2000 + (500 * sync_info.period); 223639223Sgibbs } 223739223Sgibbs 223879175Smjacob cts->protocol = PROTO_SCSI; 223979175Smjacob cts->protocol_version = SCSI_REV_2; 224079175Smjacob cts->transport = XPORT_SPI; 224179175Smjacob cts->transport_version = 2; 224279175Smjacob 224379175Smjacob spi->sync_period = sync_period; 224479175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_RATE; 224579175Smjacob spi->sync_offset = sync_offset; 224679175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 224779175Smjacob 224879175Smjacob spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 224979175Smjacob spi->bus_width = bus_width; 225079175Smjacob 225179175Smjacob if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 225279175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 225379175Smjacob spi->valid |= CTS_SPI_VALID_DISC; 225479175Smjacob } else 225579175Smjacob scsi->valid = 0; 225679175Smjacob 225739223Sgibbs xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts); 225839223Sgibbs} 225939223Sgibbs 226039223Sgibbsstatic void 226139223Sgibbsbtmapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error) 226239223Sgibbs{ 226339223Sgibbs struct bt_softc* bt; 226439223Sgibbs 226539223Sgibbs bt = (struct bt_softc*)arg; 226639223Sgibbs bt->mailbox_physbase = segs->ds_addr; 226739223Sgibbs} 226839223Sgibbs 226939223Sgibbsstatic void 227039223Sgibbsbtmapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 227139223Sgibbs{ 227239223Sgibbs struct bt_softc* bt; 227339223Sgibbs 227439223Sgibbs bt = (struct bt_softc*)arg; 227539223Sgibbs bt->bt_ccb_physbase = segs->ds_addr; 227639223Sgibbs} 227739223Sgibbs 227839223Sgibbsstatic void 227939223Sgibbsbtmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 228039223Sgibbs{ 228139223Sgibbs 228239223Sgibbs struct bt_softc* bt; 228339223Sgibbs 228439223Sgibbs bt = (struct bt_softc*)arg; 228539223Sgibbs SLIST_FIRST(&bt->sg_maps)->sg_physaddr = segs->ds_addr; 228639223Sgibbs} 228739223Sgibbs 228839223Sgibbsstatic void 228939223Sgibbsbtpoll(struct cam_sim *sim) 229039223Sgibbs{ 2291241592Sjhb bt_intr_locked(cam_sim_softc(sim)); 229239223Sgibbs} 229339223Sgibbs 229439223Sgibbsvoid 229539223Sgibbsbttimeout(void *arg) 229639223Sgibbs{ 229739223Sgibbs struct bt_ccb *bccb; 229839223Sgibbs union ccb *ccb; 229939223Sgibbs struct bt_softc *bt; 230039223Sgibbs 230139223Sgibbs bccb = (struct bt_ccb *)arg; 230239223Sgibbs ccb = bccb->ccb; 230339223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 2304241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 230539223Sgibbs xpt_print_path(ccb->ccb_h.path); 230639390Sgibbs printf("CCB %p - timed out\n", (void *)bccb); 230739223Sgibbs 230839223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 230939223Sgibbs xpt_print_path(ccb->ccb_h.path); 231039390Sgibbs printf("CCB %p - timed out CCB already completed\n", 231139390Sgibbs (void *)bccb); 231239223Sgibbs return; 231339223Sgibbs } 231439223Sgibbs 231539223Sgibbs /* 231639223Sgibbs * In order to simplify the recovery process, we ask the XPT 231739223Sgibbs * layer to halt the queue of new transactions and we traverse 231839223Sgibbs * the list of pending CCBs and remove their timeouts. This 231939223Sgibbs * means that the driver attempts to clear only one error 232039223Sgibbs * condition at a time. In general, timeouts that occur 232139223Sgibbs * close together are related anyway, so there is no benefit 232239223Sgibbs * in attempting to handle errors in parrallel. Timeouts will 232339223Sgibbs * be reinstated when the recovery process ends. 232439223Sgibbs */ 232539223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) { 232639223Sgibbs struct ccb_hdr *ccb_h; 232739223Sgibbs 232839223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) { 232939223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 233039223Sgibbs bccb->flags |= BCCB_RELEASE_SIMQ; 233139223Sgibbs } 233239223Sgibbs 233339223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 233439223Sgibbs while (ccb_h != NULL) { 233539223Sgibbs struct bt_ccb *pending_bccb; 233639223Sgibbs 233739223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 2338241592Sjhb callout_stop(&pending_bccb->timer); 233939223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 234039223Sgibbs } 234139223Sgibbs } 234239223Sgibbs 234339223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) != 0 234439223Sgibbs || bt->cur_outbox->action_code != BMBO_FREE 234540418Sgibbs || ((bccb->hccb.tag_enable == TRUE) 234639223Sgibbs && (bt->firmware_ver[0] < '5'))) { 234739223Sgibbs /* 234839223Sgibbs * Try a full host adapter/SCSI bus reset. 234939223Sgibbs * We do this only if we have already attempted 235039223Sgibbs * to clear the condition with a BDR, or we cannot 235139223Sgibbs * attempt a BDR for lack of mailbox resources 235239223Sgibbs * or because of faulty firmware. It turns out 235339223Sgibbs * that firmware versions prior to 5.xx treat BDRs 235439223Sgibbs * as untagged commands that cannot be sent until 235539223Sgibbs * all outstanding tagged commands have been processed. 235639223Sgibbs * This makes it somewhat difficult to use a BDR to 235739223Sgibbs * clear up a problem with an uncompleted tagged command. 235839223Sgibbs */ 235939223Sgibbs ccb->ccb_h.status = CAM_CMD_TIMEOUT; 236039223Sgibbs btreset(bt, /*hardreset*/TRUE); 2361241592Sjhb device_printf(bt->dev, "No longer in timeout\n"); 236239223Sgibbs } else { 236339223Sgibbs /* 236439223Sgibbs * Send a Bus Device Reset message: 236539223Sgibbs * The target that is holding up the bus may not 236639223Sgibbs * be the same as the one that triggered this timeout 236739223Sgibbs * (different commands have different timeout lengths), 236839223Sgibbs * but we have no way of determining this from our 236939223Sgibbs * timeout handler. Our strategy here is to queue a 237039223Sgibbs * BDR message to the target of the timed out command. 237139223Sgibbs * If this fails, we'll get another timeout 2 seconds 237239223Sgibbs * later which will attempt a bus reset. 237339223Sgibbs */ 237439223Sgibbs bccb->flags |= BCCB_DEVICE_RESET; 2375241592Sjhb callout_reset(&bccb->timer, 2 * hz, bttimeout, bccb); 237639223Sgibbs 237739223Sgibbs bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET; 237839223Sgibbs 237939223Sgibbs /* No Data Transfer */ 238039223Sgibbs bt->recovery_bccb->hccb.datain = TRUE; 238139223Sgibbs bt->recovery_bccb->hccb.dataout = TRUE; 238239223Sgibbs bt->recovery_bccb->hccb.btstat = 0; 238339223Sgibbs bt->recovery_bccb->hccb.sdstat = 0; 238439223Sgibbs bt->recovery_bccb->hccb.target_id = ccb->ccb_h.target_id; 238539223Sgibbs 238639223Sgibbs /* Tell the adapter about this command */ 238739223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bt->recovery_bccb); 238839223Sgibbs bt->cur_outbox->action_code = BMBO_START; 238939223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 239039223Sgibbs btnextoutbox(bt); 239139223Sgibbs } 239239223Sgibbs} 239339223Sgibbs 2394165102SmjacobMODULE_VERSION(bt, 1); 2395165102SmjacobMODULE_DEPEND(bt, cam, 1, 1, 1); 2396