adv_pci.c revision 165102
1139749Simp/*-
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 *	ABP960		- Bus-Master PCI MAC/PC (16 CDB) **
1657679Sgibbs *	ABP960U		- Bus-Master PCI MAC/PC (16 CDB) **
1739217Sgibbs *
1839217Sgibbs *   Single Channel Products:
1957679Sgibbs *	ABP940		- Bus-Master PCI (240 CDB)
2057679Sgibbs *	ABP940U		- Bus-Master PCI Ultra (240 CDB)
2157679Sgibbs *	ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB)
2257679Sgibbs *	ABP3960UA	- Bus-Master PCI MAC/PC (240 CDB)
2357679Sgibbs *	ABP970		- Bus-Master PCI MAC/PC (240 CDB)
2457679Sgibbs *	ABP970U		- Bus-Master PCI MAC/PC Ultra (240 CDB)
2539217Sgibbs *
2639217Sgibbs *   Dual Channel Products:
2739217Sgibbs *	ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
2857679Sgibbs *      ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
2957679Sgibbs *      ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
3055945Sgibbs *	ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.)
3139217Sgibbs *
3239217Sgibbs *   Footnotes:
3339217Sgibbs *	 * This board has been sold by SIIG as the Fast SCSI Pro PCI.
3439217Sgibbs *	** This board has been sold by Iomega as a Jaz Jet PCI adapter.
3539217Sgibbs *
3639217Sgibbs * Copyright (c) 1997 Justin Gibbs.
3739217Sgibbs * All rights reserved.
3839217Sgibbs *
3939217Sgibbs * Redistribution and use in source and binary forms, with or without
4039217Sgibbs * modification, are permitted provided that the following conditions
4139217Sgibbs * are met:
4239217Sgibbs * 1. Redistributions of source code must retain the above copyright
4339217Sgibbs *    notice, this list of conditions, and the following disclaimer,
4455945Sgibbs *    without modification.
4539217Sgibbs * 2. The name of the author may not be used to endorse or promote products
4639217Sgibbs *    derived from this software without specific prior written permission.
4739217Sgibbs *
4839217Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4939217Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5039217Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5139217Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
5239217Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5339217Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5439217Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5539217Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5639217Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5739217Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5839217Sgibbs * SUCH DAMAGE.
5939217Sgibbs */
6039217Sgibbs
61119418Sobrien#include <sys/cdefs.h>
62119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/advansys/adv_pci.c 165102 2006-12-11 18:28:31Z mjacob $");
63119418Sobrien
6439217Sgibbs#include <sys/param.h>
6539217Sgibbs#include <sys/systm.h>
6639217Sgibbs#include <sys/kernel.h>
67117126Sscottl#include <sys/lock.h>
68129879Sphk#include <sys/module.h>
69117126Sscottl#include <sys/mutex.h>
7039217Sgibbs
7139217Sgibbs#include <machine/bus.h>
7259082Snyan#include <machine/resource.h>
7359082Snyan#include <sys/bus.h>
7459082Snyan#include <sys/rman.h>
7539217Sgibbs
76119277Simp#include <dev/pci/pcireg.h>
77119277Simp#include <dev/pci/pcivar.h>
7839217Sgibbs
7939217Sgibbs#include <dev/advansys/advansys.h>
8039217Sgibbs
81119690Sjhb#define PCI_BASEADR0	PCIR_BAR(0)		/* I/O Address */
82119690Sjhb#define PCI_BASEADR1	PCIR_BAR(1)		/* Mem I/O Address */
8339217Sgibbs
8439217Sgibbs#define	PCI_DEVICE_ID_ADVANSYS_1200A	0x110010CD
8539217Sgibbs#define	PCI_DEVICE_ID_ADVANSYS_1200B	0x120010CD
8655945Sgibbs#define	PCI_DEVICE_ID_ADVANSYS_3000	0x130010CD
8739217Sgibbs#define	PCI_DEVICE_REV_ADVANSYS_3150	0x02
8839217Sgibbs#define	PCI_DEVICE_REV_ADVANSYS_3050	0x03
8939217Sgibbs
9039217Sgibbs#define ADV_PCI_MAX_DMA_ADDR    (0xFFFFFFFFL)
9139217Sgibbs#define ADV_PCI_MAX_DMA_COUNT   (0xFFFFFFFFL)
9239217Sgibbs
9359082Snyanstatic int adv_pci_probe(device_t);
9459082Snyanstatic int adv_pci_attach(device_t);
9539217Sgibbs
9639217Sgibbs/*
9739217Sgibbs * The overrun buffer shared amongst all PCI adapters.
9839217Sgibbs */
99155319Simpstatic  void*		overrun_buf;
10042012Sgibbsstatic	bus_dma_tag_t	overrun_dmat;
10142012Sgibbsstatic	bus_dmamap_t	overrun_dmamap;
10242012Sgibbsstatic	bus_addr_t	overrun_physbase;
10339217Sgibbs
10459082Snyanstatic int
10559082Snyanadv_pci_probe(device_t dev)
10639217Sgibbs{
10759082Snyan	int	rev = pci_get_revid(dev);
10855945Sgibbs
10959082Snyan	switch (pci_get_devid(dev)) {
11039217Sgibbs	case PCI_DEVICE_ID_ADVANSYS_1200A:
11159082Snyan		device_set_desc(dev, "AdvanSys ASC1200A SCSI controller");
112143164Simp		return BUS_PROBE_DEFAULT;
11339217Sgibbs	case PCI_DEVICE_ID_ADVANSYS_1200B:
11459082Snyan		device_set_desc(dev, "AdvanSys ASC1200B SCSI controller");
115143164Simp		return BUS_PROBE_DEFAULT;
11655945Sgibbs	case PCI_DEVICE_ID_ADVANSYS_3000:
11759082Snyan		if (rev == PCI_DEVICE_REV_ADVANSYS_3150) {
11859082Snyan			device_set_desc(dev,
11959082Snyan					"AdvanSys ASC3150 SCSI controller");
120143164Simp			return BUS_PROBE_DEFAULT;
12159082Snyan		} else if (rev == PCI_DEVICE_REV_ADVANSYS_3050) {
12259082Snyan			device_set_desc(dev,
12359082Snyan					"AdvanSys ASC3030/50 SCSI controller");
124143164Simp			return BUS_PROBE_DEFAULT;
12559082Snyan		} else if (rev >= PCI_DEVICE_REV_ADVANSYS_3150) {
12659082Snyan			device_set_desc(dev, "Unknown AdvanSys controller");
127143164Simp			return BUS_PROBE_DEFAULT;
12859082Snyan		}
12939217Sgibbs		break;
13039217Sgibbs	default:
13139217Sgibbs		break;
13239217Sgibbs	}
13359082Snyan	return ENXIO;
13439217Sgibbs}
13539217Sgibbs
13659082Snyanstatic int
13759082Snyanadv_pci_attach(device_t dev)
13839217Sgibbs{
13939217Sgibbs	struct		adv_softc *adv;
14039217Sgibbs	u_int32_t	id;
14139217Sgibbs	u_int32_t	command;
14276307Snyan	int		error, rid, irqrid;
14359082Snyan	void		*ih;
14459082Snyan	struct resource	*iores, *irqres;
14559082Snyan
14639217Sgibbs	/*
14739217Sgibbs	 * Determine the chip version.
14839217Sgibbs	 */
14961034Speter	id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4);
15059082Snyan	command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
15139217Sgibbs
15239217Sgibbs	/*
15339217Sgibbs	 * These cards do not allow memory mapped accesses, so we must
15439217Sgibbs	 * ensure that I/O accesses are available or we won't be able
15539217Sgibbs	 * to talk to them.
15639217Sgibbs	 */
15739217Sgibbs	if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN))
15839217Sgibbs	 != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) {
15939217Sgibbs		command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN;
16059082Snyan		pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1);
16139217Sgibbs	}
16239217Sgibbs
16339217Sgibbs	/*
16439217Sgibbs	 * Early chips can't handle non-zero latency timer settings.
16539217Sgibbs	 */
16639217Sgibbs	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
16739217Sgibbs	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
16859082Snyan		pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1);
16939217Sgibbs	}
17039217Sgibbs
17159171Snyan	rid = PCI_BASEADR0;
172127135Snjl	iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
173127135Snjl				       RF_ACTIVE);
17459082Snyan	if (iores == NULL)
17559082Snyan		return ENXIO;
17639217Sgibbs
17759082Snyan	if (adv_find_signature(rman_get_bustag(iores),
17859171Snyan			       rman_get_bushandle(iores)) == 0) {
17976307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
18059082Snyan		return ENXIO;
18159171Snyan	}
18239217Sgibbs
18359082Snyan	adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores));
18459171Snyan	if (adv == NULL) {
18576307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
18659082Snyan		return ENXIO;
18759171Snyan	}
18839217Sgibbs
18939217Sgibbs	/* Allocate a dmatag for our transfer DMA maps */
19039217Sgibbs	/* XXX Should be a child of the PCI bus dma tag */
191112782Smdodd	error = bus_dma_tag_create(
192112782Smdodd			/* parent	*/ NULL,
193112782Smdodd			/* alignment	*/ 1,
194112782Smdodd			/* boundary	*/ 0,
195112782Smdodd			/* lowaddr	*/ ADV_PCI_MAX_DMA_ADDR,
196112782Smdodd			/* highaddr	*/ BUS_SPACE_MAXADDR,
197112782Smdodd			/* filter	*/ NULL,
198112782Smdodd			/* filterarg	*/ NULL,
199112782Smdodd			/* maxsize	*/ BUS_SPACE_MAXSIZE_32BIT,
200112782Smdodd			/* nsegments	*/ ~0,
201112782Smdodd			/* maxsegsz	*/ ADV_PCI_MAX_DMA_COUNT,
202112782Smdodd			/* flags	*/ 0,
203117126Sscottl			/* lockfunc	*/ busdma_lock_mutex,
204117126Sscottl			/* lockarg	*/ &Giant,
205112782Smdodd			&adv->parent_dmat);
20639217Sgibbs
20739217Sgibbs	if (error != 0) {
20839217Sgibbs		printf("%s: Could not allocate DMA tag - error %d\n",
20939217Sgibbs		       adv_name(adv), error);
21039217Sgibbs		adv_free(adv);
21176307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
21259082Snyan		return ENXIO;
21339217Sgibbs	}
21439217Sgibbs
21539217Sgibbs	adv->init_level++;
21639217Sgibbs
21739217Sgibbs	if (overrun_buf == NULL) {
21839217Sgibbs		/* Need to allocate our overrun buffer */
219112782Smdodd		if (bus_dma_tag_create(
220112782Smdodd				/* parent	*/ adv->parent_dmat,
221112782Smdodd				/* alignment	*/ 8,
222112782Smdodd				/* boundary	*/ 0,
223112782Smdodd				/* lowaddr	*/ ADV_PCI_MAX_DMA_ADDR,
224112782Smdodd				/* highaddr	*/ BUS_SPACE_MAXADDR,
225112782Smdodd				/* filter	*/ NULL,
226112782Smdodd				/* filterarg	*/ NULL,
227112782Smdodd				/* maxsize	*/ ADV_OVERRUN_BSIZE,
228112782Smdodd				/* nsegments	*/ 1,
229112782Smdodd				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
230112782Smdodd				/* flags	*/ 0,
231117126Sscottl				/* lockfunc	*/ busdma_lock_mutex,
232117126Sscottl				/* lockarg	*/ &Giant,
233112782Smdodd				&overrun_dmat) != 0) {
23439217Sgibbs			bus_dma_tag_destroy(adv->parent_dmat);
23539217Sgibbs			adv_free(adv);
23676307Snyan			bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
23759082Snyan			return ENXIO;
23839217Sgibbs       		}
23939217Sgibbs		if (bus_dmamem_alloc(overrun_dmat,
240155319Simp				     &overrun_buf,
24139217Sgibbs				     BUS_DMA_NOWAIT,
24239217Sgibbs				     &overrun_dmamap) != 0) {
24339217Sgibbs			bus_dma_tag_destroy(overrun_dmat);
24439217Sgibbs			bus_dma_tag_destroy(adv->parent_dmat);
24539217Sgibbs			adv_free(adv);
24676307Snyan			bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
24759082Snyan			return ENXIO;
24839217Sgibbs		}
24939217Sgibbs		/* And permanently map it in */
25039217Sgibbs		bus_dmamap_load(overrun_dmat, overrun_dmamap,
25139217Sgibbs				overrun_buf, ADV_OVERRUN_BSIZE,
25239217Sgibbs				adv_map, &overrun_physbase,
25339217Sgibbs				/*flags*/0);
25439217Sgibbs	}
25539217Sgibbs
25639217Sgibbs	adv->overrun_physbase = overrun_physbase;
25739217Sgibbs
25839217Sgibbs	/*
25939217Sgibbs	 * Stop the chip.
26039217Sgibbs	 */
26139217Sgibbs	ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
26239217Sgibbs	ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
26339217Sgibbs
26439217Sgibbs	adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
26539217Sgibbs	adv->type = ADV_PCI;
26639217Sgibbs
26739217Sgibbs	/*
26839217Sgibbs	 * Setup active negation and signal filtering.
26939217Sgibbs	 */
27039217Sgibbs	{
27139217Sgibbs		u_int8_t extra_cfg;
27239217Sgibbs
27339217Sgibbs		if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150)
27439217Sgibbs			adv->type |= ADV_ULTRA;
27555945Sgibbs		if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050)
27639217Sgibbs			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER;
27739217Sgibbs		else
27839217Sgibbs			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE;
27939217Sgibbs		ADV_OUTB(adv, ADV_REG_IFC, extra_cfg);
28039217Sgibbs	}
28139217Sgibbs
28239217Sgibbs	if (adv_init(adv) != 0) {
28339217Sgibbs		adv_free(adv);
28476307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
28559082Snyan		return ENXIO;
28639217Sgibbs	}
28739217Sgibbs
28839217Sgibbs	adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT;
28939217Sgibbs	adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR;
29039217Sgibbs
291153072Sru#if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT
29241591Sarchie	{
29341591Sarchie		u_int16_t config_msw;
29441591Sarchie
29541591Sarchie		config_msw = ADV_INW(adv, ADV_CONFIG_MSW);
29641591Sarchie		config_msw &= 0xFFC0;
29741591Sarchie		ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw);
29841591Sarchie	}
29939217Sgibbs#endif
30039217Sgibbs
30139217Sgibbs	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
30239217Sgibbs	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
30339217Sgibbs		adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB;
30439217Sgibbs		adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN;
30539217Sgibbs		adv->fix_asyn_xfer = ~0;
30639217Sgibbs	}
30739217Sgibbs
30876307Snyan	irqrid = 0;
309127135Snjl	irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid,
310127135Snjl					RF_SHAREABLE | RF_ACTIVE);
31159082Snyan	if (irqres == NULL ||
31273280Smarkm	    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, adv, &ih)) {
31339217Sgibbs		adv_free(adv);
31476307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
31559082Snyan		return ENXIO;
31639217Sgibbs	}
31759082Snyan
31839217Sgibbs	adv_attach(adv);
31959082Snyan	return 0;
32039217Sgibbs}
32159082Snyan
32259082Snyanstatic device_method_t adv_pci_methods[] = {
32359082Snyan	/* Device interface */
32459082Snyan	DEVMETHOD(device_probe,		adv_pci_probe),
32559082Snyan	DEVMETHOD(device_attach,	adv_pci_attach),
32659082Snyan	{ 0, 0 }
32759082Snyan};
32859082Snyan
32959082Snyanstatic driver_t adv_pci_driver = {
33059082Snyan	"adv", adv_pci_methods, sizeof(struct adv_softc)
33159082Snyan};
33259082Snyan
33359082Snyanstatic devclass_t adv_pci_devclass;
33459082SnyanDRIVER_MODULE(adv, pci, adv_pci_driver, adv_pci_devclass, 0, 0);
335165102SmjacobMODULE_DEPEND(adv, pci, 1, 1, 1);
336