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