Esempio n. 1
0
void
qlw_update_task(void *xsc)
{
	struct qlw_softc *sc = xsc;
	int bus;

	for (bus = 0; bus < sc->sc_numbusses; bus++)
		qlw_update_bus(sc, bus);
}
Esempio n. 2
0
void
qlw_update_task(void *arg1, void *arg2)
{
	struct qlw_softc *sc = arg1;
	int bus;

	for (bus = 0; bus < sc->sc_numbusses; bus++)
		qlw_update_bus(sc, bus);
}
Esempio n. 3
0
int
qlw_attach(struct qlw_softc *sc)
{
	struct scsibus_attach_args saa;
	void (*parse_nvram)(struct qlw_softc *, int);
	int reset_delay;
	int bus;

	task_set(&sc->sc_update_task, qlw_update_task, sc);

	switch (sc->sc_isp_gen) {
	case QLW_GEN_ISP1000:
		sc->sc_nvram_size = 0;
		break;
	case QLW_GEN_ISP1040:
		sc->sc_nvram_size = 128;
		sc->sc_nvram_minversion = 2;
		parse_nvram = qlw_parse_nvram_1040;
		break;
	case QLW_GEN_ISP1080:
	case QLW_GEN_ISP12160:
		sc->sc_nvram_size = 256;
		sc->sc_nvram_minversion = 1;
		parse_nvram = qlw_parse_nvram_1080;
		break;

	default:
		printf("unknown isp type\n");
		return (ENXIO);
	}

	/* after reset, mbox registers 1-3 should contain the string "ISP   " */
	if (qlw_read_mbox(sc, 1) != 0x4953 ||
	    qlw_read_mbox(sc, 2) != 0x5020 ||
	    qlw_read_mbox(sc, 3) != 0x2020) {
		/* try releasing the risc processor */
		qlw_host_cmd(sc, QLW_HOST_CMD_RELEASE);
	}

	qlw_host_cmd(sc, QLW_HOST_CMD_PAUSE);
	if (qlw_softreset(sc) != 0) {
		printf("softreset failed\n");
		return (ENXIO);
	}

	for (bus = 0; bus < sc->sc_numbusses; bus++)
		qlw_init_defaults(sc, bus);

	if (qlw_read_nvram(sc) == 0) {
		for (bus = 0; bus < sc->sc_numbusses; bus++)
			parse_nvram(sc, bus);
	}

#ifndef ISP_NOFIRMWARE
	if (sc->sc_firmware && qlw_load_firmware(sc)) {
		printf("firmware load failed\n");
		return (ENXIO);
	}
#endif

	/* execute firmware */
	sc->sc_mbox[0] = QLW_MBOX_EXEC_FIRMWARE;
	sc->sc_mbox[1] = QLW_CODE_ORG;
	if (qlw_mbox(sc, 0x0003, 0x0001)) {
		printf("ISP couldn't exec firmware: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}

	delay(250000);		/* from isp(4) */

	sc->sc_mbox[0] = QLW_MBOX_ABOUT_FIRMWARE;
	if (qlw_mbox(sc, QLW_MBOX_ABOUT_FIRMWARE_IN,
	    QLW_MBOX_ABOUT_FIRMWARE_OUT)) {
		printf("ISP not talking after firmware exec: %x\n",
		    sc->sc_mbox[0]);
		return (ENXIO);
	}
	/* The ISP1000 firmware we use doesn't return a version number. */
	if (sc->sc_isp_gen == QLW_GEN_ISP1000 && sc->sc_firmware) {
		sc->sc_mbox[1] = 1;
		sc->sc_mbox[2] = 37;
		sc->sc_mbox[3] = 0;
		sc->sc_mbox[6] = 0;
	}
	printf("%s: firmware rev %d.%d.%d, attrs 0x%x\n", DEVNAME(sc),
	    sc->sc_mbox[1], sc->sc_mbox[2], sc->sc_mbox[3], sc->sc_mbox[6]);

	/* work out how many ccbs to allocate */
	sc->sc_mbox[0] = QLW_MBOX_GET_FIRMWARE_STATUS;
	if (qlw_mbox(sc, 0x0001, 0x0007)) {
		printf("couldn't get firmware status: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}
	sc->sc_maxrequests = sc->sc_mbox[2];
	if (sc->sc_maxrequests > 512)
		sc->sc_maxrequests = 512;
	for (bus = 0; bus < sc->sc_numbusses; bus++) {
		if (sc->sc_max_queue_depth[bus] > sc->sc_maxrequests)
			sc->sc_max_queue_depth[bus] = sc->sc_maxrequests;
	}

	/* 
	 * On some 1020/1040 variants the response queue is limited to
	 * 256 entries.  We don't really need all that many anyway.
	 */
	sc->sc_maxresponses = sc->sc_maxrequests / 2;
	if (sc->sc_maxresponses < 64)
		sc->sc_maxresponses = 64;

	/* We may need up to 3 request entries per SCSI command. */
	sc->sc_maxccbs = sc->sc_maxrequests / 3;

	/* Allegedly the FIFO is busted on the 1040A. */
	if (sc->sc_isp_type == QLW_ISP1040A)
		sc->sc_isp_config &= ~QLW_PCI_FIFO_MASK;
	qlw_write(sc, QLW_CFG1, sc->sc_isp_config);

	if (sc->sc_isp_config & QLW_BURST_ENABLE)
		qlw_dma_burst_enable(sc);

	sc->sc_mbox[0] = QLW_MBOX_SET_FIRMWARE_FEATURES;
	sc->sc_mbox[1] = 0;
	if (sc->sc_fw_features & QLW_FW_FEATURE_LVD_NOTIFY)
		sc->sc_mbox[1] |= QLW_FW_FEATURE_LVD_NOTIFY;
	if (sc->sc_mbox[1] != 0 && qlw_mbox(sc, 0x0003, 0x0001)) {
		printf("couldn't set firmware features: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}

	sc->sc_mbox[0] = QLW_MBOX_SET_CLOCK_RATE;
	sc->sc_mbox[1] = sc->sc_clock;
	if (qlw_mbox(sc, 0x0003, 0x0001)) {
		printf("couldn't set clock rate: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}
	
	sc->sc_mbox[0] = QLW_MBOX_SET_RETRY_COUNT;
	sc->sc_mbox[1] = sc->sc_retry_count[0];
	sc->sc_mbox[2] = sc->sc_retry_delay[0];
	sc->sc_mbox[6] = sc->sc_retry_count[1];
	sc->sc_mbox[7] = sc->sc_retry_delay[1];
	if (qlw_mbox(sc, 0x00c7, 0x0001)) {
		printf("couldn't set retry count: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}
	
	sc->sc_mbox[0] = QLW_MBOX_SET_ASYNC_DATA_SETUP;
	sc->sc_mbox[1] = sc->sc_async_data_setup[0];
	sc->sc_mbox[2] = sc->sc_async_data_setup[1];
	if (qlw_mbox(sc, 0x0007, 0x0001)) {
		printf("couldn't set async data setup: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}

	sc->sc_mbox[0] = QLW_MBOX_SET_ACTIVE_NEGATION;
	sc->sc_mbox[1] = sc->sc_req_ack_active_neg[0] << 5;
	sc->sc_mbox[1] |= sc->sc_data_line_active_neg[0] << 4;
	sc->sc_mbox[2] = sc->sc_req_ack_active_neg[1] << 5;
	sc->sc_mbox[2] |= sc->sc_data_line_active_neg[1] << 4;
	if (qlw_mbox(sc, 0x0007, 0x0001)) {
		printf("couldn't set active negation: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}

	sc->sc_mbox[0] = QLW_MBOX_SET_TAG_AGE_LIMIT;
	sc->sc_mbox[1] = sc->sc_tag_age_limit[0];
	sc->sc_mbox[2] = sc->sc_tag_age_limit[1];
	if (qlw_mbox(sc, 0x0007, 0x0001)) {
		printf("couldn't set tag age limit: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}

	sc->sc_mbox[0] = QLW_MBOX_SET_SELECTION_TIMEOUT;
	sc->sc_mbox[1] = sc->sc_selection_timeout[0];
	sc->sc_mbox[2] = sc->sc_selection_timeout[1];
	if (qlw_mbox(sc, 0x0007, 0x0001)) {
		printf("couldn't set selection timeout: %x\n", sc->sc_mbox[0]);
		return (ENXIO);
	}

	for (bus = 0; bus < sc->sc_numbusses; bus++) {
		if (qlw_config_bus(sc, bus))
			return (ENXIO);
	}

	if (qlw_alloc_ccbs(sc)) {
		/* error already printed */
		return (ENOMEM);
	}

	sc->sc_mbox[0] = QLW_MBOX_INIT_REQ_QUEUE;
	sc->sc_mbox[1] = sc->sc_maxrequests;
	qlw_mbox_putaddr(sc->sc_mbox, sc->sc_requests);
	sc->sc_mbox[4] = 0;
	if (qlw_mbox(sc, 0x00df, 0x0001)) {
		printf("couldn't init request queue: %x\n", sc->sc_mbox[0]);
		goto free_ccbs;
	}

	sc->sc_mbox[0] = QLW_MBOX_INIT_RSP_QUEUE;
	sc->sc_mbox[1] = sc->sc_maxresponses;
	qlw_mbox_putaddr(sc->sc_mbox, sc->sc_responses);
	sc->sc_mbox[5] = 0;
	if (qlw_mbox(sc, 0x00ef, 0x0001)) {
		printf("couldn't init response queue: %x\n", sc->sc_mbox[0]);
		goto free_ccbs;
	}

	reset_delay = 0;
	for (bus = 0; bus < sc->sc_numbusses; bus++) {
		sc->sc_mbox[0] = QLW_MBOX_BUS_RESET;
		sc->sc_mbox[1] = sc->sc_reset_delay[bus];
		sc->sc_mbox[2] = bus;
		if (qlw_mbox(sc, 0x0007, 0x0001)) {
			printf("couldn't reset bus: %x\n", sc->sc_mbox[0]);
			goto free_ccbs;
		}
		sc->sc_marker_required[bus] = 1;
		sc->sc_update_required[bus] = 0xffff;

		if (sc->sc_reset_delay[bus] > reset_delay)
			reset_delay = sc->sc_reset_delay[bus];
	}

	/* wait for the busses to settle */
	delay(reset_delay * 1000000);

	/* we should be good to go now, attach scsibus */
	for (bus = 0; bus < sc->sc_numbusses; bus++) {
		sc->sc_link[bus].adapter = &qlw_switch;
		sc->sc_link[bus].adapter_softc = sc;
		sc->sc_link[bus].adapter_target = sc->sc_initiator[bus];
		sc->sc_link[bus].adapter_buswidth = QLW_MAX_TARGETS;
		sc->sc_link[bus].openings = sc->sc_max_queue_depth[bus];
		sc->sc_link[bus].pool = &sc->sc_iopool;

		memset(&saa, 0, sizeof(saa));
		saa.saa_sc_link = &sc->sc_link[bus];

		/* config_found() returns the scsibus attached to us */
		sc->sc_scsibus[bus] = (struct scsibus_softc *)
		    config_found(&sc->sc_dev, &saa, scsiprint);

		qlw_update_bus(sc, bus);
	}

	sc->sc_running = 1;
	return(0);

free_ccbs:
	qlw_free_ccbs(sc);
	return (ENXIO);
}