bt.c revision 118052
139223Sgibbs/* 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 * 3350477Speter * $FreeBSD: head/sys/dev/buslogic/bt.c 118052 2003-07-26 11:53:40Z bde $ 3439223Sgibbs */ 3539223Sgibbs 3639223Sgibbs /* 3739223Sgibbs * Special thanks to Leonard N. Zubkoff for writing such a complete and 3839223Sgibbs * well documented Mylex/BusLogic MultiMaster driver for Linux. Support 3939223Sgibbs * in this driver for the wide range of MultiMaster controllers and 4039223Sgibbs * firmware revisions, with their otherwise undocumented quirks, would not 4139223Sgibbs * have been possible without his efforts. 4239223Sgibbs */ 4339223Sgibbs 4439223Sgibbs#include <sys/param.h> 4539223Sgibbs#include <sys/systm.h> 4639223Sgibbs#include <sys/malloc.h> 4739223Sgibbs#include <sys/kernel.h> 48117126Sscottl#include <sys/lock.h> 49117126Sscottl#include <sys/mutex.h> 5039223Sgibbs#include <sys/sysctl.h> 5145791Speter#include <sys/bus.h> 5239223Sgibbs 5339223Sgibbs/* 5439223Sgibbs * XXX It appears that BusLogic PCI adapters go out to lunch if you 5539223Sgibbs * attempt to perform memory mapped I/O. 5639223Sgibbs */ 5739223Sgibbs#if 0 5839223Sgibbs#include <machine/bus_memio.h> 5939223Sgibbs#endif 6039223Sgibbs#include <machine/bus_pio.h> 6139223Sgibbs#include <machine/bus.h> 6245791Speter#include <sys/rman.h> 6339223Sgibbs 6439223Sgibbs#include <cam/cam.h> 6539223Sgibbs#include <cam/cam_ccb.h> 6639223Sgibbs#include <cam/cam_sim.h> 6739223Sgibbs#include <cam/cam_xpt_sim.h> 6839223Sgibbs#include <cam/cam_debug.h> 6939223Sgibbs 7039223Sgibbs#include <cam/scsi/scsi_message.h> 7139223Sgibbs 7239223Sgibbs#include <vm/vm.h> 7339223Sgibbs#include <vm/pmap.h> 7439223Sgibbs 7539223Sgibbs#include <dev/buslogic/btreg.h> 7639223Sgibbs 7739223Sgibbs/* MailBox Management functions */ 7839223Sgibbsstatic __inline void btnextinbox(struct bt_softc *bt); 7939223Sgibbsstatic __inline void btnextoutbox(struct bt_softc *bt); 8039223Sgibbs 8139223Sgibbsstatic __inline void 8239223Sgibbsbtnextinbox(struct bt_softc *bt) 8339223Sgibbs{ 8439223Sgibbs if (bt->cur_inbox == bt->last_inbox) 8539223Sgibbs bt->cur_inbox = bt->in_boxes; 8639223Sgibbs else 8739223Sgibbs bt->cur_inbox++; 8839223Sgibbs} 8939223Sgibbs 9039223Sgibbsstatic __inline void 9139223Sgibbsbtnextoutbox(struct bt_softc *bt) 9239223Sgibbs{ 9339223Sgibbs if (bt->cur_outbox == bt->last_outbox) 9439223Sgibbs bt->cur_outbox = bt->out_boxes; 9539223Sgibbs else 9639223Sgibbs bt->cur_outbox++; 9739223Sgibbs} 9839223Sgibbs 9939223Sgibbs/* CCB Mangement functions */ 10039223Sgibbsstatic __inline u_int32_t btccbvtop(struct bt_softc *bt, 10139223Sgibbs struct bt_ccb *bccb); 10239223Sgibbsstatic __inline struct bt_ccb* btccbptov(struct bt_softc *bt, 10339223Sgibbs u_int32_t ccb_addr); 10439223Sgibbsstatic __inline u_int32_t btsensepaddr(struct bt_softc *bt, 10539223Sgibbs struct bt_ccb *bccb); 10639223Sgibbsstatic __inline struct scsi_sense_data* btsensevaddr(struct bt_softc *bt, 10739223Sgibbs struct bt_ccb *bccb); 10839223Sgibbs 10939223Sgibbsstatic __inline u_int32_t 11039223Sgibbsbtccbvtop(struct bt_softc *bt, struct bt_ccb *bccb) 11139223Sgibbs{ 11239223Sgibbs return (bt->bt_ccb_physbase 11339223Sgibbs + (u_int32_t)((caddr_t)bccb - (caddr_t)bt->bt_ccb_array)); 11439223Sgibbs} 11539223Sgibbs 11639223Sgibbsstatic __inline struct bt_ccb * 11739223Sgibbsbtccbptov(struct bt_softc *bt, u_int32_t ccb_addr) 11839223Sgibbs{ 11939223Sgibbs return (bt->bt_ccb_array + 120106521Sjhb ((struct bt_ccb*)(uintptr_t)ccb_addr - (struct bt_ccb*)(uintptr_t)bt->bt_ccb_physbase)); 12139223Sgibbs} 12239223Sgibbs 12339223Sgibbsstatic __inline u_int32_t 12439223Sgibbsbtsensepaddr(struct bt_softc *bt, struct bt_ccb *bccb) 12539223Sgibbs{ 12639223Sgibbs u_int index; 12739223Sgibbs 12839223Sgibbs index = (u_int)(bccb - bt->bt_ccb_array); 12939223Sgibbs return (bt->sense_buffers_physbase 13039223Sgibbs + (index * sizeof(struct scsi_sense_data))); 13139223Sgibbs} 13239223Sgibbs 13339223Sgibbsstatic __inline struct scsi_sense_data * 13439223Sgibbsbtsensevaddr(struct bt_softc *bt, struct bt_ccb *bccb) 13539223Sgibbs{ 13639223Sgibbs u_int index; 13739223Sgibbs 13839223Sgibbs index = (u_int)(bccb - bt->bt_ccb_array); 13939223Sgibbs return (bt->sense_buffers + index); 14039223Sgibbs} 14139223Sgibbs 14239223Sgibbsstatic __inline struct bt_ccb* btgetccb(struct bt_softc *bt); 14339223Sgibbsstatic __inline void btfreeccb(struct bt_softc *bt, 14439223Sgibbs struct bt_ccb *bccb); 14539223Sgibbsstatic void btallocccbs(struct bt_softc *bt); 14639223Sgibbsstatic bus_dmamap_callback_t btexecuteccb; 14739223Sgibbsstatic void btdone(struct bt_softc *bt, struct bt_ccb *bccb, 14839223Sgibbs bt_mbi_comp_code_t comp_code); 14939223Sgibbs 15039223Sgibbs/* Host adapter command functions */ 15139223Sgibbsstatic int btreset(struct bt_softc* bt, int hard_reset); 15239223Sgibbs 15339223Sgibbs/* Initialization functions */ 15439223Sgibbsstatic int btinitmboxes(struct bt_softc *bt); 15539223Sgibbsstatic bus_dmamap_callback_t btmapmboxes; 15639223Sgibbsstatic bus_dmamap_callback_t btmapccbs; 15739223Sgibbsstatic bus_dmamap_callback_t btmapsgs; 15839223Sgibbs 15939223Sgibbs/* Transfer Negotiation Functions */ 16039223Sgibbsstatic void btfetchtransinfo(struct bt_softc *bt, 16139223Sgibbs struct ccb_trans_settings *cts); 16239223Sgibbs 16339223Sgibbs/* CAM SIM entry points */ 16439223Sgibbs#define ccb_bccb_ptr spriv_ptr0 16539223Sgibbs#define ccb_bt_ptr spriv_ptr1 16639223Sgibbsstatic void btaction(struct cam_sim *sim, union ccb *ccb); 16739223Sgibbsstatic void btpoll(struct cam_sim *sim); 16839223Sgibbs 16939223Sgibbs/* Our timeout handler */ 17039223Sgibbstimeout_t bttimeout; 17139223Sgibbs 17239223Sgibbsu_long bt_unit = 0; 17339223Sgibbs 17439223Sgibbs/* 17539223Sgibbs * XXX 17639223Sgibbs * Do our own re-probe protection until a configuration 17739223Sgibbs * manager can do it for us. This ensures that we don't 17839223Sgibbs * reprobe a card already found by the EISA or PCI probes. 17939223Sgibbs */ 18039223Sgibbsstruct bt_isa_port bt_isa_ports[] = 18139223Sgibbs{ 18241048Sgibbs { 0x130, 0, 4 }, 18341048Sgibbs { 0x134, 0, 5 }, 18441048Sgibbs { 0x230, 0, 2 }, 18541048Sgibbs { 0x234, 0, 3 }, 18641048Sgibbs { 0x330, 0, 0 }, 18741048Sgibbs { 0x334, 0, 1 } 18839223Sgibbs}; 18939223Sgibbs 19041048Sgibbs/* 19141048Sgibbs * I/O ports listed in the order enumerated by the 19241048Sgibbs * card for certain op codes. 19341048Sgibbs */ 19441048Sgibbsu_int16_t bt_board_ports[] = 19541048Sgibbs{ 19641048Sgibbs 0x330, 19741048Sgibbs 0x334, 19841048Sgibbs 0x230, 19941048Sgibbs 0x234, 20041048Sgibbs 0x130, 20141048Sgibbs 0x134 20241048Sgibbs}; 20341048Sgibbs 20439223Sgibbs/* Exported functions */ 20545791Spetervoid 20645791Speterbt_init_softc(device_t dev, struct resource *port, 20745791Speter struct resource *irq, struct resource *drq) 20839223Sgibbs{ 20945791Speter struct bt_softc *bt = device_get_softc(dev); 21039223Sgibbs 21139223Sgibbs SLIST_INIT(&bt->free_bt_ccbs); 21239223Sgibbs LIST_INIT(&bt->pending_ccbs); 21339223Sgibbs SLIST_INIT(&bt->sg_maps); 21445791Speter bt->dev = dev; 21545791Speter bt->unit = device_get_unit(dev); 21645791Speter bt->port = port; 21745791Speter bt->irq = irq; 21845791Speter bt->drq = drq; 21945791Speter bt->tag = rman_get_bustag(port); 22045791Speter bt->bsh = rman_get_bushandle(port); 22139223Sgibbs} 22239223Sgibbs 22339223Sgibbsvoid 22445791Speterbt_free_softc(device_t dev) 22539223Sgibbs{ 22645791Speter struct bt_softc *bt = device_get_softc(dev); 22745791Speter 22839223Sgibbs switch (bt->init_level) { 22939223Sgibbs default: 23039223Sgibbs case 11: 23139223Sgibbs bus_dmamap_unload(bt->sense_dmat, bt->sense_dmamap); 23239223Sgibbs case 10: 23339223Sgibbs bus_dmamem_free(bt->sense_dmat, bt->sense_buffers, 23439223Sgibbs bt->sense_dmamap); 23539223Sgibbs case 9: 23639223Sgibbs bus_dma_tag_destroy(bt->sense_dmat); 23739223Sgibbs case 8: 23839223Sgibbs { 23939223Sgibbs struct sg_map_node *sg_map; 24039223Sgibbs 24139223Sgibbs while ((sg_map = SLIST_FIRST(&bt->sg_maps))!= NULL) { 24239223Sgibbs SLIST_REMOVE_HEAD(&bt->sg_maps, links); 24339223Sgibbs bus_dmamap_unload(bt->sg_dmat, 24439223Sgibbs sg_map->sg_dmamap); 24539223Sgibbs bus_dmamem_free(bt->sg_dmat, sg_map->sg_vaddr, 24639223Sgibbs sg_map->sg_dmamap); 24739223Sgibbs free(sg_map, M_DEVBUF); 24839223Sgibbs } 24939223Sgibbs bus_dma_tag_destroy(bt->sg_dmat); 25039223Sgibbs } 25139223Sgibbs case 7: 25239223Sgibbs bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap); 253115555Sphk /* FALLTHROUGH */ 25439223Sgibbs case 6: 25539223Sgibbs bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array, 25639223Sgibbs bt->ccb_dmamap); 25739223Sgibbs bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap); 258115555Sphk /* FALLTHROUGH */ 25939223Sgibbs case 5: 26039223Sgibbs bus_dma_tag_destroy(bt->ccb_dmat); 261115555Sphk /* FALLTHROUGH */ 26239223Sgibbs case 4: 26339223Sgibbs bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap); 264115555Sphk /* FALLTHROUGH */ 26539223Sgibbs case 3: 26639223Sgibbs bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes, 26739223Sgibbs bt->mailbox_dmamap); 26839223Sgibbs bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap); 269115555Sphk /* FALLTHROUGH */ 27039223Sgibbs case 2: 27139223Sgibbs bus_dma_tag_destroy(bt->buffer_dmat); 272115555Sphk /* FALLTHROUGH */ 27339223Sgibbs case 1: 27439223Sgibbs bus_dma_tag_destroy(bt->mailbox_dmat); 275115555Sphk /* FALLTHROUGH */ 27639223Sgibbs case 0: 27739223Sgibbs break; 27839223Sgibbs } 27939223Sgibbs} 28039223Sgibbs 28144581Sgibbsint 28245791Speterbt_port_probe(device_t dev, struct bt_probe_info *info) 28344581Sgibbs{ 28445791Speter struct bt_softc *bt = device_get_softc(dev); 28544581Sgibbs config_data_t config_data; 28644581Sgibbs int error; 28744581Sgibbs 28844581Sgibbs /* See if there is really a card present */ 28945791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev)) 29044581Sgibbs return(1); 29144581Sgibbs 29244581Sgibbs /* 29344581Sgibbs * Determine our IRQ, and DMA settings and 29444581Sgibbs * export them to the configuration system. 29544581Sgibbs */ 29644581Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 29744581Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 29844581Sgibbs DEFAULT_CMD_TIMEOUT); 29944581Sgibbs if (error != 0) { 30044581Sgibbs printf("bt_port_probe: Could not determine IRQ or DMA " 30144581Sgibbs "settings for adapter.\n"); 30244581Sgibbs return (1); 30344581Sgibbs } 30444581Sgibbs 30544581Sgibbs if (bt->model[0] == '5') { 30644581Sgibbs /* DMA settings only make sense for ISA cards */ 30744581Sgibbs switch (config_data.dma_chan) { 30844581Sgibbs case DMA_CHAN_5: 30944581Sgibbs info->drq = 5; 31044581Sgibbs break; 31144581Sgibbs case DMA_CHAN_6: 31244581Sgibbs info->drq = 6; 31344581Sgibbs break; 31444581Sgibbs case DMA_CHAN_7: 31544581Sgibbs info->drq = 7; 31644581Sgibbs break; 31744581Sgibbs default: 31844581Sgibbs printf("bt_port_probe: Invalid DMA setting " 31944581Sgibbs "detected for adapter.\n"); 32044581Sgibbs return (1); 32144581Sgibbs } 32244581Sgibbs } else { 32344581Sgibbs /* VL/EISA/PCI DMA */ 32444581Sgibbs info->drq = -1; 32544581Sgibbs } 32644581Sgibbs switch (config_data.irq) { 32744581Sgibbs case IRQ_9: 32844581Sgibbs case IRQ_10: 32944581Sgibbs case IRQ_11: 33044581Sgibbs case IRQ_12: 33144581Sgibbs case IRQ_14: 33244581Sgibbs case IRQ_15: 33344581Sgibbs info->irq = ffs(config_data.irq) + 8; 33444581Sgibbs break; 33544581Sgibbs default: 33644581Sgibbs printf("bt_port_probe: Invalid IRQ setting %x" 33744581Sgibbs "detected for adapter.\n", config_data.irq); 33844581Sgibbs return (1); 33944581Sgibbs } 34044581Sgibbs return (0); 34144581Sgibbs} 34244581Sgibbs 34339223Sgibbs/* 34439223Sgibbs * Probe the adapter and verify that the card is a BusLogic. 34539223Sgibbs */ 34639223Sgibbsint 34745791Speterbt_probe(device_t dev) 34839223Sgibbs{ 34945791Speter struct bt_softc *bt = device_get_softc(dev); 35039223Sgibbs esetup_info_data_t esetup_info; 35139223Sgibbs u_int status; 35239223Sgibbs u_int intstat; 35339223Sgibbs u_int geometry; 35439223Sgibbs int error; 35539223Sgibbs u_int8_t param; 35639223Sgibbs 35739223Sgibbs /* 35839223Sgibbs * See if the three I/O ports look reasonable. 35939223Sgibbs * Touch the minimal number of registers in the 36039223Sgibbs * failure case. 36139223Sgibbs */ 36239223Sgibbs status = bt_inb(bt, STATUS_REG); 36339223Sgibbs if ((status == 0) 36439223Sgibbs || (status & (DIAG_ACTIVE|CMD_REG_BUSY| 36539223Sgibbs STATUS_REG_RSVD|CMD_INVALID)) != 0) { 36639223Sgibbs if (bootverbose) 36745791Speter device_printf(dev, "Failed Status Reg Test - %x\n", 36839223Sgibbs status); 36939223Sgibbs return (ENXIO); 37039223Sgibbs } 37139223Sgibbs 37239223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 37339223Sgibbs if ((intstat & INTSTAT_REG_RSVD) != 0) { 37445791Speter device_printf(dev, "Failed Intstat Reg Test\n"); 37539223Sgibbs return (ENXIO); 37639223Sgibbs } 37739223Sgibbs 37839223Sgibbs geometry = bt_inb(bt, GEOMETRY_REG); 37939223Sgibbs if (geometry == 0xFF) { 38039223Sgibbs if (bootverbose) 38145791Speter device_printf(dev, "Failed Geometry Reg Test\n"); 38239223Sgibbs return (ENXIO); 38339223Sgibbs } 38439223Sgibbs 38539223Sgibbs /* 38639223Sgibbs * Looking good so far. Final test is to reset the 38739223Sgibbs * adapter and attempt to fetch the extended setup 38839223Sgibbs * information. This should filter out all 1542 cards. 38939223Sgibbs */ 39039223Sgibbs if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) { 39139223Sgibbs if (bootverbose) 39245791Speter device_printf(dev, "Failed Reset\n"); 39339223Sgibbs return (ENXIO); 39439223Sgibbs } 39539223Sgibbs 39639223Sgibbs param = sizeof(esetup_info); 39739223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, ¶m, /*parmlen*/1, 39839223Sgibbs (u_int8_t*)&esetup_info, sizeof(esetup_info), 39939223Sgibbs DEFAULT_CMD_TIMEOUT); 40039223Sgibbs if (error != 0) { 40139223Sgibbs return (ENXIO); 40239223Sgibbs } 40339223Sgibbs 40439223Sgibbs return (0); 40539223Sgibbs} 40639223Sgibbs 40739223Sgibbs/* 40839223Sgibbs * Pull the boards setup information and record it in our softc. 40939223Sgibbs */ 41039223Sgibbsint 41145791Speterbt_fetch_adapter_info(device_t dev) 41239223Sgibbs{ 41345791Speter struct bt_softc *bt = device_get_softc(dev); 41439223Sgibbs board_id_data_t board_id; 41539223Sgibbs esetup_info_data_t esetup_info; 41639223Sgibbs config_data_t config_data; 41739223Sgibbs int error; 41839223Sgibbs u_int8_t length_param; 41939223Sgibbs 42039223Sgibbs /* First record the firmware version */ 42139223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0, 42239223Sgibbs (u_int8_t*)&board_id, sizeof(board_id), 42339223Sgibbs DEFAULT_CMD_TIMEOUT); 42439223Sgibbs if (error != 0) { 42545791Speter device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n"); 42639223Sgibbs return (error); 42739223Sgibbs } 42839223Sgibbs bt->firmware_ver[0] = board_id.firmware_rev_major; 42939223Sgibbs bt->firmware_ver[1] = '.'; 43039223Sgibbs bt->firmware_ver[2] = board_id.firmware_rev_minor; 43139223Sgibbs bt->firmware_ver[3] = '\0'; 43239223Sgibbs 43339223Sgibbs /* 43439223Sgibbs * Depending on the firmware major and minor version, 43539223Sgibbs * we may be able to fetch additional minor version info. 43639223Sgibbs */ 43739223Sgibbs if (bt->firmware_ver[0] > '0') { 43839223Sgibbs 43939223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0, 44039223Sgibbs (u_int8_t*)&bt->firmware_ver[3], 1, 44139223Sgibbs DEFAULT_CMD_TIMEOUT); 44239223Sgibbs if (error != 0) { 44345791Speter device_printf(dev, 44445791Speter "bt_fetch_adapter_info - Failed Get " 44545791Speter "Firmware 3rd Digit\n"); 44639223Sgibbs return (error); 44739223Sgibbs } 44839223Sgibbs if (bt->firmware_ver[3] == ' ') 44939223Sgibbs bt->firmware_ver[3] = '\0'; 45039223Sgibbs bt->firmware_ver[4] = '\0'; 45139223Sgibbs } 45239223Sgibbs 45339223Sgibbs if (strcmp(bt->firmware_ver, "3.3") >= 0) { 45439223Sgibbs 45539223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_FW_VER_4DIG, NULL, /*parmlen*/0, 45639223Sgibbs (u_int8_t*)&bt->firmware_ver[4], 1, 45739223Sgibbs DEFAULT_CMD_TIMEOUT); 45839223Sgibbs if (error != 0) { 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) { 49239223Sgibbs return (error); 49339223Sgibbs } 49439223Sgibbs 49539223Sgibbs bt->bios_addr = esetup_info.bios_addr << 12; 49639223Sgibbs 49768661Sgibbs bt->mailbox_addrlimit = BUS_SPACE_MAXADDR; 49839223Sgibbs if (esetup_info.bus_type == 'A' 49939223Sgibbs && bt->firmware_ver[0] == '2') { 50041514Sarchie snprintf(bt->model, sizeof(bt->model), "542B"); 50139223Sgibbs } else if (esetup_info.bus_type == 'E' 50268661Sgibbs && bt->firmware_ver[0] == '2') { 50368661Sgibbs 50468661Sgibbs /* 50568661Sgibbs * The 742A seems to object if its mailboxes are 50668661Sgibbs * allocated above the 16MB mark. 50768661Sgibbs */ 50868661Sgibbs bt->mailbox_addrlimit = BUS_SPACE_MAXADDR_24BIT; 50941514Sarchie snprintf(bt->model, sizeof(bt->model), "742A"); 51039223Sgibbs } else if (esetup_info.bus_type == 'E' 51139223Sgibbs && bt->firmware_ver[0] == '0') { 51239223Sgibbs /* AMI FastDisk EISA Series 441 0.x */ 51341514Sarchie snprintf(bt->model, sizeof(bt->model), "747A"); 51439223Sgibbs } else { 51539223Sgibbs ha_model_data_t model_data; 51639223Sgibbs int i; 51739223Sgibbs 51839223Sgibbs length_param = sizeof(model_data); 51939223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1, 52039223Sgibbs (u_int8_t*)&model_data, sizeof(model_data), 52139223Sgibbs DEFAULT_CMD_TIMEOUT); 52239223Sgibbs if (error != 0) { 52345791Speter device_printf(dev, 52445791Speter "bt_fetch_adapter_info - Failed Inquire " 52545791Speter "Model Number\n"); 52639223Sgibbs return (error); 52739223Sgibbs } 52839223Sgibbs for (i = 0; i < sizeof(model_data.ascii_model); i++) { 52939223Sgibbs bt->model[i] = model_data.ascii_model[i]; 53039223Sgibbs if (bt->model[i] == ' ') 53139223Sgibbs break; 53239223Sgibbs } 53339223Sgibbs bt->model[i] = '\0'; 53439223Sgibbs } 53539223Sgibbs 53644581Sgibbs bt->level_trigger_ints = esetup_info.level_trigger_ints ? 1 : 0; 53744581Sgibbs 53839223Sgibbs /* SG element limits */ 53939223Sgibbs bt->max_sg = esetup_info.max_sg; 54039223Sgibbs 54139223Sgibbs /* Set feature flags */ 54239223Sgibbs bt->wide_bus = esetup_info.wide_bus; 54339223Sgibbs bt->diff_bus = esetup_info.diff_bus; 54439223Sgibbs bt->ultra_scsi = esetup_info.ultra_scsi; 54539223Sgibbs 54639223Sgibbs if ((bt->firmware_ver[0] == '5') 54739223Sgibbs || (bt->firmware_ver[0] == '4' && bt->wide_bus)) 54839223Sgibbs bt->extended_lun = TRUE; 54939223Sgibbs 55039223Sgibbs bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0); 55139223Sgibbs 55239223Sgibbs bt->extended_trans = 55339223Sgibbs ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0); 55439223Sgibbs 55539223Sgibbs /* 55639223Sgibbs * Determine max CCB count and whether tagged queuing is 55739223Sgibbs * available based on controller type. Tagged queuing 55839223Sgibbs * only works on 'W' series adapters, 'C' series adapters 55939223Sgibbs * with firmware of rev 4.42 and higher, and 'S' series 56039223Sgibbs * adapters with firmware of rev 3.35 and higher. The 56139223Sgibbs * maximum CCB counts are as follows: 56239223Sgibbs * 56339223Sgibbs * 192 BT-948/958/958D 56439223Sgibbs * 100 BT-946C/956C/956CD/747C/757C/757CD/445C 56539223Sgibbs * 50 BT-545C/540CF 56639223Sgibbs * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A 56739223Sgibbs */ 56839223Sgibbs if (bt->firmware_ver[0] == '5') { 56939223Sgibbs bt->max_ccbs = 192; 57039223Sgibbs bt->tag_capable = TRUE; 57139223Sgibbs } else if (bt->firmware_ver[0] == '4') { 57239223Sgibbs if (bt->model[0] == '5') 57339223Sgibbs bt->max_ccbs = 50; 57439223Sgibbs else 57539223Sgibbs bt->max_ccbs = 100; 57639223Sgibbs bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0); 57739223Sgibbs } else { 57839223Sgibbs bt->max_ccbs = 30; 57939223Sgibbs if (bt->firmware_ver[0] == '3' 58039223Sgibbs && (strcmp(bt->firmware_ver, "3.35") >= 0)) 58139223Sgibbs bt->tag_capable = TRUE; 58239223Sgibbs else 58339223Sgibbs bt->tag_capable = FALSE; 58439223Sgibbs } 58539223Sgibbs 58639223Sgibbs if (bt->tag_capable != FALSE) 58739223Sgibbs bt->tags_permitted = ALL_TARGETS; 58839223Sgibbs 58939223Sgibbs /* Determine Sync/Wide/Disc settings */ 59039223Sgibbs if (bt->firmware_ver[0] >= '4') { 59139223Sgibbs auto_scsi_data_t auto_scsi_data; 59239223Sgibbs fetch_lram_params_t fetch_lram_params; 59339223Sgibbs int error; 59439223Sgibbs 59539223Sgibbs /* 59639223Sgibbs * These settings are stored in the 59739223Sgibbs * AutoSCSI data in LRAM of 'W' and 'C' 59839223Sgibbs * adapters. 59939223Sgibbs */ 60039223Sgibbs fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET; 60139223Sgibbs fetch_lram_params.response_len = sizeof(auto_scsi_data); 60239223Sgibbs error = bt_cmd(bt, BOP_FETCH_LRAM, 60339223Sgibbs (u_int8_t*)&fetch_lram_params, 60439223Sgibbs sizeof(fetch_lram_params), 60539223Sgibbs (u_int8_t*)&auto_scsi_data, 60639223Sgibbs sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT); 60739223Sgibbs 60839223Sgibbs if (error != 0) { 60945791Speter device_printf(dev, 61045791Speter "bt_fetch_adapter_info - Failed " 61145791Speter "Get Auto SCSI Info\n"); 61239223Sgibbs return (error); 61339223Sgibbs } 61439223Sgibbs 61539223Sgibbs bt->disc_permitted = auto_scsi_data.low_disc_permitted 61639223Sgibbs | (auto_scsi_data.high_disc_permitted << 8); 61739223Sgibbs bt->sync_permitted = auto_scsi_data.low_sync_permitted 61839223Sgibbs | (auto_scsi_data.high_sync_permitted << 8); 61939223Sgibbs bt->fast_permitted = auto_scsi_data.low_fast_permitted 62039223Sgibbs | (auto_scsi_data.high_fast_permitted << 8); 62139223Sgibbs bt->ultra_permitted = auto_scsi_data.low_ultra_permitted 62239223Sgibbs | (auto_scsi_data.high_ultra_permitted << 8); 62339223Sgibbs bt->wide_permitted = auto_scsi_data.low_wide_permitted 62439223Sgibbs | (auto_scsi_data.high_wide_permitted << 8); 62539223Sgibbs 62639223Sgibbs if (bt->ultra_scsi == FALSE) 62739223Sgibbs bt->ultra_permitted = 0; 62839223Sgibbs 62939223Sgibbs if (bt->wide_bus == FALSE) 63039223Sgibbs bt->wide_permitted = 0; 63139223Sgibbs } else { 63239223Sgibbs /* 63339223Sgibbs * 'S' and 'A' series have this information in the setup 63439223Sgibbs * information structure. 63539223Sgibbs */ 63639223Sgibbs setup_data_t setup_info; 63739223Sgibbs 63839223Sgibbs length_param = sizeof(setup_info); 63939223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param, 64039223Sgibbs /*paramlen*/1, (u_int8_t*)&setup_info, 64139223Sgibbs sizeof(setup_info), DEFAULT_CMD_TIMEOUT); 64239223Sgibbs 64339223Sgibbs if (error != 0) { 64445791Speter device_printf(dev, 64545791Speter "bt_fetch_adapter_info - Failed " 64645791Speter "Get Setup Info\n"); 64739223Sgibbs return (error); 64839223Sgibbs } 64939223Sgibbs 65039223Sgibbs if (setup_info.initiate_sync != 0) { 65139223Sgibbs bt->sync_permitted = ALL_TARGETS; 65239223Sgibbs 65339223Sgibbs if (bt->model[0] == '7') { 65439223Sgibbs if (esetup_info.sync_neg10MB != 0) 65539223Sgibbs bt->fast_permitted = ALL_TARGETS; 65639223Sgibbs if (strcmp(bt->model, "757") == 0) 65739223Sgibbs bt->wide_permitted = ALL_TARGETS; 65839223Sgibbs } 65939223Sgibbs } 66039223Sgibbs bt->disc_permitted = ALL_TARGETS; 66139223Sgibbs } 66239223Sgibbs 66339223Sgibbs /* We need as many mailboxes as we can have ccbs */ 66439223Sgibbs bt->num_boxes = bt->max_ccbs; 66539223Sgibbs 66639223Sgibbs /* Determine our SCSI ID */ 66739223Sgibbs 66839223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 66939223Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 67039223Sgibbs DEFAULT_CMD_TIMEOUT); 67139223Sgibbs if (error != 0) { 67245791Speter device_printf(dev, 67345791Speter "bt_fetch_adapter_info - Failed Get Config\n"); 67439223Sgibbs return (error); 67539223Sgibbs } 67639223Sgibbs bt->scsi_id = config_data.scsi_id; 67739223Sgibbs 67839223Sgibbs return (0); 67939223Sgibbs} 68039223Sgibbs 68139223Sgibbs/* 68239223Sgibbs * Start the board, ready for normal operation 68339223Sgibbs */ 68439223Sgibbsint 68545791Speterbt_init(device_t dev) 68639223Sgibbs{ 68745791Speter struct bt_softc *bt = device_get_softc(dev); 68845791Speter 68939223Sgibbs /* Announce the Adapter */ 69045791Speter device_printf(dev, "BT-%s FW Rev. %s ", bt->model, bt->firmware_ver); 69139223Sgibbs 69239223Sgibbs if (bt->ultra_scsi != 0) 69339223Sgibbs printf("Ultra "); 69439223Sgibbs 69539223Sgibbs if (bt->wide_bus != 0) 69639223Sgibbs printf("Wide "); 69739223Sgibbs else 69839223Sgibbs printf("Narrow "); 69939223Sgibbs 70039223Sgibbs if (bt->diff_bus != 0) 70139223Sgibbs printf("Diff "); 70239223Sgibbs 70339223Sgibbs printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id, 70439223Sgibbs bt->max_ccbs); 70539223Sgibbs 70639223Sgibbs /* 70739223Sgibbs * Create our DMA tags. These tags define the kinds of device 70861686Salex * accessible memory allocations and memory mappings we will 70939223Sgibbs * need to perform during normal operation. 71039223Sgibbs * 71139223Sgibbs * Unless we need to further restrict the allocation, we rely 71239223Sgibbs * on the restrictions of the parent dmat, hence the common 71339223Sgibbs * use of MAXADDR and MAXSIZE. 71439223Sgibbs */ 71539223Sgibbs 71639223Sgibbs /* DMA tag for mapping buffers into device visible space. */ 717112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 718112782Smdodd /* alignment */ 1, 719112782Smdodd /* boundary */ 0, 720112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 721112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 722112782Smdodd /* filter */ NULL, 723112782Smdodd /* filterarg */ NULL, 724112782Smdodd /* maxsize */ MAXBSIZE, 725112782Smdodd /* nsegments */ BT_NSEG, 726112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 727112782Smdodd /* flags */ BUS_DMA_ALLOCNOW, 728117126Sscottl /* lockfunc */ busdma_lock_mutex, 729117126Sscottl /* lockarg */ &Giant, 730112782Smdodd &bt->buffer_dmat) != 0) { 73139223Sgibbs goto error_exit; 73239223Sgibbs } 73339223Sgibbs 73439223Sgibbs bt->init_level++; 73539223Sgibbs /* DMA tag for our mailboxes */ 736112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 737112782Smdodd /* alignment */ 1, 738112782Smdodd /* boundary */ 0, 739112782Smdodd /* lowaddr */ bt->mailbox_addrlimit, 740112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 741112782Smdodd /* filter */ NULL, 742112782Smdodd /* filterarg */ NULL, 743112782Smdodd /* maxsize */ bt->num_boxes * 744112782Smdodd (sizeof(bt_mbox_in_t) + 745112782Smdodd sizeof(bt_mbox_out_t)), 746112782Smdodd /* nsegments */ 1, 747112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 748112782Smdodd /* flags */ 0, 749117126Sscottl /* lockfunc */ busdma_lock_mutex, 750117126Sscottl /* lockarg */ &Giant, 751112782Smdodd &bt->mailbox_dmat) != 0) { 75239223Sgibbs goto error_exit; 75339223Sgibbs } 75439223Sgibbs 75539223Sgibbs bt->init_level++; 75639223Sgibbs 75739223Sgibbs /* Allocation for our mailboxes */ 75839223Sgibbs if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes, 75939223Sgibbs BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) { 76039223Sgibbs goto error_exit; 76139223Sgibbs } 76239223Sgibbs 76339223Sgibbs bt->init_level++; 76439223Sgibbs 76539223Sgibbs /* And permanently map them */ 76639223Sgibbs bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap, 76739223Sgibbs bt->out_boxes, 76839223Sgibbs bt->num_boxes * (sizeof(bt_mbox_in_t) 76939223Sgibbs + sizeof(bt_mbox_out_t)), 77039223Sgibbs btmapmboxes, bt, /*flags*/0); 77139223Sgibbs 77239223Sgibbs bt->init_level++; 77339223Sgibbs 77439223Sgibbs bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes]; 77539223Sgibbs 77639223Sgibbs btinitmboxes(bt); 77739223Sgibbs 77839223Sgibbs /* DMA tag for our ccb structures */ 779112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 780112782Smdodd /* alignment */ 1, 781112782Smdodd /* boundary */ 0, 782112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 783112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 784112782Smdodd /* filter */ NULL, 785112782Smdodd /* filterarg */ NULL, 786112782Smdodd /* maxsize */ bt->max_ccbs * 787112782Smdodd sizeof(struct bt_ccb), 788112782Smdodd /* nsegments */ 1, 789112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 790112782Smdodd /* flags */ 0, 791117126Sscottl /* lockfunc */ busdma_lock_mutex, 792117126Sscottl /* lockarg */ &Giant, 793112782Smdodd &bt->ccb_dmat) != 0) { 79439223Sgibbs goto error_exit; 79539223Sgibbs } 79639223Sgibbs 79739223Sgibbs bt->init_level++; 79839223Sgibbs 79939223Sgibbs /* Allocation for our ccbs */ 80039223Sgibbs if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array, 80139223Sgibbs BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) { 80239223Sgibbs goto error_exit; 80339223Sgibbs } 80439223Sgibbs 80539223Sgibbs bt->init_level++; 80639223Sgibbs 80739223Sgibbs /* And permanently map them */ 80839223Sgibbs bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap, 80939223Sgibbs bt->bt_ccb_array, 81039223Sgibbs bt->max_ccbs * sizeof(struct bt_ccb), 81139223Sgibbs btmapccbs, bt, /*flags*/0); 81239223Sgibbs 81339223Sgibbs bt->init_level++; 81439223Sgibbs 81539223Sgibbs /* DMA tag for our S/G structures. We allocate in page sized chunks */ 816112782Smdodd if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 817112782Smdodd /* alignment */ 1, 818112782Smdodd /* boundary */ 0, 819112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR, 820112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 821112782Smdodd /* filter */ NULL, 822112782Smdodd /* filterarg */ NULL, 823112782Smdodd /* maxsize */ PAGE_SIZE, 824112782Smdodd /* nsegments */ 1, 825112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 826112782Smdodd /* flags */ 0, 827117126Sscottl /* lockfunc */ busdma_lock_mutex, 828117126Sscottl /* lockarg */ &Giant, 829112782Smdodd &bt->sg_dmat) != 0) { 83039223Sgibbs goto error_exit; 83139223Sgibbs } 83239223Sgibbs 83339223Sgibbs bt->init_level++; 83439223Sgibbs 83539223Sgibbs /* Perform initial CCB allocation */ 83639223Sgibbs bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb)); 83739223Sgibbs btallocccbs(bt); 83839223Sgibbs 83939223Sgibbs if (bt->num_ccbs == 0) { 84045791Speter device_printf(dev, 84145791Speter "bt_init - Unable to allocate initial ccbs\n"); 84239223Sgibbs goto error_exit; 84339223Sgibbs } 84439223Sgibbs 84539223Sgibbs /* 84639223Sgibbs * Note that we are going and return (to probe) 84739223Sgibbs */ 84839223Sgibbs return 0; 84939223Sgibbs 85039223Sgibbserror_exit: 85139223Sgibbs 85239223Sgibbs return (ENXIO); 85339223Sgibbs} 85439223Sgibbs 85539223Sgibbsint 85645791Speterbt_attach(device_t dev) 85739223Sgibbs{ 85845791Speter struct bt_softc *bt = device_get_softc(dev); 85939223Sgibbs int tagged_dev_openings; 86039223Sgibbs struct cam_devq *devq; 86145795Speter int error; 86239223Sgibbs 86339223Sgibbs /* 86439223Sgibbs * We reserve 1 ccb for error recovery, so don't 86539223Sgibbs * tell the XPT about it. 86639223Sgibbs */ 86739223Sgibbs if (bt->tag_capable != 0) 86839223Sgibbs tagged_dev_openings = bt->max_ccbs - 1; 86939223Sgibbs else 87039223Sgibbs tagged_dev_openings = 0; 87139223Sgibbs 87239223Sgibbs /* 87339223Sgibbs * Create the device queue for our SIM. 87439223Sgibbs */ 87539223Sgibbs devq = cam_simq_alloc(bt->max_ccbs - 1); 87639223Sgibbs if (devq == NULL) 87739223Sgibbs return (ENOMEM); 87839223Sgibbs 87939223Sgibbs /* 88039223Sgibbs * Construct our SIM entry 88139223Sgibbs */ 88239223Sgibbs bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit, 88339223Sgibbs 2, tagged_dev_openings, devq); 88439223Sgibbs if (bt->sim == NULL) { 88539223Sgibbs cam_simq_free(devq); 88639223Sgibbs return (ENOMEM); 88739223Sgibbs } 88839223Sgibbs 88939223Sgibbs if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) { 89039223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 89139223Sgibbs return (ENXIO); 89239223Sgibbs } 89339223Sgibbs 89439223Sgibbs if (xpt_create_path(&bt->path, /*periph*/NULL, 89539223Sgibbs cam_sim_path(bt->sim), CAM_TARGET_WILDCARD, 89639223Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 89739223Sgibbs xpt_bus_deregister(cam_sim_path(bt->sim)); 89839223Sgibbs cam_sim_free(bt->sim, /*free_devq*/TRUE); 89939223Sgibbs return (ENXIO); 90039223Sgibbs } 90139223Sgibbs 90245791Speter /* 90345791Speter * Setup interrupt. 90445791Speter */ 90573280Smarkm error = bus_setup_intr(dev, bt->irq, INTR_TYPE_CAM|INTR_ENTROPY, 90646743Sdfr bt_intr, bt, &bt->ih); 90745795Speter if (error) { 90845795Speter device_printf(dev, "bus_setup_intr() failed: %d\n", error); 90945795Speter return (error); 91045795Speter } 91145791Speter 91239223Sgibbs return (0); 91339223Sgibbs} 91439223Sgibbs 91539223Sgibbsint 91639223Sgibbsbt_check_probed_iop(u_int ioport) 91739223Sgibbs{ 91839223Sgibbs u_int i; 91939223Sgibbs 92041048Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 92139223Sgibbs if (bt_isa_ports[i].addr == ioport) { 92239223Sgibbs if (bt_isa_ports[i].probed != 0) 92339223Sgibbs return (1); 92439223Sgibbs else { 92539223Sgibbs return (0); 92639223Sgibbs } 92739223Sgibbs } 92839223Sgibbs } 92939223Sgibbs return (1); 93039223Sgibbs} 93139223Sgibbs 93239223Sgibbsvoid 93339223Sgibbsbt_mark_probed_bio(isa_compat_io_t port) 93439223Sgibbs{ 93539223Sgibbs if (port < BIO_DISABLED) 93641048Sgibbs bt_mark_probed_iop(bt_board_ports[port]); 93739223Sgibbs} 93839223Sgibbs 93939223Sgibbsvoid 94039223Sgibbsbt_mark_probed_iop(u_int ioport) 94139223Sgibbs{ 94239223Sgibbs u_int i; 94339223Sgibbs 94439223Sgibbs for (i = 0; i < BT_NUM_ISAPORTS; i++) { 94539223Sgibbs if (ioport == bt_isa_ports[i].addr) { 94639223Sgibbs bt_isa_ports[i].probed = 1; 94739223Sgibbs break; 94839223Sgibbs } 94939223Sgibbs } 95039223Sgibbs} 95139223Sgibbs 95241048Sgibbsvoid 95341048Sgibbsbt_find_probe_range(int ioport, int *port_index, int *max_port_index) 95441048Sgibbs{ 95541048Sgibbs if (ioport > 0) { 95641048Sgibbs int i; 95741048Sgibbs 95841048Sgibbs for (i = 0;i < BT_NUM_ISAPORTS; i++) 95941048Sgibbs if (ioport <= bt_isa_ports[i].addr) 96041048Sgibbs break; 96141048Sgibbs if ((i >= BT_NUM_ISAPORTS) 96241048Sgibbs || (ioport != bt_isa_ports[i].addr)) { 96387797Sjhb printf( 964118052Sbde"bt_find_probe_range: Invalid baseport of 0x%x specified.\n" 965118052Sbde"bt_find_probe_range: Nearest valid baseport is 0x%x.\n" 966118052Sbde"bt_find_probe_range: Failing probe.\n", 96741048Sgibbs ioport, 96841048Sgibbs (i < BT_NUM_ISAPORTS) 96941048Sgibbs ? bt_isa_ports[i].addr 97041048Sgibbs : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr); 97141048Sgibbs *port_index = *max_port_index = -1; 97241048Sgibbs return; 97341048Sgibbs } 97441048Sgibbs *port_index = *max_port_index = bt_isa_ports[i].bio; 97541048Sgibbs } else { 97641048Sgibbs *port_index = 0; 97741048Sgibbs *max_port_index = BT_NUM_ISAPORTS - 1; 97841048Sgibbs } 97941048Sgibbs} 98041048Sgibbs 98141048Sgibbsint 98241048Sgibbsbt_iop_from_bio(isa_compat_io_t bio_index) 98341048Sgibbs{ 98441048Sgibbs if (bio_index >= 0 && bio_index < BT_NUM_ISAPORTS) 98541048Sgibbs return (bt_board_ports[bio_index]); 98641048Sgibbs return (-1); 98741048Sgibbs} 98841048Sgibbs 98941048Sgibbs 99039223Sgibbsstatic void 99139223Sgibbsbtallocccbs(struct bt_softc *bt) 99239223Sgibbs{ 99339223Sgibbs struct bt_ccb *next_ccb; 99439223Sgibbs struct sg_map_node *sg_map; 99539223Sgibbs bus_addr_t physaddr; 99639223Sgibbs bt_sg_t *segs; 99739223Sgibbs int newcount; 99839223Sgibbs int i; 99939223Sgibbs 100045966Sgibbs if (bt->num_ccbs >= bt->max_ccbs) 100145966Sgibbs /* Can't allocate any more */ 100245966Sgibbs return; 100345966Sgibbs 100439223Sgibbs next_ccb = &bt->bt_ccb_array[bt->num_ccbs]; 100539223Sgibbs 100639223Sgibbs sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 100739223Sgibbs 100839223Sgibbs if (sg_map == NULL) 100945966Sgibbs goto error_exit; 101039223Sgibbs 101139223Sgibbs /* Allocate S/G space for the next batch of CCBS */ 101239223Sgibbs if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr, 101339223Sgibbs BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { 101439223Sgibbs free(sg_map, M_DEVBUF); 101545966Sgibbs goto error_exit; 101639223Sgibbs } 101739223Sgibbs 101839223Sgibbs SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links); 101939223Sgibbs 102039223Sgibbs bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, 102139223Sgibbs PAGE_SIZE, btmapsgs, bt, /*flags*/0); 102239223Sgibbs 102339223Sgibbs segs = sg_map->sg_vaddr; 102439223Sgibbs physaddr = sg_map->sg_physaddr; 102539223Sgibbs 102639223Sgibbs newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t))); 102739223Sgibbs for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) { 102839223Sgibbs int error; 102939223Sgibbs 103039223Sgibbs next_ccb->sg_list = segs; 103139223Sgibbs next_ccb->sg_list_phys = physaddr; 103239223Sgibbs next_ccb->flags = BCCB_FREE; 103339223Sgibbs error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0, 103439223Sgibbs &next_ccb->dmamap); 103539223Sgibbs if (error != 0) 103639223Sgibbs break; 103739223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links); 103839223Sgibbs segs += BT_NSEG; 103939223Sgibbs physaddr += (BT_NSEG * sizeof(bt_sg_t)); 104039223Sgibbs next_ccb++; 104139223Sgibbs bt->num_ccbs++; 104239223Sgibbs } 104339223Sgibbs 104439223Sgibbs /* Reserve a CCB for error recovery */ 104539223Sgibbs if (bt->recovery_bccb == NULL) { 104639223Sgibbs bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs); 104739223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 104839223Sgibbs } 104945966Sgibbs 105045966Sgibbs if (SLIST_FIRST(&bt->free_bt_ccbs) != NULL) 105145966Sgibbs return; 105245966Sgibbs 105345966Sgibbserror_exit: 105445966Sgibbs device_printf(bt->dev, "Can't malloc BCCBs\n"); 105539223Sgibbs} 105639223Sgibbs 105739223Sgibbsstatic __inline void 105839223Sgibbsbtfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) 105939223Sgibbs{ 106039223Sgibbs int s; 106139223Sgibbs 106239223Sgibbs s = splcam(); 106339223Sgibbs if ((bccb->flags & BCCB_ACTIVE) != 0) 106439223Sgibbs LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le); 106539223Sgibbs if (bt->resource_shortage != 0 106639223Sgibbs && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 106739223Sgibbs bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 106839223Sgibbs bt->resource_shortage = FALSE; 106939223Sgibbs } 107039223Sgibbs bccb->flags = BCCB_FREE; 107139223Sgibbs SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links); 107241048Sgibbs bt->active_ccbs--; 107339223Sgibbs splx(s); 107439223Sgibbs} 107539223Sgibbs 107639223Sgibbsstatic __inline struct bt_ccb* 107739223Sgibbsbtgetccb(struct bt_softc *bt) 107839223Sgibbs{ 107939223Sgibbs struct bt_ccb* bccb; 108039223Sgibbs int s; 108139223Sgibbs 108239223Sgibbs s = splcam(); 108339223Sgibbs if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) { 108439223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 108541048Sgibbs bt->active_ccbs++; 108645966Sgibbs } else { 108739223Sgibbs btallocccbs(bt); 108839223Sgibbs bccb = SLIST_FIRST(&bt->free_bt_ccbs); 108945966Sgibbs if (bccb != NULL) { 109039223Sgibbs SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); 109141048Sgibbs bt->active_ccbs++; 109241048Sgibbs } 109339223Sgibbs } 109439223Sgibbs splx(s); 109539223Sgibbs 109639223Sgibbs return (bccb); 109739223Sgibbs} 109839223Sgibbs 109939223Sgibbsstatic void 110039223Sgibbsbtaction(struct cam_sim *sim, union ccb *ccb) 110139223Sgibbs{ 110239223Sgibbs struct bt_softc *bt; 110339223Sgibbs 110439223Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n")); 110539223Sgibbs 110639223Sgibbs bt = (struct bt_softc *)cam_sim_softc(sim); 110739223Sgibbs 110839223Sgibbs switch (ccb->ccb_h.func_code) { 110939223Sgibbs /* Common cases first */ 111039223Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 111139223Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 111239223Sgibbs { 111339223Sgibbs struct bt_ccb *bccb; 111439223Sgibbs struct bt_hccb *hccb; 111539223Sgibbs 111639223Sgibbs /* 111739223Sgibbs * get a bccb to use. 111839223Sgibbs */ 111939223Sgibbs if ((bccb = btgetccb(bt)) == NULL) { 112039223Sgibbs int s; 112139223Sgibbs 112239223Sgibbs s = splcam(); 112339223Sgibbs bt->resource_shortage = TRUE; 112439223Sgibbs splx(s); 112539223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 112639223Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 112739223Sgibbs xpt_done(ccb); 112839223Sgibbs return; 112939223Sgibbs } 113039223Sgibbs 113139223Sgibbs hccb = &bccb->hccb; 113239223Sgibbs 113339223Sgibbs /* 113439223Sgibbs * So we can find the BCCB when an abort is requested 113539223Sgibbs */ 113639223Sgibbs bccb->ccb = ccb; 113739223Sgibbs ccb->ccb_h.ccb_bccb_ptr = bccb; 113839223Sgibbs ccb->ccb_h.ccb_bt_ptr = bt; 113939223Sgibbs 114039223Sgibbs /* 114139223Sgibbs * Put all the arguments for the xfer in the bccb 114239223Sgibbs */ 114339223Sgibbs hccb->target_id = ccb->ccb_h.target_id; 114439223Sgibbs hccb->target_lun = ccb->ccb_h.target_lun; 114539223Sgibbs hccb->btstat = 0; 114639223Sgibbs hccb->sdstat = 0; 114739223Sgibbs 114839223Sgibbs if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 114939223Sgibbs struct ccb_scsiio *csio; 115039223Sgibbs struct ccb_hdr *ccbh; 115139223Sgibbs 115239223Sgibbs csio = &ccb->csio; 115339223Sgibbs ccbh = &csio->ccb_h; 115439223Sgibbs hccb->opcode = INITIATOR_CCB_WRESID; 115541669Sgibbs hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0; 115641669Sgibbs hccb->dataout =(ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0; 115739223Sgibbs hccb->cmd_len = csio->cdb_len; 115839223Sgibbs if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) { 115939223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 116039223Sgibbs btfreeccb(bt, bccb); 116139223Sgibbs xpt_done(ccb); 116239223Sgibbs return; 116339223Sgibbs } 116439223Sgibbs hccb->sense_len = csio->sense_len; 116540418Sgibbs if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0 116640418Sgibbs && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) { 116739223Sgibbs hccb->tag_enable = TRUE; 116839223Sgibbs hccb->tag_type = (ccb->csio.tag_action & 0x3); 116939223Sgibbs } else { 117039223Sgibbs hccb->tag_enable = FALSE; 117139223Sgibbs hccb->tag_type = 0; 117239223Sgibbs } 117339223Sgibbs if ((ccbh->flags & CAM_CDB_POINTER) != 0) { 117439223Sgibbs if ((ccbh->flags & CAM_CDB_PHYS) == 0) { 117539223Sgibbs bcopy(csio->cdb_io.cdb_ptr, 117639223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 117739223Sgibbs } else { 117839223Sgibbs /* I guess I could map it in... */ 117939223Sgibbs ccbh->status = CAM_REQ_INVALID; 118039223Sgibbs btfreeccb(bt, bccb); 118139223Sgibbs xpt_done(ccb); 118239223Sgibbs return; 118339223Sgibbs } 118439223Sgibbs } else { 118539223Sgibbs bcopy(csio->cdb_io.cdb_bytes, 118639223Sgibbs hccb->scsi_cdb, hccb->cmd_len); 118739223Sgibbs } 118839223Sgibbs /* If need be, bounce our sense buffer */ 118939223Sgibbs if (bt->sense_buffers != NULL) { 119039223Sgibbs hccb->sense_addr = btsensepaddr(bt, bccb); 119139223Sgibbs } else { 119239223Sgibbs hccb->sense_addr = vtophys(&csio->sense_data); 119339223Sgibbs } 119439223Sgibbs /* 119539223Sgibbs * If we have any data to send with this command, 119639223Sgibbs * map it into bus space. 119739223Sgibbs */ 119839223Sgibbs /* Only use S/G if there is a transfer */ 119939223Sgibbs if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 120039223Sgibbs if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { 120139223Sgibbs /* 120239223Sgibbs * We've been given a pointer 120339223Sgibbs * to a single buffer. 120439223Sgibbs */ 120539223Sgibbs if ((ccbh->flags & CAM_DATA_PHYS)==0) { 120639223Sgibbs int s; 120739223Sgibbs int error; 120839223Sgibbs 120939223Sgibbs s = splsoftvm(); 121039223Sgibbs error = bus_dmamap_load( 121139223Sgibbs bt->buffer_dmat, 121239223Sgibbs bccb->dmamap, 121339223Sgibbs csio->data_ptr, 121439223Sgibbs csio->dxfer_len, 121539223Sgibbs btexecuteccb, 121639223Sgibbs bccb, 121739223Sgibbs /*flags*/0); 121839223Sgibbs if (error == EINPROGRESS) { 121939223Sgibbs /* 122039223Sgibbs * So as to maintain 122139223Sgibbs * ordering, freeze the 122239223Sgibbs * controller queue 122339223Sgibbs * until our mapping is 122439223Sgibbs * returned. 122539223Sgibbs */ 122639223Sgibbs xpt_freeze_simq(bt->sim, 122739223Sgibbs 1); 122839223Sgibbs csio->ccb_h.status |= 122939223Sgibbs CAM_RELEASE_SIMQ; 123039223Sgibbs } 123139223Sgibbs splx(s); 123239223Sgibbs } else { 123339223Sgibbs struct bus_dma_segment seg; 123439223Sgibbs 123539223Sgibbs /* Pointer to physical buffer */ 123639223Sgibbs seg.ds_addr = 123739223Sgibbs (bus_addr_t)csio->data_ptr; 123839223Sgibbs seg.ds_len = csio->dxfer_len; 123939223Sgibbs btexecuteccb(bccb, &seg, 1, 0); 124039223Sgibbs } 124139223Sgibbs } else { 124239223Sgibbs struct bus_dma_segment *segs; 124339223Sgibbs 124439223Sgibbs if ((ccbh->flags & CAM_DATA_PHYS) != 0) 124539223Sgibbs panic("btaction - Physical " 124639223Sgibbs "segment pointers " 124739223Sgibbs "unsupported"); 124839223Sgibbs 124939223Sgibbs if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) 125039223Sgibbs panic("btaction - Virtual " 125139223Sgibbs "segment addresses " 125239223Sgibbs "unsupported"); 125339223Sgibbs 125439223Sgibbs /* Just use the segments provided */ 125539223Sgibbs segs = (struct bus_dma_segment *) 125639223Sgibbs csio->data_ptr; 125739223Sgibbs btexecuteccb(bccb, segs, 125839223Sgibbs csio->sglist_cnt, 0); 125939223Sgibbs } 126039223Sgibbs } else { 126139223Sgibbs btexecuteccb(bccb, NULL, 0, 0); 126239223Sgibbs } 126339223Sgibbs } else { 126439223Sgibbs hccb->opcode = INITIATOR_BUS_DEV_RESET; 126539223Sgibbs /* No data transfer */ 126639223Sgibbs hccb->datain = TRUE; 126739223Sgibbs hccb->dataout = TRUE; 126839223Sgibbs hccb->cmd_len = 0; 126939223Sgibbs hccb->sense_len = 0; 127039223Sgibbs hccb->tag_enable = FALSE; 127139223Sgibbs hccb->tag_type = 0; 127239223Sgibbs btexecuteccb(bccb, NULL, 0, 0); 127339223Sgibbs } 127439223Sgibbs break; 127539223Sgibbs } 127639223Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 127739223Sgibbs case XPT_TARGET_IO: /* Execute target I/O request */ 127839223Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 127939223Sgibbs case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 128039223Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 128139223Sgibbs /* XXX Implement */ 128239223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 128339223Sgibbs xpt_done(ccb); 128439223Sgibbs break; 128539223Sgibbs case XPT_SET_TRAN_SETTINGS: 128639223Sgibbs { 128739223Sgibbs /* XXX Implement */ 128846581Sken ccb->ccb_h.status = CAM_PROVIDE_FAIL; 128939223Sgibbs xpt_done(ccb); 129039223Sgibbs break; 129139223Sgibbs } 129239223Sgibbs case XPT_GET_TRAN_SETTINGS: 129339223Sgibbs /* Get default/user set transfer settings for the target */ 129439223Sgibbs { 129539223Sgibbs struct ccb_trans_settings *cts; 129639223Sgibbs u_int target_mask; 129739223Sgibbs 129839223Sgibbs cts = &ccb->cts; 129939223Sgibbs target_mask = 0x01 << ccb->ccb_h.target_id; 130079175Smjacob#ifdef CAM_NEW_TRAN_CODE 130179175Smjacob if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 130279175Smjacob struct ccb_trans_settings_scsi *scsi = 130379175Smjacob &cts->proto_specific.scsi; 130479175Smjacob struct ccb_trans_settings_spi *spi = 130579175Smjacob &cts->xport_specific.spi; 130679175Smjacob cts->protocol = PROTO_SCSI; 130779175Smjacob cts->protocol_version = SCSI_REV_2; 130879175Smjacob cts->transport = XPORT_SPI; 130979175Smjacob cts->transport_version = 2; 131079175Smjacob 131179175Smjacob scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 131279175Smjacob spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 131379175Smjacob 131479175Smjacob if ((bt->disc_permitted & target_mask) != 0) 131579175Smjacob spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 131679175Smjacob if ((bt->tags_permitted & target_mask) != 0) 131779175Smjacob scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 131879175Smjacob 131979175Smjacob if ((bt->ultra_permitted & target_mask) != 0) 132079175Smjacob spi->sync_period = 12; 132179175Smjacob else if ((bt->fast_permitted & target_mask) != 0) 132279175Smjacob spi->sync_period = 25; 132379175Smjacob else if ((bt->sync_permitted & target_mask) != 0) 132479175Smjacob spi->sync_period = 50; 132579175Smjacob else 132679175Smjacob spi->sync_period = 0; 132779175Smjacob 132879175Smjacob if (spi->sync_period != 0) 132979175Smjacob spi->sync_offset = 15; 133079175Smjacob 133179175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_RATE; 133279175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 133379175Smjacob 133479175Smjacob spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 133579175Smjacob if ((bt->wide_permitted & target_mask) != 0) 133679175Smjacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 133779175Smjacob else 133879175Smjacob spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 133979175Smjacob 134079175Smjacob if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 134179175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 134279175Smjacob spi->valid |= CTS_SPI_VALID_DISC; 134379175Smjacob } else 134479175Smjacob scsi->valid = 0; 134579175Smjacob } else { 134679175Smjacob#else 134739223Sgibbs if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 134839223Sgibbs cts->flags = 0; 134939223Sgibbs if ((bt->disc_permitted & target_mask) != 0) 135039223Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 135139223Sgibbs if ((bt->tags_permitted & target_mask) != 0) 135239223Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 135339223Sgibbs if ((bt->wide_permitted & target_mask) != 0) 135439223Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 135539223Sgibbs else 135639223Sgibbs cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 135739223Sgibbs if ((bt->ultra_permitted & target_mask) != 0) 135839223Sgibbs cts->sync_period = 12; 135939223Sgibbs else if ((bt->fast_permitted & target_mask) != 0) 136039223Sgibbs cts->sync_period = 25; 136139223Sgibbs else if ((bt->sync_permitted & target_mask) != 0) 136239223Sgibbs cts->sync_period = 50; 136339223Sgibbs else 136439223Sgibbs cts->sync_period = 0; 136539223Sgibbs 136639223Sgibbs if (cts->sync_period != 0) 136739223Sgibbs cts->sync_offset = 15; 136839223Sgibbs 136939223Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 137039223Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 137139223Sgibbs | CCB_TRANS_BUS_WIDTH_VALID 137239223Sgibbs | CCB_TRANS_DISC_VALID 137339223Sgibbs | CCB_TRANS_TQ_VALID; 137439223Sgibbs } else { 137579175Smjacob#endif 137639223Sgibbs btfetchtransinfo(bt, cts); 137739223Sgibbs } 137839223Sgibbs 137939223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 138039223Sgibbs xpt_done(ccb); 138139223Sgibbs break; 138239223Sgibbs } 138339223Sgibbs case XPT_CALC_GEOMETRY: 138439223Sgibbs { 138539223Sgibbs struct ccb_calc_geometry *ccg; 138639223Sgibbs u_int32_t size_mb; 138739223Sgibbs u_int32_t secs_per_cylinder; 138839223Sgibbs 138939223Sgibbs ccg = &ccb->ccg; 139039223Sgibbs size_mb = ccg->volume_size 139139223Sgibbs / ((1024L * 1024L) / ccg->block_size); 139239223Sgibbs 139339223Sgibbs if (size_mb >= 1024 && (bt->extended_trans != 0)) { 139439223Sgibbs if (size_mb >= 2048) { 139539223Sgibbs ccg->heads = 255; 139639223Sgibbs ccg->secs_per_track = 63; 139739223Sgibbs } else { 139839223Sgibbs ccg->heads = 128; 139939223Sgibbs ccg->secs_per_track = 32; 140039223Sgibbs } 140139223Sgibbs } else { 140239223Sgibbs ccg->heads = 64; 140339223Sgibbs ccg->secs_per_track = 32; 140439223Sgibbs } 140539223Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 140639223Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 140739223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 140839223Sgibbs xpt_done(ccb); 140939223Sgibbs break; 141039223Sgibbs } 141139223Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 141239223Sgibbs { 141339223Sgibbs btreset(bt, /*hardreset*/TRUE); 141439223Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 141539223Sgibbs xpt_done(ccb); 141639223Sgibbs break; 141739223Sgibbs } 141839223Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 141939223Sgibbs /* XXX Implement */ 142039223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 142139223Sgibbs xpt_done(ccb); 142239223Sgibbs break; 142339223Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 142439223Sgibbs { 142539223Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 142639223Sgibbs 142739223Sgibbs cpi->version_num = 1; /* XXX??? */ 142839223Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE; 142939223Sgibbs if (bt->tag_capable != 0) 143039223Sgibbs cpi->hba_inquiry |= PI_TAG_ABLE; 143139223Sgibbs if (bt->wide_bus != 0) 143239223Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 143339223Sgibbs cpi->target_sprt = 0; 143439223Sgibbs cpi->hba_misc = 0; 143539223Sgibbs cpi->hba_eng_cnt = 0; 143639223Sgibbs cpi->max_target = bt->wide_bus ? 15 : 7; 143739223Sgibbs cpi->max_lun = 7; 143839223Sgibbs cpi->initiator_id = bt->scsi_id; 143939223Sgibbs cpi->bus_id = cam_sim_bus(sim); 144046581Sken cpi->base_transfer_speed = 3300; 144139223Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 144239223Sgibbs strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN); 144339223Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 144439223Sgibbs cpi->unit_number = cam_sim_unit(sim); 144539223Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 144679175Smjacob#ifdef CAM_NEW_TRAN_CODE 144779175Smjacob cpi->transport = XPORT_SPI; 144879175Smjacob cpi->transport_version = 2; 144979175Smjacob cpi->protocol = PROTO_SCSI; 145079175Smjacob cpi->protocol_version = SCSI_REV_2; 145179175Smjacob#endif 145239223Sgibbs xpt_done(ccb); 145339223Sgibbs break; 145439223Sgibbs } 145539223Sgibbs default: 145639223Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 145739223Sgibbs xpt_done(ccb); 145839223Sgibbs break; 145939223Sgibbs } 146039223Sgibbs} 146139223Sgibbs 146239223Sgibbsstatic void 146339223Sgibbsbtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 146439223Sgibbs{ 146539223Sgibbs struct bt_ccb *bccb; 146639223Sgibbs union ccb *ccb; 146739223Sgibbs struct bt_softc *bt; 146840419Sgibbs int s; 146939223Sgibbs 147039223Sgibbs bccb = (struct bt_ccb *)arg; 147139223Sgibbs ccb = bccb->ccb; 147239223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 147339223Sgibbs 147439223Sgibbs if (error != 0) { 147539223Sgibbs if (error != EFBIG) 147645791Speter device_printf(bt->dev, 147745791Speter "Unexepected error 0x%x returned from " 147845791Speter "bus_dmamap_load\n", error); 147939223Sgibbs if (ccb->ccb_h.status == CAM_REQ_INPROG) { 148039223Sgibbs xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 148139223Sgibbs ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 148239223Sgibbs } 148339223Sgibbs btfreeccb(bt, bccb); 148439223Sgibbs xpt_done(ccb); 148539223Sgibbs return; 148639223Sgibbs } 148739223Sgibbs 148839223Sgibbs if (nseg != 0) { 148939223Sgibbs bt_sg_t *sg; 149039223Sgibbs bus_dma_segment_t *end_seg; 1491115343Sscottl bus_dmasync_op_t op; 149239223Sgibbs 149339223Sgibbs end_seg = dm_segs + nseg; 149439223Sgibbs 149539223Sgibbs /* Copy the segments into our SG list */ 149639223Sgibbs sg = bccb->sg_list; 149739223Sgibbs while (dm_segs < end_seg) { 149839223Sgibbs sg->len = dm_segs->ds_len; 149939223Sgibbs sg->addr = dm_segs->ds_addr; 150039223Sgibbs sg++; 150139223Sgibbs dm_segs++; 150239223Sgibbs } 150339223Sgibbs 150439223Sgibbs if (nseg > 1) { 150539223Sgibbs bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID; 150639223Sgibbs bccb->hccb.data_len = sizeof(bt_sg_t) * nseg; 150739223Sgibbs bccb->hccb.data_addr = bccb->sg_list_phys; 150839223Sgibbs } else { 150939223Sgibbs bccb->hccb.data_len = bccb->sg_list->len; 151039223Sgibbs bccb->hccb.data_addr = bccb->sg_list->addr; 151139223Sgibbs } 151239223Sgibbs 151339223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 151439223Sgibbs op = BUS_DMASYNC_PREREAD; 151539223Sgibbs else 151639223Sgibbs op = BUS_DMASYNC_PREWRITE; 151739223Sgibbs 151839223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 151939223Sgibbs 152039223Sgibbs } else { 152141669Sgibbs bccb->hccb.opcode = INITIATOR_CCB; 152239223Sgibbs bccb->hccb.data_len = 0; 152339223Sgibbs bccb->hccb.data_addr = 0; 152439223Sgibbs } 152539223Sgibbs 152639223Sgibbs s = splcam(); 152739223Sgibbs 152839223Sgibbs /* 152939223Sgibbs * Last time we need to check if this CCB needs to 153039223Sgibbs * be aborted. 153139223Sgibbs */ 153239223Sgibbs if (ccb->ccb_h.status != CAM_REQ_INPROG) { 153339223Sgibbs if (nseg != 0) 153439223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 153539223Sgibbs btfreeccb(bt, bccb); 153639223Sgibbs xpt_done(ccb); 153739223Sgibbs splx(s); 153839223Sgibbs return; 153939223Sgibbs } 154039223Sgibbs 154139223Sgibbs bccb->flags = BCCB_ACTIVE; 154239223Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 154339223Sgibbs LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le); 154439223Sgibbs 154539223Sgibbs ccb->ccb_h.timeout_ch = 154639223Sgibbs timeout(bttimeout, (caddr_t)bccb, 154739223Sgibbs (ccb->ccb_h.timeout * hz) / 1000); 154839223Sgibbs 154939223Sgibbs /* Tell the adapter about this command */ 155039223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb); 155141048Sgibbs if (bt->cur_outbox->action_code != BMBO_FREE) { 155241048Sgibbs /* 155341048Sgibbs * We should never encounter a busy mailbox. 155441048Sgibbs * If we do, warn the user, and treat it as 155541048Sgibbs * a resource shortage. If the controller is 155641048Sgibbs * hung, one of the pending transactions will 155741048Sgibbs * timeout causing us to start recovery operations. 155841048Sgibbs */ 155945791Speter device_printf(bt->dev, 156045791Speter "Encountered busy mailbox with %d out of %d " 156145791Speter "commands active!!!\n", bt->active_ccbs, 156245791Speter bt->max_ccbs); 156341048Sgibbs untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch); 156441048Sgibbs if (nseg != 0) 156541048Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 156641048Sgibbs btfreeccb(bt, bccb); 156741048Sgibbs bt->resource_shortage = TRUE; 156841048Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 156941048Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 157041048Sgibbs xpt_done(ccb); 157141048Sgibbs return; 157241048Sgibbs } 157339223Sgibbs bt->cur_outbox->action_code = BMBO_START; 157439223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 157539223Sgibbs btnextoutbox(bt); 157639223Sgibbs splx(s); 157739223Sgibbs} 157839223Sgibbs 157939223Sgibbsvoid 158039223Sgibbsbt_intr(void *arg) 158139223Sgibbs{ 158239223Sgibbs struct bt_softc *bt; 158339223Sgibbs u_int intstat; 158439223Sgibbs 158539223Sgibbs bt = (struct bt_softc *)arg; 158639223Sgibbs while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) { 158739223Sgibbs 158839223Sgibbs if ((intstat & CMD_COMPLETE) != 0) { 158939223Sgibbs bt->latched_status = bt_inb(bt, STATUS_REG); 159039223Sgibbs bt->command_cmp = TRUE; 159139223Sgibbs } 159239223Sgibbs 159339223Sgibbs bt_outb(bt, CONTROL_REG, RESET_INTR); 159439223Sgibbs 159539223Sgibbs if ((intstat & IMB_LOADED) != 0) { 159639223Sgibbs while (bt->cur_inbox->comp_code != BMBI_FREE) { 159739223Sgibbs btdone(bt, 159839223Sgibbs btccbptov(bt, bt->cur_inbox->ccb_addr), 159939223Sgibbs bt->cur_inbox->comp_code); 160039223Sgibbs bt->cur_inbox->comp_code = BMBI_FREE; 160139223Sgibbs btnextinbox(bt); 160239223Sgibbs } 160339223Sgibbs } 160439223Sgibbs 160539223Sgibbs if ((intstat & SCSI_BUS_RESET) != 0) { 160639223Sgibbs btreset(bt, /*hardreset*/FALSE); 160739223Sgibbs } 160839223Sgibbs } 160939223Sgibbs} 161039223Sgibbs 161139223Sgibbsstatic void 161239223Sgibbsbtdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) 161339223Sgibbs{ 161439223Sgibbs union ccb *ccb; 161539223Sgibbs struct ccb_scsiio *csio; 161639223Sgibbs 161739223Sgibbs ccb = bccb->ccb; 161839223Sgibbs csio = &bccb->ccb->csio; 161939223Sgibbs 162039223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 162145791Speter device_printf(bt->dev, 162245791Speter "btdone - Attempt to free non-active BCCB %p\n", 162345791Speter (void *)bccb); 162439223Sgibbs return; 162539223Sgibbs } 162639223Sgibbs 162739223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1628115343Sscottl bus_dmasync_op_t op; 162939223Sgibbs 163039223Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 163139223Sgibbs op = BUS_DMASYNC_POSTREAD; 163239223Sgibbs else 163339223Sgibbs op = BUS_DMASYNC_POSTWRITE; 163439223Sgibbs bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op); 163539223Sgibbs bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); 163639223Sgibbs } 163739223Sgibbs 163839223Sgibbs if (bccb == bt->recovery_bccb) { 163939223Sgibbs /* 164039223Sgibbs * The recovery BCCB does not have a CCB associated 164139223Sgibbs * with it, so short circuit the normal error handling. 164239223Sgibbs * We now traverse our list of pending CCBs and process 164339223Sgibbs * any that were terminated by the recovery CCBs action. 164439223Sgibbs * We also reinstate timeouts for all remaining, pending, 164539223Sgibbs * CCBs. 164639223Sgibbs */ 164739223Sgibbs struct cam_path *path; 164839223Sgibbs struct ccb_hdr *ccb_h; 164939223Sgibbs cam_status error; 165039223Sgibbs 165139223Sgibbs /* Notify all clients that a BDR occured */ 165239223Sgibbs error = xpt_create_path(&path, /*periph*/NULL, 165339223Sgibbs cam_sim_path(bt->sim), 165439223Sgibbs bccb->hccb.target_id, 165539223Sgibbs CAM_LUN_WILDCARD); 165639223Sgibbs 165739223Sgibbs if (error == CAM_REQ_CMP) 165839223Sgibbs xpt_async(AC_SENT_BDR, path, NULL); 165939223Sgibbs 166039223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 166139223Sgibbs while (ccb_h != NULL) { 166239223Sgibbs struct bt_ccb *pending_bccb; 166339223Sgibbs 166439223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 166539223Sgibbs if (pending_bccb->hccb.target_id 166639223Sgibbs == bccb->hccb.target_id) { 166739223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_BDR; 166839223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 166939223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 167039223Sgibbs } else { 167139223Sgibbs ccb_h->timeout_ch = 167239223Sgibbs timeout(bttimeout, (caddr_t)pending_bccb, 167339223Sgibbs (ccb_h->timeout * hz) / 1000); 167439223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 167539223Sgibbs } 167639223Sgibbs } 167745791Speter device_printf(bt->dev, "No longer in timeout\n"); 167839223Sgibbs return; 167939223Sgibbs } 168039223Sgibbs 168139223Sgibbs untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch); 168239223Sgibbs 168339223Sgibbs switch (comp_code) { 168439223Sgibbs case BMBI_FREE: 168545791Speter device_printf(bt->dev, 168645791Speter "btdone - CCB completed with free status!\n"); 168739223Sgibbs break; 168839223Sgibbs case BMBI_NOT_FOUND: 168945791Speter device_printf(bt->dev, 169045791Speter "btdone - CCB Abort failed to find CCB\n"); 169139223Sgibbs break; 169239223Sgibbs case BMBI_ABORT: 169339223Sgibbs case BMBI_ERROR: 169441133Sgibbs if (bootverbose) { 169541133Sgibbs printf("bt: ccb %p - error %x occured. " 169641133Sgibbs "btstat = %x, sdstat = %x\n", 169741133Sgibbs (void *)bccb, comp_code, bccb->hccb.btstat, 169841133Sgibbs bccb->hccb.sdstat); 169941133Sgibbs } 170039223Sgibbs /* An error occured */ 170139223Sgibbs switch(bccb->hccb.btstat) { 170239223Sgibbs case BTSTAT_DATARUN_ERROR: 170341048Sgibbs if (bccb->hccb.data_len == 0) { 170441048Sgibbs /* 170541048Sgibbs * At least firmware 4.22, does this 170641048Sgibbs * for a QUEUE FULL condition. 170741048Sgibbs */ 170841048Sgibbs bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL; 170941048Sgibbs } else if (bccb->hccb.data_len < 0) { 171039223Sgibbs csio->ccb_h.status = CAM_DATA_RUN_ERR; 171139223Sgibbs break; 171239223Sgibbs } 171339223Sgibbs /* FALLTHROUGH */ 171439223Sgibbs case BTSTAT_NOERROR: 171539223Sgibbs case BTSTAT_LINKED_CMD_COMPLETE: 171639223Sgibbs case BTSTAT_LINKED_CMD_FLAG_COMPLETE: 171739223Sgibbs case BTSTAT_DATAUNDERUN_ERROR: 171839223Sgibbs 171939223Sgibbs csio->scsi_status = bccb->hccb.sdstat; 172039223Sgibbs csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 172139223Sgibbs switch(csio->scsi_status) { 172239223Sgibbs case SCSI_STATUS_CHECK_COND: 172339223Sgibbs case SCSI_STATUS_CMD_TERMINATED: 172439223Sgibbs csio->ccb_h.status |= CAM_AUTOSNS_VALID; 172539223Sgibbs /* Bounce sense back if necessary */ 172639223Sgibbs if (bt->sense_buffers != NULL) { 172739223Sgibbs csio->sense_data = 172839223Sgibbs *btsensevaddr(bt, bccb); 172939223Sgibbs } 173039223Sgibbs break; 173139223Sgibbs default: 173239223Sgibbs break; 173339223Sgibbs case SCSI_STATUS_OK: 173439223Sgibbs csio->ccb_h.status = CAM_REQ_CMP; 173539223Sgibbs break; 173639223Sgibbs } 173739223Sgibbs csio->resid = bccb->hccb.data_len; 173839223Sgibbs break; 173939223Sgibbs case BTSTAT_SELTIMEOUT: 174039223Sgibbs csio->ccb_h.status = CAM_SEL_TIMEOUT; 174139223Sgibbs break; 174239223Sgibbs case BTSTAT_UNEXPECTED_BUSFREE: 174339223Sgibbs csio->ccb_h.status = CAM_UNEXP_BUSFREE; 174439223Sgibbs break; 174539223Sgibbs case BTSTAT_INVALID_PHASE: 174639223Sgibbs csio->ccb_h.status = CAM_SEQUENCE_FAIL; 174739223Sgibbs break; 174839223Sgibbs case BTSTAT_INVALID_ACTION_CODE: 174939223Sgibbs panic("%s: Inavlid Action code", bt_name(bt)); 175039223Sgibbs break; 175139223Sgibbs case BTSTAT_INVALID_OPCODE: 175239223Sgibbs panic("%s: Inavlid CCB Opcode code", bt_name(bt)); 175339223Sgibbs break; 175439223Sgibbs case BTSTAT_LINKED_CCB_LUN_MISMATCH: 175539223Sgibbs /* We don't even support linked commands... */ 175639223Sgibbs panic("%s: Linked CCB Lun Mismatch", bt_name(bt)); 175739223Sgibbs break; 175839223Sgibbs case BTSTAT_INVALID_CCB_OR_SG_PARAM: 175939223Sgibbs panic("%s: Invalid CCB or SG list", bt_name(bt)); 176039223Sgibbs break; 176139223Sgibbs case BTSTAT_AUTOSENSE_FAILED: 176239223Sgibbs csio->ccb_h.status = CAM_AUTOSENSE_FAIL; 176339223Sgibbs break; 176439223Sgibbs case BTSTAT_TAGGED_MSG_REJECTED: 176539223Sgibbs { 176639223Sgibbs struct ccb_trans_settings neg; 176779175Smjacob#ifdef CAM_NEW_TRAN_CODE 176879175Smjacob struct ccb_trans_settings_scsi *scsi = 176979175Smjacob &neg.proto_specific.scsi; 177079175Smjacob 177179175Smjacob neg.protocol = PROTO_SCSI; 177279175Smjacob neg.protocol_version = SCSI_REV_2; 177379175Smjacob neg.transport = XPORT_SPI; 177479175Smjacob neg.transport_version = 2; 177579175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 177679175Smjacob scsi->flags = 0; 177779175Smjacob#else 177879175Smjacob 177979175Smjacob neg.flags = 0; 178079175Smjacob neg.valid = CCB_TRANS_TQ_VALID; 178179175Smjacob#endif 178239223Sgibbs xpt_print_path(csio->ccb_h.path); 178339223Sgibbs printf("refuses tagged commands. Performing " 178439223Sgibbs "non-tagged I/O\n"); 178539223Sgibbs xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path, 178639223Sgibbs /*priority*/1); 178739223Sgibbs xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg); 178839223Sgibbs bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id); 178939223Sgibbs csio->ccb_h.status = CAM_MSG_REJECT_REC; 179039223Sgibbs break; 179139223Sgibbs } 179239223Sgibbs case BTSTAT_UNSUPPORTED_MSG_RECEIVED: 179339223Sgibbs /* 179439223Sgibbs * XXX You would think that this is 179539223Sgibbs * a recoverable error... Hmmm. 179639223Sgibbs */ 179739223Sgibbs csio->ccb_h.status = CAM_REQ_CMP_ERR; 179839223Sgibbs break; 179939223Sgibbs case BTSTAT_HA_SOFTWARE_ERROR: 180039223Sgibbs case BTSTAT_HA_WATCHDOG_ERROR: 180139223Sgibbs case BTSTAT_HARDWARE_FAILURE: 180239223Sgibbs /* Hardware reset ??? Can we recover ??? */ 180339223Sgibbs csio->ccb_h.status = CAM_NO_HBA; 180439223Sgibbs break; 180539223Sgibbs case BTSTAT_TARGET_IGNORED_ATN: 180639223Sgibbs case BTSTAT_OTHER_SCSI_BUS_RESET: 180739223Sgibbs case BTSTAT_HA_SCSI_BUS_RESET: 180839223Sgibbs if ((csio->ccb_h.status & CAM_STATUS_MASK) 180939223Sgibbs != CAM_CMD_TIMEOUT) 181039223Sgibbs csio->ccb_h.status = CAM_SCSI_BUS_RESET; 181139223Sgibbs break; 181239223Sgibbs case BTSTAT_HA_BDR: 181339223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) 181439223Sgibbs csio->ccb_h.status = CAM_BDR_SENT; 181539223Sgibbs else 181639223Sgibbs csio->ccb_h.status = CAM_CMD_TIMEOUT; 181739223Sgibbs break; 181839223Sgibbs case BTSTAT_INVALID_RECONNECT: 181939223Sgibbs case BTSTAT_ABORT_QUEUE_GENERATED: 182039223Sgibbs csio->ccb_h.status = CAM_REQ_TERMIO; 182139223Sgibbs break; 182239223Sgibbs case BTSTAT_SCSI_PERROR_DETECTED: 182339223Sgibbs csio->ccb_h.status = CAM_UNCOR_PARITY; 182439223Sgibbs break; 182539223Sgibbs } 182639223Sgibbs if (csio->ccb_h.status != CAM_REQ_CMP) { 182739223Sgibbs xpt_freeze_devq(csio->ccb_h.path, /*count*/1); 182839223Sgibbs csio->ccb_h.status |= CAM_DEV_QFRZN; 182939223Sgibbs } 183039223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 183139223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 183239223Sgibbs btfreeccb(bt, bccb); 183339223Sgibbs xpt_done(ccb); 183439223Sgibbs break; 183539223Sgibbs case BMBI_OK: 183639223Sgibbs /* All completed without incident */ 183739223Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 183839223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 183939223Sgibbs ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 184039223Sgibbs btfreeccb(bt, bccb); 184139223Sgibbs xpt_done(ccb); 184239223Sgibbs break; 184339223Sgibbs } 184439223Sgibbs} 184539223Sgibbs 184639223Sgibbsstatic int 184739223Sgibbsbtreset(struct bt_softc* bt, int hard_reset) 184839223Sgibbs{ 184939223Sgibbs struct ccb_hdr *ccb_h; 185039223Sgibbs u_int status; 185139223Sgibbs u_int timeout; 185239223Sgibbs u_int8_t reset_type; 185339223Sgibbs 185439223Sgibbs if (hard_reset != 0) 185539223Sgibbs reset_type = HARD_RESET; 185639223Sgibbs else 185739223Sgibbs reset_type = SOFT_RESET; 185839223Sgibbs bt_outb(bt, CONTROL_REG, reset_type); 185939223Sgibbs 186039223Sgibbs /* Wait 5sec. for Diagnostic start */ 186139223Sgibbs timeout = 5 * 10000; 186239223Sgibbs while (--timeout) { 186339223Sgibbs status = bt_inb(bt, STATUS_REG); 186439223Sgibbs if ((status & DIAG_ACTIVE) != 0) 186539223Sgibbs break; 186639223Sgibbs DELAY(100); 186739223Sgibbs } 186839223Sgibbs if (timeout == 0) { 186939223Sgibbs if (bootverbose) 187039223Sgibbs printf("%s: btreset - Diagnostic Active failed to " 187139223Sgibbs "assert. status = 0x%x\n", bt_name(bt), status); 187239223Sgibbs return (ETIMEDOUT); 187339223Sgibbs } 187439223Sgibbs 187539223Sgibbs /* Wait 10sec. for Diagnostic end */ 187639223Sgibbs timeout = 10 * 10000; 187739223Sgibbs while (--timeout) { 187839223Sgibbs status = bt_inb(bt, STATUS_REG); 187939223Sgibbs if ((status & DIAG_ACTIVE) == 0) 188039223Sgibbs break; 188139223Sgibbs DELAY(100); 188239223Sgibbs } 188339223Sgibbs if (timeout == 0) { 188439223Sgibbs panic("%s: btreset - Diagnostic Active failed to drop. " 188539223Sgibbs "status = 0x%x\n", bt_name(bt), status); 188639223Sgibbs return (ETIMEDOUT); 188739223Sgibbs } 188839223Sgibbs 188939223Sgibbs /* Wait for the host adapter to become ready or report a failure */ 189039223Sgibbs timeout = 10000; 189139223Sgibbs while (--timeout) { 189239223Sgibbs status = bt_inb(bt, STATUS_REG); 189339223Sgibbs if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0) 189439223Sgibbs break; 189539223Sgibbs DELAY(100); 189639223Sgibbs } 189739223Sgibbs if (timeout == 0) { 189839223Sgibbs printf("%s: btreset - Host adapter failed to come ready. " 189939223Sgibbs "status = 0x%x\n", bt_name(bt), status); 190039223Sgibbs return (ETIMEDOUT); 190139223Sgibbs } 190239223Sgibbs 190339223Sgibbs /* If the diagnostics failed, tell the user */ 190439223Sgibbs if ((status & DIAG_FAIL) != 0 190539223Sgibbs || (status & HA_READY) == 0) { 190639223Sgibbs printf("%s: btreset - Adapter failed diagnostics\n", 190739223Sgibbs bt_name(bt)); 190839223Sgibbs 190939223Sgibbs if ((status & DATAIN_REG_READY) != 0) 191039223Sgibbs printf("%s: btreset - Host Adapter Error code = 0x%x\n", 191139324Sgibbs bt_name(bt), bt_inb(bt, DATAIN_REG)); 191239223Sgibbs return (ENXIO); 191339223Sgibbs } 191439223Sgibbs 191539223Sgibbs /* If we've allocated mailboxes, initialize them */ 191639223Sgibbs if (bt->init_level > 4) 191739223Sgibbs btinitmboxes(bt); 191839223Sgibbs 191939223Sgibbs /* If we've attached to the XPT, tell it about the event */ 192039223Sgibbs if (bt->path != NULL) 192139223Sgibbs xpt_async(AC_BUS_RESET, bt->path, NULL); 192239223Sgibbs 192339223Sgibbs /* 192439223Sgibbs * Perform completion processing for all outstanding CCBs. 192539223Sgibbs */ 192639223Sgibbs while ((ccb_h = LIST_FIRST(&bt->pending_ccbs)) != NULL) { 192739223Sgibbs struct bt_ccb *pending_bccb; 192839223Sgibbs 192939223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 193039223Sgibbs pending_bccb->hccb.btstat = BTSTAT_HA_SCSI_BUS_RESET; 193139223Sgibbs btdone(bt, pending_bccb, BMBI_ERROR); 193239223Sgibbs } 193339223Sgibbs 193439223Sgibbs return (0); 193539223Sgibbs} 193639223Sgibbs 193739223Sgibbs/* 193839223Sgibbs * Send a command to the adapter. 193939223Sgibbs */ 194039223Sgibbsint 194139223Sgibbsbt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, 194239223Sgibbs u_int8_t *reply_data, u_int reply_len, u_int cmd_timeout) 194339223Sgibbs{ 194439223Sgibbs u_int timeout; 194539223Sgibbs u_int status; 194645444Sgibbs u_int saved_status; 194739223Sgibbs u_int intstat; 194839223Sgibbs u_int reply_buf_size; 194939223Sgibbs int s; 195041669Sgibbs int cmd_complete; 195145444Sgibbs int error; 195239223Sgibbs 195339223Sgibbs /* No data returned to start */ 195439223Sgibbs reply_buf_size = reply_len; 195539223Sgibbs reply_len = 0; 195639223Sgibbs intstat = 0; 195741669Sgibbs cmd_complete = 0; 195845444Sgibbs saved_status = 0; 195945444Sgibbs error = 0; 196039223Sgibbs 196139223Sgibbs bt->command_cmp = 0; 196239223Sgibbs /* 196345444Sgibbs * Wait up to 10 sec. for the adapter to become 196439223Sgibbs * ready to accept commands. 196539223Sgibbs */ 196645444Sgibbs timeout = 100000; 196739223Sgibbs while (--timeout) { 196839223Sgibbs status = bt_inb(bt, STATUS_REG); 196939223Sgibbs if ((status & HA_READY) != 0 197039223Sgibbs && (status & CMD_REG_BUSY) == 0) 197139223Sgibbs break; 197245444Sgibbs /* 197345444Sgibbs * Throw away any pending data which may be 197445444Sgibbs * left over from earlier commands that we 197545444Sgibbs * timedout on. 197645444Sgibbs */ 197745444Sgibbs if ((status & DATAIN_REG_READY) != 0) 197845444Sgibbs (void)bt_inb(bt, DATAIN_REG); 197939223Sgibbs DELAY(100); 198039223Sgibbs } 198139223Sgibbs if (timeout == 0) { 198239223Sgibbs printf("%s: bt_cmd: Timeout waiting for adapter ready, " 198339223Sgibbs "status = 0x%x\n", bt_name(bt), status); 198439223Sgibbs return (ETIMEDOUT); 198539223Sgibbs } 198639223Sgibbs 198739223Sgibbs /* 198839223Sgibbs * Send the opcode followed by any necessary parameter bytes. 198939223Sgibbs */ 199039223Sgibbs bt_outb(bt, COMMAND_REG, opcode); 199139223Sgibbs 199239223Sgibbs /* 199345444Sgibbs * Wait for up to 1sec for each byte of the the 199445444Sgibbs * parameter list sent to be sent. 199539223Sgibbs */ 199639223Sgibbs timeout = 10000; 199739223Sgibbs while (param_len && --timeout) { 199839223Sgibbs DELAY(100); 199945444Sgibbs s = splcam(); 200039223Sgibbs status = bt_inb(bt, STATUS_REG); 200139223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 200245444Sgibbs splx(s); 200347432Sgibbs 200439223Sgibbs if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 200541669Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 200645444Sgibbs saved_status = status; 200741669Sgibbs cmd_complete = 1; 200839223Sgibbs break; 200941669Sgibbs } 201039223Sgibbs if (bt->command_cmp != 0) { 201145444Sgibbs saved_status = bt->latched_status; 201241669Sgibbs cmd_complete = 1; 201339223Sgibbs break; 201439223Sgibbs } 201539223Sgibbs if ((status & DATAIN_REG_READY) != 0) 201639223Sgibbs break; 201739223Sgibbs if ((status & CMD_REG_BUSY) == 0) { 201839223Sgibbs bt_outb(bt, COMMAND_REG, *params++); 201939223Sgibbs param_len--; 202045444Sgibbs timeout = 10000; 202139223Sgibbs } 202239223Sgibbs } 202339223Sgibbs if (timeout == 0) { 202439223Sgibbs printf("%s: bt_cmd: Timeout sending parameters, " 202539223Sgibbs "status = 0x%x\n", bt_name(bt), status); 202645444Sgibbs cmd_complete = 1; 202745444Sgibbs saved_status = status; 202845444Sgibbs error = ETIMEDOUT; 202939223Sgibbs } 203039223Sgibbs 203139223Sgibbs /* 203245444Sgibbs * Wait for the command to complete. 203339223Sgibbs */ 203441669Sgibbs while (cmd_complete == 0 && --cmd_timeout) { 203539223Sgibbs 203645444Sgibbs s = splcam(); 203739223Sgibbs status = bt_inb(bt, STATUS_REG); 203839223Sgibbs intstat = bt_inb(bt, INTSTAT_REG); 203947432Sgibbs /* 204047432Sgibbs * It may be that this command was issued with 204147432Sgibbs * controller interrupts disabled. We'll never 204247432Sgibbs * get to our command if an incoming mailbox 204347432Sgibbs * interrupt is pending, so take care of completed 204447432Sgibbs * mailbox commands by calling our interrupt handler. 204547432Sgibbs */ 204647432Sgibbs if ((intstat & (INTR_PENDING|IMB_LOADED)) 204747432Sgibbs == (INTR_PENDING|IMB_LOADED)) 204847432Sgibbs bt_intr(bt); 204945444Sgibbs splx(s); 205039223Sgibbs 205139223Sgibbs if (bt->command_cmp != 0) { 205245444Sgibbs /* 205345444Sgibbs * Our interrupt handler saw CMD_COMPLETE 205445444Sgibbs * status before we did. 205545444Sgibbs */ 205645444Sgibbs cmd_complete = 1; 205745444Sgibbs saved_status = bt->latched_status; 205845444Sgibbs } else if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 205945444Sgibbs == (INTR_PENDING|CMD_COMPLETE)) { 206045444Sgibbs /* 206145444Sgibbs * Our poll (in case interrupts are blocked) 206245444Sgibbs * saw the CMD_COMPLETE interrupt. 206345444Sgibbs */ 206445444Sgibbs cmd_complete = 1; 206545444Sgibbs saved_status = status; 206645444Sgibbs } else if (opcode == BOP_MODIFY_IO_ADDR 206745444Sgibbs && (status & CMD_REG_BUSY) == 0) { 206845444Sgibbs /* 206945444Sgibbs * The BOP_MODIFY_IO_ADDR does not issue a CMD_COMPLETE, 207045444Sgibbs * but it should update the status register. So, we 207145444Sgibbs * consider this command complete when the CMD_REG_BUSY 207245444Sgibbs * status clears. 207345444Sgibbs */ 207445444Sgibbs saved_status = status; 207545444Sgibbs cmd_complete = 1; 207645444Sgibbs } else if ((status & DATAIN_REG_READY) != 0) { 207739223Sgibbs u_int8_t data; 207839223Sgibbs 207939223Sgibbs data = bt_inb(bt, DATAIN_REG); 208039223Sgibbs if (reply_len < reply_buf_size) { 208139223Sgibbs *reply_data++ = data; 208239223Sgibbs } else { 208339223Sgibbs printf("%s: bt_cmd - Discarded reply data byte " 208439223Sgibbs "for opcode 0x%x\n", bt_name(bt), 208539223Sgibbs opcode); 208639223Sgibbs } 208745444Sgibbs /* 208845444Sgibbs * Reset timeout to ensure at least a second 208945444Sgibbs * between response bytes. 209045444Sgibbs */ 209145444Sgibbs cmd_timeout = MAX(cmd_timeout, 10000); 209239223Sgibbs reply_len++; 209345444Sgibbs 209445444Sgibbs } else if ((opcode == BOP_FETCH_LRAM) 209545444Sgibbs && (status & HA_READY) != 0) { 209645444Sgibbs saved_status = status; 209745444Sgibbs cmd_complete = 1; 209839223Sgibbs } 209939223Sgibbs DELAY(100); 210039223Sgibbs } 210145444Sgibbs if (cmd_timeout == 0) { 210245444Sgibbs printf("%s: bt_cmd: Timeout waiting for command (%x) " 210345444Sgibbs "to complete.\n%s: status = 0x%x, intstat = 0x%x, " 210447432Sgibbs "rlen %d\n", bt_name(bt), opcode, 210547432Sgibbs bt_name(bt), status, intstat, reply_len); 210645444Sgibbs error = (ETIMEDOUT); 210739223Sgibbs } 210839223Sgibbs 210939223Sgibbs /* 211039223Sgibbs * Clear any pending interrupts. Block interrupts so our 211139223Sgibbs * interrupt handler is not re-entered. 211239223Sgibbs */ 211339223Sgibbs s = splcam(); 211439223Sgibbs bt_intr(bt); 211539223Sgibbs splx(s); 211639223Sgibbs 211745444Sgibbs if (error != 0) 211845444Sgibbs return (error); 211945444Sgibbs 212039223Sgibbs /* 212139223Sgibbs * If the command was rejected by the controller, tell the caller. 212239223Sgibbs */ 212345444Sgibbs if ((saved_status & CMD_INVALID) != 0) { 212439223Sgibbs /* 212539223Sgibbs * Some early adapters may not recover properly from 212639223Sgibbs * an invalid command. If it appears that the controller 212739223Sgibbs * has wedged (i.e. status was not cleared by our interrupt 212839223Sgibbs * reset above), perform a soft reset. 212939223Sgibbs */ 213039223Sgibbs if (bootverbose) 213139223Sgibbs printf("%s: Invalid Command 0x%x\n", bt_name(bt), 213239223Sgibbs opcode); 213339223Sgibbs DELAY(1000); 213439223Sgibbs status = bt_inb(bt, STATUS_REG); 213539223Sgibbs if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY| 213639223Sgibbs CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0 213739223Sgibbs || (status & (HA_READY|INIT_REQUIRED)) 213839223Sgibbs != (HA_READY|INIT_REQUIRED)) { 213939223Sgibbs btreset(bt, /*hard_reset*/FALSE); 214039223Sgibbs } 214139223Sgibbs return (EINVAL); 214239223Sgibbs } 214339223Sgibbs 214439223Sgibbs if (param_len > 0) { 214539223Sgibbs /* The controller did not accept the full argument list */ 214639223Sgibbs return (E2BIG); 214739223Sgibbs } 214839223Sgibbs 214939223Sgibbs if (reply_len != reply_buf_size) { 215039223Sgibbs /* Too much or too little data received */ 215139223Sgibbs return (EMSGSIZE); 215239223Sgibbs } 215339223Sgibbs 215439223Sgibbs /* We were successful */ 215539223Sgibbs return (0); 215639223Sgibbs} 215739223Sgibbs 215839223Sgibbsstatic int 215939223Sgibbsbtinitmboxes(struct bt_softc *bt) { 216039223Sgibbs init_32b_mbox_params_t init_mbox; 216139223Sgibbs int error; 216239223Sgibbs 216339223Sgibbs bzero(bt->in_boxes, sizeof(bt_mbox_in_t) * bt->num_boxes); 216439223Sgibbs bzero(bt->out_boxes, sizeof(bt_mbox_out_t) * bt->num_boxes); 216539223Sgibbs bt->cur_inbox = bt->in_boxes; 216639223Sgibbs bt->last_inbox = bt->in_boxes + bt->num_boxes - 1; 216739223Sgibbs bt->cur_outbox = bt->out_boxes; 216839223Sgibbs bt->last_outbox = bt->out_boxes + bt->num_boxes - 1; 216939223Sgibbs 217039223Sgibbs /* Tell the adapter about them */ 217139223Sgibbs init_mbox.num_boxes = bt->num_boxes; 217239223Sgibbs init_mbox.base_addr[0] = bt->mailbox_physbase & 0xFF; 217339223Sgibbs init_mbox.base_addr[1] = (bt->mailbox_physbase >> 8) & 0xFF; 217439223Sgibbs init_mbox.base_addr[2] = (bt->mailbox_physbase >> 16) & 0xFF; 217539223Sgibbs init_mbox.base_addr[3] = (bt->mailbox_physbase >> 24) & 0xFF; 217639223Sgibbs error = bt_cmd(bt, BOP_INITIALIZE_32BMBOX, (u_int8_t *)&init_mbox, 217739223Sgibbs /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL, 217839223Sgibbs /*reply_len*/0, DEFAULT_CMD_TIMEOUT); 217939223Sgibbs 218039223Sgibbs if (error != 0) 218139223Sgibbs printf("btinitmboxes: Initialization command failed\n"); 218239223Sgibbs else if (bt->strict_rr != 0) { 218339223Sgibbs /* 218439223Sgibbs * If the controller supports 218539223Sgibbs * strict round robin mode, 218639223Sgibbs * enable it 218739223Sgibbs */ 218839223Sgibbs u_int8_t param; 218939223Sgibbs 219039223Sgibbs param = 0; 219139223Sgibbs error = bt_cmd(bt, BOP_ENABLE_STRICT_RR, ¶m, 1, 219239223Sgibbs /*reply_buf*/NULL, /*reply_len*/0, 219339223Sgibbs DEFAULT_CMD_TIMEOUT); 219439223Sgibbs 219539223Sgibbs if (error != 0) { 219639223Sgibbs printf("btinitmboxes: Unable to enable strict RR\n"); 219739223Sgibbs error = 0; 219839223Sgibbs } else if (bootverbose) { 219939223Sgibbs printf("%s: Using Strict Round Robin Mailbox Mode\n", 220039223Sgibbs bt_name(bt)); 220139223Sgibbs } 220239223Sgibbs } 220339223Sgibbs 220439223Sgibbs return (error); 220539223Sgibbs} 220639223Sgibbs 220739223Sgibbs/* 220839223Sgibbs * Update the XPT's idea of the negotiated transfer 220939223Sgibbs * parameters for a particular target. 221039223Sgibbs */ 221139223Sgibbsstatic void 221279175Smjacobbtfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts) 221339223Sgibbs{ 221439223Sgibbs setup_data_t setup_info; 221539223Sgibbs u_int target; 221639223Sgibbs u_int targ_offset; 221739223Sgibbs u_int targ_mask; 221839223Sgibbs u_int sync_period; 221979175Smjacob u_int sync_offset; 222079175Smjacob u_int bus_width; 222139223Sgibbs int error; 222239223Sgibbs u_int8_t param; 222339223Sgibbs targ_syncinfo_t sync_info; 222479175Smjacob#ifdef CAM_NEW_TRAN_CODE 222579175Smjacob struct ccb_trans_settings_scsi *scsi = 222679175Smjacob &cts->proto_specific.scsi; 222779175Smjacob struct ccb_trans_settings_spi *spi = 222879175Smjacob &cts->xport_specific.spi; 222939223Sgibbs 223079175Smjacob spi->valid = 0; 223179175Smjacob scsi->valid = 0; 223279175Smjacob#else 223379175Smjacob 223479175Smjacob cts->valid = 0; 223579175Smjacob#endif 223679175Smjacob 223739223Sgibbs target = cts->ccb_h.target_id; 223839223Sgibbs targ_offset = (target & 0x7); 223939223Sgibbs targ_mask = (0x01 << targ_offset); 224039223Sgibbs 224139223Sgibbs /* 224239223Sgibbs * Inquire Setup Information. This command retreives the 224339223Sgibbs * Wide negotiation status for recent adapters as well as 224439223Sgibbs * the sync info for older models. 224539223Sgibbs */ 224639223Sgibbs param = sizeof(setup_info); 224739223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, ¶m, /*paramlen*/1, 224839223Sgibbs (u_int8_t*)&setup_info, sizeof(setup_info), 224939223Sgibbs DEFAULT_CMD_TIMEOUT); 225039223Sgibbs 225139223Sgibbs if (error != 0) { 225245444Sgibbs printf("%s: btfetchtransinfo - Inquire Setup Info Failed %x\n", 225345444Sgibbs bt_name(bt), error); 225439223Sgibbs return; 225539223Sgibbs } 225639223Sgibbs 225739223Sgibbs sync_info = (target < 8) ? setup_info.low_syncinfo[targ_offset] 225839223Sgibbs : setup_info.high_syncinfo[targ_offset]; 225939223Sgibbs 226039223Sgibbs if (sync_info.sync == 0) 226179175Smjacob sync_offset = 0; 226239223Sgibbs else 226379175Smjacob sync_offset = sync_info.offset; 226439223Sgibbs 226579175Smjacob 226679175Smjacob bus_width = MSG_EXT_WDTR_BUS_8_BIT; 226739223Sgibbs if (strcmp(bt->firmware_ver, "5.06L") >= 0) { 226839223Sgibbs u_int wide_active; 226939223Sgibbs 227039223Sgibbs wide_active = 227139223Sgibbs (target < 8) ? (setup_info.low_wide_active & targ_mask) 227239223Sgibbs : (setup_info.high_wide_active & targ_mask); 227339223Sgibbs 227439223Sgibbs if (wide_active) 227579175Smjacob bus_width = MSG_EXT_WDTR_BUS_16_BIT; 227639507Sgibbs } else if ((bt->wide_permitted & targ_mask) != 0) { 227739507Sgibbs struct ccb_getdev cgd; 227839507Sgibbs 227939507Sgibbs /* 228039507Sgibbs * Prior to rev 5.06L, wide status isn't provided, 228139507Sgibbs * so we "guess" that wide transfers are in effect 228239507Sgibbs * if the user settings allow for wide and the inquiry 228339507Sgibbs * data for the device indicates that it can handle 228439507Sgibbs * wide transfers. 228539507Sgibbs */ 228639507Sgibbs xpt_setup_ccb(&cgd.ccb_h, cts->ccb_h.path, /*priority*/1); 228739507Sgibbs cgd.ccb_h.func_code = XPT_GDEV_TYPE; 228839507Sgibbs xpt_action((union ccb *)&cgd); 228939507Sgibbs if ((cgd.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP 229039507Sgibbs && (cgd.inq_data.flags & SID_WBus16) != 0) 229179175Smjacob bus_width = MSG_EXT_WDTR_BUS_16_BIT; 229239223Sgibbs } 229339223Sgibbs 229444581Sgibbs if (bt->firmware_ver[0] >= '3') { 229539223Sgibbs /* 229639223Sgibbs * For adapters that can do fast or ultra speeds, 229739223Sgibbs * use the more exact Target Sync Information command. 229839223Sgibbs */ 229939223Sgibbs target_sync_info_data_t sync_info; 230039223Sgibbs 230139223Sgibbs param = sizeof(sync_info); 230239223Sgibbs error = bt_cmd(bt, BOP_TARG_SYNC_INFO, ¶m, /*paramlen*/1, 230339223Sgibbs (u_int8_t*)&sync_info, sizeof(sync_info), 230439223Sgibbs DEFAULT_CMD_TIMEOUT); 230539223Sgibbs 230639223Sgibbs if (error != 0) { 230739223Sgibbs printf("%s: btfetchtransinfo - Inquire Sync " 230839223Sgibbs "Info Failed 0x%x\n", bt_name(bt), error); 230939223Sgibbs return; 231039223Sgibbs } 231139223Sgibbs sync_period = sync_info.sync_rate[target] * 100; 231239223Sgibbs } else { 231339223Sgibbs sync_period = 2000 + (500 * sync_info.period); 231439223Sgibbs } 231539223Sgibbs 231679175Smjacob#ifdef CAM_NEW_TRAN_CODE 231779175Smjacob cts->protocol = PROTO_SCSI; 231879175Smjacob cts->protocol_version = SCSI_REV_2; 231979175Smjacob cts->transport = XPORT_SPI; 232079175Smjacob cts->transport_version = 2; 232179175Smjacob 232279175Smjacob spi->sync_period = sync_period; 232379175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_RATE; 232479175Smjacob spi->sync_offset = sync_offset; 232579175Smjacob spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 232679175Smjacob 232779175Smjacob spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 232879175Smjacob spi->bus_width = bus_width; 232979175Smjacob 233079175Smjacob if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 233179175Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 233279175Smjacob spi->valid |= CTS_SPI_VALID_DISC; 233379175Smjacob } else 233479175Smjacob scsi->valid = 0; 233579175Smjacob 233679175Smjacob#else 233739223Sgibbs /* Convert ns value to standard SCSI sync rate */ 233839223Sgibbs if (cts->sync_offset != 0) 233939223Sgibbs cts->sync_period = scsi_calc_syncparam(sync_period); 234039223Sgibbs else 234139223Sgibbs cts->sync_period = 0; 234279175Smjacob cts->sync_offset = sync_offset; 234379175Smjacob cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 234439223Sgibbs 234539223Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 234639223Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 234739223Sgibbs | CCB_TRANS_BUS_WIDTH_VALID; 234879175Smjacob 234979175Smjacob#endif 235039223Sgibbs xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts); 235139223Sgibbs} 235239223Sgibbs 235339223Sgibbsstatic void 235439223Sgibbsbtmapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error) 235539223Sgibbs{ 235639223Sgibbs struct bt_softc* bt; 235739223Sgibbs 235839223Sgibbs bt = (struct bt_softc*)arg; 235939223Sgibbs bt->mailbox_physbase = segs->ds_addr; 236039223Sgibbs} 236139223Sgibbs 236239223Sgibbsstatic void 236339223Sgibbsbtmapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 236439223Sgibbs{ 236539223Sgibbs struct bt_softc* bt; 236639223Sgibbs 236739223Sgibbs bt = (struct bt_softc*)arg; 236839223Sgibbs bt->bt_ccb_physbase = segs->ds_addr; 236939223Sgibbs} 237039223Sgibbs 237139223Sgibbsstatic void 237239223Sgibbsbtmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 237339223Sgibbs{ 237439223Sgibbs 237539223Sgibbs struct bt_softc* bt; 237639223Sgibbs 237739223Sgibbs bt = (struct bt_softc*)arg; 237839223Sgibbs SLIST_FIRST(&bt->sg_maps)->sg_physaddr = segs->ds_addr; 237939223Sgibbs} 238039223Sgibbs 238139223Sgibbsstatic void 238239223Sgibbsbtpoll(struct cam_sim *sim) 238339223Sgibbs{ 238440132Sgibbs bt_intr(cam_sim_softc(sim)); 238539223Sgibbs} 238639223Sgibbs 238739223Sgibbsvoid 238839223Sgibbsbttimeout(void *arg) 238939223Sgibbs{ 239039223Sgibbs struct bt_ccb *bccb; 239139223Sgibbs union ccb *ccb; 239239223Sgibbs struct bt_softc *bt; 239339223Sgibbs int s; 239439223Sgibbs 239539223Sgibbs bccb = (struct bt_ccb *)arg; 239639223Sgibbs ccb = bccb->ccb; 239739223Sgibbs bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; 239839223Sgibbs xpt_print_path(ccb->ccb_h.path); 239939390Sgibbs printf("CCB %p - timed out\n", (void *)bccb); 240039223Sgibbs 240139223Sgibbs s = splcam(); 240239223Sgibbs 240339223Sgibbs if ((bccb->flags & BCCB_ACTIVE) == 0) { 240439223Sgibbs xpt_print_path(ccb->ccb_h.path); 240539390Sgibbs printf("CCB %p - timed out CCB already completed\n", 240639390Sgibbs (void *)bccb); 240739223Sgibbs splx(s); 240839223Sgibbs return; 240939223Sgibbs } 241039223Sgibbs 241139223Sgibbs /* 241239223Sgibbs * In order to simplify the recovery process, we ask the XPT 241339223Sgibbs * layer to halt the queue of new transactions and we traverse 241439223Sgibbs * the list of pending CCBs and remove their timeouts. This 241539223Sgibbs * means that the driver attempts to clear only one error 241639223Sgibbs * condition at a time. In general, timeouts that occur 241739223Sgibbs * close together are related anyway, so there is no benefit 241839223Sgibbs * in attempting to handle errors in parrallel. Timeouts will 241939223Sgibbs * be reinstated when the recovery process ends. 242039223Sgibbs */ 242139223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) == 0) { 242239223Sgibbs struct ccb_hdr *ccb_h; 242339223Sgibbs 242439223Sgibbs if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) { 242539223Sgibbs xpt_freeze_simq(bt->sim, /*count*/1); 242639223Sgibbs bccb->flags |= BCCB_RELEASE_SIMQ; 242739223Sgibbs } 242839223Sgibbs 242939223Sgibbs ccb_h = LIST_FIRST(&bt->pending_ccbs); 243039223Sgibbs while (ccb_h != NULL) { 243139223Sgibbs struct bt_ccb *pending_bccb; 243239223Sgibbs 243339223Sgibbs pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; 243439223Sgibbs untimeout(bttimeout, pending_bccb, ccb_h->timeout_ch); 243539223Sgibbs ccb_h = LIST_NEXT(ccb_h, sim_links.le); 243639223Sgibbs } 243739223Sgibbs } 243839223Sgibbs 243939223Sgibbs if ((bccb->flags & BCCB_DEVICE_RESET) != 0 244039223Sgibbs || bt->cur_outbox->action_code != BMBO_FREE 244140418Sgibbs || ((bccb->hccb.tag_enable == TRUE) 244239223Sgibbs && (bt->firmware_ver[0] < '5'))) { 244339223Sgibbs /* 244439223Sgibbs * Try a full host adapter/SCSI bus reset. 244539223Sgibbs * We do this only if we have already attempted 244639223Sgibbs * to clear the condition with a BDR, or we cannot 244739223Sgibbs * attempt a BDR for lack of mailbox resources 244839223Sgibbs * or because of faulty firmware. It turns out 244939223Sgibbs * that firmware versions prior to 5.xx treat BDRs 245039223Sgibbs * as untagged commands that cannot be sent until 245139223Sgibbs * all outstanding tagged commands have been processed. 245239223Sgibbs * This makes it somewhat difficult to use a BDR to 245339223Sgibbs * clear up a problem with an uncompleted tagged command. 245439223Sgibbs */ 245539223Sgibbs ccb->ccb_h.status = CAM_CMD_TIMEOUT; 245639223Sgibbs btreset(bt, /*hardreset*/TRUE); 245739223Sgibbs printf("%s: No longer in timeout\n", bt_name(bt)); 245839223Sgibbs } else { 245939223Sgibbs /* 246039223Sgibbs * Send a Bus Device Reset message: 246139223Sgibbs * The target that is holding up the bus may not 246239223Sgibbs * be the same as the one that triggered this timeout 246339223Sgibbs * (different commands have different timeout lengths), 246439223Sgibbs * but we have no way of determining this from our 246539223Sgibbs * timeout handler. Our strategy here is to queue a 246639223Sgibbs * BDR message to the target of the timed out command. 246739223Sgibbs * If this fails, we'll get another timeout 2 seconds 246839223Sgibbs * later which will attempt a bus reset. 246939223Sgibbs */ 247039223Sgibbs bccb->flags |= BCCB_DEVICE_RESET; 247139223Sgibbs ccb->ccb_h.timeout_ch = 247239223Sgibbs timeout(bttimeout, (caddr_t)bccb, 2 * hz); 247339223Sgibbs 247439223Sgibbs bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET; 247539223Sgibbs 247639223Sgibbs /* No Data Transfer */ 247739223Sgibbs bt->recovery_bccb->hccb.datain = TRUE; 247839223Sgibbs bt->recovery_bccb->hccb.dataout = TRUE; 247939223Sgibbs bt->recovery_bccb->hccb.btstat = 0; 248039223Sgibbs bt->recovery_bccb->hccb.sdstat = 0; 248139223Sgibbs bt->recovery_bccb->hccb.target_id = ccb->ccb_h.target_id; 248239223Sgibbs 248339223Sgibbs /* Tell the adapter about this command */ 248439223Sgibbs bt->cur_outbox->ccb_addr = btccbvtop(bt, bt->recovery_bccb); 248539223Sgibbs bt->cur_outbox->action_code = BMBO_START; 248639223Sgibbs bt_outb(bt, COMMAND_REG, BOP_START_MBOX); 248739223Sgibbs btnextoutbox(bt); 248839223Sgibbs } 248939223Sgibbs 249039223Sgibbs splx(s); 249139223Sgibbs} 249239223Sgibbs 2493