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: stable/11/sys/dev/buslogic/bt.c 315812 2017-03-23 06:40: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); 249115555Sphk /* FALLTHROUGH */ 25039223Sgibbs case 5: 25139223Sgibbs bus_dma_tag_destroy(bt->ccb_dmat); 252115555Sphk /* FALLTHROUGH */ 25339223Sgibbs case 4: 25439223Sgibbs bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap); 255115555Sphk /* FALLTHROUGH */ 25639223Sgibbs case 3: 25739223Sgibbs bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes, 25839223Sgibbs bt->mailbox_dmamap); 259115555Sphk /* FALLTHROUGH */ 26039223Sgibbs case 2: 26139223Sgibbs bus_dma_tag_destroy(bt->buffer_dmat); 262115555Sphk /* FALLTHROUGH */ 26339223Sgibbs case 1: 26439223Sgibbs bus_dma_tag_destroy(bt->mailbox_dmat); 265115555Sphk /* FALLTHROUGH */ 26639223Sgibbs case 0: 26739223Sgibbs break; 26839223Sgibbs } 269241592Sjhb mtx_destroy(&bt->lock); 27039223Sgibbs} 27139223Sgibbs 27244581Sgibbsint 27345791Speterbt_port_probe(device_t dev, struct bt_probe_info *info) 27444581Sgibbs{ 27545791Speter struct bt_softc *bt = device_get_softc(dev); 27644581Sgibbs config_data_t config_data; 27744581Sgibbs int error; 27844581Sgibbs 27944581Sgibbs /* See if there is really a card present */ 28045791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev)) 28144581Sgibbs return(1); 28244581Sgibbs 28344581Sgibbs /* 28444581Sgibbs * Determine our IRQ, and DMA settings and 28544581Sgibbs * export them to the configuration system. 28644581Sgibbs */ 287241592Sjhb mtx_lock(&bt->lock); 28844581Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 28944581Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 29044581Sgibbs DEFAULT_CMD_TIMEOUT); 291241592Sjhb mtx_unlock(&bt->lock); 29244581Sgibbs if (error != 0) { 29344581Sgibbs printf("bt_port_probe: Could not determine IRQ or DMA " 29444581Sgibbs "settings for adapter.\n"); 29544581Sgibbs return (1); 29644581Sgibbs } 29744581Sgibbs 29844581Sgibbs if (bt->model[0] == '5') { 29944581Sgibbs /* DMA settings only make sense for ISA cards */ 30044581Sgibbs switch (config_data.dma_chan) { 30144581Sgibbs case DMA_CHAN_5: 30244581Sgibbs info->drq = 5; 30344581Sgibbs break; 30444581Sgibbs case DMA_CHAN_6: 30544581Sgibbs info->drq = 6; 30644581Sgibbs break; 30744581Sgibbs case DMA_CHAN_7: 30844581Sgibbs info->drq = 7; 30944581Sgibbs break; 31044581Sgibbs default: 31144581Sgibbs printf("bt_port_probe: Invalid DMA setting " 31244581Sgibbs "detected for adapter.\n"); 31344581Sgibbs return (1); 31444581Sgibbs } 31544581Sgibbs } else { 31644581Sgibbs /* VL/EISA/PCI DMA */ 31744581Sgibbs info->drq = -1; 31844581Sgibbs } 31944581Sgibbs switch (config_data.irq) { 32044581Sgibbs case IRQ_9: 32144581Sgibbs case IRQ_10: 32244581Sgibbs case IRQ_11: 32344581Sgibbs case IRQ_12: 32444581Sgibbs case IRQ_14: 32544581Sgibbs case IRQ_15: 32644581Sgibbs info->irq = ffs(config_data.irq) + 8; 32744581Sgibbs break; 32844581Sgibbs default: 32944581Sgibbs printf("bt_port_probe: Invalid IRQ setting %x" 33044581Sgibbs "detected for adapter.\n", config_data.irq); 33144581Sgibbs return (1); 33244581Sgibbs } 33344581Sgibbs return (0); 33444581Sgibbs} 33544581Sgibbs 33639223Sgibbs/* 33739223Sgibbs * Probe the adapter and verify that the card is a BusLogic. 33839223Sgibbs */ 33939223Sgibbsint 34045791Speterbt_probe(device_t dev) 34139223Sgibbs{ 34245791Speter struct bt_softc *bt = device_get_softc(dev); 34339223Sgibbs esetup_info_data_t esetup_info; 34439223Sgibbs u_int status; 34539223Sgibbs u_int intstat; 34639223Sgibbs u_int geometry; 34739223Sgibbs int error; 34839223Sgibbs u_int8_t param; 34939223Sgibbs 35039223Sgibbs /* 35139223Sgibbs * See if the three I/O ports look reasonable. 35239223Sgibbs * Touch the minimal number of registers in the 35339223Sgibbs * failure case. 35439223Sgibbs */ 35539223Sgibbs status = bt_inb(bt, STATUS_REG); 35639223Sgibbs if ((status == 0) 35739223Sgibbs || (status & (DIAG_ACTIVE|CMD_REG_BUSY| 35839223Sgibbs STATUS_REG_RSVD|CMD_INVALID)) != 0) { 35939223Sgibbs if (bootverbose) 36045791Speter device_printf(dev, "Failed Status Reg Test - %x\n", 36139223Sgibbs status); 36239223Sgibbs return (ENXIO); 36339223Sgibbs } 36439223Sgibbs 36539223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 36639223Sgibbs if ((intstat & INTSTAT_REG_RSVD) != 0) { 36745791Speter device_printf(dev, "Failed Intstat Reg Test\n"); 36839223Sgibbs return (ENXIO); 36939223Sgibbs } 37039223Sgibbs 37139223Sgibbs geometry = bt_inb(bt, GEOMETRY_REG); 37239223Sgibbs if (geometry == 0xFF) { 37339223Sgibbs if (bootverbose) 37445791Speter device_printf(dev, "Failed Geometry Reg Test\n"); 37539223Sgibbs return (ENXIO); 37639223Sgibbs } 37739223Sgibbs 37839223Sgibbs /* 37939223Sgibbs * Looking good so far. Final test is to reset the 38039223Sgibbs * adapter and attempt to fetch the extended setup 38139223Sgibbs * information. This should filter out all 1542 cards. 38239223Sgibbs */ 383241592Sjhb mtx_lock(&bt->lock); 38439223Sgibbs if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) { 385241592Sjhb mtx_unlock(&bt->lock); 38639223Sgibbs if (bootverbose) 38745791Speter device_printf(dev, "Failed Reset\n"); 38839223Sgibbs return (ENXIO); 38939223Sgibbs } 39039223Sgibbs 39139223Sgibbs param = sizeof(esetup_info); 39239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, ¶m, /*parmlen*/1, 39339223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 39439223Sgibbs DEFAULT_CMD_TIMEOUT); 395241592Sjhb mtx_unlock(&bt->lock); 39639223Sgibbs if (error != 0) { 39739223Sgibbs return (ENXIO); 39839223Sgibbs } 39939223Sgibbs 40039223Sgibbs return (0); 40139223Sgibbs} 40239223Sgibbs 40339223Sgibbs/* 40439223Sgibbs * Pull the boards setup information and record it in our softc. 40539223Sgibbs */ 40639223Sgibbsint 40745791Speterbt_fetch_adapter_info(device_t dev) 40839223Sgibbs{ 40945791Speter struct bt_softc *bt = device_get_softc(dev); 41039223Sgibbs board_id_data_t board_id; 41139223Sgibbs esetup_info_data_t esetup_info; 41239223Sgibbs config_data_t config_data; 41339223Sgibbs int error; 41439223Sgibbs u_int8_t length_param; 41539223Sgibbs 41639223Sgibbs /* First record the firmware version */ 417241592Sjhb mtx_lock(&bt->lock); 41839223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0, 41939223Sgibbs (u_int8_t*)&board_id, sizeof(board_id), 42039223Sgibbs DEFAULT_CMD_TIMEOUT); 42139223Sgibbs if (error != 0) { 422241592Sjhb mtx_unlock(&bt->lock); 42345791Speter device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n"); 42439223Sgibbs return (error); 42539223Sgibbs } 42639223Sgibbs bt->firmware_ver[0] = board_id.firmware_rev_major; 42739223Sgibbs bt->firmware_ver[1] = '.'; 42839223Sgibbs bt->firmware_ver[2] = board_id.firmware_rev_minor; 42939223Sgibbs bt->firmware_ver[3] = '\0'; 43039223Sgibbs 43139223Sgibbs /* 43239223Sgibbs * Depending on the firmware major and minor version, 43339223Sgibbs * we may be able to fetch additional minor version info. 43439223Sgibbs */ 43539223Sgibbs if (bt->firmware_ver[0] > '0') { 43639223Sgibbs 43739223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0, 43839223Sgibbs (u_int8_t*)&bt->firmware_ver[3], 1, 43939223Sgibbs DEFAULT_CMD_TIMEOUT); 44039223Sgibbs if (error != 0) { 441241592Sjhb mtx_unlock(&bt->lock); 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) { 458241592Sjhb mtx_unlock(&bt->lock); 45945791Speter device_printf(dev, 46045791Speter "bt_fetch_adapter_info - Failed Get " 46145791Speter "Firmware 4th Digit\n"); 46239223Sgibbs return (error); 46339223Sgibbs } 46439223Sgibbs if (bt->firmware_ver[4] == ' ') 46539223Sgibbs bt->firmware_ver[4] = '\0'; 46639223Sgibbs bt->firmware_ver[5] = '\0'; 46739223Sgibbs } 46839223Sgibbs 46939223Sgibbs /* 47039223Sgibbs * Some boards do not handle the "recently documented" 47139223Sgibbs * Inquire Board Model Number command correctly or do not give 47239223Sgibbs * exact information. Use the Firmware and Extended Setup 47339223Sgibbs * information in these cases to come up with the right answer. 47439223Sgibbs * The major firmware revision number indicates: 47539223Sgibbs * 47639223Sgibbs * 5.xx BusLogic "W" Series Host Adapters: 47739223Sgibbs * BT-948/958/958D 47839223Sgibbs * 4.xx BusLogic "C" Series Host Adapters: 47939223Sgibbs * BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF 48039223Sgibbs * 3.xx BusLogic "S" Series Host Adapters: 48139223Sgibbs * BT-747S/747D/757S/757D/445S/545S/542D 48239223Sgibbs * BT-542B/742A (revision H) 48339223Sgibbs * 2.xx BusLogic "A" Series Host Adapters: 48439223Sgibbs * BT-542B/742A (revision G and below) 48539223Sgibbs * 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter 48639223Sgibbs */ 48739223Sgibbs length_param = sizeof(esetup_info); 48839223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &length_param, /*parmlen*/1, 48939223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 49039223Sgibbs DEFAULT_CMD_TIMEOUT); 49139223Sgibbs if (error != 0) { 492241592Sjhb mtx_unlock(&bt->lock); 49339223Sgibbs return (error); 49439223Sgibbs } 49539223Sgibbs 49639223Sgibbs bt->bios_addr = esetup_info.bios_addr << 12; 49739223Sgibbs 49868661Sgibbs bt->mailbox_addrlimit = BUS_SPACE_MAXADDR; 49939223Sgibbs if (esetup_info.bus_type == 'A' 50039223Sgibbs && bt->firmware_ver[0] == '2') { 50141514Sarchie snprintf(bt->model, sizeof(bt->model), "542B"); 50239223Sgibbs } else if (esetup_info.bus_type == 'E' 50368661Sgibbs && bt->firmware_ver[0] == '2') { 50468661Sgibbs 50568661Sgibbs /* 50668661Sgibbs * The 742A seems to object if its mailboxes are 50768661Sgibbs * allocated above the 16MB mark. 50868661Sgibbs */ 50968661Sgibbs bt->mailbox_addrlimit = BUS_SPACE_MAXADDR_24BIT; 51041514Sarchie snprintf(bt->model, sizeof(bt->model), "742A"); 51139223Sgibbs } else if (esetup_info.bus_type == 'E' 51239223Sgibbs && bt->firmware_ver[0] == '0') { 51339223Sgibbs /* AMI FastDisk EISA Series 441 0.x */ 51441514Sarchie snprintf(bt->model, sizeof(bt->model), "747A"); 51539223Sgibbs } else { 51639223Sgibbs ha_model_data_t model_data; 51739223Sgibbs int i; 51839223Sgibbs 51939223Sgibbs length_param = sizeof(model_data); 52039223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1, 52139223Sgibbs (u_int8_t*)&model_data, sizeof(model_data), 52239223Sgibbs DEFAULT_CMD_TIMEOUT); 52339223Sgibbs if (error != 0) { 524241592Sjhb mtx_unlock(&bt->lock); 52545791Speter device_printf(dev, 52645791Speter "bt_fetch_adapter_info - Failed Inquire " 52745791Speter "Model Number\n"); 52839223Sgibbs return (error); 52939223Sgibbs } 53039223Sgibbs for (i = 0; i < sizeof(model_data.ascii_model); i++) { 53139223Sgibbs bt->model[i] = model_data.ascii_model[i]; 53239223Sgibbs if (bt->model[i] == ' ') 53339223Sgibbs break; 53439223Sgibbs } 53539223Sgibbs bt->model[i] = '\0'; 53639223Sgibbs } 53739223Sgibbs 53844581Sgibbs bt->level_trigger_ints = esetup_info.level_trigger_ints ? 1 : 0; 53944581Sgibbs 54039223Sgibbs /* SG element limits */ 54139223Sgibbs bt->max_sg = esetup_info.max_sg; 54239223Sgibbs 54339223Sgibbs /* Set feature flags */ 54439223Sgibbs bt->wide_bus = esetup_info.wide_bus; 54539223Sgibbs bt->diff_bus = esetup_info.diff_bus; 54639223Sgibbs bt->ultra_scsi = esetup_info.ultra_scsi; 54739223Sgibbs 54839223Sgibbs if ((bt->firmware_ver[0] == '5') 54939223Sgibbs || (bt->firmware_ver[0] == '4' && bt->wide_bus)) 55039223Sgibbs bt->extended_lun = TRUE; 55139223Sgibbs 55239223Sgibbs bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0); 55339223Sgibbs 55439223Sgibbs bt->extended_trans = 55539223Sgibbs ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0); 55639223Sgibbs 55739223Sgibbs /* 55839223Sgibbs * Determine max CCB count and whether tagged queuing is 55939223Sgibbs * available based on controller type. Tagged queuing 56039223Sgibbs * only works on 'W' series adapters, 'C' series adapters 56139223Sgibbs * with firmware of rev 4.42 and higher, and 'S' series 56239223Sgibbs * adapters with firmware of rev 3.35 and higher. The 56339223Sgibbs * maximum CCB counts are as follows: 56439223Sgibbs * 56539223Sgibbs * 192 BT-948/958/958D 56639223Sgibbs * 100 BT-946C/956C/956CD/747C/757C/757CD/445C 56739223Sgibbs * 50 BT-545C/540CF 56839223Sgibbs * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A 56939223Sgibbs */ 57039223Sgibbs if (bt->firmware_ver[0] == '5') { 57139223Sgibbs bt->max_ccbs = 192; 57239223Sgibbs bt->tag_capable = TRUE; 57339223Sgibbs } else if (bt->firmware_ver[0] == '4') { 57439223Sgibbs if (bt->model[0] == '5') 57539223Sgibbs bt->max_ccbs = 50; 57639223Sgibbs else 57739223Sgibbs bt->max_ccbs = 100; 57839223Sgibbs bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0); 57939223Sgibbs } else { 58039223Sgibbs bt->max_ccbs = 30; 58139223Sgibbs if (bt->firmware_ver[0] == '3' 58239223Sgibbs && (strcmp(bt->firmware_ver, "3.35") >= 0)) 58339223Sgibbs bt->tag_capable = TRUE; 58439223Sgibbs else 58539223Sgibbs bt->tag_capable = FALSE; 58639223Sgibbs } 58739223Sgibbs 58839223Sgibbs if (bt->tag_capable != FALSE) 58939223Sgibbs bt->tags_permitted = ALL_TARGETS; 59039223Sgibbs 59139223Sgibbs /* Determine Sync/Wide/Disc settings */ 59239223Sgibbs if (bt->firmware_ver[0] >= '4') { 59339223Sgibbs auto_scsi_data_t auto_scsi_data; 59439223Sgibbs fetch_lram_params_t fetch_lram_params; 59539223Sgibbs int error; 59639223Sgibbs 59739223Sgibbs /* 59839223Sgibbs * These settings are stored in the 59939223Sgibbs * AutoSCSI data in LRAM of 'W' and 'C' 60039223Sgibbs * adapters. 60139223Sgibbs */ 60239223Sgibbs fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET; 60339223Sgibbs fetch_lram_params.response_len = sizeof(auto_scsi_data); 60439223Sgibbs error = bt_cmd(bt, BOP_FETCH_LRAM, 60539223Sgibbs (u_int8_t*)&fetch_lram_params, 60639223Sgibbs sizeof(fetch_lram_params), 60739223Sgibbs (u_int8_t*)&auto_scsi_data, 60839223Sgibbs sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT); 60939223Sgibbs 61039223Sgibbs if (error != 0) { 611241592Sjhb mtx_unlock(&bt->lock); 61245791Speter device_printf(dev, 61345791Speter "bt_fetch_adapter_info - Failed " 61445791Speter "Get Auto SCSI Info\n"); 61539223Sgibbs return (error); 61639223Sgibbs } 61739223Sgibbs 61839223Sgibbs bt->disc_permitted = auto_scsi_data.low_disc_permitted 61939223Sgibbs | (auto_scsi_data.high_disc_permitted << 8); 62039223Sgibbs bt->sync_permitted = auto_scsi_data.low_sync_permitted 62139223Sgibbs | (auto_scsi_data.high_sync_permitted << 8); 62239223Sgibbs bt->fast_permitted = auto_scsi_data.low_fast_permitted 62339223Sgibbs | (auto_scsi_data.high_fast_permitted << 8); 62439223Sgibbs bt->ultra_permitted = auto_scsi_data.low_ultra_permitted 62539223Sgibbs | (auto_scsi_data.high_ultra_permitted << 8); 62639223Sgibbs bt->wide_permitted = auto_scsi_data.low_wide_permitted 62739223Sgibbs | (auto_scsi_data.high_wide_permitted << 8); 62839223Sgibbs 62939223Sgibbs if (bt->ultra_scsi == FALSE) 63039223Sgibbs bt->ultra_permitted = 0; 63139223Sgibbs 63239223Sgibbs if (bt->wide_bus == FALSE) 63339223Sgibbs bt->wide_permitted = 0; 63439223Sgibbs } else { 63539223Sgibbs /* 63639223Sgibbs * 'S' and 'A' series have this information in the setup 63739223Sgibbs * information structure. 63839223Sgibbs */ 63939223Sgibbs setup_data_t setup_info; 64039223Sgibbs 64139223Sgibbs length_param = sizeof(setup_info); 64239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param, 64339223Sgibbs /*paramlen*/1, (u_int8_t*)&setup_info, 64439223Sgibbs sizeof(setup_info), DEFAULT_CMD_TIMEOUT); 64539223Sgibbs 64639223Sgibbs if (error != 0) { 647241592Sjhb mtx_unlock(&bt->lock); 64845791Speter device_printf(dev, 64945791Speter "bt_fetch_adapter_info - Failed " 65045791Speter "Get Setup Info\n"); 65139223Sgibbs return (error); 65239223Sgibbs } 65339223Sgibbs 65439223Sgibbs if (setup_info.initiate_sync != 0) { 65539223Sgibbs bt->sync_permitted = ALL_TARGETS; 65639223Sgibbs 65739223Sgibbs if (bt->model[0] == '7') { 65839223Sgibbs if (esetup_info.sync_neg10MB != 0) 65939223Sgibbs bt->fast_permitted = ALL_TARGETS; 66039223Sgibbs if (strcmp(bt->model, "757") == 0) 66139223Sgibbs bt->wide_permitted = ALL_TARGETS; 66239223Sgibbs } 66339223Sgibbs } 66439223Sgibbs bt->disc_permitted = ALL_TARGETS; 66539223Sgibbs } 66639223Sgibbs 66739223Sgibbs /* We need as many mailboxes as we can have ccbs */ 66839223Sgibbs bt->num_boxes = bt->max_ccbs; 66939223Sgibbs 67039223Sgibbs /* Determine our SCSI ID */ 67139223Sgibbs 67239223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 67339223Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 67439223Sgibbs DEFAULT_CMD_TIMEOUT); 675241592Sjhb mtx_unlock(&bt->lock); 67639223Sgibbs if (error != 0) { 67745791Speter device_printf(dev, 67845791Speter "bt_fetch_adapter_info - Failed Get Config\n"); 67939223Sgibbs return (error); 68039223Sgibbs } 68139223Sgibbs bt->scsi_id = config_data.scsi_id; 68239223Sgibbs 68339223Sgibbs return (0); 68439223Sgibbs} 68539223Sgibbs 68639223Sgibbs/* 68739223Sgibbs * Start the board, ready for normal operation 68839223Sgibbs */ 68939223Sgibbsint 69045791Speterbt_init(device_t dev) 69139223Sgibbs{ 69245791Speter struct bt_softc *bt = device_get_softc(dev); 69345791Speter 69439223Sgibbs /* Announce the Adapter */ 69545791Speter device_printf(dev, "BT-%s FW Rev. %s ", bt->model, bt->firmware_ver); 69639223Sgibbs 69739223Sgibbs if (bt->ultra_scsi != 0) 69839223Sgibbs printf("Ultra "); 69939223Sgibbs 70039223Sgibbs if (bt->wide_bus != 0) 70139223Sgibbs printf("Wide "); 70239223Sgibbs else 70339223Sgibbs printf("Narrow "); 70439223Sgibbs 70539223Sgibbs if (bt->diff_bus != 0) 70639223Sgibbs printf("Diff "); 70739223Sgibbs 70839223Sgibbs printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id, 70939223Sgibbs bt->max_ccbs); 71039223Sgibbs 71139223Sgibbs /* 71239223Sgibbs * Create our DMA tags. These tags define the kinds of device 71361686Salex * accessible memory allocations and memory mappings we will 71439223Sgibbs * need to perform during normal operation. 71539223Sgibbs * 71639223Sgibbs * Unless we need to further restrict the allocation, we rely 71739223Sgibbs * on the restrictions of the parent dmat, hence the common 71839223Sgibbs * use of MAXADDR and MAXSIZE. 71939223Sgibbs */ 72039223Sgibbs 72139223Sgibbs /* DMA tag for mapping buffers into device visible space. */ 722112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 723112782Smdodd /* alignment */ 1, 724112782Smdodd /* boundary */ 0, 725112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 726112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 727112782Smdodd /* filter */ NULL, 728112782Smdodd /* filterarg */ NULL, 729280347Smav /* maxsize */ DFLTPHYS, 730112782Smdodd /* nsegments */ BT_NSEG, 731112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 732112782Smdodd /* flags */ BUS_DMA_ALLOCNOW, 733117126Sscottl /* lockfunc */ busdma_lock_mutex, 734241592Sjhb /* lockarg */ &bt->lock, 735112782Smdodd &bt->buffer_dmat) != 0) { 73639223Sgibbs goto error_exit; 73739223Sgibbs } 73839223Sgibbs 73939223Sgibbs bt->init_level++; 74039223Sgibbs /* DMA tag for our mailboxes */ 741112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 742112782Smdodd /* alignment */ 1, 743112782Smdodd /* boundary */ 0, 744112782Smdodd /* lowaddr */ bt->mailbox_addrlimit, 745112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 746112782Smdodd /* filter */ NULL, 747112782Smdodd /* filterarg */ NULL, 748112782Smdodd /* maxsize */ bt->num_boxes * 749112782Smdodd (sizeof(bt_mbox_in_t) + 750112782Smdodd sizeof(bt_mbox_out_t)), 751112782Smdodd /* nsegments */ 1, 752112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 753112782Smdodd /* flags */ 0, 754241592Sjhb /* lockfunc */ NULL, 755241592Sjhb /* lockarg */ NULL, 756112782Smdodd &bt->mailbox_dmat) != 0) { 75739223Sgibbs goto error_exit; 75839223Sgibbs } 75939223Sgibbs 76039223Sgibbs bt->init_level++; 76139223Sgibbs 76239223Sgibbs /* Allocation for our mailboxes */ 76339223Sgibbs if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes, 76439223Sgibbs BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) { 76539223Sgibbs goto error_exit; 76639223Sgibbs } 76739223Sgibbs 76839223Sgibbs bt->init_level++; 76939223Sgibbs 77039223Sgibbs /* And permanently map them */ 77139223Sgibbs bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap, 77239223Sgibbs bt->out_boxes, 77339223Sgibbs bt->num_boxes * (sizeof(bt_mbox_in_t) 77439223Sgibbs + sizeof(bt_mbox_out_t)), 77539223Sgibbs btmapmboxes, bt, /*flags*/0); 77639223Sgibbs 77739223Sgibbs bt->init_level++; 77839223Sgibbs 77939223Sgibbs bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes]; 78039223Sgibbs 781241592Sjhb mtx_lock(&bt->lock); 78239223Sgibbs btinitmboxes(bt); 783241592Sjhb mtx_unlock(&bt->lock); 78439223Sgibbs 78539223Sgibbs /* DMA tag for our ccb structures */ 786112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 787112782Smdodd /* alignment */ 1, 788112782Smdodd /* boundary */ 0, 789112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 790112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 791112782Smdodd /* filter */ NULL, 792112782Smdodd /* filterarg */ NULL, 793112782Smdodd /* maxsize */ bt->max_ccbs * 794112782Smdodd sizeof(struct bt_ccb), 795112782Smdodd /* nsegments */ 1, 796112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 797112782Smdodd /* flags */ 0, 798241592Sjhb /* lockfunc */ NULL, 799241592Sjhb /* lockarg */ NULL, 800112782Smdodd &bt->ccb_dmat) != 0) { 80139223Sgibbs goto error_exit; 80239223Sgibbs } 80339223Sgibbs 80439223Sgibbs bt->init_level++; 80539223Sgibbs 80639223Sgibbs /* Allocation for our ccbs */ 80739223Sgibbs if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array, 80839223Sgibbs BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) { 80939223Sgibbs goto error_exit; 81039223Sgibbs } 81139223Sgibbs 81239223Sgibbs bt->init_level++; 81339223Sgibbs 81439223Sgibbs /* And permanently map them */ 81539223Sgibbs bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap, 81639223Sgibbs bt->bt_ccb_array, 81739223Sgibbs bt->max_ccbs * sizeof(struct bt_ccb), 81839223Sgibbs btmapccbs, bt, /*flags*/0); 81939223Sgibbs 82039223Sgibbs bt->init_level++; 82139223Sgibbs 82239223Sgibbs /* DMA tag for our S/G structures. We allocate in page sized chunks */ 823112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 824112782Smdodd /* alignment */ 1, 825112782Smdodd /* boundary */ 0, 826112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 827112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 828112782Smdodd /* filter */ NULL, 829112782Smdodd /* filterarg */ NULL, 830112782Smdodd /* maxsize */ PAGE_SIZE, 831112782Smdodd /* nsegments */ 1, 832112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 833112782Smdodd /* flags */ 0, 834241592Sjhb /* lockfunc */ NULL, 835241592Sjhb /* lockarg */ NULL, 836112782Smdodd &bt->sg_dmat) != 0) { 83739223Sgibbs goto error_exit; 83839223Sgibbs } 83939223Sgibbs 84039223Sgibbs bt->init_level++; 84139223Sgibbs 84239223Sgibbs /* Perform initial CCB allocation */ 84339223Sgibbs bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb)); 84439223Sgibbs btallocccbs(bt); 84539223Sgibbs 84639223Sgibbs if (bt->num_ccbs == 0) { 84745791Speter device_printf(dev, 84845791Speter "bt_init - Unable to allocate initial ccbs\n"); 84939223Sgibbs goto error_exit; 85039223Sgibbs } 85139223Sgibbs 85239223Sgibbs /* 853241592Sjhb * Note that we are going and return (to attach) 85439223Sgibbs */ 85539223Sgibbs return 0; 85639223Sgibbs 85739223Sgibbserror_exit: 85839223Sgibbs 85939223Sgibbs return (ENXIO); 86039223Sgibbs} 86139223Sgibbs 86239223Sgibbsint 86345791Speterbt_attach(device_t dev) 86439223Sgibbs{ 86545791Speter struct bt_softc *bt = device_get_softc(dev); 86639223Sgibbs int tagged_dev_openings; 86739223Sgibbs struct cam_devq *devq; 86845795Speter int error; 86939223Sgibbs 87039223Sgibbs /* 87139223Sgibbs * We reserve 1 ccb for error recovery, so don't 87239223Sgibbs * tell the XPT about it. 87339223Sgibbs */ 87439223Sgibbs if (bt->tag_capable != 0) 87539223Sgibbs tagged_dev_openings = bt->max_ccbs - 1; 87639223Sgibbs else 87739223Sgibbs tagged_dev_openings = 0; 87839223Sgibbs 87939223Sgibbs /* 88039223Sgibbs * Create the device queue for our SIM. 88139223Sgibbs */ 88239223Sgibbs devq = cam_simq_alloc(bt->max_ccbs - 1); 88339223Sgibbs if (devq == NULL) 88439223Sgibbs return (ENOMEM); 88539223Sgibbs 88639223Sgibbs /* 88739223Sgibbs * Construct our SIM entry 88839223Sgibbs */ 889241592Sjhb bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, 890241592Sjhb device_get_unit(bt->dev), &bt->lock, 2, tagged_dev_openings, devq); 89139223Sgibbs if (bt->sim == NULL) { 89239223Sgibbs cam_simq_free(devq); 89339223Sgibbs return (ENOMEM); 89439223Sgibbs } 895241592Sjhb 896241592Sjhb mtx_lock(&bt->lock); 897170872Sscottl if (xpt_bus_register(bt->sim, dev, 0) != CAM_SUCCESS) { 89839223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 899241592Sjhb mtx_unlock(&bt->lock); 90039223Sgibbs return (ENXIO); 90139223Sgibbs } 90239223Sgibbs 90339223Sgibbs if (xpt_create_path(&bt->path, /*periph*/NULL, 90439223Sgibbs cam_sim_path(bt->sim), CAM_TARGET_WILDCARD, 90539223Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 90639223Sgibbs xpt_bus_deregister(cam_sim_path(bt->sim)); 90739223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 908241592Sjhb mtx_unlock(&bt->lock); 90939223Sgibbs return (ENXIO); 91039223Sgibbs } 911241592Sjhb mtx_unlock(&bt->lock); 91239223Sgibbs 91345791Speter /* 91445791Speter * Setup interrupt. 91545791Speter */ 916241592Sjhb error = bus_setup_intr(dev, bt->irq, INTR_TYPE_CAM | INTR_ENTROPY | 917241592Sjhb INTR_MPSAFE, NULL, bt_intr, bt, &bt->ih); 91845795Speter if (error) { 91945795Speter device_printf(dev, "bus_setup_intr() failed: %d\n", error); 92045795Speter return (error); 92145795Speter } 92245791Speter 92339223Sgibbs return (0); 92439223Sgibbs} 92539223Sgibbs 92639223Sgibbsint 92739223Sgibbsbt_check_probed_iop(u_int ioport) 92839223Sgibbs{ 92939223Sgibbs u_int i; 93039223Sgibbs 93141048Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 93239223Sgibbs if (bt_isa_ports[i].addr == ioport) { 93339223Sgibbs if (bt_isa_ports[i].probed != 0) 93439223Sgibbs return (1); 93539223Sgibbs else { 93639223Sgibbs return (0); 93739223Sgibbs } 93839223Sgibbs } 93939223Sgibbs } 94039223Sgibbs return (1); 94139223Sgibbs} 94239223Sgibbs 94339223Sgibbsvoid 94439223Sgibbsbt_mark_probed_bio(isa_compat_io_t port) 94539223Sgibbs{ 94639223Sgibbs if (port < BIO_DISABLED) 94741048Sgibbs bt_mark_probed_iop(bt_board_ports[port]); 94839223Sgibbs} 94939223Sgibbs 95039223Sgibbsvoid 95139223Sgibbsbt_mark_probed_iop(u_int ioport) 95239223Sgibbs{ 95339223Sgibbs u_int i; 95439223Sgibbs 95539223Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 95639223Sgibbs if (ioport == bt_isa_ports[i].addr) { 95739223Sgibbs bt_isa_ports[i].probed = 1; 95839223Sgibbs break; 95939223Sgibbs } 96039223Sgibbs } 96139223Sgibbs} 96239223Sgibbs 96341048Sgibbsvoid 96441048Sgibbsbt_find_probe_range(int ioport, int *port_index, int *max_port_index) 96541048Sgibbs{ 96641048Sgibbs if (ioport > 0) { 96741048Sgibbs int i; 96841048Sgibbs 96941048Sgibbs for (i = 0;i < BT_NUM_ISAPORTS; i++) 97041048Sgibbs if (ioport <= bt_isa_ports[i].addr) 97141048Sgibbs break; 97241048Sgibbs if ((i >= BT_NUM_ISAPORTS) 97341048Sgibbs || (ioport != bt_isa_ports[i].addr)) { 97487797Sjhb printf( 975118052Sbde"bt_find_probe_range: Invalid baseport of 0x%x specified.\n" 976118052Sbde"bt_find_probe_range: Nearest valid baseport is 0x%x.\n" 977118052Sbde"bt_find_probe_range: Failing probe.\n", 97841048Sgibbs ioport, 97941048Sgibbs (i < BT_NUM_ISAPORTS) 98041048Sgibbs ? bt_isa_ports[i].addr 98141048Sgibbs : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr); 98241048Sgibbs *port_index = *max_port_index = -1; 98341048Sgibbs return; 98441048Sgibbs } 98541048Sgibbs *port_index = *max_port_index = bt_isa_ports[i].bio; 98641048Sgibbs } else { 98741048Sgibbs *port_index = 0; 98841048Sgibbs *max_port_index = BT_NUM_ISAPORTS - 1; 98941048Sgibbs } 99041048Sgibbs} 99141048Sgibbs 99241048Sgibbsint 99341048Sgibbsbt_iop_from_bio(isa_compat_io_t bio_index) 99441048Sgibbs{ 995217538Sjhb if (bio_index < BT_NUM_ISAPORTS) 99641048Sgibbs return (bt_board_ports[bio_index]); 99741048Sgibbs return (-1); 99841048Sgibbs} 99941048Sgibbs 100041048Sgibbs 100139223Sgibbsstatic void 100239223Sgibbsbtallocccbs(struct bt_softc *bt) 100339223Sgibbs{ 100439223Sgibbs struct bt_ccb *next_ccb; 100539223Sgibbs struct sg_map_node *sg_map; 100639223Sgibbs bus_addr_t physaddr; 100739223Sgibbs bt_sg_t *segs; 100839223Sgibbs int newcount; 100939223Sgibbs int i; 101039223Sgibbs 101145966Sgibbs if (bt->num_ccbs >= bt->max_ccbs) 101245966Sgibbs /* Can't allocate any more */ 101345966Sgibbs return; 101445966Sgibbs 101539223Sgibbs next_ccb = &bt->bt_ccb_array[bt->num_ccbs]; 101639223Sgibbs 101739223Sgibbs sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 101839223Sgibbs 101939223Sgibbs if (sg_map == NULL) 102045966Sgibbs goto error_exit; 102139223Sgibbs 102239223Sgibbs /* Allocate S/G space for the next batch of CCBS */ 102339223Sgibbs if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr, 102439223Sgibbs BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { 102539223Sgibbs free(sg_map, M_DEVBUF); 102645966Sgibbs goto error_exit; 102739223Sgibbs } 102839223Sgibbs 102939223Sgibbs SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links); 103039223Sgibbs 103139223Sgibbs bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, 103239223Sgibbs PAGE_SIZE, btmapsgs, bt, /*flags*/0); 103339223Sgibbs 103439223Sgibbs segs = sg_map->sg_vaddr; 103539223Sgibbs physaddr = sg_map->sg_physaddr; 103639223Sgibbs 103739223Sgibbs newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t))); 103839223Sgibbs for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) { 103939223Sgibbs int error; 104039223Sgibbs 104139223Sgibbs next_ccb->sg_list = segs; 104239223Sgibbs next_ccb->sg_list_phys = physaddr; 104339223Sgibbs next_ccb->flags = BCCB_FREE; 1044241592Sjhb callout_init_mtx(&next_ccb->timer, &bt->lock, 0); 104539223Sgibbs error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0, 104639223Sgibbs &next_ccb->dmamap); 104739223Sgibbs if (error != 0) 104839223Sgibbs break; 104939223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links); 105039223Sgibbs segs += BT_NSEG; 105139223Sgibbs physaddr += (BT_NSEG * sizeof(bt_sg_t)); 105239223Sgibbs next_ccb++; 105339223Sgibbs bt->num_ccbs++; 105439223Sgibbs } 105539223Sgibbs 105639223Sgibbs /* Reserve a CCB for error recovery */ 105739223Sgibbs if (bt->recovery_bccb == NULL) { 105839223Sgibbs bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs); 105939223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 106039223Sgibbs } 106145966Sgibbs 106245966Sgibbs if (SLIST_FIRST(&bt->free_bt_ccbs) != NULL) 106345966Sgibbs return; 106445966Sgibbs 106545966Sgibbserror_exit: 106645966Sgibbs device_printf(bt->dev, "Can't malloc BCCBs\n"); 106739223Sgibbs} 106839223Sgibbs 106939223Sgibbsstatic __inline void 107039223Sgibbsbtfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) 107139223Sgibbs{ 107239223Sgibbs 1073241592Sjhb if (!dumping) 1074241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 107539223Sgibbs if ((bccb->flags & BCCB_ACTIVE) != 0) 107639223Sgibbs LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le); 107739223Sgibbs if (bt->resource_shortage != 0 107839223Sgibbs && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 107939223Sgibbs bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 108039223Sgibbs bt->resource_shortage = FALSE; 108139223Sgibbs } 108239223Sgibbs bccb->flags = BCCB_FREE; 108339223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links); 108441048Sgibbs bt->active_ccbs--; 108539223Sgibbs} 108639223Sgibbs 108739223Sgibbsstatic __inline struct bt_ccb* 108839223Sgibbsbtgetccb(struct bt_softc *bt) 108939223Sgibbs{ 109039223Sgibbs struct bt_ccb* bccb; 109139223Sgibbs 1092241592Sjhb if (!dumping) 1093241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 109439223Sgibbs if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) { 109539223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 109641048Sgibbs bt->active_ccbs++; 109745966Sgibbs } else { 109839223Sgibbs btallocccbs(bt); 109939223Sgibbs bccb = SLIST_FIRST(&bt->free_bt_ccbs); 110045966Sgibbs if (bccb != NULL) { 110139223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 110241048Sgibbs bt->active_ccbs++; 110341048Sgibbs } 110439223Sgibbs } 110539223Sgibbs 110639223Sgibbs return (bccb); 110739223Sgibbs} 110839223Sgibbs 110939223Sgibbsstatic void 111039223Sgibbsbtaction(struct cam_sim *sim, union ccb *ccb) 111139223Sgibbs{ 111239223Sgibbs struct bt_softc *bt; 111339223Sgibbs 111439223Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n")); 111539223Sgibbs 111639223Sgibbs bt = (struct bt_softc *)cam_sim_softc(sim); 1117241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 111839223Sgibbs 111939223Sgibbs switch (ccb->ccb_h.func_code) { 112039223Sgibbs /* Common cases first */ 112139223Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 112239223Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 112339223Sgibbs { 112439223Sgibbs struct bt_ccb *bccb; 112539223Sgibbs struct bt_hccb *hccb; 112639223Sgibbs 112739223Sgibbs /* 112839223Sgibbs * get a bccb to use. 112939223Sgibbs */ 113039223Sgibbs if ((bccb = btgetccb(bt)) == NULL) { 113139223Sgibbs 113239223Sgibbs bt->resource_shortage = TRUE; 113339223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 113439223Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 113539223Sgibbs xpt_done(ccb); 113639223Sgibbs return; 113739223Sgibbs } 113839223Sgibbs 113939223Sgibbs hccb = &bccb->hccb; 114039223Sgibbs 114139223Sgibbs /* 114239223Sgibbs * So we can find the BCCB when an abort is requested 114339223Sgibbs */ 114439223Sgibbs bccb->ccb = ccb; 114539223Sgibbs ccb->ccb_h.ccb_bccb_ptr = bccb; 114639223Sgibbs ccb->ccb_h.ccb_bt_ptr = bt; 114739223Sgibbs 114839223Sgibbs /* 114939223Sgibbs * Put all the arguments for the xfer in the bccb 115039223Sgibbs */ 115139223Sgibbs hccb->target_id = ccb->ccb_h.target_id; 115239223Sgibbs hccb->target_lun = ccb->ccb_h.target_lun; 115339223Sgibbs hccb->btstat = 0; 115439223Sgibbs hccb->sdstat = 0; 115539223Sgibbs 115639223Sgibbs if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 115739223Sgibbs struct ccb_scsiio *csio; 115839223Sgibbs struct ccb_hdr *ccbh; 1159246713Skib int error; 116039223Sgibbs 116139223Sgibbs csio = &ccb->csio; 116239223Sgibbs ccbh = &csio->ccb_h; 116339223Sgibbs hccb->opcode = INITIATOR_CCB_WRESID; 116441669Sgibbs hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0; 116541669Sgibbs hccb->dataout =(ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0; 116639223Sgibbs hccb->cmd_len = csio->cdb_len; 116739223Sgibbs if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) { 116839223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 116939223Sgibbs btfreeccb(bt, bccb); 117039223Sgibbs xpt_done(ccb); 117139223Sgibbs return; 117239223Sgibbs } 117339223Sgibbs hccb->sense_len = csio->sense_len; 117440418Sgibbs if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0 117540418Sgibbs && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) { 117639223Sgibbs hccb->tag_enable = TRUE; 117739223Sgibbs hccb->tag_type = (ccb->csio.tag_action & 0x3); 117839223Sgibbs } else { 117939223Sgibbs hccb->tag_enable = FALSE; 118039223Sgibbs hccb->tag_type = 0; 118139223Sgibbs } 118239223Sgibbs if ((ccbh->flags & CAM_CDB_POINTER) != 0) { 118339223Sgibbs if ((ccbh->flags & CAM_CDB_PHYS) == 0) { 118439223Sgibbs bcopy(csio->cdb_io.cdb_ptr, 118539223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 118639223Sgibbs } else { 118739223Sgibbs /* I guess I could map it in... */ 118839223Sgibbs ccbh->status = CAM_REQ_INVALID; 118939223Sgibbs btfreeccb(bt, bccb); 119039223Sgibbs xpt_done(ccb); 119139223Sgibbs return; 119239223Sgibbs } 119339223Sgibbs } else { 119439223Sgibbs bcopy(csio->cdb_io.cdb_bytes, 119539223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 119639223Sgibbs } 119739223Sgibbs /* If need be, bounce our sense buffer */ 119839223Sgibbs if (bt->sense_buffers != NULL) { 119939223Sgibbs hccb->sense_addr = btsensepaddr(bt, bccb); 120039223Sgibbs } else { 120139223Sgibbs hccb->sense_addr = vtophys(&csio->sense_data); 120239223Sgibbs } 120339223Sgibbs /* 120439223Sgibbs * If we have any data to send with this command, 120539223Sgibbs * map it into bus space. 120639223Sgibbs */ 1207246713Skib error = bus_dmamap_load_ccb( 1208246713Skib bt->buffer_dmat, 1209246713Skib bccb->dmamap, 1210246713Skib ccb, 1211246713Skib btexecuteccb, 1212246713Skib bccb, 1213246713Skib /*flags*/0); 1214246713Skib if (error == EINPROGRESS) { 1215246713Skib /* 1216246713Skib * So as to maintain ordering, freeze the 1217246713Skib * controller queue until our mapping is 1218246713Skib * returned. 1219246713Skib */ 1220246713Skib xpt_freeze_simq(bt->sim, 1); 1221246713Skib csio->ccb_h.status |= CAM_RELEASE_SIMQ; 122239223Sgibbs } 122339223Sgibbs } else { 122439223Sgibbs hccb->opcode = INITIATOR_BUS_DEV_RESET; 122539223Sgibbs /* No data transfer */ 122639223Sgibbs hccb->datain = TRUE; 122739223Sgibbs hccb->dataout = TRUE; 122839223Sgibbs hccb->cmd_len = 0; 122939223Sgibbs hccb->sense_len = 0; 123039223Sgibbs hccb->tag_enable = FALSE; 123139223Sgibbs hccb->tag_type = 0; 123239223Sgibbs btexecuteccb(bccb, NULL, 0, 0); 123339223Sgibbs } 123439223Sgibbs break; 123539223Sgibbs } 123639223Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 123739223Sgibbs /* XXX Implement */ 123839223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 123939223Sgibbs xpt_done(ccb); 124039223Sgibbs break; 124139223Sgibbs case XPT_SET_TRAN_SETTINGS: 124239223Sgibbs { 124339223Sgibbs /* XXX Implement */ 124446581Sken ccb->ccb_h.status = CAM_PROVIDE_FAIL; 124539223Sgibbs xpt_done(ccb); 124639223Sgibbs break; 124739223Sgibbs } 124839223Sgibbs case XPT_GET_TRAN_SETTINGS: 124939223Sgibbs /* Get default/user set transfer settings for the target */ 125039223Sgibbs { 125139223Sgibbs struct ccb_trans_settings *cts; 125239223Sgibbs u_int target_mask; 125339223Sgibbs 125439223Sgibbs cts = &ccb->cts; 125539223Sgibbs target_mask = 0x01 << ccb->ccb_h.target_id; 125679175Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 125779175Smjacob struct ccb_trans_settings_scsi *scsi = 125879175Smjacob &cts->proto_specific.scsi; 125979175Smjacob struct ccb_trans_settings_spi *spi = 126079175Smjacob &cts->xport_specific.spi; 126179175Smjacob cts->protocol = PROTO_SCSI; 126279175Smjacob cts->protocol_version = SCSI_REV_2; 126379175Smjacob cts->transport = XPORT_SPI; 126479175Smjacob cts->transport_version = 2; 126579175Smjacob 126679175Smjacob scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 126779175Smjacob spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 126879175Smjacob 126979175Smjacob if ((bt->disc_permitted & target_mask) != 0) 127079175Smjacob spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 127179175Smjacob if ((bt->tags_permitted & target_mask) != 0) 127279175Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 127379175Smjacob 127479175Smjacob if ((bt->ultra_permitted & target_mask) != 0) 127579175Smjacob spi->sync_period = 12; 127679175Smjacob else if ((bt->fast_permitted & target_mask) != 0) 127779175Smjacob spi->sync_period = 25; 127879175Smjacob else if ((bt->sync_permitted & target_mask) != 0) 127979175Smjacob spi->sync_period = 50; 128079175Smjacob else 128179175Smjacob spi->sync_period = 0; 128279175Smjacob 128379175Smjacob if (spi->sync_period != 0) 128479175Smjacob spi->sync_offset = 15; 128579175Smjacob 128679175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_RATE; 128779175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 128879175Smjacob 128979175Smjacob spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 129079175Smjacob if ((bt->wide_permitted & target_mask) != 0) 129179175Smjacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 129279175Smjacob else 129379175Smjacob spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 129479175Smjacob 129579175Smjacob if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 129679175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 129779175Smjacob spi->valid |= CTS_SPI_VALID_DISC; 129879175Smjacob } else 129979175Smjacob scsi->valid = 0; 130079175Smjacob } else { 130139223Sgibbs btfetchtransinfo(bt, cts); 130239223Sgibbs } 130339223Sgibbs 130439223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 130539223Sgibbs xpt_done(ccb); 130639223Sgibbs break; 130739223Sgibbs } 130839223Sgibbs case XPT_CALC_GEOMETRY: 130939223Sgibbs { 131039223Sgibbs struct ccb_calc_geometry *ccg; 131139223Sgibbs u_int32_t size_mb; 131239223Sgibbs u_int32_t secs_per_cylinder; 131339223Sgibbs 131439223Sgibbs ccg = &ccb->ccg; 131539223Sgibbs size_mb = ccg->volume_size 131639223Sgibbs / ((1024L * 1024L) / ccg->block_size); 131739223Sgibbs 131839223Sgibbs if (size_mb >= 1024 && (bt->extended_trans != 0)) { 131939223Sgibbs if (size_mb >= 2048) { 132039223Sgibbs ccg->heads = 255; 132139223Sgibbs ccg->secs_per_track = 63; 132239223Sgibbs } else { 132339223Sgibbs ccg->heads = 128; 132439223Sgibbs ccg->secs_per_track = 32; 132539223Sgibbs } 132639223Sgibbs } else { 132739223Sgibbs ccg->heads = 64; 132839223Sgibbs ccg->secs_per_track = 32; 132939223Sgibbs } 133039223Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 133139223Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 133239223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 133339223Sgibbs xpt_done(ccb); 133439223Sgibbs break; 133539223Sgibbs } 133639223Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 133739223Sgibbs { 133839223Sgibbs btreset(bt, /*hardreset*/TRUE); 133939223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 134039223Sgibbs xpt_done(ccb); 134139223Sgibbs break; 134239223Sgibbs } 134339223Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 134439223Sgibbs /* XXX Implement */ 134539223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 134639223Sgibbs xpt_done(ccb); 134739223Sgibbs break; 134839223Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 134939223Sgibbs { 135039223Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 135139223Sgibbs 135239223Sgibbs cpi->version_num = 1; /* XXX??? */ 135339223Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE; 135439223Sgibbs if (bt->tag_capable != 0) 135539223Sgibbs cpi->hba_inquiry |= PI_TAG_ABLE; 135639223Sgibbs if (bt->wide_bus != 0) 135739223Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 135839223Sgibbs cpi->target_sprt = 0; 135939223Sgibbs cpi->hba_misc = 0; 136039223Sgibbs cpi->hba_eng_cnt = 0; 136139223Sgibbs cpi->max_target = bt->wide_bus ? 15 : 7; 136239223Sgibbs cpi->max_lun = 7; 136339223Sgibbs cpi->initiator_id = bt->scsi_id; 136439223Sgibbs cpi->bus_id = cam_sim_bus(sim); 136546581Sken cpi->base_transfer_speed = 3300; 1366315812Smav strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1367315812Smav strlcpy(cpi->hba_vid, "BusLogic", HBA_IDLEN); 1368315812Smav strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 136939223Sgibbs cpi->unit_number = cam_sim_unit(sim); 137039223Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 137179175Smjacob cpi->transport = XPORT_SPI; 137279175Smjacob cpi->transport_version = 2; 137379175Smjacob cpi->protocol = PROTO_SCSI; 137479175Smjacob cpi->protocol_version = SCSI_REV_2; 137539223Sgibbs xpt_done(ccb); 137639223Sgibbs break; 137739223Sgibbs } 137839223Sgibbs default: 137939223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 138039223Sgibbs xpt_done(ccb); 138139223Sgibbs break; 138239223Sgibbs } 138339223Sgibbs} 138439223Sgibbs 138539223Sgibbsstatic void 138639223Sgibbsbtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 138739223Sgibbs{ 138839223Sgibbs struct bt_ccb *bccb; 138939223Sgibbs union ccb *ccb; 139039223Sgibbs struct bt_softc *bt; 139139223Sgibbs 139239223Sgibbs bccb = (struct bt_ccb *)arg; 139339223Sgibbs ccb = bccb->ccb; 139439223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 139539223Sgibbs 139639223Sgibbs if (error != 0) { 139739223Sgibbs if (error != EFBIG) 139845791Speter device_printf(bt->dev, 139945791Speter "Unexepected error 0x%x returned from " 140045791Speter "bus_dmamap_load\n", error); 140139223Sgibbs if (ccb->ccb_h.status == CAM_REQ_INPROG) { 140239223Sgibbs xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 140339223Sgibbs ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 140439223Sgibbs } 140539223Sgibbs btfreeccb(bt, bccb); 140639223Sgibbs xpt_done(ccb); 140739223Sgibbs return; 140839223Sgibbs } 140939223Sgibbs 141039223Sgibbs if (nseg != 0) { 141139223Sgibbs bt_sg_t *sg; 141239223Sgibbs bus_dma_segment_t *end_seg; 1413115343Sscottl bus_dmasync_op_t op; 141439223Sgibbs 141539223Sgibbs end_seg = dm_segs + nseg; 141639223Sgibbs 141739223Sgibbs /* Copy the segments into our SG list */ 141839223Sgibbs sg = bccb->sg_list; 141939223Sgibbs while (dm_segs < end_seg) { 142039223Sgibbs sg->len = dm_segs->ds_len; 142139223Sgibbs sg->addr = dm_segs->ds_addr; 142239223Sgibbs sg++; 142339223Sgibbs dm_segs++; 142439223Sgibbs } 142539223Sgibbs 142639223Sgibbs if (nseg > 1) { 142739223Sgibbs bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID; 142839223Sgibbs bccb->hccb.data_len = sizeof(bt_sg_t) * nseg; 142939223Sgibbs bccb->hccb.data_addr = bccb->sg_list_phys; 143039223Sgibbs } else { 143139223Sgibbs bccb->hccb.data_len = bccb->sg_list->len; 143239223Sgibbs bccb->hccb.data_addr = bccb->sg_list->addr; 143339223Sgibbs } 143439223Sgibbs 143539223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 143639223Sgibbs op = BUS_DMASYNC_PREREAD; 143739223Sgibbs else 143839223Sgibbs op = BUS_DMASYNC_PREWRITE; 143939223Sgibbs 144039223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 144139223Sgibbs 144239223Sgibbs } else { 144341669Sgibbs bccb->hccb.opcode = INITIATOR_CCB; 144439223Sgibbs bccb->hccb.data_len = 0; 144539223Sgibbs bccb->hccb.data_addr = 0; 144639223Sgibbs } 144739223Sgibbs 144839223Sgibbs /* 144939223Sgibbs * Last time we need to check if this CCB needs to 145039223Sgibbs * be aborted. 145139223Sgibbs */ 145239223Sgibbs if (ccb->ccb_h.status != CAM_REQ_INPROG) { 145339223Sgibbs if (nseg != 0) 145439223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 145539223Sgibbs btfreeccb(bt, bccb); 145639223Sgibbs xpt_done(ccb); 145739223Sgibbs return; 145839223Sgibbs } 145939223Sgibbs 146039223Sgibbs bccb->flags = BCCB_ACTIVE; 146139223Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 146239223Sgibbs LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le); 146339223Sgibbs 1464274819Ssmh callout_reset_sbt(&bccb->timer, SBT_1MS * ccb->ccb_h.timeout, 0, 1465274819Ssmh bttimeout, bccb, 0); 146639223Sgibbs 146739223Sgibbs /* Tell the adapter about this command */ 146839223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb); 146941048Sgibbs if (bt->cur_outbox->action_code != BMBO_FREE) { 147041048Sgibbs /* 147141048Sgibbs * We should never encounter a busy mailbox. 147241048Sgibbs * If we do, warn the user, and treat it as 147341048Sgibbs * a resource shortage. If the controller is 147441048Sgibbs * hung, one of the pending transactions will 147541048Sgibbs * timeout causing us to start recovery operations. 147641048Sgibbs */ 147745791Speter device_printf(bt->dev, 147845791Speter "Encountered busy mailbox with %d out of %d " 147945791Speter "commands active!!!\n", bt->active_ccbs, 148045791Speter bt->max_ccbs); 1481241592Sjhb callout_stop(&bccb->timer); 148241048Sgibbs if (nseg != 0) 148341048Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 148441048Sgibbs btfreeccb(bt, bccb); 148541048Sgibbs bt->resource_shortage = TRUE; 148641048Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 148741048Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 148841048Sgibbs xpt_done(ccb); 148941048Sgibbs return; 149041048Sgibbs } 149139223Sgibbs bt->cur_outbox->action_code = BMBO_START; 149239223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 149339223Sgibbs btnextoutbox(bt); 149439223Sgibbs} 149539223Sgibbs 149639223Sgibbsvoid 149739223Sgibbsbt_intr(void *arg) 149839223Sgibbs{ 149939223Sgibbs struct bt_softc *bt; 1500241592Sjhb 1501241592Sjhb bt = arg; 1502241592Sjhb mtx_lock(&bt->lock); 1503241592Sjhb bt_intr_locked(bt); 1504241592Sjhb mtx_unlock(&bt->lock); 1505241592Sjhb} 1506241592Sjhb 1507241592Sjhbvoid 1508241592Sjhbbt_intr_locked(struct bt_softc *bt) 1509241592Sjhb{ 151039223Sgibbs u_int intstat; 151139223Sgibbs 151239223Sgibbs while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) { 151339223Sgibbs 151439223Sgibbs if ((intstat & CMD_COMPLETE) != 0) { 151539223Sgibbs bt->latched_status = bt_inb(bt, STATUS_REG); 151639223Sgibbs bt->command_cmp = TRUE; 151739223Sgibbs } 151839223Sgibbs 151939223Sgibbs bt_outb(bt, CONTROL_REG, RESET_INTR); 152039223Sgibbs 152139223Sgibbs if ((intstat & IMB_LOADED) != 0) { 152239223Sgibbs while (bt->cur_inbox->comp_code != BMBI_FREE) { 152339223Sgibbs btdone(bt, 152439223Sgibbs btccbptov(bt, bt->cur_inbox->ccb_addr), 152539223Sgibbs bt->cur_inbox->comp_code); 152639223Sgibbs bt->cur_inbox->comp_code = BMBI_FREE; 152739223Sgibbs btnextinbox(bt); 152839223Sgibbs } 152939223Sgibbs } 153039223Sgibbs 153139223Sgibbs if ((intstat & SCSI_BUS_RESET) != 0) { 153239223Sgibbs btreset(bt, /*hardreset*/FALSE); 153339223Sgibbs } 153439223Sgibbs } 153539223Sgibbs} 153639223Sgibbs 153739223Sgibbsstatic void 153839223Sgibbsbtdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) 153939223Sgibbs{ 154039223Sgibbs union ccb *ccb; 154139223Sgibbs struct ccb_scsiio *csio; 154239223Sgibbs 154339223Sgibbs ccb = bccb->ccb; 154439223Sgibbs csio = &bccb->ccb->csio; 154539223Sgibbs 154639223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 154745791Speter device_printf(bt->dev, 154845791Speter "btdone - Attempt to free non-active BCCB %p\n", 154945791Speter (void *)bccb); 155039223Sgibbs return; 155139223Sgibbs } 155239223Sgibbs 155339223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1554115343Sscottl bus_dmasync_op_t op; 155539223Sgibbs 155639223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 155739223Sgibbs op = BUS_DMASYNC_POSTREAD; 155839223Sgibbs else 155939223Sgibbs op = BUS_DMASYNC_POSTWRITE; 156039223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 156139223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 156239223Sgibbs } 156339223Sgibbs 156439223Sgibbs if (bccb == bt->recovery_bccb) { 156539223Sgibbs /* 156639223Sgibbs * The recovery BCCB does not have a CCB associated 156739223Sgibbs * with it, so short circuit the normal error handling. 156839223Sgibbs * We now traverse our list of pending CCBs and process 156939223Sgibbs * any that were terminated by the recovery CCBs action. 157039223Sgibbs * We also reinstate timeouts for all remaining, pending, 157139223Sgibbs * CCBs. 157239223Sgibbs */ 157339223Sgibbs struct cam_path *path; 157439223Sgibbs struct ccb_hdr *ccb_h; 157539223Sgibbs cam_status error; 157639223Sgibbs 1577298955Spfg /* Notify all clients that a BDR occurred */ 157839223Sgibbs error = xpt_create_path(&path, /*periph*/NULL, 157939223Sgibbs cam_sim_path(bt->sim), 158039223Sgibbs bccb->hccb.target_id, 158139223Sgibbs CAM_LUN_WILDCARD); 158239223Sgibbs 1583256893Smav if (error == CAM_REQ_CMP) { 158439223Sgibbs xpt_async(AC_SENT_BDR, path, NULL); 1585256893Smav xpt_free_path(path); 1586256893Smav } 158739223Sgibbs 158839223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 158939223Sgibbs while (ccb_h != NULL) { 159039223Sgibbs struct bt_ccb *pending_bccb; 159139223Sgibbs 159239223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 159339223Sgibbs if (pending_bccb->hccb.target_id 159439223Sgibbs == bccb->hccb.target_id) { 159539223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_BDR; 159639223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 159739223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 159839223Sgibbs } else { 1599274819Ssmh callout_reset_sbt(&pending_bccb->timer, 1600274819Ssmh SBT_1MS * ccb_h->timeout, 0, bttimeout, 1601274819Ssmh pending_bccb, 0); 160239223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 160339223Sgibbs } 160439223Sgibbs } 160545791Speter device_printf(bt->dev, "No longer in timeout\n"); 160639223Sgibbs return; 160739223Sgibbs } 160839223Sgibbs 1609241592Sjhb callout_stop(&bccb->timer); 161039223Sgibbs 161139223Sgibbs switch (comp_code) { 161239223Sgibbs case BMBI_FREE: 161345791Speter device_printf(bt->dev, 161445791Speter "btdone - CCB completed with free status!\n"); 161539223Sgibbs break; 161639223Sgibbs case BMBI_NOT_FOUND: 161745791Speter device_printf(bt->dev, 161845791Speter "btdone - CCB Abort failed to find CCB\n"); 161939223Sgibbs break; 162039223Sgibbs case BMBI_ABORT: 162139223Sgibbs case BMBI_ERROR: 162241133Sgibbs if (bootverbose) { 1623298955Spfg printf("bt: ccb %p - error %x occurred. " 162441133Sgibbs "btstat = %x, sdstat = %x\n", 162541133Sgibbs (void *)bccb, comp_code, bccb->hccb.btstat, 162641133Sgibbs bccb->hccb.sdstat); 162741133Sgibbs } 1628298955Spfg /* An error occurred */ 162939223Sgibbs switch(bccb->hccb.btstat) { 163039223Sgibbs case BTSTAT_DATARUN_ERROR: 163141048Sgibbs if (bccb->hccb.data_len == 0) { 163241048Sgibbs /* 163341048Sgibbs * At least firmware 4.22, does this 163441048Sgibbs * for a QUEUE FULL condition. 163541048Sgibbs */ 163641048Sgibbs bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL; 163741048Sgibbs } else if (bccb->hccb.data_len < 0) { 163839223Sgibbs csio->ccb_h.status = CAM_DATA_RUN_ERR; 163939223Sgibbs break; 164039223Sgibbs } 164139223Sgibbs /* FALLTHROUGH */ 164239223Sgibbs case BTSTAT_NOERROR: 164339223Sgibbs case BTSTAT_LINKED_CMD_COMPLETE: 164439223Sgibbs case BTSTAT_LINKED_CMD_FLAG_COMPLETE: 164539223Sgibbs case BTSTAT_DATAUNDERUN_ERROR: 164639223Sgibbs 164739223Sgibbs csio->scsi_status = bccb->hccb.sdstat; 164839223Sgibbs csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 164939223Sgibbs switch(csio->scsi_status) { 165039223Sgibbs case SCSI_STATUS_CHECK_COND: 165139223Sgibbs case SCSI_STATUS_CMD_TERMINATED: 165239223Sgibbs csio->ccb_h.status |= CAM_AUTOSNS_VALID; 165339223Sgibbs /* Bounce sense back if necessary */ 165439223Sgibbs if (bt->sense_buffers != NULL) { 165539223Sgibbs csio->sense_data = 165639223Sgibbs *btsensevaddr(bt, bccb); 165739223Sgibbs } 165839223Sgibbs break; 165939223Sgibbs default: 166039223Sgibbs break; 166139223Sgibbs case SCSI_STATUS_OK: 166239223Sgibbs csio->ccb_h.status = CAM_REQ_CMP; 166339223Sgibbs break; 166439223Sgibbs } 166539223Sgibbs csio->resid = bccb->hccb.data_len; 166639223Sgibbs break; 166739223Sgibbs case BTSTAT_SELTIMEOUT: 166839223Sgibbs csio->ccb_h.status = CAM_SEL_TIMEOUT; 166939223Sgibbs break; 167039223Sgibbs case BTSTAT_UNEXPECTED_BUSFREE: 167139223Sgibbs csio->ccb_h.status = CAM_UNEXP_BUSFREE; 167239223Sgibbs break; 167339223Sgibbs case BTSTAT_INVALID_PHASE: 167439223Sgibbs csio->ccb_h.status = CAM_SEQUENCE_FAIL; 167539223Sgibbs break; 167639223Sgibbs case BTSTAT_INVALID_ACTION_CODE: 167739223Sgibbs panic("%s: Inavlid Action code", bt_name(bt)); 167839223Sgibbs break; 167939223Sgibbs case BTSTAT_INVALID_OPCODE: 168039223Sgibbs panic("%s: Inavlid CCB Opcode code", bt_name(bt)); 168139223Sgibbs break; 168239223Sgibbs case BTSTAT_LINKED_CCB_LUN_MISMATCH: 168339223Sgibbs /* We don't even support linked commands... */ 168439223Sgibbs panic("%s: Linked CCB Lun Mismatch", bt_name(bt)); 168539223Sgibbs break; 168639223Sgibbs case BTSTAT_INVALID_CCB_OR_SG_PARAM: 168739223Sgibbs panic("%s: Invalid CCB or SG list", bt_name(bt)); 168839223Sgibbs break; 168939223Sgibbs case BTSTAT_AUTOSENSE_FAILED: 169039223Sgibbs csio->ccb_h.status = CAM_AUTOSENSE_FAIL; 169139223Sgibbs break; 169239223Sgibbs case BTSTAT_TAGGED_MSG_REJECTED: 169339223Sgibbs { 169439223Sgibbs struct ccb_trans_settings neg; 169579175Smjacob struct ccb_trans_settings_scsi *scsi = 169679175Smjacob &neg.proto_specific.scsi; 169779175Smjacob 169879175Smjacob neg.protocol = PROTO_SCSI; 169979175Smjacob neg.protocol_version = SCSI_REV_2; 170079175Smjacob neg.transport = XPORT_SPI; 170179175Smjacob neg.transport_version = 2; 170279175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 170379175Smjacob scsi->flags = 0; 170439223Sgibbs xpt_print_path(csio->ccb_h.path); 170539223Sgibbs printf("refuses tagged commands. Performing " 170639223Sgibbs "non-tagged I/O\n"); 170739223Sgibbs xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path, 170839223Sgibbs /*priority*/1); 170939223Sgibbs xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg); 171039223Sgibbs bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id); 171139223Sgibbs csio->ccb_h.status = CAM_MSG_REJECT_REC; 171239223Sgibbs break; 171339223Sgibbs } 171439223Sgibbs case BTSTAT_UNSUPPORTED_MSG_RECEIVED: 171539223Sgibbs /* 171639223Sgibbs * XXX You would think that this is 171739223Sgibbs * a recoverable error... Hmmm. 171839223Sgibbs */ 171939223Sgibbs csio->ccb_h.status = CAM_REQ_CMP_ERR; 172039223Sgibbs break; 172139223Sgibbs case BTSTAT_HA_SOFTWARE_ERROR: 172239223Sgibbs case BTSTAT_HA_WATCHDOG_ERROR: 172339223Sgibbs case BTSTAT_HARDWARE_FAILURE: 172439223Sgibbs /* Hardware reset ??? Can we recover ??? */ 172539223Sgibbs csio->ccb_h.status = CAM_NO_HBA; 172639223Sgibbs break; 172739223Sgibbs case BTSTAT_TARGET_IGNORED_ATN: 172839223Sgibbs case BTSTAT_OTHER_SCSI_BUS_RESET: 172939223Sgibbs case BTSTAT_HA_SCSI_BUS_RESET: 173039223Sgibbs if ((csio->ccb_h.status & CAM_STATUS_MASK) 173139223Sgibbs != CAM_CMD_TIMEOUT) 173239223Sgibbs csio->ccb_h.status = CAM_SCSI_BUS_RESET; 173339223Sgibbs break; 173439223Sgibbs case BTSTAT_HA_BDR: 173539223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) 173639223Sgibbs csio->ccb_h.status = CAM_BDR_SENT; 173739223Sgibbs else 173839223Sgibbs csio->ccb_h.status = CAM_CMD_TIMEOUT; 173939223Sgibbs break; 174039223Sgibbs case BTSTAT_INVALID_RECONNECT: 174139223Sgibbs case BTSTAT_ABORT_QUEUE_GENERATED: 174239223Sgibbs csio->ccb_h.status = CAM_REQ_TERMIO; 174339223Sgibbs break; 174439223Sgibbs case BTSTAT_SCSI_PERROR_DETECTED: 174539223Sgibbs csio->ccb_h.status = CAM_UNCOR_PARITY; 174639223Sgibbs break; 174739223Sgibbs } 174839223Sgibbs if (csio->ccb_h.status != CAM_REQ_CMP) { 174939223Sgibbs xpt_freeze_devq(csio->ccb_h.path, /*count*/1); 175039223Sgibbs csio->ccb_h.status |= CAM_DEV_QFRZN; 175139223Sgibbs } 175239223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 175339223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 175439223Sgibbs btfreeccb(bt, bccb); 175539223Sgibbs xpt_done(ccb); 175639223Sgibbs break; 175739223Sgibbs case BMBI_OK: 175839223Sgibbs /* All completed without incident */ 175939223Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 176039223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 176139223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 176239223Sgibbs btfreeccb(bt, bccb); 176339223Sgibbs xpt_done(ccb); 176439223Sgibbs break; 176539223Sgibbs } 176639223Sgibbs} 176739223Sgibbs 176839223Sgibbsstatic int 176939223Sgibbsbtreset(struct bt_softc* bt, int hard_reset) 177039223Sgibbs{ 177139223Sgibbs struct ccb_hdr *ccb_h; 177239223Sgibbs u_int status; 177339223Sgibbs u_int timeout; 177439223Sgibbs u_int8_t reset_type; 177539223Sgibbs 177639223Sgibbs if (hard_reset != 0) 177739223Sgibbs reset_type = HARD_RESET; 177839223Sgibbs else 177939223Sgibbs reset_type = SOFT_RESET; 178039223Sgibbs bt_outb(bt, CONTROL_REG, reset_type); 178139223Sgibbs 178239223Sgibbs /* Wait 5sec. for Diagnostic start */ 178339223Sgibbs timeout = 5 * 10000; 178439223Sgibbs while (--timeout) { 178539223Sgibbs status = bt_inb(bt, STATUS_REG); 178639223Sgibbs if ((status & DIAG_ACTIVE) != 0) 178739223Sgibbs break; 178839223Sgibbs DELAY(100); 178939223Sgibbs } 179039223Sgibbs if (timeout == 0) { 179139223Sgibbs if (bootverbose) 1792241592Sjhb device_printf(bt->dev, 1793241592Sjhb "btreset - Diagnostic Active failed to " 1794241592Sjhb "assert. status = 0x%x\n", status); 179539223Sgibbs return (ETIMEDOUT); 179639223Sgibbs } 179739223Sgibbs 179839223Sgibbs /* Wait 10sec. for Diagnostic end */ 179939223Sgibbs timeout = 10 * 10000; 180039223Sgibbs while (--timeout) { 180139223Sgibbs status = bt_inb(bt, STATUS_REG); 180239223Sgibbs if ((status & DIAG_ACTIVE) == 0) 180339223Sgibbs break; 180439223Sgibbs DELAY(100); 180539223Sgibbs } 180639223Sgibbs if (timeout == 0) { 180739223Sgibbs panic("%s: btreset - Diagnostic Active failed to drop. " 180839223Sgibbs "status = 0x%x\n", bt_name(bt), status); 180939223Sgibbs return (ETIMEDOUT); 181039223Sgibbs } 181139223Sgibbs 181239223Sgibbs /* Wait for the host adapter to become ready or report a failure */ 181339223Sgibbs timeout = 10000; 181439223Sgibbs while (--timeout) { 181539223Sgibbs status = bt_inb(bt, STATUS_REG); 181639223Sgibbs if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0) 181739223Sgibbs break; 181839223Sgibbs DELAY(100); 181939223Sgibbs } 182039223Sgibbs if (timeout == 0) { 1821241592Sjhb device_printf(bt->dev, 1822241592Sjhb "btreset - Host adapter failed to come ready. " 1823241592Sjhb "status = 0x%x\n", status); 182439223Sgibbs return (ETIMEDOUT); 182539223Sgibbs } 182639223Sgibbs 182739223Sgibbs /* If the diagnostics failed, tell the user */ 182839223Sgibbs if ((status & DIAG_FAIL) != 0 182939223Sgibbs || (status & HA_READY) == 0) { 1830241592Sjhb device_printf(bt->dev, 1831241592Sjhb "btreset - Adapter failed diagnostics\n"); 183239223Sgibbs 183339223Sgibbs if ((status & DATAIN_REG_READY) != 0) 1834241592Sjhb device_printf(bt->dev, 1835241592Sjhb "btreset - Host Adapter Error code = 0x%x\n", 1836241592Sjhb bt_inb(bt, DATAIN_REG)); 183739223Sgibbs return (ENXIO); 183839223Sgibbs } 183939223Sgibbs 184039223Sgibbs /* If we've allocated mailboxes, initialize them */ 184139223Sgibbs if (bt->init_level > 4) 184239223Sgibbs btinitmboxes(bt); 184339223Sgibbs 184439223Sgibbs /* If we've attached to the XPT, tell it about the event */ 184539223Sgibbs if (bt->path != NULL) 184639223Sgibbs xpt_async(AC_BUS_RESET, bt->path, NULL); 184739223Sgibbs 184839223Sgibbs /* 184939223Sgibbs * Perform completion processing for all outstanding CCBs. 185039223Sgibbs */ 185139223Sgibbs while ((ccb_h = LIST_FIRST(&bt->pending_ccbs)) != NULL) { 185239223Sgibbs struct bt_ccb *pending_bccb; 185339223Sgibbs 185439223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 185539223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_SCSI_BUS_RESET; 185639223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 185739223Sgibbs } 185839223Sgibbs 185939223Sgibbs return (0); 186039223Sgibbs} 186139223Sgibbs 186239223Sgibbs/* 186339223Sgibbs * Send a command to the adapter. 186439223Sgibbs */ 186539223Sgibbsint 186639223Sgibbsbt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, 186739223Sgibbs u_int8_t *reply_data, u_int reply_len, u_int cmd_timeout) 186839223Sgibbs{ 186939223Sgibbs u_int timeout; 187039223Sgibbs u_int status; 187145444Sgibbs u_int saved_status; 187239223Sgibbs u_int intstat; 187339223Sgibbs u_int reply_buf_size; 187441669Sgibbs int cmd_complete; 187545444Sgibbs int error; 187639223Sgibbs 187739223Sgibbs /* No data returned to start */ 187839223Sgibbs reply_buf_size = reply_len; 187939223Sgibbs reply_len = 0; 188039223Sgibbs intstat = 0; 188141669Sgibbs cmd_complete = 0; 188245444Sgibbs saved_status = 0; 188345444Sgibbs error = 0; 188439223Sgibbs 188539223Sgibbs bt->command_cmp = 0; 188639223Sgibbs /* 188745444Sgibbs * Wait up to 10 sec. for the adapter to become 188839223Sgibbs * ready to accept commands. 188939223Sgibbs */ 189045444Sgibbs timeout = 100000; 189139223Sgibbs while (--timeout) { 189239223Sgibbs status = bt_inb(bt, STATUS_REG); 189339223Sgibbs if ((status & HA_READY) != 0 189439223Sgibbs && (status & CMD_REG_BUSY) == 0) 189539223Sgibbs break; 189645444Sgibbs /* 189745444Sgibbs * Throw away any pending data which may be 189845444Sgibbs * left over from earlier commands that we 189945444Sgibbs * timedout on. 190045444Sgibbs */ 190145444Sgibbs if ((status & DATAIN_REG_READY) != 0) 190245444Sgibbs (void)bt_inb(bt, DATAIN_REG); 190339223Sgibbs DELAY(100); 190439223Sgibbs } 190539223Sgibbs if (timeout == 0) { 1906241592Sjhb device_printf(bt->dev, 1907241592Sjhb "bt_cmd: Timeout waiting for adapter ready, " 1908241592Sjhb "status = 0x%x\n", status); 190939223Sgibbs return (ETIMEDOUT); 191039223Sgibbs } 191139223Sgibbs 191239223Sgibbs /* 191339223Sgibbs * Send the opcode followed by any necessary parameter bytes. 191439223Sgibbs */ 191539223Sgibbs bt_outb(bt, COMMAND_REG, opcode); 191639223Sgibbs 191739223Sgibbs /* 1918240518Seadler * Wait for up to 1sec for each byte of the 191945444Sgibbs * parameter list sent to be sent. 192039223Sgibbs */ 192139223Sgibbs timeout = 10000; 192239223Sgibbs while (param_len && --timeout) { 192339223Sgibbs DELAY(100); 192439223Sgibbs status = bt_inb(bt, STATUS_REG); 192539223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 192647432Sgibbs 192739223Sgibbs if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 192841669Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 192945444Sgibbs saved_status = status; 193041669Sgibbs cmd_complete = 1; 193139223Sgibbs break; 193241669Sgibbs } 193339223Sgibbs if (bt->command_cmp != 0) { 193445444Sgibbs saved_status = bt->latched_status; 193541669Sgibbs cmd_complete = 1; 193639223Sgibbs break; 193739223Sgibbs } 193839223Sgibbs if ((status & DATAIN_REG_READY) != 0) 193939223Sgibbs break; 194039223Sgibbs if ((status & CMD_REG_BUSY) == 0) { 194139223Sgibbs bt_outb(bt, COMMAND_REG, *params++); 194239223Sgibbs param_len--; 194345444Sgibbs timeout = 10000; 194439223Sgibbs } 194539223Sgibbs } 194639223Sgibbs if (timeout == 0) { 1947241592Sjhb device_printf(bt->dev, "bt_cmd: Timeout sending parameters, " 1948241592Sjhb "status = 0x%x\n", status); 194945444Sgibbs cmd_complete = 1; 195045444Sgibbs saved_status = status; 195145444Sgibbs error = ETIMEDOUT; 195239223Sgibbs } 195339223Sgibbs 195439223Sgibbs /* 195545444Sgibbs * Wait for the command to complete. 195639223Sgibbs */ 195741669Sgibbs while (cmd_complete == 0 && --cmd_timeout) { 195839223Sgibbs 195939223Sgibbs status = bt_inb(bt, STATUS_REG); 196039223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 196147432Sgibbs /* 196247432Sgibbs * It may be that this command was issued with 196347432Sgibbs * controller interrupts disabled. We'll never 196447432Sgibbs * get to our command if an incoming mailbox 196547432Sgibbs * interrupt is pending, so take care of completed 196647432Sgibbs * mailbox commands by calling our interrupt handler. 196747432Sgibbs */ 196847432Sgibbs if ((intstat & (INTR_PENDING|IMB_LOADED)) 196947432Sgibbs == (INTR_PENDING|IMB_LOADED)) 1970241592Sjhb bt_intr_locked(bt); 197139223Sgibbs 197239223Sgibbs if (bt->command_cmp != 0) { 197345444Sgibbs /* 197445444Sgibbs * Our interrupt handler saw CMD_COMPLETE 197545444Sgibbs * status before we did. 197645444Sgibbs */ 197745444Sgibbs cmd_complete = 1; 197845444Sgibbs saved_status = bt->latched_status; 197945444Sgibbs } else if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 198045444Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 198145444Sgibbs /* 198245444Sgibbs * Our poll (in case interrupts are blocked) 198345444Sgibbs * saw the CMD_COMPLETE interrupt. 198445444Sgibbs */ 198545444Sgibbs cmd_complete = 1; 198645444Sgibbs saved_status = status; 198745444Sgibbs } else if (opcode == BOP_MODIFY_IO_ADDR 198845444Sgibbs && (status & CMD_REG_BUSY) == 0) { 198945444Sgibbs /* 199045444Sgibbs * The BOP_MODIFY_IO_ADDR does not issue a CMD_COMPLETE, 199145444Sgibbs * but it should update the status register. So, we 199245444Sgibbs * consider this command complete when the CMD_REG_BUSY 199345444Sgibbs * status clears. 199445444Sgibbs */ 199545444Sgibbs saved_status = status; 199645444Sgibbs cmd_complete = 1; 199745444Sgibbs } else if ((status & DATAIN_REG_READY) != 0) { 199839223Sgibbs u_int8_t data; 199939223Sgibbs 200039223Sgibbs data = bt_inb(bt, DATAIN_REG); 200139223Sgibbs if (reply_len < reply_buf_size) { 200239223Sgibbs *reply_data++ = data; 200339223Sgibbs } else { 2004241592Sjhb device_printf(bt->dev, 2005241592Sjhb "bt_cmd - Discarded reply data byte " 2006241592Sjhb "for opcode 0x%x\n", opcode); 200739223Sgibbs } 200845444Sgibbs /* 200945444Sgibbs * Reset timeout to ensure at least a second 201045444Sgibbs * between response bytes. 201145444Sgibbs */ 201245444Sgibbs cmd_timeout = MAX(cmd_timeout, 10000); 201339223Sgibbs reply_len++; 201445444Sgibbs 201545444Sgibbs } else if ((opcode == BOP_FETCH_LRAM) 201645444Sgibbs && (status & HA_READY) != 0) { 201745444Sgibbs saved_status = status; 201845444Sgibbs cmd_complete = 1; 201939223Sgibbs } 202039223Sgibbs DELAY(100); 202139223Sgibbs } 202245444Sgibbs if (cmd_timeout == 0) { 2023241592Sjhb device_printf(bt->dev, 2024241592Sjhb "bt_cmd: Timeout waiting for command (%x) " 2025241592Sjhb "to complete.\n", opcode); 2026241592Sjhb device_printf(bt->dev, "status = 0x%x, intstat = 0x%x, " 2027241592Sjhb "rlen %d\n", status, intstat, reply_len); 202845444Sgibbs error = (ETIMEDOUT); 202939223Sgibbs } 203039223Sgibbs 203139223Sgibbs /* 2032241592Sjhb * Clear any pending interrupts. 203339223Sgibbs */ 2034241592Sjhb bt_intr_locked(bt); 203539223Sgibbs 203645444Sgibbs if (error != 0) 203745444Sgibbs return (error); 203845444Sgibbs 203939223Sgibbs /* 204039223Sgibbs * If the command was rejected by the controller, tell the caller. 204139223Sgibbs */ 204245444Sgibbs if ((saved_status & CMD_INVALID) != 0) { 204339223Sgibbs /* 204439223Sgibbs * Some early adapters may not recover properly from 204539223Sgibbs * an invalid command. If it appears that the controller 204639223Sgibbs * has wedged (i.e. status was not cleared by our interrupt 204739223Sgibbs * reset above), perform a soft reset. 204839223Sgibbs */ 204939223Sgibbs if (bootverbose) 2050241592Sjhb device_printf(bt->dev, "Invalid Command 0x%x\n", 205139223Sgibbs opcode); 205239223Sgibbs DELAY(1000); 205339223Sgibbs status = bt_inb(bt, STATUS_REG); 205439223Sgibbs if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY| 205539223Sgibbs CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0 205639223Sgibbs || (status & (HA_READY|INIT_REQUIRED)) 205739223Sgibbs != (HA_READY|INIT_REQUIRED)) { 205839223Sgibbs btreset(bt, /*hard_reset*/FALSE); 205939223Sgibbs } 206039223Sgibbs return (EINVAL); 206139223Sgibbs } 206239223Sgibbs 206339223Sgibbs if (param_len > 0) { 206439223Sgibbs /* The controller did not accept the full argument list */ 206539223Sgibbs return (E2BIG); 206639223Sgibbs } 206739223Sgibbs 206839223Sgibbs if (reply_len != reply_buf_size) { 206939223Sgibbs /* Too much or too little data received */ 207039223Sgibbs return (EMSGSIZE); 207139223Sgibbs } 207239223Sgibbs 207339223Sgibbs /* We were successful */ 207439223Sgibbs return (0); 207539223Sgibbs} 207639223Sgibbs 207739223Sgibbsstatic int 207839223Sgibbsbtinitmboxes(struct bt_softc *bt) { 207939223Sgibbs init_32b_mbox_params_t init_mbox; 208039223Sgibbs int error; 208139223Sgibbs 208239223Sgibbs bzero(bt->in_boxes, sizeof(bt_mbox_in_t) * bt->num_boxes); 208339223Sgibbs bzero(bt->out_boxes, sizeof(bt_mbox_out_t) * bt->num_boxes); 208439223Sgibbs bt->cur_inbox = bt->in_boxes; 208539223Sgibbs bt->last_inbox = bt->in_boxes + bt->num_boxes - 1; 208639223Sgibbs bt->cur_outbox = bt->out_boxes; 208739223Sgibbs bt->last_outbox = bt->out_boxes + bt->num_boxes - 1; 208839223Sgibbs 208939223Sgibbs /* Tell the adapter about them */ 209039223Sgibbs init_mbox.num_boxes = bt->num_boxes; 209139223Sgibbs init_mbox.base_addr[0] = bt->mailbox_physbase & 0xFF; 209239223Sgibbs init_mbox.base_addr[1] = (bt->mailbox_physbase >> 8) & 0xFF; 209339223Sgibbs init_mbox.base_addr[2] = (bt->mailbox_physbase >> 16) & 0xFF; 209439223Sgibbs init_mbox.base_addr[3] = (bt->mailbox_physbase >> 24) & 0xFF; 209539223Sgibbs error = bt_cmd(bt, BOP_INITIALIZE_32BMBOX, (u_int8_t *)&init_mbox, 209639223Sgibbs /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL, 209739223Sgibbs /*reply_len*/0, DEFAULT_CMD_TIMEOUT); 209839223Sgibbs 209939223Sgibbs if (error != 0) 210039223Sgibbs printf("btinitmboxes: Initialization command failed\n"); 210139223Sgibbs else if (bt->strict_rr != 0) { 210239223Sgibbs /* 210339223Sgibbs * If the controller supports 210439223Sgibbs * strict round robin mode, 210539223Sgibbs * enable it 210639223Sgibbs */ 210739223Sgibbs u_int8_t param; 210839223Sgibbs 210939223Sgibbs param = 0; 211039223Sgibbs error = bt_cmd(bt, BOP_ENABLE_STRICT_RR, ¶m, 1, 211139223Sgibbs /*reply_buf*/NULL, /*reply_len*/0, 211239223Sgibbs DEFAULT_CMD_TIMEOUT); 211339223Sgibbs 211439223Sgibbs if (error != 0) { 211539223Sgibbs printf("btinitmboxes: Unable to enable strict RR\n"); 211639223Sgibbs error = 0; 211739223Sgibbs } else if (bootverbose) { 2118241592Sjhb device_printf(bt->dev, 2119241592Sjhb "Using Strict Round Robin Mailbox Mode\n"); 212039223Sgibbs } 212139223Sgibbs } 212239223Sgibbs 212339223Sgibbs return (error); 212439223Sgibbs} 212539223Sgibbs 212639223Sgibbs/* 212739223Sgibbs * Update the XPT's idea of the negotiated transfer 212839223Sgibbs * parameters for a particular target. 212939223Sgibbs */ 213039223Sgibbsstatic void 213179175Smjacobbtfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts) 213239223Sgibbs{ 213339223Sgibbs setup_data_t setup_info; 213439223Sgibbs u_int target; 213539223Sgibbs u_int targ_offset; 213639223Sgibbs u_int targ_mask; 213739223Sgibbs u_int sync_period; 213879175Smjacob u_int sync_offset; 213979175Smjacob u_int bus_width; 214039223Sgibbs int error; 214139223Sgibbs u_int8_t param; 214239223Sgibbs targ_syncinfo_t sync_info; 214379175Smjacob struct ccb_trans_settings_scsi *scsi = 214479175Smjacob &cts->proto_specific.scsi; 214579175Smjacob struct ccb_trans_settings_spi *spi = 214679175Smjacob &cts->xport_specific.spi; 214739223Sgibbs 214879175Smjacob spi->valid = 0; 214979175Smjacob scsi->valid = 0; 215079175Smjacob 215139223Sgibbs target = cts->ccb_h.target_id; 215239223Sgibbs targ_offset = (target & 0x7); 215339223Sgibbs targ_mask = (0x01 << targ_offset); 215439223Sgibbs 215539223Sgibbs /* 215639223Sgibbs * Inquire Setup Information. This command retreives the 215739223Sgibbs * Wide negotiation status for recent adapters as well as 215839223Sgibbs * the sync info for older models. 215939223Sgibbs */ 216039223Sgibbs param = sizeof(setup_info); 216139223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, ¶m, /*paramlen*/1, 216239223Sgibbs (u_int8_t*)&setup_info, sizeof(setup_info), 216339223Sgibbs DEFAULT_CMD_TIMEOUT); 216439223Sgibbs 216539223Sgibbs if (error != 0) { 2166241592Sjhb device_printf(bt->dev, 2167241592Sjhb "btfetchtransinfo - Inquire Setup Info Failed %x\n", 2168241592Sjhb error); 216939223Sgibbs return; 217039223Sgibbs } 217139223Sgibbs 217239223Sgibbs sync_info = (target < 8) ? setup_info.low_syncinfo[targ_offset] 217339223Sgibbs : setup_info.high_syncinfo[targ_offset]; 217439223Sgibbs 217539223Sgibbs if (sync_info.sync == 0) 217679175Smjacob sync_offset = 0; 217739223Sgibbs else 217879175Smjacob sync_offset = sync_info.offset; 217939223Sgibbs 218079175Smjacob 218179175Smjacob bus_width = MSG_EXT_WDTR_BUS_8_BIT; 218239223Sgibbs if (strcmp(bt->firmware_ver, "5.06L") >= 0) { 218339223Sgibbs u_int wide_active; 218439223Sgibbs 218539223Sgibbs wide_active = 218639223Sgibbs (target < 8) ? (setup_info.low_wide_active & targ_mask) 218739223Sgibbs : (setup_info.high_wide_active & targ_mask); 218839223Sgibbs 218939223Sgibbs if (wide_active) 219079175Smjacob bus_width = MSG_EXT_WDTR_BUS_16_BIT; 219139507Sgibbs } else if ((bt->wide_permitted & targ_mask) != 0) { 219239507Sgibbs struct ccb_getdev cgd; 219339507Sgibbs 219439507Sgibbs /* 219539507Sgibbs * Prior to rev 5.06L, wide status isn't provided, 219639507Sgibbs * so we "guess" that wide transfers are in effect 219739507Sgibbs * if the user settings allow for wide and the inquiry 219839507Sgibbs * data for the device indicates that it can handle 219939507Sgibbs * wide transfers. 220039507Sgibbs */ 220139507Sgibbs xpt_setup_ccb(&cgd.ccb_h, cts->ccb_h.path, /*priority*/1); 220239507Sgibbs cgd.ccb_h.func_code = XPT_GDEV_TYPE; 220339507Sgibbs xpt_action((union ccb *)&cgd); 220439507Sgibbs if ((cgd.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP 220539507Sgibbs && (cgd.inq_data.flags & SID_WBus16) != 0) 220679175Smjacob bus_width = MSG_EXT_WDTR_BUS_16_BIT; 220739223Sgibbs } 220839223Sgibbs 220944581Sgibbs if (bt->firmware_ver[0] >= '3') { 221039223Sgibbs /* 221139223Sgibbs * For adapters that can do fast or ultra speeds, 221239223Sgibbs * use the more exact Target Sync Information command. 221339223Sgibbs */ 221439223Sgibbs target_sync_info_data_t sync_info; 221539223Sgibbs 221639223Sgibbs param = sizeof(sync_info); 221739223Sgibbs error = bt_cmd(bt, BOP_TARG_SYNC_INFO, ¶m, /*paramlen*/1, 221839223Sgibbs (u_int8_t*)&sync_info, sizeof(sync_info), 221939223Sgibbs DEFAULT_CMD_TIMEOUT); 222039223Sgibbs 222139223Sgibbs if (error != 0) { 2222241592Sjhb device_printf(bt->dev, 2223241592Sjhb "btfetchtransinfo - Inquire Sync " 2224241592Sjhb "Info Failed 0x%x\n", error); 222539223Sgibbs return; 222639223Sgibbs } 222739223Sgibbs sync_period = sync_info.sync_rate[target] * 100; 222839223Sgibbs } else { 222939223Sgibbs sync_period = 2000 + (500 * sync_info.period); 223039223Sgibbs } 223139223Sgibbs 223279175Smjacob cts->protocol = PROTO_SCSI; 223379175Smjacob cts->protocol_version = SCSI_REV_2; 223479175Smjacob cts->transport = XPORT_SPI; 223579175Smjacob cts->transport_version = 2; 223679175Smjacob 223779175Smjacob spi->sync_period = sync_period; 223879175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_RATE; 223979175Smjacob spi->sync_offset = sync_offset; 224079175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 224179175Smjacob 224279175Smjacob spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 224379175Smjacob spi->bus_width = bus_width; 224479175Smjacob 224579175Smjacob if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 224679175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 224779175Smjacob spi->valid |= CTS_SPI_VALID_DISC; 224879175Smjacob } else 224979175Smjacob scsi->valid = 0; 225079175Smjacob 225139223Sgibbs xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts); 225239223Sgibbs} 225339223Sgibbs 225439223Sgibbsstatic void 225539223Sgibbsbtmapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error) 225639223Sgibbs{ 225739223Sgibbs struct bt_softc* bt; 225839223Sgibbs 225939223Sgibbs bt = (struct bt_softc*)arg; 226039223Sgibbs bt->mailbox_physbase = segs->ds_addr; 226139223Sgibbs} 226239223Sgibbs 226339223Sgibbsstatic void 226439223Sgibbsbtmapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 226539223Sgibbs{ 226639223Sgibbs struct bt_softc* bt; 226739223Sgibbs 226839223Sgibbs bt = (struct bt_softc*)arg; 226939223Sgibbs bt->bt_ccb_physbase = segs->ds_addr; 227039223Sgibbs} 227139223Sgibbs 227239223Sgibbsstatic void 227339223Sgibbsbtmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 227439223Sgibbs{ 227539223Sgibbs 227639223Sgibbs struct bt_softc* bt; 227739223Sgibbs 227839223Sgibbs bt = (struct bt_softc*)arg; 227939223Sgibbs SLIST_FIRST(&bt->sg_maps)->sg_physaddr = segs->ds_addr; 228039223Sgibbs} 228139223Sgibbs 228239223Sgibbsstatic void 228339223Sgibbsbtpoll(struct cam_sim *sim) 228439223Sgibbs{ 2285241592Sjhb bt_intr_locked(cam_sim_softc(sim)); 228639223Sgibbs} 228739223Sgibbs 228839223Sgibbsvoid 228939223Sgibbsbttimeout(void *arg) 229039223Sgibbs{ 229139223Sgibbs struct bt_ccb *bccb; 229239223Sgibbs union ccb *ccb; 229339223Sgibbs struct bt_softc *bt; 229439223Sgibbs 229539223Sgibbs bccb = (struct bt_ccb *)arg; 229639223Sgibbs ccb = bccb->ccb; 229739223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 2298241592Sjhb mtx_assert(&bt->lock, MA_OWNED); 229939223Sgibbs xpt_print_path(ccb->ccb_h.path); 230039390Sgibbs printf("CCB %p - timed out\n", (void *)bccb); 230139223Sgibbs 230239223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 230339223Sgibbs xpt_print_path(ccb->ccb_h.path); 230439390Sgibbs printf("CCB %p - timed out CCB already completed\n", 230539390Sgibbs (void *)bccb); 230639223Sgibbs return; 230739223Sgibbs } 230839223Sgibbs 230939223Sgibbs /* 231039223Sgibbs * In order to simplify the recovery process, we ask the XPT 231139223Sgibbs * layer to halt the queue of new transactions and we traverse 231239223Sgibbs * the list of pending CCBs and remove their timeouts. This 231339223Sgibbs * means that the driver attempts to clear only one error 231439223Sgibbs * condition at a time. In general, timeouts that occur 231539223Sgibbs * close together are related anyway, so there is no benefit 2316298955Spfg * in attempting to handle errors in parallel. Timeouts will 231739223Sgibbs * be reinstated when the recovery process ends. 231839223Sgibbs */ 231939223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) { 232039223Sgibbs struct ccb_hdr *ccb_h; 232139223Sgibbs 232239223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) { 232339223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 232439223Sgibbs bccb->flags |= BCCB_RELEASE_SIMQ; 232539223Sgibbs } 232639223Sgibbs 232739223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 232839223Sgibbs while (ccb_h != NULL) { 232939223Sgibbs struct bt_ccb *pending_bccb; 233039223Sgibbs 233139223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 2332241592Sjhb callout_stop(&pending_bccb->timer); 233339223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 233439223Sgibbs } 233539223Sgibbs } 233639223Sgibbs 233739223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) != 0 233839223Sgibbs || bt->cur_outbox->action_code != BMBO_FREE 233940418Sgibbs || ((bccb->hccb.tag_enable == TRUE) 234039223Sgibbs && (bt->firmware_ver[0] < '5'))) { 234139223Sgibbs /* 234239223Sgibbs * Try a full host adapter/SCSI bus reset. 234339223Sgibbs * We do this only if we have already attempted 234439223Sgibbs * to clear the condition with a BDR, or we cannot 234539223Sgibbs * attempt a BDR for lack of mailbox resources 234639223Sgibbs * or because of faulty firmware. It turns out 234739223Sgibbs * that firmware versions prior to 5.xx treat BDRs 234839223Sgibbs * as untagged commands that cannot be sent until 234939223Sgibbs * all outstanding tagged commands have been processed. 235039223Sgibbs * This makes it somewhat difficult to use a BDR to 235139223Sgibbs * clear up a problem with an uncompleted tagged command. 235239223Sgibbs */ 235339223Sgibbs ccb->ccb_h.status = CAM_CMD_TIMEOUT; 235439223Sgibbs btreset(bt, /*hardreset*/TRUE); 2355241592Sjhb device_printf(bt->dev, "No longer in timeout\n"); 235639223Sgibbs } else { 235739223Sgibbs /* 235839223Sgibbs * Send a Bus Device Reset message: 235939223Sgibbs * The target that is holding up the bus may not 236039223Sgibbs * be the same as the one that triggered this timeout 236139223Sgibbs * (different commands have different timeout lengths), 236239223Sgibbs * but we have no way of determining this from our 236339223Sgibbs * timeout handler. Our strategy here is to queue a 236439223Sgibbs * BDR message to the target of the timed out command. 236539223Sgibbs * If this fails, we'll get another timeout 2 seconds 236639223Sgibbs * later which will attempt a bus reset. 236739223Sgibbs */ 236839223Sgibbs bccb->flags |= BCCB_DEVICE_RESET; 2369241592Sjhb callout_reset(&bccb->timer, 2 * hz, bttimeout, bccb); 237039223Sgibbs 237139223Sgibbs bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET; 237239223Sgibbs 237339223Sgibbs /* No Data Transfer */ 237439223Sgibbs bt->recovery_bccb->hccb.datain = TRUE; 237539223Sgibbs bt->recovery_bccb->hccb.dataout = TRUE; 237639223Sgibbs bt->recovery_bccb->hccb.btstat = 0; 237739223Sgibbs bt->recovery_bccb->hccb.sdstat = 0; 237839223Sgibbs bt->recovery_bccb->hccb.target_id = ccb->ccb_h.target_id; 237939223Sgibbs 238039223Sgibbs /* Tell the adapter about this command */ 238139223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bt->recovery_bccb); 238239223Sgibbs bt->cur_outbox->action_code = BMBO_START; 238339223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 238439223Sgibbs btnextoutbox(bt); 238539223Sgibbs } 238639223Sgibbs} 238739223Sgibbs 2388165102SmjacobMODULE_VERSION(bt, 1); 2389165102SmjacobMODULE_DEPEND(bt, cam, 1, 1, 1); 2390