示例#1
0
/*
 * Update the XPT's idea of the negotiated transfer
 * parameters for a particular target.
 */
static void
ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts)
{
	setup_data_t	setup_info;
	u_int		target;
	u_int		targ_offset;
	u_int		sync_period;
	int		error;
	uint8_t	param;
	targ_syncinfo_t	sync_info;
	struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;

	target = cts->ccb_h.target_id;
	targ_offset = (target & 0x7);

	/*
	 * Inquire Setup Information.  This command retreives
	 * the sync info for older models.
	 */
	param = sizeof(setup_info);
	error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
	    (uint8_t*)&setup_info, sizeof(setup_info), DEFAULT_CMD_TIMEOUT);

	if (error != 0) {
		device_printf(aha->dev,
		    "ahafetchtransinfo - Inquire Setup Info Failed %d\n",
		    error);
		return;
	}

	sync_info = setup_info.syncinfo[targ_offset];

	if (sync_info.sync == 0)
		spi->sync_offset = 0;
	else
		spi->sync_offset = sync_info.offset;

	spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;

	if (aha->boardid >= BOARD_1542CF)
		sync_period = 1000;
	else
		sync_period = 2000;
	sync_period += 500 * sync_info.period;

	/* Convert ns value to standard SCSI sync rate */
	if (spi->sync_offset != 0)
		spi->sync_period = scsi_calc_syncparam(sync_period);
	else
		spi->sync_period = 0;

	spi->valid = CTS_SPI_VALID_SYNC_RATE
		   | CTS_SPI_VALID_SYNC_OFFSET
		   | CTS_SPI_VALID_BUS_WIDTH;
        xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
}
示例#2
0
static int
ahainitmboxes(struct aha_softc *aha)
{
	int error;
	init_24b_mbox_params_t init_mbox;

	bzero(aha->in_boxes, sizeof(aha_mbox_in_t) * aha->num_boxes);
	bzero(aha->out_boxes, sizeof(aha_mbox_out_t) * aha->num_boxes);
	aha->cur_inbox = aha->in_boxes;
	aha->last_inbox = aha->in_boxes + aha->num_boxes - 1;
	aha->cur_outbox = aha->out_boxes;
	aha->last_outbox = aha->out_boxes + aha->num_boxes - 1;

	/* Tell the adapter about them */
	init_mbox.num_mboxes = aha->num_boxes;
	ahautoa24(aha->mailbox_physbase, init_mbox.base_addr);
	error = aha_cmd(aha, AOP_INITIALIZE_MBOX, (uint8_t *)&init_mbox,
	    /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
	    /*reply_len*/0, DEFAULT_CMD_TIMEOUT);

	if (error != 0)
		printf("ahainitmboxes: Initialization command failed\n");
	return (error);
}
示例#3
0
/*
 * Check if the device can be found at the port given
 */
static int
aha_isa_probe(device_t dev)
{
	/*
	 * find unit and check we have that many defined
	 */
	struct	aha_softc *aha = device_get_softc(dev);
	int	error;
	u_long	port_start;
	int	port_rid;
	int	drq;
	int	irq;
	config_data_t config_data;

	aha->dev = dev;
	/* Check isapnp ids */
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, aha_ids) == ENXIO)
		return (ENXIO);

	port_rid = 0;
	aha->port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &port_rid,
	    AHA_NREGS, RF_ACTIVE);

	if (aha->port == NULL)
		return (ENXIO);

	port_start = rman_get_start(aha->port);
	aha_alloc(aha);

	/* See if there is really a card present */
	if (aha_probe(aha) || aha_fetch_adapter_info(aha)) {
		aha_free(aha);
		bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port);
		return (ENXIO);
	}

	/*
	 * Determine our IRQ, and DMA settings and
	 * export them to the configuration system.
	 */
	error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
	    (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT);

	if (error != 0) {
		device_printf(dev, "Could not determine IRQ or DMA "
		    "settings for adapter at %#jx.  Failing probe\n",
		    (uintmax_t)port_start);
		aha_free(aha);
		bus_release_resource(dev, SYS_RES_IOPORT, port_rid,
		    aha->port);
		return (ENXIO);
	}

	bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port);
	aha->port = NULL;

	switch (config_data.dma_chan) {
	case DMA_CHAN_5:
		drq = 5;
		break;
	case DMA_CHAN_6:
		drq = 6;
		break;
	case DMA_CHAN_7:
		drq = 7;
		break;
	default:
		device_printf(dev, "Invalid DMA setting for adapter at %#jx.",
		    (uintmax_t)port_start);
		return (ENXIO);
	}
	error = bus_set_resource(dev, SYS_RES_DRQ, 0, drq, 1);
	if (error)
		return error;

	irq = ffs(config_data.irq) + 8;
	error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
	return (error);
}
示例#4
0
/*
 * Pull the boards setup information and record it in our softc.
 */
