bt.c revision 46581
139223Sgibbs/* 239223Sgibbs * Generic driver for the BusLogic MultiMaster SCSI host adapters 339223Sgibbs * Product specific probe and attach routines can be found in: 439223Sgibbs * i386/isa/bt_isa.c BT-54X, BT-445 cards 539223Sgibbs * i386/eisa/bt_eisa.c BT-74x, BT-75x cards 639223Sgibbs * pci/bt_pci.c BT-946, BT-948, BT-956, BT-958 cards 739223Sgibbs * 844581Sgibbs * Copyright (c) 1998, 1999 Justin T. Gibbs. 939223Sgibbs * All rights reserved. 1039223Sgibbs * 1139223Sgibbs * Redistribution and use in source and binary forms, with or without 1239223Sgibbs * modification, are permitted provided that the following conditions 1339223Sgibbs * are met: 1439223Sgibbs * 1. Redistributions of source code must retain the above copyright 1539223Sgibbs * notice, this list of conditions, and the following disclaimer, 1639223Sgibbs * without modification, immediately at the beginning of the file. 1739223Sgibbs * 2. The name of the author may not be used to endorse or promote products 1839223Sgibbs * derived from this software without specific prior written permission. 1939223Sgibbs * 2039223Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2139223Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2239223Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2339223Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2439223Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2539223Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2639223Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2739223Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2839223Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2939223Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3039223Sgibbs * SUCH DAMAGE. 3139223Sgibbs * 3246581Sken * $Id: bt.c,v 1.19 1999/05/05 06:45:09 imp Exp $ 3339223Sgibbs */ 3439223Sgibbs 3539223Sgibbs /* 3639223Sgibbs * Special thanks to Leonard N. Zubkoff for writing such a complete and 3739223Sgibbs * well documented Mylex/BusLogic MultiMaster driver for Linux. Support 3839223Sgibbs * in this driver for the wide range of MultiMaster controllers and 3939223Sgibbs * firmware revisions, with their otherwise undocumented quirks, would not 4039223Sgibbs * have been possible without his efforts. 4139223Sgibbs */ 4239223Sgibbs 4339223Sgibbs#include <sys/param.h> 4439223Sgibbs#include <sys/systm.h> 4539223Sgibbs#include <sys/malloc.h> 4639223Sgibbs#include <sys/buf.h> 4739223Sgibbs#include <sys/kernel.h> 4839223Sgibbs#include <sys/sysctl.h> 4945791Speter#include <sys/bus.h> 5039223Sgibbs 5139223Sgibbs/* 5239223Sgibbs * XXX It appears that BusLogic PCI adapters go out to lunch if you 5339223Sgibbs * attempt to perform memory mapped I/O. 5439223Sgibbs */ 5539223Sgibbs#if 0 5639223Sgibbs#include "pci.h" 5739223Sgibbs#if NPCI > 0 5839223Sgibbs#include <machine/bus_memio.h> 5939223Sgibbs#endif 6039223Sgibbs#endif 6139223Sgibbs#include <machine/bus_pio.h> 6239223Sgibbs#include <machine/bus.h> 6339223Sgibbs#include <machine/clock.h> 6445791Speter#include <sys/rman.h> 6539223Sgibbs 6639223Sgibbs#include <cam/cam.h> 6739223Sgibbs#include <cam/cam_ccb.h> 6839223Sgibbs#include <cam/cam_sim.h> 6939223Sgibbs#include <cam/cam_xpt_sim.h> 7039223Sgibbs#include <cam/cam_debug.h> 7139223Sgibbs 7239223Sgibbs#include <cam/scsi/scsi_message.h> 7339223Sgibbs 7439223Sgibbs#include <vm/vm.h> 7539223Sgibbs#include <vm/pmap.h> 7639223Sgibbs 7739223Sgibbs#include <dev/buslogic/btreg.h> 7839223Sgibbs 7945444Sgibbs#ifndef MAX 8045444Sgibbs#define MAX(a, b) ((a) > (b) ? (a) : (b)) 8145444Sgibbs#endif 8245444Sgibbs 8339223Sgibbs/* MailBox Management functions */ 8439223Sgibbsstatic __inline void btnextinbox(struct bt_softc *bt); 8539223Sgibbsstatic __inline void btnextoutbox(struct bt_softc *bt); 8639223Sgibbs 8739223Sgibbsstatic __inline void 8839223Sgibbsbtnextinbox(struct bt_softc *bt) 8939223Sgibbs{ 9039223Sgibbs if (bt->cur_inbox == bt->last_inbox) 9139223Sgibbs bt->cur_inbox = bt->in_boxes; 9239223Sgibbs else 9339223Sgibbs bt->cur_inbox++; 9439223Sgibbs} 9539223Sgibbs 9639223Sgibbsstatic __inline void 9739223Sgibbsbtnextoutbox(struct bt_softc *bt) 9839223Sgibbs{ 9939223Sgibbs if (bt->cur_outbox == bt->last_outbox) 10039223Sgibbs bt->cur_outbox = bt->out_boxes; 10139223Sgibbs else 10239223Sgibbs bt->cur_outbox++; 10339223Sgibbs} 10439223Sgibbs 10539223Sgibbs/* CCB Mangement functions */ 10639223Sgibbsstatic __inline u_int32_t btccbvtop(struct bt_softc *bt, 10739223Sgibbs struct bt_ccb *bccb); 10839223Sgibbsstatic __inline struct bt_ccb* btccbptov(struct bt_softc *bt, 10939223Sgibbs u_int32_t ccb_addr); 11039223Sgibbsstatic __inline u_int32_t btsensepaddr(struct bt_softc *bt, 11139223Sgibbs struct bt_ccb *bccb); 11239223Sgibbsstatic __inline struct scsi_sense_data* btsensevaddr(struct bt_softc *bt, 11339223Sgibbs struct bt_ccb *bccb); 11439223Sgibbs 11539223Sgibbsstatic __inline u_int32_t 11639223Sgibbsbtccbvtop(struct bt_softc *bt, struct bt_ccb *bccb) 11739223Sgibbs{ 11839223Sgibbs return (bt->bt_ccb_physbase 11939223Sgibbs + (u_int32_t)((caddr_t)bccb - (caddr_t)bt->bt_ccb_array)); 12039223Sgibbs} 12139223Sgibbs 12239223Sgibbsstatic __inline struct bt_ccb * 12339223Sgibbsbtccbptov(struct bt_softc *bt, u_int32_t ccb_addr) 12439223Sgibbs{ 12539223Sgibbs return (bt->bt_ccb_array + 12639223Sgibbs ((struct bt_ccb*)ccb_addr-(struct bt_ccb*)bt->bt_ccb_physbase)); 12739223Sgibbs} 12839223Sgibbs 12939223Sgibbsstatic __inline u_int32_t 13039223Sgibbsbtsensepaddr(struct bt_softc *bt, struct bt_ccb *bccb) 13139223Sgibbs{ 13239223Sgibbs u_int index; 13339223Sgibbs 13439223Sgibbs index = (u_int)(bccb - bt->bt_ccb_array); 13539223Sgibbs return (bt->sense_buffers_physbase 13639223Sgibbs + (index * sizeof(struct scsi_sense_data))); 13739223Sgibbs} 13839223Sgibbs 13939223Sgibbsstatic __inline struct scsi_sense_data * 14039223Sgibbsbtsensevaddr(struct bt_softc *bt, struct bt_ccb *bccb) 14139223Sgibbs{ 14239223Sgibbs u_int index; 14339223Sgibbs 14439223Sgibbs index = (u_int)(bccb - bt->bt_ccb_array); 14539223Sgibbs return (bt->sense_buffers + index); 14639223Sgibbs} 14739223Sgibbs 14839223Sgibbsstatic __inline struct bt_ccb* btgetccb(struct bt_softc *bt); 14939223Sgibbsstatic __inline void btfreeccb(struct bt_softc *bt, 15039223Sgibbs struct bt_ccb *bccb); 15139223Sgibbsstatic void btallocccbs(struct bt_softc *bt); 15239223Sgibbsstatic bus_dmamap_callback_t btexecuteccb; 15339223Sgibbsstatic void btdone(struct bt_softc *bt, struct bt_ccb *bccb, 15439223Sgibbs bt_mbi_comp_code_t comp_code); 15539223Sgibbs 15639223Sgibbs/* Host adapter command functions */ 15739223Sgibbsstatic int btreset(struct bt_softc* bt, int hard_reset); 15839223Sgibbs 15939223Sgibbs/* Initialization functions */ 16039223Sgibbsstatic int btinitmboxes(struct bt_softc *bt); 16139223Sgibbsstatic bus_dmamap_callback_t btmapmboxes; 16239223Sgibbsstatic bus_dmamap_callback_t btmapccbs; 16339223Sgibbsstatic bus_dmamap_callback_t btmapsgs; 16439223Sgibbs 16539223Sgibbs/* Transfer Negotiation Functions */ 16639223Sgibbsstatic void btfetchtransinfo(struct bt_softc *bt, 16739223Sgibbs struct ccb_trans_settings *cts); 16839223Sgibbs 16939223Sgibbs/* CAM SIM entry points */ 17039223Sgibbs#define ccb_bccb_ptr spriv_ptr0 17139223Sgibbs#define ccb_bt_ptr spriv_ptr1 17239223Sgibbsstatic void btaction(struct cam_sim *sim, union ccb *ccb); 17339223Sgibbsstatic void btpoll(struct cam_sim *sim); 17439223Sgibbs 17539223Sgibbs/* Our timeout handler */ 17639223Sgibbstimeout_t bttimeout; 17739223Sgibbs 17839223Sgibbsu_long bt_unit = 0; 17939223Sgibbs 18039223Sgibbs/* 18139223Sgibbs * XXX 18239223Sgibbs * Do our own re-probe protection until a configuration 18339223Sgibbs * manager can do it for us. This ensures that we don't 18439223Sgibbs * reprobe a card already found by the EISA or PCI probes. 18539223Sgibbs */ 18639223Sgibbsstruct bt_isa_port bt_isa_ports[] = 18739223Sgibbs{ 18841048Sgibbs { 0x130, 0, 4 }, 18941048Sgibbs { 0x134, 0, 5 }, 19041048Sgibbs { 0x230, 0, 2 }, 19141048Sgibbs { 0x234, 0, 3 }, 19241048Sgibbs { 0x330, 0, 0 }, 19341048Sgibbs { 0x334, 0, 1 } 19439223Sgibbs}; 19539223Sgibbs 19641048Sgibbs/* 19741048Sgibbs * I/O ports listed in the order enumerated by the 19841048Sgibbs * card for certain op codes. 19941048Sgibbs */ 20041048Sgibbsu_int16_t bt_board_ports[] = 20141048Sgibbs{ 20241048Sgibbs 0x330, 20341048Sgibbs 0x334, 20441048Sgibbs 0x230, 20541048Sgibbs 0x234, 20641048Sgibbs 0x130, 20741048Sgibbs 0x134 20841048Sgibbs}; 20941048Sgibbs 21039223Sgibbs/* Exported functions */ 21145791Spetervoid 21245791Speterbt_init_softc(device_t dev, struct resource *port, 21345791Speter struct resource *irq, struct resource *drq) 21439223Sgibbs{ 21545791Speter struct bt_softc *bt = device_get_softc(dev); 21639223Sgibbs 21739223Sgibbs SLIST_INIT(&bt->free_bt_ccbs); 21839223Sgibbs LIST_INIT(&bt->pending_ccbs); 21939223Sgibbs SLIST_INIT(&bt->sg_maps); 22045791Speter bt->dev = dev; 22145791Speter bt->unit = device_get_unit(dev); 22245791Speter bt->port = port; 22345791Speter bt->irq = irq; 22445791Speter bt->drq = drq; 22545791Speter bt->tag = rman_get_bustag(port); 22645791Speter bt->bsh = rman_get_bushandle(port); 22739223Sgibbs} 22839223Sgibbs 22939223Sgibbsvoid 23045791Speterbt_free_softc(device_t dev) 23139223Sgibbs{ 23245791Speter struct bt_softc *bt = device_get_softc(dev); 23345791Speter 23439223Sgibbs switch (bt->init_level) { 23539223Sgibbs default: 23639223Sgibbs case 11: 23739223Sgibbs bus_dmamap_unload(bt->sense_dmat, bt->sense_dmamap); 23839223Sgibbs case 10: 23939223Sgibbs bus_dmamem_free(bt->sense_dmat, bt->sense_buffers, 24039223Sgibbs bt->sense_dmamap); 24139223Sgibbs case 9: 24239223Sgibbs bus_dma_tag_destroy(bt->sense_dmat); 24339223Sgibbs case 8: 24439223Sgibbs { 24539223Sgibbs struct sg_map_node *sg_map; 24639223Sgibbs 24739223Sgibbs while ((sg_map = SLIST_FIRST(&bt->sg_maps))!= NULL) { 24839223Sgibbs SLIST_REMOVE_HEAD(&bt->sg_maps, links); 24939223Sgibbs bus_dmamap_unload(bt->sg_dmat, 25039223Sgibbs sg_map->sg_dmamap); 25139223Sgibbs bus_dmamem_free(bt->sg_dmat, sg_map->sg_vaddr, 25239223Sgibbs sg_map->sg_dmamap); 25339223Sgibbs free(sg_map, M_DEVBUF); 25439223Sgibbs } 25539223Sgibbs bus_dma_tag_destroy(bt->sg_dmat); 25639223Sgibbs } 25739223Sgibbs case 7: 25839223Sgibbs bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap); 25939223Sgibbs case 6: 26039223Sgibbs bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array, 26139223Sgibbs bt->ccb_dmamap); 26239223Sgibbs bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap); 26339223Sgibbs case 5: 26439223Sgibbs bus_dma_tag_destroy(bt->ccb_dmat); 26539223Sgibbs case 4: 26639223Sgibbs bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap); 26739223Sgibbs case 3: 26839223Sgibbs bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes, 26939223Sgibbs bt->mailbox_dmamap); 27039223Sgibbs bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap); 27139223Sgibbs case 2: 27239223Sgibbs bus_dma_tag_destroy(bt->buffer_dmat); 27339223Sgibbs case 1: 27439223Sgibbs bus_dma_tag_destroy(bt->mailbox_dmat); 27539223Sgibbs case 0: 27639223Sgibbs break; 27739223Sgibbs } 27839223Sgibbs} 27939223Sgibbs 28044581Sgibbsint 28145791Speterbt_port_probe(device_t dev, struct bt_probe_info *info) 28244581Sgibbs{ 28345791Speter struct bt_softc *bt = device_get_softc(dev); 28444581Sgibbs config_data_t config_data; 28544581Sgibbs int error; 28644581Sgibbs 28744581Sgibbs /* See if there is really a card present */ 28845791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev)) 28944581Sgibbs return(1); 29044581Sgibbs 29144581Sgibbs /* 29244581Sgibbs * Determine our IRQ, and DMA settings and 29344581Sgibbs * export them to the configuration system. 29444581Sgibbs */ 29544581Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 29644581Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 29744581Sgibbs DEFAULT_CMD_TIMEOUT); 29844581Sgibbs if (error != 0) { 29944581Sgibbs printf("bt_port_probe: Could not determine IRQ or DMA " 30044581Sgibbs "settings for adapter.\n"); 30144581Sgibbs return (1); 30244581Sgibbs } 30344581Sgibbs 30444581Sgibbs if (bt->model[0] == '5') { 30544581Sgibbs /* DMA settings only make sense for ISA cards */ 30644581Sgibbs switch (config_data.dma_chan) { 30744581Sgibbs case DMA_CHAN_5: 30844581Sgibbs info->drq = 5; 30944581Sgibbs break; 31044581Sgibbs case DMA_CHAN_6: 31144581Sgibbs info->drq = 6; 31244581Sgibbs break; 31344581Sgibbs case DMA_CHAN_7: 31444581Sgibbs info->drq = 7; 31544581Sgibbs break; 31644581Sgibbs default: 31744581Sgibbs printf("bt_port_probe: Invalid DMA setting " 31844581Sgibbs "detected for adapter.\n"); 31944581Sgibbs return (1); 32044581Sgibbs } 32144581Sgibbs } else { 32244581Sgibbs /* VL/EISA/PCI DMA */ 32344581Sgibbs info->drq = -1; 32444581Sgibbs } 32544581Sgibbs switch (config_data.irq) { 32644581Sgibbs case IRQ_9: 32744581Sgibbs case IRQ_10: 32844581Sgibbs case IRQ_11: 32944581Sgibbs case IRQ_12: 33044581Sgibbs case IRQ_14: 33144581Sgibbs case IRQ_15: 33244581Sgibbs info->irq = ffs(config_data.irq) + 8; 33344581Sgibbs break; 33444581Sgibbs default: 33544581Sgibbs printf("bt_port_probe: Invalid IRQ setting %x" 33644581Sgibbs "detected for adapter.\n", config_data.irq); 33744581Sgibbs return (1); 33844581Sgibbs } 33944581Sgibbs return (0); 34044581Sgibbs} 34144581Sgibbs 34239223Sgibbs/* 34339223Sgibbs * Probe the adapter and verify that the card is a BusLogic. 34439223Sgibbs */ 34539223Sgibbsint 34645791Speterbt_probe(device_t dev) 34739223Sgibbs{ 34845791Speter struct bt_softc *bt = device_get_softc(dev); 34939223Sgibbs esetup_info_data_t esetup_info; 35039223Sgibbs u_int status; 35139223Sgibbs u_int intstat; 35239223Sgibbs u_int geometry; 35339223Sgibbs int error; 35439223Sgibbs u_int8_t param; 35539223Sgibbs 35639223Sgibbs /* 35739223Sgibbs * See if the three I/O ports look reasonable. 35839223Sgibbs * Touch the minimal number of registers in the 35939223Sgibbs * failure case. 36039223Sgibbs */ 36139223Sgibbs status = bt_inb(bt, STATUS_REG); 36239223Sgibbs if ((status == 0) 36339223Sgibbs || (status & (DIAG_ACTIVE|CMD_REG_BUSY| 36439223Sgibbs STATUS_REG_RSVD|CMD_INVALID)) != 0) { 36539223Sgibbs if (bootverbose) 36645791Speter device_printf(dev, "Failed Status Reg Test - %x\n", 36739223Sgibbs status); 36839223Sgibbs return (ENXIO); 36939223Sgibbs } 37039223Sgibbs 37139223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 37239223Sgibbs if ((intstat & INTSTAT_REG_RSVD) != 0) { 37345791Speter device_printf(dev, "Failed Intstat Reg Test\n"); 37439223Sgibbs return (ENXIO); 37539223Sgibbs } 37639223Sgibbs 37739223Sgibbs geometry = bt_inb(bt, GEOMETRY_REG); 37839223Sgibbs if (geometry == 0xFF) { 37939223Sgibbs if (bootverbose) 38045791Speter device_printf(dev, "Failed Geometry Reg Test\n"); 38139223Sgibbs return (ENXIO); 38239223Sgibbs } 38339223Sgibbs 38439223Sgibbs /* 38539223Sgibbs * Looking good so far. Final test is to reset the 38639223Sgibbs * adapter and attempt to fetch the extended setup 38739223Sgibbs * information. This should filter out all 1542 cards. 38839223Sgibbs */ 38939223Sgibbs if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) { 39039223Sgibbs if (bootverbose) 39145791Speter device_printf(dev, "Failed Reset\n"); 39239223Sgibbs return (ENXIO); 39339223Sgibbs } 39439223Sgibbs 39539223Sgibbs param = sizeof(esetup_info); 39639223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, ¶m, /*parmlen*/1, 39739223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 39839223Sgibbs DEFAULT_CMD_TIMEOUT); 39939223Sgibbs if (error != 0) { 40039223Sgibbs return (ENXIO); 40139223Sgibbs } 40239223Sgibbs 40339223Sgibbs return (0); 40439223Sgibbs} 40539223Sgibbs 40639223Sgibbs/* 40739223Sgibbs * Pull the boards setup information and record it in our softc. 40839223Sgibbs */ 40939223Sgibbsint 41045791Speterbt_fetch_adapter_info(device_t dev) 41139223Sgibbs{ 41245791Speter struct bt_softc *bt = device_get_softc(dev); 41339223Sgibbs board_id_data_t board_id; 41439223Sgibbs esetup_info_data_t esetup_info; 41539223Sgibbs config_data_t config_data; 41639223Sgibbs int error; 41739223Sgibbs u_int8_t length_param; 41839223Sgibbs 41939223Sgibbs /* First record the firmware version */ 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) { 42445791Speter device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n"); 42539223Sgibbs return (error); 42639223Sgibbs } 42739223Sgibbs bt->firmware_ver[0] = board_id.firmware_rev_major; 42839223Sgibbs bt->firmware_ver[1] = '.'; 42939223Sgibbs bt->firmware_ver[2] = board_id.firmware_rev_minor; 43039223Sgibbs bt->firmware_ver[3] = '\0'; 43139223Sgibbs 43239223Sgibbs /* 43339223Sgibbs * Depending on the firmware major and minor version, 43439223Sgibbs * we may be able to fetch additional minor version info. 43539223Sgibbs */ 43639223Sgibbs if (bt->firmware_ver[0] > '0') { 43739223Sgibbs 43839223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0, 43939223Sgibbs (u_int8_t*)&bt->firmware_ver[3], 1, 44039223Sgibbs DEFAULT_CMD_TIMEOUT); 44139223Sgibbs if (error != 0) { 44245791Speter device_printf(dev, 44345791Speter "bt_fetch_adapter_info - Failed Get " 44445791Speter "Firmware 3rd Digit\n"); 44539223Sgibbs return (error); 44639223Sgibbs } 44739223Sgibbs if (bt->firmware_ver[3] == ' ') 44839223Sgibbs bt->firmware_ver[3] = '\0'; 44939223Sgibbs bt->firmware_ver[4] = '\0'; 45039223Sgibbs } 45139223Sgibbs 45239223Sgibbs if (strcmp(bt->firmware_ver, "3.3") >= 0) { 45339223Sgibbs 45439223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_4DIG, NULL, /*parmlen*/0, 45539223Sgibbs (u_int8_t*)&bt->firmware_ver[4], 1, 45639223Sgibbs DEFAULT_CMD_TIMEOUT); 45739223Sgibbs if (error != 0) { 45845791Speter device_printf(dev, 45945791Speter "bt_fetch_adapter_info - Failed Get " 46045791Speter "Firmware 4th Digit\n"); 46139223Sgibbs return (error); 46239223Sgibbs } 46339223Sgibbs if (bt->firmware_ver[4] == ' ') 46439223Sgibbs bt->firmware_ver[4] = '\0'; 46539223Sgibbs bt->firmware_ver[5] = '\0'; 46639223Sgibbs } 46739223Sgibbs 46839223Sgibbs /* 46939223Sgibbs * Some boards do not handle the "recently documented" 47039223Sgibbs * Inquire Board Model Number command correctly or do not give 47139223Sgibbs * exact information. Use the Firmware and Extended Setup 47239223Sgibbs * information in these cases to come up with the right answer. 47339223Sgibbs * The major firmware revision number indicates: 47439223Sgibbs * 47539223Sgibbs * 5.xx BusLogic "W" Series Host Adapters: 47639223Sgibbs * BT-948/958/958D 47739223Sgibbs * 4.xx BusLogic "C" Series Host Adapters: 47839223Sgibbs * BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF 47939223Sgibbs * 3.xx BusLogic "S" Series Host Adapters: 48039223Sgibbs * BT-747S/747D/757S/757D/445S/545S/542D 48139223Sgibbs * BT-542B/742A (revision H) 48239223Sgibbs * 2.xx BusLogic "A" Series Host Adapters: 48339223Sgibbs * BT-542B/742A (revision G and below) 48439223Sgibbs * 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter 48539223Sgibbs */ 48639223Sgibbs length_param = sizeof(esetup_info); 48739223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &length_param, /*parmlen*/1, 48839223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 48939223Sgibbs DEFAULT_CMD_TIMEOUT); 49039223Sgibbs if (error != 0) { 49139223Sgibbs return (error); 49239223Sgibbs } 49339223Sgibbs 49439223Sgibbs bt->bios_addr = esetup_info.bios_addr << 12; 49539223Sgibbs 49639223Sgibbs if (esetup_info.bus_type == 'A' 49739223Sgibbs && bt->firmware_ver[0] == '2') { 49841514Sarchie snprintf(bt->model, sizeof(bt->model), "542B"); 49939223Sgibbs } else if (esetup_info.bus_type == 'E' 50039223Sgibbs && (strncmp(bt->firmware_ver, "2.1", 3) == 0 50139223Sgibbs || strncmp(bt->firmware_ver, "2.20", 4) == 0)) { 50241514Sarchie snprintf(bt->model, sizeof(bt->model), "742A"); 50339223Sgibbs } else if (esetup_info.bus_type == 'E' 50439223Sgibbs && bt->firmware_ver[0] == '0') { 50539223Sgibbs /* AMI FastDisk EISA Series 441 0.x */ 50641514Sarchie snprintf(bt->model, sizeof(bt->model), "747A"); 50739223Sgibbs } else { 50839223Sgibbs ha_model_data_t model_data; 50939223Sgibbs int i; 51039223Sgibbs 51139223Sgibbs length_param = sizeof(model_data); 51239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1, 51339223Sgibbs (u_int8_t*)&model_data, sizeof(model_data), 51439223Sgibbs DEFAULT_CMD_TIMEOUT); 51539223Sgibbs if (error != 0) { 51645791Speter device_printf(dev, 51745791Speter "bt_fetch_adapter_info - Failed Inquire " 51845791Speter "Model Number\n"); 51939223Sgibbs return (error); 52039223Sgibbs } 52139223Sgibbs for (i = 0; i < sizeof(model_data.ascii_model); i++) { 52239223Sgibbs bt->model[i] = model_data.ascii_model[i]; 52339223Sgibbs if (bt->model[i] == ' ') 52439223Sgibbs break; 52539223Sgibbs } 52639223Sgibbs bt->model[i] = '\0'; 52739223Sgibbs } 52839223Sgibbs 52944581Sgibbs bt->level_trigger_ints = esetup_info.level_trigger_ints ? 1 : 0; 53044581Sgibbs 53139223Sgibbs /* SG element limits */ 53239223Sgibbs bt->max_sg = esetup_info.max_sg; 53339223Sgibbs 53439223Sgibbs /* Set feature flags */ 53539223Sgibbs bt->wide_bus = esetup_info.wide_bus; 53639223Sgibbs bt->diff_bus = esetup_info.diff_bus; 53739223Sgibbs bt->ultra_scsi = esetup_info.ultra_scsi; 53839223Sgibbs 53939223Sgibbs if ((bt->firmware_ver[0] == '5') 54039223Sgibbs || (bt->firmware_ver[0] == '4' && bt->wide_bus)) 54139223Sgibbs bt->extended_lun = TRUE; 54239223Sgibbs 54339223Sgibbs bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0); 54439223Sgibbs 54539223Sgibbs bt->extended_trans = 54639223Sgibbs ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0); 54739223Sgibbs 54839223Sgibbs /* 54939223Sgibbs * Determine max CCB count and whether tagged queuing is 55039223Sgibbs * available based on controller type. Tagged queuing 55139223Sgibbs * only works on 'W' series adapters, 'C' series adapters 55239223Sgibbs * with firmware of rev 4.42 and higher, and 'S' series 55339223Sgibbs * adapters with firmware of rev 3.35 and higher. The 55439223Sgibbs * maximum CCB counts are as follows: 55539223Sgibbs * 55639223Sgibbs * 192 BT-948/958/958D 55739223Sgibbs * 100 BT-946C/956C/956CD/747C/757C/757CD/445C 55839223Sgibbs * 50 BT-545C/540CF 55939223Sgibbs * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A 56039223Sgibbs */ 56139223Sgibbs if (bt->firmware_ver[0] == '5') { 56239223Sgibbs bt->max_ccbs = 192; 56339223Sgibbs bt->tag_capable = TRUE; 56439223Sgibbs } else if (bt->firmware_ver[0] == '4') { 56539223Sgibbs if (bt->model[0] == '5') 56639223Sgibbs bt->max_ccbs = 50; 56739223Sgibbs else 56839223Sgibbs bt->max_ccbs = 100; 56939223Sgibbs bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0); 57039223Sgibbs } else { 57139223Sgibbs bt->max_ccbs = 30; 57239223Sgibbs if (bt->firmware_ver[0] == '3' 57339223Sgibbs && (strcmp(bt->firmware_ver, "3.35") >= 0)) 57439223Sgibbs bt->tag_capable = TRUE; 57539223Sgibbs else 57639223Sgibbs bt->tag_capable = FALSE; 57739223Sgibbs } 57839223Sgibbs 57939223Sgibbs if (bt->tag_capable != FALSE) 58039223Sgibbs bt->tags_permitted = ALL_TARGETS; 58139223Sgibbs 58239223Sgibbs /* Determine Sync/Wide/Disc settings */ 58339223Sgibbs if (bt->firmware_ver[0] >= '4') { 58439223Sgibbs auto_scsi_data_t auto_scsi_data; 58539223Sgibbs fetch_lram_params_t fetch_lram_params; 58639223Sgibbs int error; 58739223Sgibbs 58839223Sgibbs /* 58939223Sgibbs * These settings are stored in the 59039223Sgibbs * AutoSCSI data in LRAM of 'W' and 'C' 59139223Sgibbs * adapters. 59239223Sgibbs */ 59339223Sgibbs fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET; 59439223Sgibbs fetch_lram_params.response_len = sizeof(auto_scsi_data); 59539223Sgibbs error = bt_cmd(bt, BOP_FETCH_LRAM, 59639223Sgibbs (u_int8_t*)&fetch_lram_params, 59739223Sgibbs sizeof(fetch_lram_params), 59839223Sgibbs (u_int8_t*)&auto_scsi_data, 59939223Sgibbs sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT); 60039223Sgibbs 60139223Sgibbs if (error != 0) { 60245791Speter device_printf(dev, 60345791Speter "bt_fetch_adapter_info - Failed " 60445791Speter "Get Auto SCSI Info\n"); 60539223Sgibbs return (error); 60639223Sgibbs } 60739223Sgibbs 60839223Sgibbs bt->disc_permitted = auto_scsi_data.low_disc_permitted 60939223Sgibbs | (auto_scsi_data.high_disc_permitted << 8); 61039223Sgibbs bt->sync_permitted = auto_scsi_data.low_sync_permitted 61139223Sgibbs | (auto_scsi_data.high_sync_permitted << 8); 61239223Sgibbs bt->fast_permitted = auto_scsi_data.low_fast_permitted 61339223Sgibbs | (auto_scsi_data.high_fast_permitted << 8); 61439223Sgibbs bt->ultra_permitted = auto_scsi_data.low_ultra_permitted 61539223Sgibbs | (auto_scsi_data.high_ultra_permitted << 8); 61639223Sgibbs bt->wide_permitted = auto_scsi_data.low_wide_permitted 61739223Sgibbs | (auto_scsi_data.high_wide_permitted << 8); 61839223Sgibbs 61939223Sgibbs if (bt->ultra_scsi == FALSE) 62039223Sgibbs bt->ultra_permitted = 0; 62139223Sgibbs 62239223Sgibbs if (bt->wide_bus == FALSE) 62339223Sgibbs bt->wide_permitted = 0; 62439223Sgibbs } else { 62539223Sgibbs /* 62639223Sgibbs * 'S' and 'A' series have this information in the setup 62739223Sgibbs * information structure. 62839223Sgibbs */ 62939223Sgibbs setup_data_t setup_info; 63039223Sgibbs 63139223Sgibbs length_param = sizeof(setup_info); 63239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param, 63339223Sgibbs /*paramlen*/1, (u_int8_t*)&setup_info, 63439223Sgibbs sizeof(setup_info), DEFAULT_CMD_TIMEOUT); 63539223Sgibbs 63639223Sgibbs if (error != 0) { 63745791Speter device_printf(dev, 63845791Speter "bt_fetch_adapter_info - Failed " 63945791Speter "Get Setup Info\n"); 64039223Sgibbs return (error); 64139223Sgibbs } 64239223Sgibbs 64339223Sgibbs if (setup_info.initiate_sync != 0) { 64439223Sgibbs bt->sync_permitted = ALL_TARGETS; 64539223Sgibbs 64639223Sgibbs if (bt->model[0] == '7') { 64739223Sgibbs if (esetup_info.sync_neg10MB != 0) 64839223Sgibbs bt->fast_permitted = ALL_TARGETS; 64939223Sgibbs if (strcmp(bt->model, "757") == 0) 65039223Sgibbs bt->wide_permitted = ALL_TARGETS; 65139223Sgibbs } 65239223Sgibbs } 65339223Sgibbs bt->disc_permitted = ALL_TARGETS; 65439223Sgibbs } 65539223Sgibbs 65639223Sgibbs /* We need as many mailboxes as we can have ccbs */ 65739223Sgibbs bt->num_boxes = bt->max_ccbs; 65839223Sgibbs 65939223Sgibbs /* Determine our SCSI ID */ 66039223Sgibbs 66139223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 66239223Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 66339223Sgibbs DEFAULT_CMD_TIMEOUT); 66439223Sgibbs if (error != 0) { 66545791Speter device_printf(dev, 66645791Speter "bt_fetch_adapter_info - Failed Get Config\n"); 66739223Sgibbs return (error); 66839223Sgibbs } 66939223Sgibbs bt->scsi_id = config_data.scsi_id; 67039223Sgibbs 67139223Sgibbs return (0); 67239223Sgibbs} 67339223Sgibbs 67439223Sgibbs/* 67539223Sgibbs * Start the board, ready for normal operation 67639223Sgibbs */ 67739223Sgibbsint 67845791Speterbt_init(device_t dev) 67939223Sgibbs{ 68045791Speter struct bt_softc *bt = device_get_softc(dev); 68145791Speter 68239223Sgibbs /* Announce the Adapter */ 68345791Speter device_printf(dev, "BT-%s FW Rev. %s ", bt->model, bt->firmware_ver); 68439223Sgibbs 68539223Sgibbs if (bt->ultra_scsi != 0) 68639223Sgibbs printf("Ultra "); 68739223Sgibbs 68839223Sgibbs if (bt->wide_bus != 0) 68939223Sgibbs printf("Wide "); 69039223Sgibbs else 69139223Sgibbs printf("Narrow "); 69239223Sgibbs 69339223Sgibbs if (bt->diff_bus != 0) 69439223Sgibbs printf("Diff "); 69539223Sgibbs 69639223Sgibbs printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id, 69739223Sgibbs bt->max_ccbs); 69839223Sgibbs 69939223Sgibbs /* 70039223Sgibbs * Create our DMA tags. These tags define the kinds of device 70139223Sgibbs * accessable memory allocations and memory mappings we will 70239223Sgibbs * need to perform during normal operation. 70339223Sgibbs * 70439223Sgibbs * Unless we need to further restrict the allocation, we rely 70539223Sgibbs * on the restrictions of the parent dmat, hence the common 70639223Sgibbs * use of MAXADDR and MAXSIZE. 70739223Sgibbs */ 70839223Sgibbs 70939223Sgibbs /* DMA tag for mapping buffers into device visible space. */ 71039223Sgibbs if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0, 71139223Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR, 71239223Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 71339223Sgibbs /*filter*/NULL, /*filterarg*/NULL, 71439223Sgibbs /*maxsize*/MAXBSIZE, /*nsegments*/BT_NSEG, 71539223Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 71639223Sgibbs /*flags*/BUS_DMA_ALLOCNOW, 71739223Sgibbs &bt->buffer_dmat) != 0) { 71839223Sgibbs goto error_exit; 71939223Sgibbs } 72039223Sgibbs 72139223Sgibbs bt->init_level++; 72239223Sgibbs /* DMA tag for our mailboxes */ 72339223Sgibbs if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0, 72439223Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR, 72539223Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 72639223Sgibbs /*filter*/NULL, /*filterarg*/NULL, 72739223Sgibbs bt->num_boxes * (sizeof(bt_mbox_in_t) 72839223Sgibbs + sizeof(bt_mbox_out_t)), 72939223Sgibbs /*nsegments*/1, 73039223Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 73139223Sgibbs /*flags*/0, &bt->mailbox_dmat) != 0) { 73239223Sgibbs goto error_exit; 73339223Sgibbs } 73439223Sgibbs 73539223Sgibbs bt->init_level++; 73639223Sgibbs 73739223Sgibbs /* Allocation for our mailboxes */ 73839223Sgibbs if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes, 73939223Sgibbs BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) { 74039223Sgibbs goto error_exit; 74139223Sgibbs } 74239223Sgibbs 74339223Sgibbs bt->init_level++; 74439223Sgibbs 74539223Sgibbs /* And permanently map them */ 74639223Sgibbs bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap, 74739223Sgibbs bt->out_boxes, 74839223Sgibbs bt->num_boxes * (sizeof(bt_mbox_in_t) 74939223Sgibbs + sizeof(bt_mbox_out_t)), 75039223Sgibbs btmapmboxes, bt, /*flags*/0); 75139223Sgibbs 75239223Sgibbs bt->init_level++; 75339223Sgibbs 75439223Sgibbs bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes]; 75539223Sgibbs 75639223Sgibbs btinitmboxes(bt); 75739223Sgibbs 75839223Sgibbs /* DMA tag for our ccb structures */ 75939223Sgibbs if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0, 76039223Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR, 76139223Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 76239223Sgibbs /*filter*/NULL, /*filterarg*/NULL, 76339223Sgibbs bt->max_ccbs * sizeof(struct bt_ccb), 76439223Sgibbs /*nsegments*/1, 76539223Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 76639223Sgibbs /*flags*/0, &bt->ccb_dmat) != 0) { 76739223Sgibbs goto error_exit; 76839223Sgibbs } 76939223Sgibbs 77039223Sgibbs bt->init_level++; 77139223Sgibbs 77239223Sgibbs /* Allocation for our ccbs */ 77339223Sgibbs if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array, 77439223Sgibbs BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) { 77539223Sgibbs goto error_exit; 77639223Sgibbs } 77739223Sgibbs 77839223Sgibbs bt->init_level++; 77939223Sgibbs 78039223Sgibbs /* And permanently map them */ 78139223Sgibbs bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap, 78239223Sgibbs bt->bt_ccb_array, 78339223Sgibbs bt->max_ccbs * sizeof(struct bt_ccb), 78439223Sgibbs btmapccbs, bt, /*flags*/0); 78539223Sgibbs 78639223Sgibbs bt->init_level++; 78739223Sgibbs 78839223Sgibbs /* DMA tag for our S/G structures. We allocate in page sized chunks */ 78939223Sgibbs if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0, 79039223Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR, 79139223Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 79239223Sgibbs /*filter*/NULL, /*filterarg*/NULL, 79339223Sgibbs PAGE_SIZE, /*nsegments*/1, 79439223Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 79539223Sgibbs /*flags*/0, &bt->sg_dmat) != 0) { 79639223Sgibbs goto error_exit; 79739223Sgibbs } 79839223Sgibbs 79939223Sgibbs bt->init_level++; 80039223Sgibbs 80139223Sgibbs /* Perform initial CCB allocation */ 80239223Sgibbs bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb)); 80339223Sgibbs btallocccbs(bt); 80439223Sgibbs 80539223Sgibbs if (bt->num_ccbs == 0) { 80645791Speter device_printf(dev, 80745791Speter "bt_init - Unable to allocate initial ccbs\n"); 80839223Sgibbs goto error_exit; 80939223Sgibbs } 81039223Sgibbs 81139223Sgibbs /* 81239223Sgibbs * Note that we are going and return (to probe) 81339223Sgibbs */ 81439223Sgibbs return 0; 81539223Sgibbs 81639223Sgibbserror_exit: 81739223Sgibbs 81839223Sgibbs return (ENXIO); 81939223Sgibbs} 82039223Sgibbs 82139223Sgibbsint 82245791Speterbt_attach(device_t dev) 82339223Sgibbs{ 82445791Speter struct bt_softc *bt = device_get_softc(dev); 82539223Sgibbs int tagged_dev_openings; 82639223Sgibbs struct cam_devq *devq; 82745795Speter int error; 82839223Sgibbs 82939223Sgibbs /* 83039223Sgibbs * We reserve 1 ccb for error recovery, so don't 83139223Sgibbs * tell the XPT about it. 83239223Sgibbs */ 83339223Sgibbs if (bt->tag_capable != 0) 83439223Sgibbs tagged_dev_openings = bt->max_ccbs - 1; 83539223Sgibbs else 83639223Sgibbs tagged_dev_openings = 0; 83739223Sgibbs 83839223Sgibbs /* 83939223Sgibbs * Create the device queue for our SIM. 84039223Sgibbs */ 84139223Sgibbs devq = cam_simq_alloc(bt->max_ccbs - 1); 84239223Sgibbs if (devq == NULL) 84339223Sgibbs return (ENOMEM); 84439223Sgibbs 84539223Sgibbs /* 84639223Sgibbs * Construct our SIM entry 84739223Sgibbs */ 84839223Sgibbs bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit, 84939223Sgibbs 2, tagged_dev_openings, devq); 85039223Sgibbs if (bt->sim == NULL) { 85139223Sgibbs cam_simq_free(devq); 85239223Sgibbs return (ENOMEM); 85339223Sgibbs } 85439223Sgibbs 85539223Sgibbs if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) { 85639223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 85739223Sgibbs return (ENXIO); 85839223Sgibbs } 85939223Sgibbs 86039223Sgibbs if (xpt_create_path(&bt->path, /*periph*/NULL, 86139223Sgibbs cam_sim_path(bt->sim), CAM_TARGET_WILDCARD, 86239223Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 86339223Sgibbs xpt_bus_deregister(cam_sim_path(bt->sim)); 86439223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 86539223Sgibbs return (ENXIO); 86639223Sgibbs } 86739223Sgibbs 86845791Speter /* 86945791Speter * Setup interrupt. 87045791Speter */ 87145795Speter error = bus_setup_intr(dev, bt->irq, bt_intr, bt, &bt->ih); 87245795Speter if (error) { 87345795Speter device_printf(dev, "bus_setup_intr() failed: %d\n", error); 87445795Speter return (error); 87545795Speter } 87645791Speter 87739223Sgibbs return (0); 87839223Sgibbs} 87939223Sgibbs 88039223Sgibbsint 88139223Sgibbsbt_check_probed_iop(u_int ioport) 88239223Sgibbs{ 88339223Sgibbs u_int i; 88439223Sgibbs 88541048Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 88639223Sgibbs if (bt_isa_ports[i].addr == ioport) { 88739223Sgibbs if (bt_isa_ports[i].probed != 0) 88839223Sgibbs return (1); 88939223Sgibbs else { 89039223Sgibbs return (0); 89139223Sgibbs } 89239223Sgibbs } 89339223Sgibbs } 89439223Sgibbs return (1); 89539223Sgibbs} 89639223Sgibbs 89739223Sgibbsvoid 89839223Sgibbsbt_mark_probed_bio(isa_compat_io_t port) 89939223Sgibbs{ 90039223Sgibbs if (port < BIO_DISABLED) 90141048Sgibbs bt_mark_probed_iop(bt_board_ports[port]); 90239223Sgibbs} 90339223Sgibbs 90439223Sgibbsvoid 90539223Sgibbsbt_mark_probed_iop(u_int ioport) 90639223Sgibbs{ 90739223Sgibbs u_int i; 90839223Sgibbs 90939223Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 91039223Sgibbs if (ioport == bt_isa_ports[i].addr) { 91139223Sgibbs bt_isa_ports[i].probed = 1; 91239223Sgibbs break; 91339223Sgibbs } 91439223Sgibbs } 91539223Sgibbs} 91639223Sgibbs 91741048Sgibbsvoid 91841048Sgibbsbt_find_probe_range(int ioport, int *port_index, int *max_port_index) 91941048Sgibbs{ 92041048Sgibbs if (ioport > 0) { 92141048Sgibbs int i; 92241048Sgibbs 92341048Sgibbs for (i = 0;i < BT_NUM_ISAPORTS; i++) 92441048Sgibbs if (ioport <= bt_isa_ports[i].addr) 92541048Sgibbs break; 92641048Sgibbs if ((i >= BT_NUM_ISAPORTS) 92741048Sgibbs || (ioport != bt_isa_ports[i].addr)) { 92841048Sgibbs printf(" 92941048Sgibbsbt_isa_probe: Invalid baseport of 0x%x specified. 93041048Sgibbsbt_isa_probe: Nearest valid baseport is 0x%x. 93141048Sgibbsbt_isa_probe: Failing probe.\n", 93241048Sgibbs ioport, 93341048Sgibbs (i < BT_NUM_ISAPORTS) 93441048Sgibbs ? bt_isa_ports[i].addr 93541048Sgibbs : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr); 93641048Sgibbs *port_index = *max_port_index = -1; 93741048Sgibbs return; 93841048Sgibbs } 93941048Sgibbs *port_index = *max_port_index = bt_isa_ports[i].bio; 94041048Sgibbs } else { 94141048Sgibbs *port_index = 0; 94241048Sgibbs *max_port_index = BT_NUM_ISAPORTS - 1; 94341048Sgibbs } 94441048Sgibbs} 94541048Sgibbs 94641048Sgibbsint 94741048Sgibbsbt_iop_from_bio(isa_compat_io_t bio_index) 94841048Sgibbs{ 94941048Sgibbs if (bio_index >= 0 && bio_index < BT_NUM_ISAPORTS) 95041048Sgibbs return (bt_board_ports[bio_index]); 95141048Sgibbs return (-1); 95241048Sgibbs} 95341048Sgibbs 95441048Sgibbs 95539223Sgibbsstatic void 95639223Sgibbsbtallocccbs(struct bt_softc *bt) 95739223Sgibbs{ 95839223Sgibbs struct bt_ccb *next_ccb; 95939223Sgibbs struct sg_map_node *sg_map; 96039223Sgibbs bus_addr_t physaddr; 96139223Sgibbs bt_sg_t *segs; 96239223Sgibbs int newcount; 96339223Sgibbs int i; 96439223Sgibbs 96545966Sgibbs if (bt->num_ccbs >= bt->max_ccbs) 96645966Sgibbs /* Can't allocate any more */ 96745966Sgibbs return; 96845966Sgibbs 96939223Sgibbs next_ccb = &bt->bt_ccb_array[bt->num_ccbs]; 97039223Sgibbs 97139223Sgibbs sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 97239223Sgibbs 97339223Sgibbs if (sg_map == NULL) 97445966Sgibbs goto error_exit; 97539223Sgibbs 97639223Sgibbs /* Allocate S/G space for the next batch of CCBS */ 97739223Sgibbs if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr, 97839223Sgibbs BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { 97939223Sgibbs free(sg_map, M_DEVBUF); 98045966Sgibbs goto error_exit; 98139223Sgibbs } 98239223Sgibbs 98339223Sgibbs SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links); 98439223Sgibbs 98539223Sgibbs bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, 98639223Sgibbs PAGE_SIZE, btmapsgs, bt, /*flags*/0); 98739223Sgibbs 98839223Sgibbs segs = sg_map->sg_vaddr; 98939223Sgibbs physaddr = sg_map->sg_physaddr; 99039223Sgibbs 99139223Sgibbs newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t))); 99239223Sgibbs for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) { 99339223Sgibbs int error; 99439223Sgibbs 99539223Sgibbs next_ccb->sg_list = segs; 99639223Sgibbs next_ccb->sg_list_phys = physaddr; 99739223Sgibbs next_ccb->flags = BCCB_FREE; 99839223Sgibbs error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0, 99939223Sgibbs &next_ccb->dmamap); 100039223Sgibbs if (error != 0) 100139223Sgibbs break; 100239223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links); 100339223Sgibbs segs += BT_NSEG; 100439223Sgibbs physaddr += (BT_NSEG * sizeof(bt_sg_t)); 100539223Sgibbs next_ccb++; 100639223Sgibbs bt->num_ccbs++; 100739223Sgibbs } 100839223Sgibbs 100939223Sgibbs /* Reserve a CCB for error recovery */ 101039223Sgibbs if (bt->recovery_bccb == NULL) { 101139223Sgibbs bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs); 101239223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 101339223Sgibbs } 101445966Sgibbs 101545966Sgibbs if (SLIST_FIRST(&bt->free_bt_ccbs) != NULL) 101645966Sgibbs return; 101745966Sgibbs 101845966Sgibbserror_exit: 101945966Sgibbs device_printf(bt->dev, "Can't malloc BCCBs\n"); 102039223Sgibbs} 102139223Sgibbs 102239223Sgibbsstatic __inline void 102339223Sgibbsbtfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) 102439223Sgibbs{ 102539223Sgibbs int s; 102639223Sgibbs 102739223Sgibbs s = splcam(); 102839223Sgibbs if ((bccb->flags & BCCB_ACTIVE) != 0) 102939223Sgibbs LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le); 103039223Sgibbs if (bt->resource_shortage != 0 103139223Sgibbs && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 103239223Sgibbs bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 103339223Sgibbs bt->resource_shortage = FALSE; 103439223Sgibbs } 103539223Sgibbs bccb->flags = BCCB_FREE; 103639223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links); 103741048Sgibbs bt->active_ccbs--; 103839223Sgibbs splx(s); 103939223Sgibbs} 104039223Sgibbs 104139223Sgibbsstatic __inline struct bt_ccb* 104239223Sgibbsbtgetccb(struct bt_softc *bt) 104339223Sgibbs{ 104439223Sgibbs struct bt_ccb* bccb; 104539223Sgibbs int s; 104639223Sgibbs 104739223Sgibbs s = splcam(); 104839223Sgibbs if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) { 104939223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 105041048Sgibbs bt->active_ccbs++; 105145966Sgibbs } else { 105239223Sgibbs btallocccbs(bt); 105339223Sgibbs bccb = SLIST_FIRST(&bt->free_bt_ccbs); 105445966Sgibbs if (bccb != NULL) { 105539223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 105641048Sgibbs bt->active_ccbs++; 105741048Sgibbs } 105839223Sgibbs } 105939223Sgibbs splx(s); 106039223Sgibbs 106139223Sgibbs return (bccb); 106239223Sgibbs} 106339223Sgibbs 106439223Sgibbsstatic void 106539223Sgibbsbtaction(struct cam_sim *sim, union ccb *ccb) 106639223Sgibbs{ 106739223Sgibbs struct bt_softc *bt; 106839223Sgibbs 106939223Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n")); 107039223Sgibbs 107139223Sgibbs bt = (struct bt_softc *)cam_sim_softc(sim); 107239223Sgibbs 107339223Sgibbs switch (ccb->ccb_h.func_code) { 107439223Sgibbs /* Common cases first */ 107539223Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 107639223Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 107739223Sgibbs { 107839223Sgibbs struct bt_ccb *bccb; 107939223Sgibbs struct bt_hccb *hccb; 108039223Sgibbs 108139223Sgibbs /* 108239223Sgibbs * get a bccb to use. 108339223Sgibbs */ 108439223Sgibbs if ((bccb = btgetccb(bt)) == NULL) { 108539223Sgibbs int s; 108639223Sgibbs 108739223Sgibbs s = splcam(); 108839223Sgibbs bt->resource_shortage = TRUE; 108939223Sgibbs splx(s); 109039223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 109139223Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 109239223Sgibbs xpt_done(ccb); 109339223Sgibbs return; 109439223Sgibbs } 109539223Sgibbs 109639223Sgibbs hccb = &bccb->hccb; 109739223Sgibbs 109839223Sgibbs /* 109939223Sgibbs * So we can find the BCCB when an abort is requested 110039223Sgibbs */ 110139223Sgibbs bccb->ccb = ccb; 110239223Sgibbs ccb->ccb_h.ccb_bccb_ptr = bccb; 110339223Sgibbs ccb->ccb_h.ccb_bt_ptr = bt; 110439223Sgibbs 110539223Sgibbs /* 110639223Sgibbs * Put all the arguments for the xfer in the bccb 110739223Sgibbs */ 110839223Sgibbs hccb->target_id = ccb->ccb_h.target_id; 110939223Sgibbs hccb->target_lun = ccb->ccb_h.target_lun; 111039223Sgibbs hccb->btstat = 0; 111139223Sgibbs hccb->sdstat = 0; 111239223Sgibbs 111339223Sgibbs if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 111439223Sgibbs struct ccb_scsiio *csio; 111539223Sgibbs struct ccb_hdr *ccbh; 111639223Sgibbs 111739223Sgibbs csio = &ccb->csio; 111839223Sgibbs ccbh = &csio->ccb_h; 111939223Sgibbs hccb->opcode = INITIATOR_CCB_WRESID; 112041669Sgibbs hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0; 112141669Sgibbs hccb->dataout =(ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0; 112239223Sgibbs hccb->cmd_len = csio->cdb_len; 112339223Sgibbs if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) { 112439223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 112539223Sgibbs btfreeccb(bt, bccb); 112639223Sgibbs xpt_done(ccb); 112739223Sgibbs return; 112839223Sgibbs } 112939223Sgibbs hccb->sense_len = csio->sense_len; 113040418Sgibbs if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0 113140418Sgibbs && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) { 113239223Sgibbs hccb->tag_enable = TRUE; 113339223Sgibbs hccb->tag_type = (ccb->csio.tag_action & 0x3); 113439223Sgibbs } else { 113539223Sgibbs hccb->tag_enable = FALSE; 113639223Sgibbs hccb->tag_type = 0; 113739223Sgibbs } 113839223Sgibbs if ((ccbh->flags & CAM_CDB_POINTER) != 0) { 113939223Sgibbs if ((ccbh->flags & CAM_CDB_PHYS) == 0) { 114039223Sgibbs bcopy(csio->cdb_io.cdb_ptr, 114139223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 114239223Sgibbs } else { 114339223Sgibbs /* I guess I could map it in... */ 114439223Sgibbs ccbh->status = CAM_REQ_INVALID; 114539223Sgibbs btfreeccb(bt, bccb); 114639223Sgibbs xpt_done(ccb); 114739223Sgibbs return; 114839223Sgibbs } 114939223Sgibbs } else { 115039223Sgibbs bcopy(csio->cdb_io.cdb_bytes, 115139223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 115239223Sgibbs } 115339223Sgibbs /* If need be, bounce our sense buffer */ 115439223Sgibbs if (bt->sense_buffers != NULL) { 115539223Sgibbs hccb->sense_addr = btsensepaddr(bt, bccb); 115639223Sgibbs } else { 115739223Sgibbs hccb->sense_addr = vtophys(&csio->sense_data); 115839223Sgibbs } 115939223Sgibbs /* 116039223Sgibbs * If we have any data to send with this command, 116139223Sgibbs * map it into bus space. 116239223Sgibbs */ 116339223Sgibbs /* Only use S/G if there is a transfer */ 116439223Sgibbs if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 116539223Sgibbs if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { 116639223Sgibbs /* 116739223Sgibbs * We've been given a pointer 116839223Sgibbs * to a single buffer. 116939223Sgibbs */ 117039223Sgibbs if ((ccbh->flags & CAM_DATA_PHYS)==0) { 117139223Sgibbs int s; 117239223Sgibbs int error; 117339223Sgibbs 117439223Sgibbs s = splsoftvm(); 117539223Sgibbs error = bus_dmamap_load( 117639223Sgibbs bt->buffer_dmat, 117739223Sgibbs bccb->dmamap, 117839223Sgibbs csio->data_ptr, 117939223Sgibbs csio->dxfer_len, 118039223Sgibbs btexecuteccb, 118139223Sgibbs bccb, 118239223Sgibbs /*flags*/0); 118339223Sgibbs if (error == EINPROGRESS) { 118439223Sgibbs /* 118539223Sgibbs * So as to maintain 118639223Sgibbs * ordering, freeze the 118739223Sgibbs * controller queue 118839223Sgibbs * until our mapping is 118939223Sgibbs * returned. 119039223Sgibbs */ 119139223Sgibbs xpt_freeze_simq(bt->sim, 119239223Sgibbs 1); 119339223Sgibbs csio->ccb_h.status |= 119439223Sgibbs CAM_RELEASE_SIMQ; 119539223Sgibbs } 119639223Sgibbs splx(s); 119739223Sgibbs } else { 119839223Sgibbs struct bus_dma_segment seg; 119939223Sgibbs 120039223Sgibbs /* Pointer to physical buffer */ 120139223Sgibbs seg.ds_addr = 120239223Sgibbs (bus_addr_t)csio->data_ptr; 120339223Sgibbs seg.ds_len = csio->dxfer_len; 120439223Sgibbs btexecuteccb(bccb, &seg, 1, 0); 120539223Sgibbs } 120639223Sgibbs } else { 120739223Sgibbs struct bus_dma_segment *segs; 120839223Sgibbs 120939223Sgibbs if ((ccbh->flags & CAM_DATA_PHYS) != 0) 121039223Sgibbs panic("btaction - Physical " 121139223Sgibbs "segment pointers " 121239223Sgibbs "unsupported"); 121339223Sgibbs 121439223Sgibbs if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) 121539223Sgibbs panic("btaction - Virtual " 121639223Sgibbs "segment addresses " 121739223Sgibbs "unsupported"); 121839223Sgibbs 121939223Sgibbs /* Just use the segments provided */ 122039223Sgibbs segs = (struct bus_dma_segment *) 122139223Sgibbs csio->data_ptr; 122239223Sgibbs btexecuteccb(bccb, segs, 122339223Sgibbs csio->sglist_cnt, 0); 122439223Sgibbs } 122539223Sgibbs } else { 122639223Sgibbs btexecuteccb(bccb, NULL, 0, 0); 122739223Sgibbs } 122839223Sgibbs } else { 122939223Sgibbs hccb->opcode = INITIATOR_BUS_DEV_RESET; 123039223Sgibbs /* No data transfer */ 123139223Sgibbs hccb->datain = TRUE; 123239223Sgibbs hccb->dataout = TRUE; 123339223Sgibbs hccb->cmd_len = 0; 123439223Sgibbs hccb->sense_len = 0; 123539223Sgibbs hccb->tag_enable = FALSE; 123639223Sgibbs hccb->tag_type = 0; 123739223Sgibbs btexecuteccb(bccb, NULL, 0, 0); 123839223Sgibbs } 123939223Sgibbs break; 124039223Sgibbs } 124139223Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 124239223Sgibbs case XPT_TARGET_IO: /* Execute target I/O request */ 124339223Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 124439223Sgibbs case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 124539223Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 124639223Sgibbs /* XXX Implement */ 124739223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 124839223Sgibbs xpt_done(ccb); 124939223Sgibbs break; 125039223Sgibbs case XPT_SET_TRAN_SETTINGS: 125139223Sgibbs { 125239223Sgibbs /* XXX Implement */ 125346581Sken ccb->ccb_h.status = CAM_PROVIDE_FAIL; 125439223Sgibbs xpt_done(ccb); 125539223Sgibbs break; 125639223Sgibbs } 125739223Sgibbs case XPT_GET_TRAN_SETTINGS: 125839223Sgibbs /* Get default/user set transfer settings for the target */ 125939223Sgibbs { 126039223Sgibbs struct ccb_trans_settings *cts; 126139223Sgibbs u_int target_mask; 126239223Sgibbs 126339223Sgibbs cts = &ccb->cts; 126439223Sgibbs target_mask = 0x01 << ccb->ccb_h.target_id; 126539223Sgibbs if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 126639223Sgibbs cts->flags = 0; 126739223Sgibbs if ((bt->disc_permitted & target_mask) != 0) 126839223Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 126939223Sgibbs if ((bt->tags_permitted & target_mask) != 0) 127039223Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 127139223Sgibbs if ((bt->wide_permitted & target_mask) != 0) 127239223Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 127339223Sgibbs else 127439223Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 127539223Sgibbs if ((bt->ultra_permitted & target_mask) != 0) 127639223Sgibbs cts->sync_period = 12; 127739223Sgibbs else if ((bt->fast_permitted & target_mask) != 0) 127839223Sgibbs cts->sync_period = 25; 127939223Sgibbs else if ((bt->sync_permitted & target_mask) != 0) 128039223Sgibbs cts->sync_period = 50; 128139223Sgibbs else 128239223Sgibbs cts->sync_period = 0; 128339223Sgibbs 128439223Sgibbs if (cts->sync_period != 0) 128539223Sgibbs cts->sync_offset = 15; 128639223Sgibbs 128739223Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 128839223Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 128939223Sgibbs | CCB_TRANS_BUS_WIDTH_VALID 129039223Sgibbs | CCB_TRANS_DISC_VALID 129139223Sgibbs | CCB_TRANS_TQ_VALID; 129239223Sgibbs } else { 129339223Sgibbs btfetchtransinfo(bt, cts); 129439223Sgibbs } 129539223Sgibbs 129639223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 129739223Sgibbs xpt_done(ccb); 129839223Sgibbs break; 129939223Sgibbs } 130039223Sgibbs case XPT_CALC_GEOMETRY: 130139223Sgibbs { 130239223Sgibbs struct ccb_calc_geometry *ccg; 130339223Sgibbs u_int32_t size_mb; 130439223Sgibbs u_int32_t secs_per_cylinder; 130539223Sgibbs 130639223Sgibbs ccg = &ccb->ccg; 130739223Sgibbs size_mb = ccg->volume_size 130839223Sgibbs / ((1024L * 1024L) / ccg->block_size); 130939223Sgibbs 131039223Sgibbs if (size_mb >= 1024 && (bt->extended_trans != 0)) { 131139223Sgibbs if (size_mb >= 2048) { 131239223Sgibbs ccg->heads = 255; 131339223Sgibbs ccg->secs_per_track = 63; 131439223Sgibbs } else { 131539223Sgibbs ccg->heads = 128; 131639223Sgibbs ccg->secs_per_track = 32; 131739223Sgibbs } 131839223Sgibbs } else { 131939223Sgibbs ccg->heads = 64; 132039223Sgibbs ccg->secs_per_track = 32; 132139223Sgibbs } 132239223Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 132339223Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 132439223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 132539223Sgibbs xpt_done(ccb); 132639223Sgibbs break; 132739223Sgibbs } 132839223Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 132939223Sgibbs { 133039223Sgibbs btreset(bt, /*hardreset*/TRUE); 133139223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 133239223Sgibbs xpt_done(ccb); 133339223Sgibbs break; 133439223Sgibbs } 133539223Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 133639223Sgibbs /* XXX Implement */ 133739223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 133839223Sgibbs xpt_done(ccb); 133939223Sgibbs break; 134039223Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 134139223Sgibbs { 134239223Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 134339223Sgibbs 134439223Sgibbs cpi->version_num = 1; /* XXX??? */ 134539223Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE; 134639223Sgibbs if (bt->tag_capable != 0) 134739223Sgibbs cpi->hba_inquiry |= PI_TAG_ABLE; 134839223Sgibbs if (bt->wide_bus != 0) 134939223Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 135039223Sgibbs cpi->target_sprt = 0; 135139223Sgibbs cpi->hba_misc = 0; 135239223Sgibbs cpi->hba_eng_cnt = 0; 135339223Sgibbs cpi->max_target = bt->wide_bus ? 15 : 7; 135439223Sgibbs cpi->max_lun = 7; 135539223Sgibbs cpi->initiator_id = bt->scsi_id; 135639223Sgibbs cpi->bus_id = cam_sim_bus(sim); 135746581Sken cpi->base_transfer_speed = 3300; 135839223Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 135939223Sgibbs strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN); 136039223Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 136139223Sgibbs cpi->unit_number = cam_sim_unit(sim); 136239223Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 136339223Sgibbs xpt_done(ccb); 136439223Sgibbs break; 136539223Sgibbs } 136639223Sgibbs default: 136739223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 136839223Sgibbs xpt_done(ccb); 136939223Sgibbs break; 137039223Sgibbs } 137139223Sgibbs} 137239223Sgibbs 137339223Sgibbsstatic void 137439223Sgibbsbtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 137539223Sgibbs{ 137639223Sgibbs struct bt_ccb *bccb; 137739223Sgibbs union ccb *ccb; 137839223Sgibbs struct bt_softc *bt; 137940419Sgibbs int s; 138039223Sgibbs 138139223Sgibbs bccb = (struct bt_ccb *)arg; 138239223Sgibbs ccb = bccb->ccb; 138339223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 138439223Sgibbs 138539223Sgibbs if (error != 0) { 138639223Sgibbs if (error != EFBIG) 138745791Speter device_printf(bt->dev, 138845791Speter "Unexepected error 0x%x returned from " 138945791Speter "bus_dmamap_load\n", error); 139039223Sgibbs if (ccb->ccb_h.status == CAM_REQ_INPROG) { 139139223Sgibbs xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 139239223Sgibbs ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 139339223Sgibbs } 139439223Sgibbs btfreeccb(bt, bccb); 139539223Sgibbs xpt_done(ccb); 139639223Sgibbs return; 139739223Sgibbs } 139839223Sgibbs 139939223Sgibbs if (nseg != 0) { 140039223Sgibbs bt_sg_t *sg; 140139223Sgibbs bus_dma_segment_t *end_seg; 140239223Sgibbs bus_dmasync_op_t op; 140339223Sgibbs 140439223Sgibbs end_seg = dm_segs + nseg; 140539223Sgibbs 140639223Sgibbs /* Copy the segments into our SG list */ 140739223Sgibbs sg = bccb->sg_list; 140839223Sgibbs while (dm_segs < end_seg) { 140939223Sgibbs sg->len = dm_segs->ds_len; 141039223Sgibbs sg->addr = dm_segs->ds_addr; 141139223Sgibbs sg++; 141239223Sgibbs dm_segs++; 141339223Sgibbs } 141439223Sgibbs 141539223Sgibbs if (nseg > 1) { 141639223Sgibbs bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID; 141739223Sgibbs bccb->hccb.data_len = sizeof(bt_sg_t) * nseg; 141839223Sgibbs bccb->hccb.data_addr = bccb->sg_list_phys; 141939223Sgibbs } else { 142039223Sgibbs bccb->hccb.data_len = bccb->sg_list->len; 142139223Sgibbs bccb->hccb.data_addr = bccb->sg_list->addr; 142239223Sgibbs } 142339223Sgibbs 142439223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 142539223Sgibbs op = BUS_DMASYNC_PREREAD; 142639223Sgibbs else 142739223Sgibbs op = BUS_DMASYNC_PREWRITE; 142839223Sgibbs 142939223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 143039223Sgibbs 143139223Sgibbs } else { 143241669Sgibbs bccb->hccb.opcode = INITIATOR_CCB; 143339223Sgibbs bccb->hccb.data_len = 0; 143439223Sgibbs bccb->hccb.data_addr = 0; 143539223Sgibbs } 143639223Sgibbs 143739223Sgibbs s = splcam(); 143839223Sgibbs 143939223Sgibbs /* 144039223Sgibbs * Last time we need to check if this CCB needs to 144139223Sgibbs * be aborted. 144239223Sgibbs */ 144339223Sgibbs if (ccb->ccb_h.status != CAM_REQ_INPROG) { 144439223Sgibbs if (nseg != 0) 144539223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 144639223Sgibbs btfreeccb(bt, bccb); 144739223Sgibbs xpt_done(ccb); 144839223Sgibbs splx(s); 144939223Sgibbs return; 145039223Sgibbs } 145139223Sgibbs 145239223Sgibbs bccb->flags = BCCB_ACTIVE; 145339223Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 145439223Sgibbs LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le); 145539223Sgibbs 145639223Sgibbs ccb->ccb_h.timeout_ch = 145739223Sgibbs timeout(bttimeout, (caddr_t)bccb, 145839223Sgibbs (ccb->ccb_h.timeout * hz) / 1000); 145939223Sgibbs 146039223Sgibbs /* Tell the adapter about this command */ 146139223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb); 146241048Sgibbs if (bt->cur_outbox->action_code != BMBO_FREE) { 146341048Sgibbs /* 146441048Sgibbs * We should never encounter a busy mailbox. 146541048Sgibbs * If we do, warn the user, and treat it as 146641048Sgibbs * a resource shortage. If the controller is 146741048Sgibbs * hung, one of the pending transactions will 146841048Sgibbs * timeout causing us to start recovery operations. 146941048Sgibbs */ 147045791Speter device_printf(bt->dev, 147145791Speter "Encountered busy mailbox with %d out of %d " 147245791Speter "commands active!!!\n", bt->active_ccbs, 147345791Speter bt->max_ccbs); 147441048Sgibbs untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch); 147541048Sgibbs if (nseg != 0) 147641048Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 147741048Sgibbs btfreeccb(bt, bccb); 147841048Sgibbs bt->resource_shortage = TRUE; 147941048Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 148041048Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 148141048Sgibbs xpt_done(ccb); 148241048Sgibbs return; 148341048Sgibbs } 148439223Sgibbs bt->cur_outbox->action_code = BMBO_START; 148539223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 148639223Sgibbs btnextoutbox(bt); 148739223Sgibbs splx(s); 148839223Sgibbs} 148939223Sgibbs 149039223Sgibbsvoid 149139223Sgibbsbt_intr(void *arg) 149239223Sgibbs{ 149339223Sgibbs struct bt_softc *bt; 149439223Sgibbs u_int intstat; 149539223Sgibbs 149639223Sgibbs bt = (struct bt_softc *)arg; 149739223Sgibbs while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) { 149839223Sgibbs 149939223Sgibbs if ((intstat & CMD_COMPLETE) != 0) { 150039223Sgibbs bt->latched_status = bt_inb(bt, STATUS_REG); 150139223Sgibbs bt->command_cmp = TRUE; 150239223Sgibbs } 150339223Sgibbs 150439223Sgibbs bt_outb(bt, CONTROL_REG, RESET_INTR); 150539223Sgibbs 150639223Sgibbs if ((intstat & IMB_LOADED) != 0) { 150739223Sgibbs while (bt->cur_inbox->comp_code != BMBI_FREE) { 150839223Sgibbs btdone(bt, 150939223Sgibbs btccbptov(bt, bt->cur_inbox->ccb_addr), 151039223Sgibbs bt->cur_inbox->comp_code); 151139223Sgibbs bt->cur_inbox->comp_code = BMBI_FREE; 151239223Sgibbs btnextinbox(bt); 151339223Sgibbs } 151439223Sgibbs } 151539223Sgibbs 151639223Sgibbs if ((intstat & SCSI_BUS_RESET) != 0) { 151739223Sgibbs btreset(bt, /*hardreset*/FALSE); 151839223Sgibbs } 151939223Sgibbs } 152039223Sgibbs} 152139223Sgibbs 152239223Sgibbsstatic void 152339223Sgibbsbtdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) 152439223Sgibbs{ 152539223Sgibbs union ccb *ccb; 152639223Sgibbs struct ccb_scsiio *csio; 152739223Sgibbs 152839223Sgibbs ccb = bccb->ccb; 152939223Sgibbs csio = &bccb->ccb->csio; 153039223Sgibbs 153139223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 153245791Speter device_printf(bt->dev, 153345791Speter "btdone - Attempt to free non-active BCCB %p\n", 153445791Speter (void *)bccb); 153539223Sgibbs return; 153639223Sgibbs } 153739223Sgibbs 153839223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 153939223Sgibbs bus_dmasync_op_t op; 154039223Sgibbs 154139223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 154239223Sgibbs op = BUS_DMASYNC_POSTREAD; 154339223Sgibbs else 154439223Sgibbs op = BUS_DMASYNC_POSTWRITE; 154539223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 154639223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 154739223Sgibbs } 154839223Sgibbs 154939223Sgibbs if (bccb == bt->recovery_bccb) { 155039223Sgibbs /* 155139223Sgibbs * The recovery BCCB does not have a CCB associated 155239223Sgibbs * with it, so short circuit the normal error handling. 155339223Sgibbs * We now traverse our list of pending CCBs and process 155439223Sgibbs * any that were terminated by the recovery CCBs action. 155539223Sgibbs * We also reinstate timeouts for all remaining, pending, 155639223Sgibbs * CCBs. 155739223Sgibbs */ 155839223Sgibbs struct cam_path *path; 155939223Sgibbs struct ccb_hdr *ccb_h; 156039223Sgibbs cam_status error; 156139223Sgibbs 156239223Sgibbs /* Notify all clients that a BDR occured */ 156339223Sgibbs error = xpt_create_path(&path, /*periph*/NULL, 156439223Sgibbs cam_sim_path(bt->sim), 156539223Sgibbs bccb->hccb.target_id, 156639223Sgibbs CAM_LUN_WILDCARD); 156739223Sgibbs 156839223Sgibbs if (error == CAM_REQ_CMP) 156939223Sgibbs xpt_async(AC_SENT_BDR, path, NULL); 157039223Sgibbs 157139223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 157239223Sgibbs while (ccb_h != NULL) { 157339223Sgibbs struct bt_ccb *pending_bccb; 157439223Sgibbs 157539223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 157639223Sgibbs if (pending_bccb->hccb.target_id 157739223Sgibbs == bccb->hccb.target_id) { 157839223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_BDR; 157939223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 158039223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 158139223Sgibbs } else { 158239223Sgibbs ccb_h->timeout_ch = 158339223Sgibbs timeout(bttimeout, (caddr_t)pending_bccb, 158439223Sgibbs (ccb_h->timeout * hz) / 1000); 158539223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 158639223Sgibbs } 158739223Sgibbs } 158845791Speter device_printf(bt->dev, "No longer in timeout\n"); 158939223Sgibbs return; 159039223Sgibbs } 159139223Sgibbs 159239223Sgibbs untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch); 159339223Sgibbs 159439223Sgibbs switch (comp_code) { 159539223Sgibbs case BMBI_FREE: 159645791Speter device_printf(bt->dev, 159745791Speter "btdone - CCB completed with free status!\n"); 159839223Sgibbs break; 159939223Sgibbs case BMBI_NOT_FOUND: 160045791Speter device_printf(bt->dev, 160145791Speter "btdone - CCB Abort failed to find CCB\n"); 160239223Sgibbs break; 160339223Sgibbs case BMBI_ABORT: 160439223Sgibbs case BMBI_ERROR: 160541133Sgibbs if (bootverbose) { 160641133Sgibbs printf("bt: ccb %p - error %x occured. " 160741133Sgibbs "btstat = %x, sdstat = %x\n", 160841133Sgibbs (void *)bccb, comp_code, bccb->hccb.btstat, 160941133Sgibbs bccb->hccb.sdstat); 161041133Sgibbs } 161139223Sgibbs /* An error occured */ 161239223Sgibbs switch(bccb->hccb.btstat) { 161339223Sgibbs case BTSTAT_DATARUN_ERROR: 161441048Sgibbs if (bccb->hccb.data_len == 0) { 161541048Sgibbs /* 161641048Sgibbs * At least firmware 4.22, does this 161741048Sgibbs * for a QUEUE FULL condition. 161841048Sgibbs */ 161941048Sgibbs bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL; 162041048Sgibbs } else if (bccb->hccb.data_len < 0) { 162139223Sgibbs csio->ccb_h.status = CAM_DATA_RUN_ERR; 162239223Sgibbs break; 162339223Sgibbs } 162439223Sgibbs /* FALLTHROUGH */ 162539223Sgibbs case BTSTAT_NOERROR: 162639223Sgibbs case BTSTAT_LINKED_CMD_COMPLETE: 162739223Sgibbs case BTSTAT_LINKED_CMD_FLAG_COMPLETE: 162839223Sgibbs case BTSTAT_DATAUNDERUN_ERROR: 162939223Sgibbs 163039223Sgibbs csio->scsi_status = bccb->hccb.sdstat; 163139223Sgibbs csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 163239223Sgibbs switch(csio->scsi_status) { 163339223Sgibbs case SCSI_STATUS_CHECK_COND: 163439223Sgibbs case SCSI_STATUS_CMD_TERMINATED: 163539223Sgibbs csio->ccb_h.status |= CAM_AUTOSNS_VALID; 163639223Sgibbs /* Bounce sense back if necessary */ 163739223Sgibbs if (bt->sense_buffers != NULL) { 163839223Sgibbs csio->sense_data = 163939223Sgibbs *btsensevaddr(bt, bccb); 164039223Sgibbs } 164139223Sgibbs break; 164239223Sgibbs default: 164339223Sgibbs break; 164439223Sgibbs case SCSI_STATUS_OK: 164539223Sgibbs csio->ccb_h.status = CAM_REQ_CMP; 164639223Sgibbs break; 164739223Sgibbs } 164839223Sgibbs csio->resid = bccb->hccb.data_len; 164939223Sgibbs break; 165039223Sgibbs case BTSTAT_SELTIMEOUT: 165139223Sgibbs csio->ccb_h.status = CAM_SEL_TIMEOUT; 165239223Sgibbs break; 165339223Sgibbs case BTSTAT_UNEXPECTED_BUSFREE: 165439223Sgibbs csio->ccb_h.status = CAM_UNEXP_BUSFREE; 165539223Sgibbs break; 165639223Sgibbs case BTSTAT_INVALID_PHASE: 165739223Sgibbs csio->ccb_h.status = CAM_SEQUENCE_FAIL; 165839223Sgibbs break; 165939223Sgibbs case BTSTAT_INVALID_ACTION_CODE: 166039223Sgibbs panic("%s: Inavlid Action code", bt_name(bt)); 166139223Sgibbs break; 166239223Sgibbs case BTSTAT_INVALID_OPCODE: 166339223Sgibbs panic("%s: Inavlid CCB Opcode code", bt_name(bt)); 166439223Sgibbs break; 166539223Sgibbs case BTSTAT_LINKED_CCB_LUN_MISMATCH: 166639223Sgibbs /* We don't even support linked commands... */ 166739223Sgibbs panic("%s: Linked CCB Lun Mismatch", bt_name(bt)); 166839223Sgibbs break; 166939223Sgibbs case BTSTAT_INVALID_CCB_OR_SG_PARAM: 167039223Sgibbs panic("%s: Invalid CCB or SG list", bt_name(bt)); 167139223Sgibbs break; 167239223Sgibbs case BTSTAT_AUTOSENSE_FAILED: 167339223Sgibbs csio->ccb_h.status = CAM_AUTOSENSE_FAIL; 167439223Sgibbs break; 167539223Sgibbs case BTSTAT_TAGGED_MSG_REJECTED: 167639223Sgibbs { 167739223Sgibbs struct ccb_trans_settings neg; 167839223Sgibbs 167939223Sgibbs xpt_print_path(csio->ccb_h.path); 168039223Sgibbs printf("refuses tagged commands. Performing " 168139223Sgibbs "non-tagged I/O\n"); 168239223Sgibbs neg.flags = 0; 168339223Sgibbs neg.valid = CCB_TRANS_TQ_VALID; 168439223Sgibbs xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path, 168539223Sgibbs /*priority*/1); 168639223Sgibbs xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg); 168739223Sgibbs bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id); 168839223Sgibbs csio->ccb_h.status = CAM_MSG_REJECT_REC; 168939223Sgibbs break; 169039223Sgibbs } 169139223Sgibbs case BTSTAT_UNSUPPORTED_MSG_RECEIVED: 169239223Sgibbs /* 169339223Sgibbs * XXX You would think that this is 169439223Sgibbs * a recoverable error... Hmmm. 169539223Sgibbs */ 169639223Sgibbs csio->ccb_h.status = CAM_REQ_CMP_ERR; 169739223Sgibbs break; 169839223Sgibbs case BTSTAT_HA_SOFTWARE_ERROR: 169939223Sgibbs case BTSTAT_HA_WATCHDOG_ERROR: 170039223Sgibbs case BTSTAT_HARDWARE_FAILURE: 170139223Sgibbs /* Hardware reset ??? Can we recover ??? */ 170239223Sgibbs csio->ccb_h.status = CAM_NO_HBA; 170339223Sgibbs break; 170439223Sgibbs case BTSTAT_TARGET_IGNORED_ATN: 170539223Sgibbs case BTSTAT_OTHER_SCSI_BUS_RESET: 170639223Sgibbs case BTSTAT_HA_SCSI_BUS_RESET: 170739223Sgibbs if ((csio->ccb_h.status & CAM_STATUS_MASK) 170839223Sgibbs != CAM_CMD_TIMEOUT) 170939223Sgibbs csio->ccb_h.status = CAM_SCSI_BUS_RESET; 171039223Sgibbs break; 171139223Sgibbs case BTSTAT_HA_BDR: 171239223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) 171339223Sgibbs csio->ccb_h.status = CAM_BDR_SENT; 171439223Sgibbs else 171539223Sgibbs csio->ccb_h.status = CAM_CMD_TIMEOUT; 171639223Sgibbs break; 171739223Sgibbs case BTSTAT_INVALID_RECONNECT: 171839223Sgibbs case BTSTAT_ABORT_QUEUE_GENERATED: 171939223Sgibbs csio->ccb_h.status = CAM_REQ_TERMIO; 172039223Sgibbs break; 172139223Sgibbs case BTSTAT_SCSI_PERROR_DETECTED: 172239223Sgibbs csio->ccb_h.status = CAM_UNCOR_PARITY; 172339223Sgibbs break; 172439223Sgibbs } 172539223Sgibbs if (csio->ccb_h.status != CAM_REQ_CMP) { 172639223Sgibbs xpt_freeze_devq(csio->ccb_h.path, /*count*/1); 172739223Sgibbs csio->ccb_h.status |= CAM_DEV_QFRZN; 172839223Sgibbs } 172939223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 173039223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 173139223Sgibbs btfreeccb(bt, bccb); 173239223Sgibbs xpt_done(ccb); 173339223Sgibbs break; 173439223Sgibbs case BMBI_OK: 173539223Sgibbs /* All completed without incident */ 173639223Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 173739223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 173839223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 173939223Sgibbs btfreeccb(bt, bccb); 174039223Sgibbs xpt_done(ccb); 174139223Sgibbs break; 174239223Sgibbs } 174339223Sgibbs} 174439223Sgibbs 174539223Sgibbsstatic int 174639223Sgibbsbtreset(struct bt_softc* bt, int hard_reset) 174739223Sgibbs{ 174839223Sgibbs struct ccb_hdr *ccb_h; 174939223Sgibbs u_int status; 175039223Sgibbs u_int timeout; 175139223Sgibbs u_int8_t reset_type; 175239223Sgibbs 175339223Sgibbs if (hard_reset != 0) 175439223Sgibbs reset_type = HARD_RESET; 175539223Sgibbs else 175639223Sgibbs reset_type = SOFT_RESET; 175739223Sgibbs bt_outb(bt, CONTROL_REG, reset_type); 175839223Sgibbs 175939223Sgibbs /* Wait 5sec. for Diagnostic start */ 176039223Sgibbs timeout = 5 * 10000; 176139223Sgibbs while (--timeout) { 176239223Sgibbs status = bt_inb(bt, STATUS_REG); 176339223Sgibbs if ((status & DIAG_ACTIVE) != 0) 176439223Sgibbs break; 176539223Sgibbs DELAY(100); 176639223Sgibbs } 176739223Sgibbs if (timeout == 0) { 176839223Sgibbs if (bootverbose) 176939223Sgibbs printf("%s: btreset - Diagnostic Active failed to " 177039223Sgibbs "assert. status = 0x%x\n", bt_name(bt), status); 177139223Sgibbs return (ETIMEDOUT); 177239223Sgibbs } 177339223Sgibbs 177439223Sgibbs /* Wait 10sec. for Diagnostic end */ 177539223Sgibbs timeout = 10 * 10000; 177639223Sgibbs while (--timeout) { 177739223Sgibbs status = bt_inb(bt, STATUS_REG); 177839223Sgibbs if ((status & DIAG_ACTIVE) == 0) 177939223Sgibbs break; 178039223Sgibbs DELAY(100); 178139223Sgibbs } 178239223Sgibbs if (timeout == 0) { 178339223Sgibbs panic("%s: btreset - Diagnostic Active failed to drop. " 178439223Sgibbs "status = 0x%x\n", bt_name(bt), status); 178539223Sgibbs return (ETIMEDOUT); 178639223Sgibbs } 178739223Sgibbs 178839223Sgibbs /* Wait for the host adapter to become ready or report a failure */ 178939223Sgibbs timeout = 10000; 179039223Sgibbs while (--timeout) { 179139223Sgibbs status = bt_inb(bt, STATUS_REG); 179239223Sgibbs if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0) 179339223Sgibbs break; 179439223Sgibbs DELAY(100); 179539223Sgibbs } 179639223Sgibbs if (timeout == 0) { 179739223Sgibbs printf("%s: btreset - Host adapter failed to come ready. " 179839223Sgibbs "status = 0x%x\n", bt_name(bt), status); 179939223Sgibbs return (ETIMEDOUT); 180039223Sgibbs } 180139223Sgibbs 180239223Sgibbs /* If the diagnostics failed, tell the user */ 180339223Sgibbs if ((status & DIAG_FAIL) != 0 180439223Sgibbs || (status & HA_READY) == 0) { 180539223Sgibbs printf("%s: btreset - Adapter failed diagnostics\n", 180639223Sgibbs bt_name(bt)); 180739223Sgibbs 180839223Sgibbs if ((status & DATAIN_REG_READY) != 0) 180939223Sgibbs printf("%s: btreset - Host Adapter Error code = 0x%x\n", 181039324Sgibbs bt_name(bt), bt_inb(bt, DATAIN_REG)); 181139223Sgibbs return (ENXIO); 181239223Sgibbs } 181339223Sgibbs 181439223Sgibbs /* If we've allocated mailboxes, initialize them */ 181539223Sgibbs if (bt->init_level > 4) 181639223Sgibbs btinitmboxes(bt); 181739223Sgibbs 181839223Sgibbs /* If we've attached to the XPT, tell it about the event */ 181939223Sgibbs if (bt->path != NULL) 182039223Sgibbs xpt_async(AC_BUS_RESET, bt->path, NULL); 182139223Sgibbs 182239223Sgibbs /* 182339223Sgibbs * Perform completion processing for all outstanding CCBs. 182439223Sgibbs */ 182539223Sgibbs while ((ccb_h = LIST_FIRST(&bt->pending_ccbs)) != NULL) { 182639223Sgibbs struct bt_ccb *pending_bccb; 182739223Sgibbs 182839223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 182939223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_SCSI_BUS_RESET; 183039223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 183139223Sgibbs } 183239223Sgibbs 183339223Sgibbs return (0); 183439223Sgibbs} 183539223Sgibbs 183639223Sgibbs/* 183739223Sgibbs * Send a command to the adapter. 183839223Sgibbs */ 183939223Sgibbsint 184039223Sgibbsbt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, 184139223Sgibbs u_int8_t *reply_data, u_int reply_len, u_int cmd_timeout) 184239223Sgibbs{ 184339223Sgibbs u_int timeout; 184439223Sgibbs u_int status; 184545444Sgibbs u_int saved_status; 184639223Sgibbs u_int intstat; 184739223Sgibbs u_int reply_buf_size; 184839223Sgibbs int s; 184941669Sgibbs int cmd_complete; 185045444Sgibbs int error; 185139223Sgibbs 185239223Sgibbs /* No data returned to start */ 185339223Sgibbs reply_buf_size = reply_len; 185439223Sgibbs reply_len = 0; 185539223Sgibbs intstat = 0; 185641669Sgibbs cmd_complete = 0; 185745444Sgibbs saved_status = 0; 185845444Sgibbs error = 0; 185939223Sgibbs 186039223Sgibbs bt->command_cmp = 0; 186139223Sgibbs /* 186245444Sgibbs * Wait up to 10 sec. for the adapter to become 186339223Sgibbs * ready to accept commands. 186439223Sgibbs */ 186545444Sgibbs timeout = 100000; 186639223Sgibbs while (--timeout) { 186739223Sgibbs status = bt_inb(bt, STATUS_REG); 186839223Sgibbs if ((status & HA_READY) != 0 186939223Sgibbs && (status & CMD_REG_BUSY) == 0) 187039223Sgibbs break; 187145444Sgibbs /* 187245444Sgibbs * Throw away any pending data which may be 187345444Sgibbs * left over from earlier commands that we 187445444Sgibbs * timedout on. 187545444Sgibbs */ 187645444Sgibbs if ((status & DATAIN_REG_READY) != 0) 187745444Sgibbs (void)bt_inb(bt, DATAIN_REG); 187839223Sgibbs DELAY(100); 187939223Sgibbs } 188039223Sgibbs if (timeout == 0) { 188139223Sgibbs printf("%s: bt_cmd: Timeout waiting for adapter ready, " 188239223Sgibbs "status = 0x%x\n", bt_name(bt), status); 188339223Sgibbs return (ETIMEDOUT); 188439223Sgibbs } 188539223Sgibbs 188639223Sgibbs /* 188739223Sgibbs * Send the opcode followed by any necessary parameter bytes. 188839223Sgibbs */ 188939223Sgibbs bt_outb(bt, COMMAND_REG, opcode); 189039223Sgibbs 189139223Sgibbs /* 189245444Sgibbs * Wait for up to 1sec for each byte of the the 189345444Sgibbs * parameter list sent to be sent. 189439223Sgibbs */ 189539223Sgibbs timeout = 10000; 189639223Sgibbs while (param_len && --timeout) { 189739223Sgibbs DELAY(100); 189845444Sgibbs s = splcam(); 189939223Sgibbs status = bt_inb(bt, STATUS_REG); 190039223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 190145444Sgibbs splx(s); 190239223Sgibbs if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 190341669Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 190445444Sgibbs saved_status = status; 190541669Sgibbs cmd_complete = 1; 190639223Sgibbs break; 190741669Sgibbs } 190839223Sgibbs if (bt->command_cmp != 0) { 190945444Sgibbs saved_status = bt->latched_status; 191041669Sgibbs cmd_complete = 1; 191139223Sgibbs break; 191239223Sgibbs } 191339223Sgibbs if ((status & DATAIN_REG_READY) != 0) 191439223Sgibbs break; 191545444Sgibbs 191639223Sgibbs if ((status & CMD_REG_BUSY) == 0) { 191739223Sgibbs bt_outb(bt, COMMAND_REG, *params++); 191839223Sgibbs param_len--; 191945444Sgibbs timeout = 10000; 192039223Sgibbs } 192139223Sgibbs } 192239223Sgibbs if (timeout == 0) { 192339223Sgibbs printf("%s: bt_cmd: Timeout sending parameters, " 192439223Sgibbs "status = 0x%x\n", bt_name(bt), status); 192545444Sgibbs cmd_complete = 1; 192645444Sgibbs saved_status = status; 192745444Sgibbs error = ETIMEDOUT; 192839223Sgibbs } 192939223Sgibbs 193039223Sgibbs /* 193145444Sgibbs * Wait for the command to complete. 193239223Sgibbs */ 193341669Sgibbs while (cmd_complete == 0 && --cmd_timeout) { 193439223Sgibbs 193545444Sgibbs s = splcam(); 193639223Sgibbs status = bt_inb(bt, STATUS_REG); 193739223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 193845444Sgibbs splx(s); 193939223Sgibbs 194039223Sgibbs if (bt->command_cmp != 0) { 194145444Sgibbs /* 194245444Sgibbs * Our interrupt handler saw CMD_COMPLETE 194345444Sgibbs * status before we did. 194445444Sgibbs */ 194545444Sgibbs cmd_complete = 1; 194645444Sgibbs saved_status = bt->latched_status; 194745444Sgibbs } else if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 194845444Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 194945444Sgibbs /* 195045444Sgibbs * Our poll (in case interrupts are blocked) 195145444Sgibbs * saw the CMD_COMPLETE interrupt. 195245444Sgibbs */ 195345444Sgibbs cmd_complete = 1; 195445444Sgibbs saved_status = status; 195545444Sgibbs } else if (opcode == BOP_MODIFY_IO_ADDR 195645444Sgibbs && (status & CMD_REG_BUSY) == 0) { 195745444Sgibbs /* 195845444Sgibbs * The BOP_MODIFY_IO_ADDR does not issue a CMD_COMPLETE, 195945444Sgibbs * but it should update the status register. So, we 196045444Sgibbs * consider this command complete when the CMD_REG_BUSY 196145444Sgibbs * status clears. 196245444Sgibbs */ 196345444Sgibbs saved_status = status; 196445444Sgibbs cmd_complete = 1; 196545444Sgibbs } else if ((status & DATAIN_REG_READY) != 0) { 196639223Sgibbs u_int8_t data; 196739223Sgibbs 196839223Sgibbs data = bt_inb(bt, DATAIN_REG); 196939223Sgibbs if (reply_len < reply_buf_size) { 197039223Sgibbs *reply_data++ = data; 197139223Sgibbs } else { 197239223Sgibbs printf("%s: bt_cmd - Discarded reply data byte " 197339223Sgibbs "for opcode 0x%x\n", bt_name(bt), 197439223Sgibbs opcode); 197539223Sgibbs } 197645444Sgibbs /* 197745444Sgibbs * Reset timeout to ensure at least a second 197845444Sgibbs * between response bytes. 197945444Sgibbs */ 198045444Sgibbs cmd_timeout = MAX(cmd_timeout, 10000); 198139223Sgibbs reply_len++; 198245444Sgibbs 198345444Sgibbs } else if ((opcode == BOP_FETCH_LRAM) 198445444Sgibbs && (status & HA_READY) != 0) { 198545444Sgibbs saved_status = status; 198645444Sgibbs cmd_complete = 1; 198739223Sgibbs } 198839223Sgibbs DELAY(100); 198939223Sgibbs } 199045444Sgibbs if (cmd_timeout == 0) { 199145444Sgibbs printf("%s: bt_cmd: Timeout waiting for command (%x) " 199245444Sgibbs "to complete.\n%s: status = 0x%x, intstat = 0x%x, " 199345444Sgibbs "rlen %d\n", bt_name(bt), opcode, bt_name(bt), 199445444Sgibbs status, intstat, reply_len); 199545444Sgibbs error = (ETIMEDOUT); 199639223Sgibbs } 199739223Sgibbs 199839223Sgibbs /* 199939223Sgibbs * Clear any pending interrupts. Block interrupts so our 200039223Sgibbs * interrupt handler is not re-entered. 200139223Sgibbs */ 200239223Sgibbs s = splcam(); 200339223Sgibbs bt_intr(bt); 200439223Sgibbs splx(s); 200539223Sgibbs 200645444Sgibbs if (error != 0) 200745444Sgibbs return (error); 200845444Sgibbs 200939223Sgibbs /* 201039223Sgibbs * If the command was rejected by the controller, tell the caller. 201139223Sgibbs */ 201245444Sgibbs if ((saved_status & CMD_INVALID) != 0) { 201339223Sgibbs /* 201439223Sgibbs * Some early adapters may not recover properly from 201539223Sgibbs * an invalid command. If it appears that the controller 201639223Sgibbs * has wedged (i.e. status was not cleared by our interrupt 201739223Sgibbs * reset above), perform a soft reset. 201839223Sgibbs */ 201939223Sgibbs if (bootverbose) 202039223Sgibbs printf("%s: Invalid Command 0x%x\n", bt_name(bt), 202139223Sgibbs opcode); 202239223Sgibbs DELAY(1000); 202339223Sgibbs status = bt_inb(bt, STATUS_REG); 202439223Sgibbs if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY| 202539223Sgibbs CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0 202639223Sgibbs || (status & (HA_READY|INIT_REQUIRED)) 202739223Sgibbs != (HA_READY|INIT_REQUIRED)) { 202839223Sgibbs btreset(bt, /*hard_reset*/FALSE); 202939223Sgibbs } 203039223Sgibbs return (EINVAL); 203139223Sgibbs } 203239223Sgibbs 203339223Sgibbs if (param_len > 0) { 203439223Sgibbs /* The controller did not accept the full argument list */ 203539223Sgibbs return (E2BIG); 203639223Sgibbs } 203739223Sgibbs 203839223Sgibbs if (reply_len != reply_buf_size) { 203939223Sgibbs /* Too much or too little data received */ 204039223Sgibbs return (EMSGSIZE); 204139223Sgibbs } 204239223Sgibbs 204339223Sgibbs /* We were successful */ 204439223Sgibbs return (0); 204539223Sgibbs} 204639223Sgibbs 204739223Sgibbsstatic int 204839223Sgibbsbtinitmboxes(struct bt_softc *bt) { 204939223Sgibbs init_32b_mbox_params_t init_mbox; 205039223Sgibbs int error; 205139223Sgibbs 205239223Sgibbs bzero(bt->in_boxes, sizeof(bt_mbox_in_t) * bt->num_boxes); 205339223Sgibbs bzero(bt->out_boxes, sizeof(bt_mbox_out_t) * bt->num_boxes); 205439223Sgibbs bt->cur_inbox = bt->in_boxes; 205539223Sgibbs bt->last_inbox = bt->in_boxes + bt->num_boxes - 1; 205639223Sgibbs bt->cur_outbox = bt->out_boxes; 205739223Sgibbs bt->last_outbox = bt->out_boxes + bt->num_boxes - 1; 205839223Sgibbs 205939223Sgibbs /* Tell the adapter about them */ 206039223Sgibbs init_mbox.num_boxes = bt->num_boxes; 206139223Sgibbs init_mbox.base_addr[0] = bt->mailbox_physbase & 0xFF; 206239223Sgibbs init_mbox.base_addr[1] = (bt->mailbox_physbase >> 8) & 0xFF; 206339223Sgibbs init_mbox.base_addr[2] = (bt->mailbox_physbase >> 16) & 0xFF; 206439223Sgibbs init_mbox.base_addr[3] = (bt->mailbox_physbase >> 24) & 0xFF; 206539223Sgibbs error = bt_cmd(bt, BOP_INITIALIZE_32BMBOX, (u_int8_t *)&init_mbox, 206639223Sgibbs /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL, 206739223Sgibbs /*reply_len*/0, DEFAULT_CMD_TIMEOUT); 206839223Sgibbs 206939223Sgibbs if (error != 0) 207039223Sgibbs printf("btinitmboxes: Initialization command failed\n"); 207139223Sgibbs else if (bt->strict_rr != 0) { 207239223Sgibbs /* 207339223Sgibbs * If the controller supports 207439223Sgibbs * strict round robin mode, 207539223Sgibbs * enable it 207639223Sgibbs */ 207739223Sgibbs u_int8_t param; 207839223Sgibbs 207939223Sgibbs param = 0; 208039223Sgibbs error = bt_cmd(bt, BOP_ENABLE_STRICT_RR, ¶m, 1, 208139223Sgibbs /*reply_buf*/NULL, /*reply_len*/0, 208239223Sgibbs DEFAULT_CMD_TIMEOUT); 208339223Sgibbs 208439223Sgibbs if (error != 0) { 208539223Sgibbs printf("btinitmboxes: Unable to enable strict RR\n"); 208639223Sgibbs error = 0; 208739223Sgibbs } else if (bootverbose) { 208839223Sgibbs printf("%s: Using Strict Round Robin Mailbox Mode\n", 208939223Sgibbs bt_name(bt)); 209039223Sgibbs } 209139223Sgibbs } 209239223Sgibbs 209339223Sgibbs return (error); 209439223Sgibbs} 209539223Sgibbs 209639223Sgibbs/* 209739223Sgibbs * Update the XPT's idea of the negotiated transfer 209839223Sgibbs * parameters for a particular target. 209939223Sgibbs */ 210039223Sgibbsstatic void 210139223Sgibbsbtfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings* cts) 210239223Sgibbs{ 210339223Sgibbs setup_data_t setup_info; 210439223Sgibbs u_int target; 210539223Sgibbs u_int targ_offset; 210639223Sgibbs u_int targ_mask; 210739223Sgibbs u_int sync_period; 210839223Sgibbs int error; 210939223Sgibbs u_int8_t param; 211039223Sgibbs targ_syncinfo_t sync_info; 211139223Sgibbs 211239223Sgibbs target = cts->ccb_h.target_id; 211339223Sgibbs targ_offset = (target & 0x7); 211439223Sgibbs targ_mask = (0x01 << targ_offset); 211539223Sgibbs 211639223Sgibbs /* 211739223Sgibbs * Inquire Setup Information. This command retreives the 211839223Sgibbs * Wide negotiation status for recent adapters as well as 211939223Sgibbs * the sync info for older models. 212039223Sgibbs */ 212139223Sgibbs param = sizeof(setup_info); 212239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, ¶m, /*paramlen*/1, 212339223Sgibbs (u_int8_t*)&setup_info, sizeof(setup_info), 212439223Sgibbs DEFAULT_CMD_TIMEOUT); 212539223Sgibbs 212639223Sgibbs if (error != 0) { 212745444Sgibbs printf("%s: btfetchtransinfo - Inquire Setup Info Failed %x\n", 212845444Sgibbs bt_name(bt), error); 212945444Sgibbs cts->valid = 0; 213039223Sgibbs return; 213139223Sgibbs } 213239223Sgibbs 213339223Sgibbs sync_info = (target < 8) ? setup_info.low_syncinfo[targ_offset] 213439223Sgibbs : setup_info.high_syncinfo[targ_offset]; 213539223Sgibbs 213639223Sgibbs if (sync_info.sync == 0) 213739223Sgibbs cts->sync_offset = 0; 213839223Sgibbs else 213939223Sgibbs cts->sync_offset = sync_info.offset; 214039223Sgibbs 214139223Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 214239223Sgibbs if (strcmp(bt->firmware_ver, "5.06L") >= 0) { 214339223Sgibbs u_int wide_active; 214439223Sgibbs 214539223Sgibbs wide_active = 214639223Sgibbs (target < 8) ? (setup_info.low_wide_active & targ_mask) 214739223Sgibbs : (setup_info.high_wide_active & targ_mask); 214839223Sgibbs 214939223Sgibbs if (wide_active) 215039223Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 215139507Sgibbs } else if ((bt->wide_permitted & targ_mask) != 0) { 215239507Sgibbs struct ccb_getdev cgd; 215339507Sgibbs 215439507Sgibbs /* 215539507Sgibbs * Prior to rev 5.06L, wide status isn't provided, 215639507Sgibbs * so we "guess" that wide transfers are in effect 215739507Sgibbs * if the user settings allow for wide and the inquiry 215839507Sgibbs * data for the device indicates that it can handle 215939507Sgibbs * wide transfers. 216039507Sgibbs */ 216139507Sgibbs xpt_setup_ccb(&cgd.ccb_h, cts->ccb_h.path, /*priority*/1); 216239507Sgibbs cgd.ccb_h.func_code = XPT_GDEV_TYPE; 216339507Sgibbs xpt_action((union ccb *)&cgd); 216439507Sgibbs if ((cgd.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP 216539507Sgibbs && (cgd.inq_data.flags & SID_WBus16) != 0) 216639507Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 216739223Sgibbs } 216839223Sgibbs 216944581Sgibbs if (bt->firmware_ver[0] >= '3') { 217039223Sgibbs /* 217139223Sgibbs * For adapters that can do fast or ultra speeds, 217239223Sgibbs * use the more exact Target Sync Information command. 217339223Sgibbs */ 217439223Sgibbs target_sync_info_data_t sync_info; 217539223Sgibbs 217639223Sgibbs param = sizeof(sync_info); 217739223Sgibbs error = bt_cmd(bt, BOP_TARG_SYNC_INFO, ¶m, /*paramlen*/1, 217839223Sgibbs (u_int8_t*)&sync_info, sizeof(sync_info), 217939223Sgibbs DEFAULT_CMD_TIMEOUT); 218039223Sgibbs 218139223Sgibbs if (error != 0) { 218239223Sgibbs printf("%s: btfetchtransinfo - Inquire Sync " 218339223Sgibbs "Info Failed 0x%x\n", bt_name(bt), error); 218445444Sgibbs cts->valid = 0; 218539223Sgibbs return; 218639223Sgibbs } 218739223Sgibbs sync_period = sync_info.sync_rate[target] * 100; 218839223Sgibbs } else { 218939223Sgibbs sync_period = 2000 + (500 * sync_info.period); 219039223Sgibbs } 219139223Sgibbs 219239223Sgibbs /* Convert ns value to standard SCSI sync rate */ 219339223Sgibbs if (cts->sync_offset != 0) 219439223Sgibbs cts->sync_period = scsi_calc_syncparam(sync_period); 219539223Sgibbs else 219639223Sgibbs cts->sync_period = 0; 219739223Sgibbs 219839223Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 219939223Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 220039223Sgibbs | CCB_TRANS_BUS_WIDTH_VALID; 220139223Sgibbs xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts); 220239223Sgibbs} 220339223Sgibbs 220439223Sgibbsstatic void 220539223Sgibbsbtmapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error) 220639223Sgibbs{ 220739223Sgibbs struct bt_softc* bt; 220839223Sgibbs 220939223Sgibbs bt = (struct bt_softc*)arg; 221039223Sgibbs bt->mailbox_physbase = segs->ds_addr; 221139223Sgibbs} 221239223Sgibbs 221339223Sgibbsstatic void 221439223Sgibbsbtmapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 221539223Sgibbs{ 221639223Sgibbs struct bt_softc* bt; 221739223Sgibbs 221839223Sgibbs bt = (struct bt_softc*)arg; 221939223Sgibbs bt->bt_ccb_physbase = segs->ds_addr; 222039223Sgibbs} 222139223Sgibbs 222239223Sgibbsstatic void 222339223Sgibbsbtmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 222439223Sgibbs{ 222539223Sgibbs 222639223Sgibbs struct bt_softc* bt; 222739223Sgibbs 222839223Sgibbs bt = (struct bt_softc*)arg; 222939223Sgibbs SLIST_FIRST(&bt->sg_maps)->sg_physaddr = segs->ds_addr; 223039223Sgibbs} 223139223Sgibbs 223239223Sgibbsstatic void 223339223Sgibbsbtpoll(struct cam_sim *sim) 223439223Sgibbs{ 223540132Sgibbs bt_intr(cam_sim_softc(sim)); 223639223Sgibbs} 223739223Sgibbs 223839223Sgibbsvoid 223939223Sgibbsbttimeout(void *arg) 224039223Sgibbs{ 224139223Sgibbs struct bt_ccb *bccb; 224239223Sgibbs union ccb *ccb; 224339223Sgibbs struct bt_softc *bt; 224439223Sgibbs int s; 224539223Sgibbs 224639223Sgibbs bccb = (struct bt_ccb *)arg; 224739223Sgibbs ccb = bccb->ccb; 224839223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 224939223Sgibbs xpt_print_path(ccb->ccb_h.path); 225039390Sgibbs printf("CCB %p - timed out\n", (void *)bccb); 225139223Sgibbs 225239223Sgibbs s = splcam(); 225339223Sgibbs 225439223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 225539223Sgibbs xpt_print_path(ccb->ccb_h.path); 225639390Sgibbs printf("CCB %p - timed out CCB already completed\n", 225739390Sgibbs (void *)bccb); 225839223Sgibbs splx(s); 225939223Sgibbs return; 226039223Sgibbs } 226139223Sgibbs 226239223Sgibbs /* 226339223Sgibbs * In order to simplify the recovery process, we ask the XPT 226439223Sgibbs * layer to halt the queue of new transactions and we traverse 226539223Sgibbs * the list of pending CCBs and remove their timeouts. This 226639223Sgibbs * means that the driver attempts to clear only one error 226739223Sgibbs * condition at a time. In general, timeouts that occur 226839223Sgibbs * close together are related anyway, so there is no benefit 226939223Sgibbs * in attempting to handle errors in parrallel. Timeouts will 227039223Sgibbs * be reinstated when the recovery process ends. 227139223Sgibbs */ 227239223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) { 227339223Sgibbs struct ccb_hdr *ccb_h; 227439223Sgibbs 227539223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) { 227639223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 227739223Sgibbs bccb->flags |= BCCB_RELEASE_SIMQ; 227839223Sgibbs } 227939223Sgibbs 228039223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 228139223Sgibbs while (ccb_h != NULL) { 228239223Sgibbs struct bt_ccb *pending_bccb; 228339223Sgibbs 228439223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 228539223Sgibbs untimeout(bttimeout, pending_bccb, ccb_h->timeout_ch); 228639223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 228739223Sgibbs } 228839223Sgibbs } 228939223Sgibbs 229039223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) != 0 229139223Sgibbs || bt->cur_outbox->action_code != BMBO_FREE 229240418Sgibbs || ((bccb->hccb.tag_enable == TRUE) 229339223Sgibbs && (bt->firmware_ver[0] < '5'))) { 229439223Sgibbs /* 229539223Sgibbs * Try a full host adapter/SCSI bus reset. 229639223Sgibbs * We do this only if we have already attempted 229739223Sgibbs * to clear the condition with a BDR, or we cannot 229839223Sgibbs * attempt a BDR for lack of mailbox resources 229939223Sgibbs * or because of faulty firmware. It turns out 230039223Sgibbs * that firmware versions prior to 5.xx treat BDRs 230139223Sgibbs * as untagged commands that cannot be sent until 230239223Sgibbs * all outstanding tagged commands have been processed. 230339223Sgibbs * This makes it somewhat difficult to use a BDR to 230439223Sgibbs * clear up a problem with an uncompleted tagged command. 230539223Sgibbs */ 230639223Sgibbs ccb->ccb_h.status = CAM_CMD_TIMEOUT; 230739223Sgibbs btreset(bt, /*hardreset*/TRUE); 230839223Sgibbs printf("%s: No longer in timeout\n", bt_name(bt)); 230939223Sgibbs } else { 231039223Sgibbs /* 231139223Sgibbs * Send a Bus Device Reset message: 231239223Sgibbs * The target that is holding up the bus may not 231339223Sgibbs * be the same as the one that triggered this timeout 231439223Sgibbs * (different commands have different timeout lengths), 231539223Sgibbs * but we have no way of determining this from our 231639223Sgibbs * timeout handler. Our strategy here is to queue a 231739223Sgibbs * BDR message to the target of the timed out command. 231839223Sgibbs * If this fails, we'll get another timeout 2 seconds 231939223Sgibbs * later which will attempt a bus reset. 232039223Sgibbs */ 232139223Sgibbs bccb->flags |= BCCB_DEVICE_RESET; 232239223Sgibbs ccb->ccb_h.timeout_ch = 232339223Sgibbs timeout(bttimeout, (caddr_t)bccb, 2 * hz); 232439223Sgibbs 232539223Sgibbs bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET; 232639223Sgibbs 232739223Sgibbs /* No Data Transfer */ 232839223Sgibbs bt->recovery_bccb->hccb.datain = TRUE; 232939223Sgibbs bt->recovery_bccb->hccb.dataout = TRUE; 233039223Sgibbs bt->recovery_bccb->hccb.btstat = 0; 233139223Sgibbs bt->recovery_bccb->hccb.sdstat = 0; 233239223Sgibbs bt->recovery_bccb->hccb.target_id = ccb->ccb_h.target_id; 233339223Sgibbs 233439223Sgibbs /* Tell the adapter about this command */ 233539223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bt->recovery_bccb); 233639223Sgibbs bt->cur_outbox->action_code = BMBO_START; 233739223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 233839223Sgibbs btnextoutbox(bt); 233939223Sgibbs } 234039223Sgibbs 234139223Sgibbs splx(s); 234239223Sgibbs} 234339223Sgibbs 2344