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$");
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;
14176307Snyan	int		error, rid, irqrid;
14259082Snyan	void		*ih;
14359082Snyan	struct resource	*iores, *irqres;
14459082Snyan
14539217Sgibbs	/*
14639217Sgibbs	 * Determine the chip version.
14739217Sgibbs	 */
148241492Sjhb	id = pci_get_devid(dev);
149241492Sjhb	pci_enable_busmaster(dev);
15039217Sgibbs
15139217Sgibbs	/*
15239217Sgibbs	 * Early chips can't handle non-zero latency timer settings.
15339217Sgibbs	 */
15439217Sgibbs	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
15539217Sgibbs	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
15659082Snyan		pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1);
15739217Sgibbs	}
15839217Sgibbs
15959171Snyan	rid = PCI_BASEADR0;
160127135Snjl	iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
161127135Snjl				       RF_ACTIVE);
16259082Snyan	if (iores == NULL)
16359082Snyan		return ENXIO;
16439217Sgibbs
165241492Sjhb	if (adv_find_signature(iores) == 0) {
16676307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
16759082Snyan		return ENXIO;
16859171Snyan	}
16939217Sgibbs
170241492Sjhb	adv = adv_alloc(dev, iores, 0);
17159171Snyan	if (adv == NULL) {
17276307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
17359082Snyan		return ENXIO;
17459171Snyan	}
17539217Sgibbs
17639217Sgibbs	/* Allocate a dmatag for our transfer DMA maps */
177112782Smdodd	error = bus_dma_tag_create(
178232854Sscottl			/* parent	*/ bus_get_dma_tag(dev),
179112782Smdodd			/* alignment	*/ 1,
180112782Smdodd			/* boundary	*/ 0,
181112782Smdodd			/* lowaddr	*/ ADV_PCI_MAX_DMA_ADDR,
182112782Smdodd			/* highaddr	*/ BUS_SPACE_MAXADDR,
183112782Smdodd			/* filter	*/ NULL,
184112782Smdodd			/* filterarg	*/ NULL,
185112782Smdodd			/* maxsize	*/ BUS_SPACE_MAXSIZE_32BIT,
186112782Smdodd			/* nsegments	*/ ~0,
187112782Smdodd			/* maxsegsz	*/ ADV_PCI_MAX_DMA_COUNT,
188112782Smdodd			/* flags	*/ 0,
189241492Sjhb			/* lockfunc	*/ NULL,
190241492Sjhb			/* lockarg	*/ NULL,
191112782Smdodd			&adv->parent_dmat);
19239217Sgibbs
19339217Sgibbs	if (error != 0) {
194241492Sjhb		device_printf(dev, "Could not allocate DMA tag - error %d\n",
195241492Sjhb		    error);
19639217Sgibbs		adv_free(adv);
19776307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
19859082Snyan		return ENXIO;
19939217Sgibbs	}
20039217Sgibbs
20139217Sgibbs	adv->init_level++;
20239217Sgibbs
20339217Sgibbs	if (overrun_buf == NULL) {
20439217Sgibbs		/* Need to allocate our overrun buffer */
205112782Smdodd		if (bus_dma_tag_create(
206112782Smdodd				/* parent	*/ adv->parent_dmat,
207112782Smdodd				/* alignment	*/ 8,
208112782Smdodd				/* boundary	*/ 0,
209112782Smdodd				/* lowaddr	*/ ADV_PCI_MAX_DMA_ADDR,
210112782Smdodd				/* highaddr	*/ BUS_SPACE_MAXADDR,
211112782Smdodd				/* filter	*/ NULL,
212112782Smdodd				/* filterarg	*/ NULL,
213112782Smdodd				/* maxsize	*/ ADV_OVERRUN_BSIZE,
214112782Smdodd				/* nsegments	*/ 1,
215112782Smdodd				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
216112782Smdodd				/* flags	*/ 0,
217241492Sjhb				/* lockfunc	*/ NULL,
218241492Sjhb				/* lockarg	*/ NULL,
219112782Smdodd				&overrun_dmat) != 0) {
22039217Sgibbs			bus_dma_tag_destroy(adv->parent_dmat);
22139217Sgibbs			adv_free(adv);
22276307Snyan			bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
22359082Snyan			return ENXIO;
22439217Sgibbs       		}
22539217Sgibbs		if (bus_dmamem_alloc(overrun_dmat,
226155319Simp				     &overrun_buf,
22739217Sgibbs				     BUS_DMA_NOWAIT,
22839217Sgibbs				     &overrun_dmamap) != 0) {
22939217Sgibbs			bus_dma_tag_destroy(overrun_dmat);
23039217Sgibbs			bus_dma_tag_destroy(adv->parent_dmat);
23139217Sgibbs			adv_free(adv);
23276307Snyan			bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
23359082Snyan			return ENXIO;
23439217Sgibbs		}
23539217Sgibbs		/* And permanently map it in */
23639217Sgibbs		bus_dmamap_load(overrun_dmat, overrun_dmamap,
23739217Sgibbs				overrun_buf, ADV_OVERRUN_BSIZE,
23839217Sgibbs				adv_map, &overrun_physbase,
23939217Sgibbs				/*flags*/0);
24039217Sgibbs	}
24139217Sgibbs
24239217Sgibbs	adv->overrun_physbase = overrun_physbase;
24339217Sgibbs
24439217Sgibbs	/*
24539217Sgibbs	 * Stop the chip.
24639217Sgibbs	 */
24739217Sgibbs	ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
24839217Sgibbs	ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
24939217Sgibbs
25039217Sgibbs	adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
25139217Sgibbs	adv->type = ADV_PCI;
25239217Sgibbs
25339217Sgibbs	/*
25439217Sgibbs	 * Setup active negation and signal filtering.
25539217Sgibbs	 */
25639217Sgibbs	{
25739217Sgibbs		u_int8_t extra_cfg;
25839217Sgibbs
25939217Sgibbs		if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150)
26039217Sgibbs			adv->type |= ADV_ULTRA;
26155945Sgibbs		if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050)
26239217Sgibbs			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER;
26339217Sgibbs		else
26439217Sgibbs			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE;
26539217Sgibbs		ADV_OUTB(adv, ADV_REG_IFC, extra_cfg);
26639217Sgibbs	}
26739217Sgibbs
26839217Sgibbs	if (adv_init(adv) != 0) {
26939217Sgibbs		adv_free(adv);
27076307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
27159082Snyan		return ENXIO;
27239217Sgibbs	}
27339217Sgibbs
27439217Sgibbs	adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT;
27539217Sgibbs	adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR;
27639217Sgibbs
277153072Sru#if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT
27841591Sarchie	{
27941591Sarchie		u_int16_t config_msw;
28041591Sarchie
28141591Sarchie		config_msw = ADV_INW(adv, ADV_CONFIG_MSW);
28241591Sarchie		config_msw &= 0xFFC0;
28341591Sarchie		ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw);
28441591Sarchie	}
28539217Sgibbs#endif
28639217Sgibbs
28739217Sgibbs	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
28839217Sgibbs	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
28939217Sgibbs		adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB;
29039217Sgibbs		adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN;
29139217Sgibbs		adv->fix_asyn_xfer = ~0;
29239217Sgibbs	}
29339217Sgibbs
29476307Snyan	irqrid = 0;
295127135Snjl	irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid,
296127135Snjl					RF_SHAREABLE | RF_ACTIVE);
29759082Snyan	if (irqres == NULL ||
298241492Sjhb	    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE,
299241492Sjhb	    NULL, adv_intr, adv, &ih) != 0) {
300241492Sjhb		if (irqres != NULL)
301241492Sjhb			bus_release_resource(dev, SYS_RES_IRQ, irqrid, irqres);
30239217Sgibbs		adv_free(adv);
30376307Snyan		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
30459082Snyan		return ENXIO;
30539217Sgibbs	}
30659082Snyan
307241492Sjhb	if (adv_attach(adv) != 0) {
308241492Sjhb		bus_teardown_intr(dev, irqres, ih);
309241492Sjhb		bus_release_resource(dev, SYS_RES_IRQ, irqrid, irqres);
310241492Sjhb		adv_free(adv);
311241492Sjhb		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
312241492Sjhb		return ENXIO;
313241492Sjhb	}
31459082Snyan	return 0;
31539217Sgibbs}
31659082Snyan
31759082Snyanstatic device_method_t adv_pci_methods[] = {
31859082Snyan	/* Device interface */
31959082Snyan	DEVMETHOD(device_probe,		adv_pci_probe),
32059082Snyan	DEVMETHOD(device_attach,	adv_pci_attach),
32159082Snyan	{ 0, 0 }
32259082Snyan};
32359082Snyan
32459082Snyanstatic driver_t adv_pci_driver = {
32559082Snyan	"adv", adv_pci_methods, sizeof(struct adv_softc)
32659082Snyan};
32759082Snyan
32859082Snyanstatic devclass_t adv_pci_devclass;
32959082SnyanDRIVER_MODULE(adv, pci, adv_pci_driver, adv_pci_devclass, 0, 0);
330165102SmjacobMODULE_DEPEND(adv, pci, 1, 1, 1);
331