int
aha_fetch_adapter_info(struct aha_softc *aha)
{
	setup_data_t	setup_info;
	config_data_t config_data;
	uint8_t length_param;
	int	 error;
	struct	aha_extbios extbios;

	switch (aha->boardid) {
	case BOARD_1540_16HEAD_BIOS:
		snprintf(aha->model, sizeof(aha->model), "1540 16 head BIOS");
		break;
	case BOARD_1540_64HEAD_BIOS:
		snprintf(aha->model, sizeof(aha->model), "1540 64 head BIOS");
		break;
	case BOARD_1542:
		snprintf(aha->model, sizeof(aha->model), "1540/1542 64 head BIOS");
		break;
	case BOARD_1542C:
		snprintf(aha->model, sizeof(aha->model), "1542C");
		break;
	case BOARD_1542CF:
		snprintf(aha->model, sizeof(aha->model), "1542CF");
		break;
	case BOARD_1542CP:
		snprintf(aha->model, sizeof(aha->model), "1542CP");
		break;
	default:
		snprintf(aha->model, sizeof(aha->model), "Unknown");
		break;
	}
	/*
	 * If we are a new type of 1542 board (anything newer than a 1542C)
	 * then disable the extended bios so that the
	 * mailbox interface is unlocked.
	 * This is also true for the 1542B Version 3.20. First Adaptec
	 * board that supports >1Gb drives.
	 * No need to check the extended bios flags as some of the
	 * extensions that cause us problems are not flagged in that byte.
	 */
	if (PROBABLY_NEW_BOARD(aha->boardid) ||
		(aha->boardid == 0x41
		&& aha->fw_major == 0x31 &&
		aha->fw_minor >= 0x34)) {
		error = aha_cmd(aha, AOP_RETURN_EXT_BIOS_INFO, NULL,
		    /*paramlen*/0, (u_char *)&extbios, sizeof(extbios),
		    DEFAULT_CMD_TIMEOUT);
		if (error != 0) {
			device_printf(aha->dev,
			    "AOP_RETURN_EXT_BIOS_INFO - Failed.");
			return (error);
		}
		error = aha_cmd(aha, AOP_MBOX_IF_ENABLE, (uint8_t *)&extbios,
		    /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT);
		if (error != 0) {
			device_printf(aha->dev, "AOP_MBOX_IF_ENABLE - Failed.");
			return (error);
		}
	}
	if (aha->boardid < 0x41)
		device_printf(aha->dev, "Warning: aha-1542A won't work.\n");

	aha->max_sg = 17;		/* Need >= 17 to do 64k I/O */
	aha->diff_bus = 0;
	aha->extended_lun = 0;
	aha->extended_trans = 0;
	aha->max_ccbs = 16;
	/* Determine Sync/Wide/Disc settings */
	length_param = sizeof(setup_info);
	error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &length_param,
	    /*paramlen*/1, (uint8_t*)&setup_info, sizeof(setup_info),
	    DEFAULT_CMD_TIMEOUT);
	if (error != 0) {
		device_printf(aha->dev, "aha_fetch_adapter_info - Failed "
		    "Get Setup Info\n");
		return (error);
	}
	if (setup_info.initiate_sync != 0) {
		aha->sync_permitted = ALL_TARGETS;
	}
	aha->disc_permitted = ALL_TARGETS;

	/* We need as many mailboxes as we can have ccbs */
	aha->num_boxes = aha->max_ccbs;

	/* Determine our SCSI ID */
	error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
	    (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT);
	if (error != 0) {
		device_printf(aha->dev,
		    "aha_fetch_adapter_info - Failed Get Config\n");
		return (error);
	}
	aha->scsi_id = config_data.scsi_id;
	return (0);
}
示例#5
0
/*
 * Probe the adapter and verify that the card is an Adaptec.
 */
