aha_mca.c revision 302408
118334Speter/*-
2132718Skan * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
3169689Skan * All rights reserved.
4169689Skan *
518334Speter * Redistribution and use in source and binary forms, with or without
690075Sobrien * modification, are permitted provided that the following conditions
718334Speter * are met:
890075Sobrien * 1. Redistributions of source code must retain the above copyright
990075Sobrien *    notice, this list of conditions and the following disclaimer.
1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1190075Sobrien *    notice, this list of conditions and the following disclaimer in the
1218334Speter *    documentation and/or other materials provided with the distribution.
1390075Sobrien *
1490075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1590075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1690075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1718334Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1818334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1990075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2218334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2318334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2450397Sobrien * SUCH DAMAGE.
25132718Skan *
26132718Skan * Based on aha_isa.c
2750397Sobrien */
2850397Sobrien
2950397Sobrien#include <sys/cdefs.h>
3050397Sobrien__FBSDID("$FreeBSD: stable/11/sys/dev/aha/aha_mca.c 241611 2012-10-16 15:25:04Z pluknet $");
31132718Skan
3290075Sobrien#include <sys/types.h>
3390075Sobrien#include <sys/param.h>
3450397Sobrien#include <sys/systm.h>
3550397Sobrien#include <sys/kernel.h>
3650397Sobrien#include <sys/lock.h>
3790075Sobrien#include <sys/mutex.h>
3890075Sobrien
3990075Sobrien#include <sys/module.h>
40117395Skan#include <sys/bus.h>
41117395Skan#include <machine/bus.h>
42132718Skan#include <machine/resource.h>
43117395Skan#include <sys/rman.h>
4418334Speter
4552284Sobrien#include <isa/isavar.h>
4652284Sobrien
4718334Speter#include <dev/mca/mca_busreg.h>
4818334Speter#include <dev/mca/mca_busvar.h>
4918334Speter
5018334Speter#include <dev/aha/ahareg.h>
5118334Speter
5218334Speterstatic struct mca_ident aha_mca_devs[] = {
5318334Speter	{ 0x0f1f, "Adaptec AHA-1640 SCSI Adapter" },
5418334Speter	{ 0, NULL },
5518334Speter};
5618334Speter
5718334Speter#define AHA_MCA_IOPORT_POS		MCA_ADP_POS(MCA_POS1)
5818334Speter# define AHA_MCA_IOPORT_MASK1		0x07
5918334Speter# define AHA_MCA_IOPORT_MASK2		0xc0
6018334Speter# define AHA_MCA_IOPORT_SIZE		0x03
6150397Sobrien# define AHA_MCA_IOPORT(pos)		(0x30 + \
6218334Speter					(((uint32_t)pos & \
6318334Speter						AHA_MCA_IOPORT_MASK1) << 8) + \
6490075Sobrien					(((uint32_t)pos & \
6590075Sobrien						AHA_MCA_IOPORT_MASK2) >> 4))
6690075Sobrien
6790075Sobrien#define AHA_MCA_DRQ_POS			MCA_ADP_POS(MCA_POS3)
68169689Skan# define AHA_MCA_DRQ_MASK		0x0f
69169689Skan# define AHA_MCA_DRQ(pos)		(pos & AHA_MCA_DRQ_MASK)
70169689Skan
7118334Speter#define AHA_MCA_IRQ_POS			MCA_ADP_POS(MCA_POS2)
7218334Speter# define AHA_MCA_IRQ_MASK		0x07
7318334Speter# define AHA_MCA_IRQ(pos)		((pos & AHA_MCA_IRQ_MASK) + 8)
74169689Skan
75169689Skan/*
7618334Speter * Not needed as the board knows its config
77117395Skan * internally and the ID will be fetched
7818334Speter * via AOP_INQUIRE_SETUP_INFO command.
7918334Speter */
8018334Speter#define AHA_MCA_SCSIID_POS		MCA_ADP_POS(MCA_POS2)
8118334Speter#define AHA_MCA_SCSIID_MASK		0xe0
82132718Skan#define AHA_MCA_SCSIID(pos)		((pos & AHA_MCA_SCSIID_MASK) >> 5)
83132718Skan
8418334Speterstatic int
8518334Speteraha_mca_probe (device_t dev)
8618334Speter{
8718334Speter	const char *	desc;
8818334Speter	mca_id_t	id = mca_get_id(dev);
8918334Speter	uint32_t	iobase = 0;
9018334Speter	uint32_t	iosize = 0;
9118334Speter	uint8_t		drq = 0;
9218334Speter	uint8_t		irq = 0;
9318334Speter	uint8_t		pos;
9418334Speter
9518334Speter	desc = mca_match_id(id, aha_mca_devs);
9618334Speter	if (!desc)
9718334Speter		return (ENXIO);
9818334Speter	device_set_desc(dev, desc);
9918334Speter
10018334Speter	pos = mca_pos_read(dev, AHA_MCA_IOPORT_POS);
101117395Skan	iobase = AHA_MCA_IOPORT(pos);
10218334Speter	iosize = AHA_MCA_IOPORT_SIZE;
10318334Speter
10418334Speter	pos = mca_pos_read(dev, AHA_MCA_DRQ_POS);
10518334Speter	drq = AHA_MCA_DRQ(pos);
10618334Speter
10718334Speter	pos = mca_pos_read(dev, AHA_MCA_IRQ_POS);
10818334Speter	irq = AHA_MCA_IRQ(pos);
10918334Speter
11090075Sobrien	mca_add_iospace(dev, iobase, iosize);
11190075Sobrien	mca_add_drq(dev, drq);
11290075Sobrien	mca_add_irq(dev, irq);
11390075Sobrien
11490075Sobrien	return (0);
11590075Sobrien}
11690075Sobrien
11718334Speterstatic int
11818334Speteraha_mca_attach (device_t dev)
11918334Speter{
12018334Speter	struct aha_softc *	sc = device_get_softc(dev);
12118334Speter	int			error = ENOMEM;
122169689Skan
12318334Speter	sc->portrid = 0;
124169689Skan	sc->port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->portrid,
125132718Skan	    RF_ACTIVE);
126132718Skan	if (sc->port == NULL) {
127132718Skan		device_printf(dev, "No I/O space?!\n");
128132718Skan		goto bad;
129132718Skan	}
130132718Skan
131132718Skan	sc->irqrid = 0;
132132718Skan	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
133132718Skan	    RF_ACTIVE);
134132718Skan	if (sc->irq == NULL) {
135132718Skan		device_printf(dev, "No IRQ?!\n");
136132718Skan		goto bad;
137132718Skan	}
138169689Skan
139132718Skan	sc->drqrid = 0;
140132718Skan	sc->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &sc->drqrid,
141132718Skan	    RF_ACTIVE);
142132718Skan	if (sc->drq == NULL) {
143132718Skan		device_printf(dev, "No DRQ?!\n");
144132718Skan		goto bad;
145132718Skan	}
146132718Skan
147132718Skan	aha_alloc(sc);
14890075Sobrien	error = aha_probe(sc);
149132718Skan	if (error) {
150169689Skan		device_printf(dev, "aha_probe() failed!\n");
151169689Skan		goto bad;
152169689Skan	}
15390075Sobrien
15490075Sobrien	error = aha_fetch_adapter_info(sc);
155132718Skan	if (error) {
156132718Skan		device_printf(dev, "aha_fetch_adapter_info() failed!\n");
15752284Sobrien		goto bad;
15818334Speter	}
15918334Speter
16018334Speter	isa_dmacascade(rman_get_start(sc->drq));
16118334Speter
16218334Speter	error = bus_dma_tag_create(
16318334Speter				/* parent	*/ bus_get_dma_tag(dev),
16418334Speter				/* alignemnt	*/ 1,
16518334Speter				/* boundary	*/ 0,
16618334Speter				/* lowaddr	*/ BUS_SPACE_MAXADDR_24BIT,
167169689Skan				/* highaddr	*/ BUS_SPACE_MAXADDR,
168169689Skan				/* filter	*/ NULL,
16918334Speter				/* filterarg	*/ NULL,
170132718Skan				/* maxsize	*/ BUS_SPACE_MAXSIZE_24BIT,
17118334Speter				/* nsegments	*/ ~0,
17218334Speter				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
17318334Speter				/* flags	*/ 0,
17450397Sobrien				/* lockfunc	*/ NULL,
17550397Sobrien				/* lockarg	*/ NULL,
17650397Sobrien				&sc->parent_dmat);
17750397Sobrien	if (error) {
17890075Sobrien		device_printf(dev, "bus_dma_tag_create() failed!\n");
17918334Speter		goto bad;
18018334Speter	}
18118334Speter
182169689Skan	error = aha_init(sc);
18318334Speter	if (error) {
18418334Speter		device_printf(dev, "aha_init() failed\n");
18518334Speter		goto bad;
18618334Speter	}
18718334Speter
188169689Skan	error = aha_attach(sc);
18918334Speter	if (error) {
19018334Speter		device_printf(dev, "aha_attach() failed\n");
191169689Skan		goto bad;
19218334Speter	}
19318334Speter
19418334Speter	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_CAM | INTR_ENTROPY |
19518334Speter	    INTR_MPSAFE, NULL, aha_intr, sc, &sc->ih);
19618334Speter	if (error) {
19718334Speter		device_printf(dev, "Unable to register interrupt handler\n");
19818334Speter		aha_detach(sc);
19918334Speter		goto bad;
20018334Speter	}
20118334Speter
20250397Sobrien	return (0);
20318334Speter
20418334Speterbad:
20550397Sobrien	aha_free(sc);
20650397Sobrien	bus_free_resource(dev, SYS_RES_IOPORT, sc->port);
20750397Sobrien	bus_free_resource(dev, SYS_RES_IRQ, sc->irq);
20850397Sobrien	bus_free_resource(dev, SYS_RES_DRQ, sc->drq);
20950397Sobrien	return (error);
21018334Speter}
21118334Speter
21290075Sobrienstatic device_method_t aha_mca_methods[] = {
21390075Sobrien	DEVMETHOD(device_probe,         aha_mca_probe),
21490075Sobrien	DEVMETHOD(device_attach,        aha_mca_attach),
21590075Sobrien
21618334Speter	{ 0, 0 }
21718334Speter};
21818334Speter
21918334Speterstatic driver_t aha_mca_driver = {
22018334Speter	"aha",
22118334Speter	aha_mca_methods,
22218334Speter	1,
22318334Speter/*
22418334Speter	sizeof(struct aha_softc *),
22518334Speter */
22618334Speter};
22718334Speter
22818334Speterstatic devclass_t aha_devclass;
22918334Speter
23018334SpeterDRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0);
23118334SpeterMODULE_DEPEND(aha, mca, 1, 1, 1);
23218334Speter