adv_pci.c revision 55945
139217Sgibbs/*
239217Sgibbs * Device probe and attach routines for the following
339217Sgibbs * Advanced Systems Inc. SCSI controllers:
439217Sgibbs *
539217Sgibbs *   Connectivity Products:
655945Sgibbs *	ABP902/3902	- Bus-Master PCI (16 CDB)
755945Sgibbs *	ABP3905		- Bus-Master PCI (16 CDB)
855945Sgibbs *	ABP915		- Bus-Master PCI (16 CDB)
955945Sgibbs *	ABP920		- Bus-Master PCI (16 CDB)
1055945Sgibbs *	ABP3922		- Bus-Master PCI (16 CDB)
1155945Sgibbs *	ABP3925		- Bus-Master PCI (16 CDB)
1255945Sgibbs *	ABP930		- Bus-Master PCI (16 CDB) *
1355945Sgibbs *	ABP930U		- Bus-Master PCI Ultra (16 CDB)
1455945Sgibbs *	ABP930UA	- Bus-Master PCI Ultra (16 CDB)
1555945Sgibbs *	ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB)
1655945Sgibbs *	ABP960		- Bus-Master PCI MAC/PC (16 CDB) **
1755945Sgibbs *	ABP960U		- Bus-Master PCI MAC/PC Ultra (16 CDB)
1855945Sgibbs *	ABP970U		- Bus-Master PCI MAC/PC Ultra (240 CDB)
1955945Sgibbs *	ABP3960UA	- Bus-Master PCI MAC/PC (240 CDB)
2039217Sgibbs *
2139217Sgibbs *   Single Channel Products:
2239217Sgibbs *	ABP940 - Bus-Master PCI (240 CDB)
2339217Sgibbs *	ABP940U - Bus-Master PCI Ultra (240 CDB)
2439217Sgibbs *	ABP970 - Bus-Master PCI MAC/PC (240 CDB)
2539217Sgibbs *	ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
2639217Sgibbs *
2739217Sgibbs *   Dual Channel Products:
2839217Sgibbs *	ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
2955945Sgibbs *	ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.)
3039217Sgibbs *
3139217Sgibbs *   Footnotes:
3239217Sgibbs *	 * This board has been sold by SIIG as the Fast SCSI Pro PCI.
3339217Sgibbs *	** This board has been sold by Iomega as a Jaz Jet PCI adapter.
3439217Sgibbs *
3539217Sgibbs * Copyright (c) 1997 Justin Gibbs.
3639217Sgibbs * All rights reserved.
3739217Sgibbs *
3839217Sgibbs * Redistribution and use in source and binary forms, with or without
3939217Sgibbs * modification, are permitted provided that the following conditions
4039217Sgibbs * are met:
4139217Sgibbs * 1. Redistributions of source code must retain the above copyright
4239217Sgibbs *    notice, this list of conditions, and the following disclaimer,
4355945Sgibbs *    without modification.
4439217Sgibbs * 2. The name of the author may not be used to endorse or promote products
4539217Sgibbs *    derived from this software without specific prior written permission.
4639217Sgibbs *
4739217Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4839217Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4939217Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5039217Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
5139217Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5239217Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5339217Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5439217Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5539217Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5639217Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5739217Sgibbs * SUCH DAMAGE.
5839217Sgibbs *
5950477Speter * $FreeBSD: head/sys/dev/advansys/adv_pci.c 55945 2000-01-14 03:33:38Z gibbs $
6039217Sgibbs */
6139217Sgibbs
6239217Sgibbs#include <sys/param.h>
6339217Sgibbs#include <sys/systm.h>
6439217Sgibbs#include <sys/kernel.h>
6539217Sgibbs
6639217Sgibbs#include <machine/bus_pio.h>
6739217Sgibbs#include <machine/bus.h>
6839217Sgibbs
6939217Sgibbs#include <pci/pcireg.h>
7039217Sgibbs#include <pci/pcivar.h>
7139217Sgibbs
7239217Sgibbs#include <dev/advansys/advansys.h>
7339217Sgibbs
7439217Sgibbs#define PCI_BASEADR0	PCI_MAP_REG_START	/* I/O Address */
7539217Sgibbs#define PCI_BASEADR1	PCI_MAP_REG_START + 4	/* Mem I/O Address */
7639217Sgibbs
7739217Sgibbs#define	PCI_DEVICE_ID_ADVANSYS_1200A	0x110010CD
7839217Sgibbs#define	PCI_DEVICE_ID_ADVANSYS_1200B	0x120010CD
7955945Sgibbs#define	PCI_DEVICE_ID_ADVANSYS_3000	0x130010CD
8039217Sgibbs#define	PCI_DEVICE_REV_ADVANSYS_3150	0x02
8139217Sgibbs#define	PCI_DEVICE_REV_ADVANSYS_3050	0x03
8239217Sgibbs
8339217Sgibbs#define ADV_PCI_MAX_DMA_ADDR    (0xFFFFFFFFL)
8439217Sgibbs#define ADV_PCI_MAX_DMA_COUNT   (0xFFFFFFFFL)
8539217Sgibbs
8641771Sdillonstatic const char* advpciprobe(pcici_t tag, pcidi_t type);
8739217Sgibbsstatic void advpciattach(pcici_t config_id, int unit);
8839217Sgibbs
8939217Sgibbs/*
9039217Sgibbs * The overrun buffer shared amongst all PCI adapters.
9139217Sgibbs */
9239217Sgibbsstatic  u_int8_t*	overrun_buf;
9342012Sgibbsstatic	bus_dma_tag_t	overrun_dmat;
9442012Sgibbsstatic	bus_dmamap_t	overrun_dmamap;
9542012Sgibbsstatic	bus_addr_t	overrun_physbase;
9639217Sgibbs
9739217Sgibbsstatic struct  pci_device adv_pci_driver = {
9839217Sgibbs	"adv",
9939217Sgibbs        advpciprobe,
10039217Sgibbs        advpciattach,
10139217Sgibbs        &adv_unit,
10239217Sgibbs	NULL
10339217Sgibbs};
10439217Sgibbs
10546024SpeterCOMPAT_PCI_DRIVER (adv_pci, adv_pci_driver);
10639217Sgibbs
10741771Sdillonstatic const char*
10839217Sgibbsadvpciprobe(pcici_t tag, pcidi_t type)
10939217Sgibbs{
11055945Sgibbs	int rev;
11155945Sgibbs
11255945Sgibbs	rev = pci_conf_read(tag, PCI_CLASS_REG) & PCI_REVISION_MASK;
11339217Sgibbs	switch (type) {
11439217Sgibbs	case PCI_DEVICE_ID_ADVANSYS_1200A:
11539217Sgibbs		return ("AdvanSys ASC1200A SCSI controller");
11639217Sgibbs	case PCI_DEVICE_ID_ADVANSYS_1200B:
11739217Sgibbs		return ("AdvanSys ASC1200B SCSI controller");
11855945Sgibbs	case PCI_DEVICE_ID_ADVANSYS_3000:
11939217Sgibbs		if (rev == PCI_DEVICE_REV_ADVANSYS_3150)
12055945Sgibbs			return ("AdvanSys ASC3150 SCSI controller");
12155945Sgibbs		else if (rev == PCI_DEVICE_REV_ADVANSYS_3050)
12255945Sgibbs			return ("AdvanSys ASC3030/50 SCSI controller");
12355945Sgibbs		else if (rev >= PCI_DEVICE_REV_ADVANSYS_3150)
12455945Sgibbs			return ("Unknown AdvanSys controller");
12539217Sgibbs		break;
12639217Sgibbs	default:
12739217Sgibbs		break;
12839217Sgibbs	}
12939217Sgibbs	return (NULL);
13039217Sgibbs}
13139217Sgibbs
13239217Sgibbsstatic void
13339217Sgibbsadvpciattach(pcici_t config_id, int unit)
13439217Sgibbs{
13539217Sgibbs	u_int16_t	io_port;
13639217Sgibbs	struct		adv_softc *adv;
13739217Sgibbs	u_int32_t	id;
13839217Sgibbs	u_int32_t	command;
13939217Sgibbs	int		error;
14039217Sgibbs
14139217Sgibbs	/*
14239217Sgibbs	 * Determine the chip version.
14339217Sgibbs	 */
14439217Sgibbs	id = pci_cfgread(config_id, PCI_ID_REG, /*bytes*/4);
14539217Sgibbs	command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1);
14639217Sgibbs
14739217Sgibbs	/*
14839217Sgibbs	 * These cards do not allow memory mapped accesses, so we must
14939217Sgibbs	 * ensure that I/O accesses are available or we won't be able
15039217Sgibbs	 * to talk to them.
15139217Sgibbs	 */
15239217Sgibbs	if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN))
15339217Sgibbs	 != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) {
15439217Sgibbs		command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN;
15539217Sgibbs		pci_cfgwrite(config_id, PCIR_COMMAND, command, /*bytes*/1);
15639217Sgibbs	}
15739217Sgibbs
15839217Sgibbs	/*
15939217Sgibbs	 * Early chips can't handle non-zero latency timer settings.
16039217Sgibbs	 */
16139217Sgibbs	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
16239217Sgibbs	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
16339217Sgibbs		pci_cfgwrite(config_id, PCIR_LATTIMER, /*value*/0, /*bytes*/1);
16439217Sgibbs	}
16539217Sgibbs
16639217Sgibbs
16739217Sgibbs	if (pci_map_port(config_id, PCI_BASEADR0, &io_port) == 0)
16839217Sgibbs		return;
16939217Sgibbs
17039217Sgibbs	if (adv_find_signature(I386_BUS_SPACE_IO, io_port) == 0)
17139217Sgibbs		return;
17239217Sgibbs
17339217Sgibbs	adv = adv_alloc(unit, I386_BUS_SPACE_IO, io_port);
17439217Sgibbs	if (adv == NULL)
17539217Sgibbs		return;
17639217Sgibbs
17739217Sgibbs	/* Allocate a dmatag for our transfer DMA maps */
17839217Sgibbs	/* XXX Should be a child of the PCI bus dma tag */
17949860Sgibbs	error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
18039217Sgibbs				   /*boundary*/0,
18139217Sgibbs				   /*lowaddr*/ADV_PCI_MAX_DMA_ADDR,
18239217Sgibbs				   /*highaddr*/BUS_SPACE_MAXADDR,
18339217Sgibbs				   /*filter*/NULL, /*filterarg*/NULL,
18439217Sgibbs				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
18539217Sgibbs				   /*nsegments*/BUS_SPACE_UNRESTRICTED,
18639217Sgibbs				   /*maxsegsz*/ADV_PCI_MAX_DMA_COUNT,
18739217Sgibbs				   /*flags*/0,
18839217Sgibbs				   &adv->parent_dmat);
18939217Sgibbs
19039217Sgibbs	if (error != 0) {
19139217Sgibbs		printf("%s: Could not allocate DMA tag - error %d\n",
19239217Sgibbs		       adv_name(adv), error);
19339217Sgibbs		adv_free(adv);
19439217Sgibbs		return;
19539217Sgibbs	}
19639217Sgibbs
19739217Sgibbs	adv->init_level++;
19839217Sgibbs
19939217Sgibbs	if (overrun_buf == NULL) {
20039217Sgibbs		/* Need to allocate our overrun buffer */
20139217Sgibbs		if (bus_dma_tag_create(adv->parent_dmat,
20239217Sgibbs				       /*alignment*/8, /*boundary*/0,
20339217Sgibbs				       ADV_PCI_MAX_DMA_ADDR, BUS_SPACE_MAXADDR,
20439217Sgibbs				       /*filter*/NULL, /*filterarg*/NULL,
20539217Sgibbs				       ADV_OVERRUN_BSIZE, /*nsegments*/1,
20639217Sgibbs				       BUS_SPACE_MAXSIZE_32BIT, /*flags*/0,
20739217Sgibbs				       &overrun_dmat) != 0) {
20839217Sgibbs			bus_dma_tag_destroy(adv->parent_dmat);
20939217Sgibbs			adv_free(adv);
21039217Sgibbs			return;
21139217Sgibbs       		}
21239217Sgibbs		if (bus_dmamem_alloc(overrun_dmat,
21339217Sgibbs				     (void **)&overrun_buf,
21439217Sgibbs				     BUS_DMA_NOWAIT,
21539217Sgibbs				     &overrun_dmamap) != 0) {
21639217Sgibbs			bus_dma_tag_destroy(overrun_dmat);
21739217Sgibbs			bus_dma_tag_destroy(adv->parent_dmat);
21839217Sgibbs			adv_free(adv);
21939217Sgibbs			return;
22039217Sgibbs		}
22139217Sgibbs		/* And permanently map it in */
22239217Sgibbs		bus_dmamap_load(overrun_dmat, overrun_dmamap,
22339217Sgibbs				overrun_buf, ADV_OVERRUN_BSIZE,
22439217Sgibbs				adv_map, &overrun_physbase,
22539217Sgibbs				/*flags*/0);
22639217Sgibbs	}
22739217Sgibbs
22839217Sgibbs	adv->overrun_physbase = overrun_physbase;
22939217Sgibbs
23039217Sgibbs	/*
23139217Sgibbs	 * Stop the chip.
23239217Sgibbs	 */
23339217Sgibbs	ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
23439217Sgibbs	ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
23539217Sgibbs
23639217Sgibbs	adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
23739217Sgibbs	adv->type = ADV_PCI;
23839217Sgibbs
23939217Sgibbs	/*
24039217Sgibbs	 * Setup active negation and signal filtering.
24139217Sgibbs	 */
24239217Sgibbs	{
24339217Sgibbs		u_int8_t extra_cfg;
24439217Sgibbs
24539217Sgibbs		if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150)
24639217Sgibbs			adv->type |= ADV_ULTRA;
24755945Sgibbs		if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050)
24839217Sgibbs			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER;
24939217Sgibbs		else
25039217Sgibbs			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE;
25139217Sgibbs		ADV_OUTB(adv, ADV_REG_IFC, extra_cfg);
25239217Sgibbs	}
25339217Sgibbs
25439217Sgibbs	if (adv_init(adv) != 0) {
25539217Sgibbs		adv_free(adv);
25639217Sgibbs		return;
25739217Sgibbs	}
25839217Sgibbs
25939217Sgibbs	adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT;
26039217Sgibbs	adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR;
26139217Sgibbs
26239217Sgibbs#if CC_DISABLE_PCI_PARITY_INT
26341591Sarchie	{
26441591Sarchie		u_int16_t config_msw;
26541591Sarchie
26641591Sarchie		config_msw = ADV_INW(adv, ADV_CONFIG_MSW);
26741591Sarchie		config_msw &= 0xFFC0;
26841591Sarchie		ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw);
26941591Sarchie	}
27039217Sgibbs#endif
27139217Sgibbs
27239217Sgibbs	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
27339217Sgibbs	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
27439217Sgibbs		adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB;
27539217Sgibbs		adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN;
27639217Sgibbs		adv->fix_asyn_xfer = ~0;
27739217Sgibbs	}
27839217Sgibbs
27939217Sgibbs	if ((pci_map_int(config_id, adv_intr, (void *)adv, &cam_imask)) == 0) {
28039217Sgibbs		adv_free(adv);
28139217Sgibbs		return;
28239217Sgibbs	}
28339217Sgibbs
28439217Sgibbs	adv_attach(adv);
28539217Sgibbs}
286