int
aha_probe(struct aha_softc* aha)
{
	u_int	 status;
	u_int	 intstat;
	int	 error;
	board_id_data_t	board_id;

	/*
	 * See if the three I/O ports look reasonable.
	 * Touch the minimal number of registers in the
	 * failure case.
	 */
	status = aha_inb(aha, STATUS_REG);
	if ((status == 0) ||
	    (status & (DIAG_ACTIVE|CMD_REG_BUSY | STATUS_REG_RSVD)) != 0) {
		PRVERB((aha->dev, "status reg test failed %x\n", status));
		return (ENXIO);
	}

	intstat = aha_inb(aha, INTSTAT_REG);
	if ((intstat & INTSTAT_REG_RSVD) != 0) {
		PRVERB((aha->dev, "Failed Intstat Reg Test\n"));
		return (ENXIO);
	}

	/*
	 * Looking good so far.  Final test is to reset the
	 * adapter and fetch the board ID and ensure we aren't
	 * looking at a BusLogic.
	 */
	if ((error = ahareset(aha, /*hard_reset*/TRUE)) != 0) {
		PRVERB((aha->dev, "Failed Reset\n"));
		return (ENXIO);
	}

	/*
	 * Get the board ID.  We use this to see if we're dealing with
	 * a buslogic card or an aha card (or clone).
	 */
	error = aha_cmd(aha, AOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
	    (uint8_t*)&board_id, sizeof(board_id), DEFAULT_CMD_TIMEOUT);
	if (error != 0) {
		PRVERB((aha->dev, "INQUIRE failed %x\n", error));
		return (ENXIO);
	}
	aha->fw_major = board_id.firmware_rev_major;
	aha->fw_minor = board_id.firmware_rev_minor;
	aha->boardid = board_id.board_type;

	/*
	 * The Buslogic cards have an id of either 0x41 or 0x42.  So
	 * if those come up in the probe, we test the geometry register
	 * of the board.  Adaptec boards that are this old will not have
	 * this register, and return 0xff, while buslogic cards will return
	 * something different.
	 *
	 * It appears that for reasons unknow, for the for the
	 * aha-1542B cards, we need to wait a little bit before trying
	 * to read the geometry register.  I picked 10ms since we have
	 * reports that a for loop to 1000 did the trick, and this
	 * errs on the side of conservatism.  Besides, no one will
	 * notice a 10mS delay here, even the 1542B card users :-)
	 *
	 * Some compatible cards return 0 here.  Some cards also
	 * seem to return 0x7f.
	 *
	 * XXX I'm not sure how this will impact other cloned cards
	 *
	 * This really should be replaced with the esetup command, since
	 * that appears to be more reliable.  This becomes more and more
	 * true over time as we discover more cards that don't read the
	 * geometry register consistently.
	 */
	if (aha->boardid <= 0x42) {
		/* Wait 10ms before reading */
		DELAY(10000);
		status = aha_inb(aha, GEOMETRY_REG);
		if (status != 0xff && status != 0x00 && status != 0x7f) {
			PRVERB((aha->dev, "Geometry Register test failed %#x\n",
				status));
			return (ENXIO);
		}
	}

	return (0);
}
示例#6
0
/*
 * Check if the device can be found at the port given
 * and if so, set it up ready for further work
 * as an argument, takes the isa_device structure from
 * autoconf.c
 */
static int
aha_isa_probe(device_t dev)
{
	/*
	 * find unit and check we have that many defined
	 */
	struct	aha_softc **sc = device_get_softc(dev);
	struct	aha_softc *aha;
	int	port_index;
	int	max_port_index;
	int	error;
	u_long	port_start, port_count;
	struct resource *port_res;
	int	port_rid;
	int	drq;
	int	irq;

	aha = NULL;

	/* Check isapnp ids */
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, aha_ids) == ENXIO)
		return (ENXIO);

	error = bus_get_resource(dev, SYS_RES_IOPORT, 0,
				 &port_start, &port_count);
	if (error != 0)
		port_start = 0;

	/*
	 * Bound our board search if the user has
	 * specified an exact port.
	 */
	aha_find_probe_range(port_start, &port_index, &max_port_index);

	if (port_index < 0)
		return ENXIO;

	/* Attempt to find an adapter */
	for (;port_index <= max_port_index; port_index++) {
		config_data_t config_data;
		u_int ioport;
		int error;

		ioport = aha_iop_from_bio(port_index);

		error = bus_set_resource(dev, SYS_RES_IOPORT, 0,
					 ioport, AHA_NREGS);
		if (error)
			return error;
		
		port_rid = 0;
		port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid,
		    0, ~0, AHA_NREGS, RF_ACTIVE);
		if (!port_res)
			continue;

		/* Allocate a softc for use during probing */
		aha = aha_alloc(device_get_unit(dev), rman_get_bustag(port_res),
		    rman_get_bushandle(port_res));

		if (aha == NULL) {
			bus_release_resource(dev, SYS_RES_IOPORT, port_rid, 
			    port_res);
			break;
		}

		/* See if there is really a card present */
		if (aha_probe(aha) || aha_fetch_adapter_info(aha)) {
			aha_free(aha);
			bus_release_resource(dev, SYS_RES_IOPORT, port_rid,
			    port_res);
			continue;
		}

		/*
		 * Determine our IRQ, and DMA settings and
		 * export them to the configuration system.
		 */
		error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
		    (u_int8_t*)&config_data, sizeof(config_data), 
		    DEFAULT_CMD_TIMEOUT);

		if (error != 0) {
			printf("aha_isa_probe: Could not determine IRQ or DMA "
			    "settings for adapter at 0x%x.  Failing probe\n",
			    ioport);
			aha_free(aha);
			bus_release_resource(dev, SYS_RES_IOPORT, port_rid, 
			    port_res);
			continue;
		}

		bus_release_resource(dev, SYS_RES_IOPORT, port_rid, port_res);

		switch (config_data.dma_chan) {
		case DMA_CHAN_5:
			drq = 5;
			break;
		case DMA_CHAN_6:
			drq = 6;
			break;
		case DMA_CHAN_7:
			drq = 7;
			break;
		default:
			printf("aha_isa_probe: Invalid DMA setting "
			    "detected for adapter at 0x%x.  "
			    "Failing probe\n", ioport);
			return (ENXIO);
		}
		error = bus_set_resource(dev, SYS_RES_DRQ, 0, drq, 1);
		if (error)
			return error;

		irq = ffs(config_data.irq) + 8;
		error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
		if (error)
			return error;

		*sc = aha;
		aha_unit++;

		return (0);
	}

	return (ENXIO);
}