aic_isa.c revision 127135
152417Sluoqi/*-
252417Sluoqi * Copyright (c) 1999 Luoqi Chen.
352417Sluoqi * All rights reserved.
452417Sluoqi *
552417Sluoqi * Redistribution and use in source and binary forms, with or without
652417Sluoqi * modification, are permitted provided that the following conditions
752417Sluoqi * are met:
852417Sluoqi * 1. Redistributions of source code must retain the above copyright
952417Sluoqi *    notice, this list of conditions and the following disclaimer.
1052417Sluoqi * 2. Redistributions in binary form must reproduce the above copyright
1152417Sluoqi *    notice, this list of conditions and the following disclaimer in the
1252417Sluoqi *    documentation and/or other materials provided with the distribution.
1352417Sluoqi *
1452417Sluoqi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1552417Sluoqi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1652417Sluoqi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1752417Sluoqi * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1852417Sluoqi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1952417Sluoqi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2052417Sluoqi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2152417Sluoqi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2252417Sluoqi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2352417Sluoqi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2452417Sluoqi * SUCH DAMAGE.
2552417Sluoqi */
2652417Sluoqi
27119418Sobrien#include <sys/cdefs.h>
28119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/aic/aic_isa.c 127135 2004-03-17 17:50:55Z njl $");
29119418Sobrien
3052417Sluoqi#include <sys/param.h>
3152417Sluoqi#include <sys/kernel.h>
3252417Sluoqi#include <sys/module.h>
3352417Sluoqi#include <sys/bus.h>
3452417Sluoqi
3552417Sluoqi#include <machine/bus_pio.h>
3652417Sluoqi#include <machine/bus.h>
3752417Sluoqi#include <machine/resource.h>
3852417Sluoqi#include <sys/rman.h>
3952417Sluoqi
4052417Sluoqi#include <isa/isavar.h>
4152417Sluoqi#include <dev/aic/aic6360reg.h>
4252417Sluoqi#include <dev/aic/aicvar.h>
4352417Sluoqi
4452417Sluoqistruct aic_isa_softc {
4552417Sluoqi	struct	aic_softc sc_aic;
4652417Sluoqi	struct	resource *sc_port;
4752417Sluoqi	struct	resource *sc_irq;
4852417Sluoqi	struct	resource *sc_drq;
4952417Sluoqi	void	*sc_ih;
5052417Sluoqi};
5152417Sluoqi
5292739Salfredstatic int aic_isa_alloc_resources(device_t);
5392739Salfredstatic void aic_isa_release_resources(device_t);
5492739Salfredstatic int aic_isa_probe(device_t);
5592739Salfredstatic int aic_isa_attach(device_t);
5652417Sluoqi
5752417Sluoqistatic u_int aic_isa_ports[] = { 0x340, 0x140 };
5852417Sluoqi#define	AIC_ISA_NUMPORTS (sizeof(aic_isa_ports) / sizeof(aic_isa_ports[0]))
5952417Sluoqi#define	AIC_ISA_PORTSIZE 0x20
6052417Sluoqi
6177844Simpstatic struct isa_pnp_id aic_ids[] = {
6277844Simp	{ 0x15309004, "Adaptec AHA-1530P" },
6377844Simp	{ 0x15209004, "Adaptec AHA-1520P" },
6477844Simp 	{ 0 }
6577844Simp};
6677844Simp
6752417Sluoqistatic int
6852417Sluoqiaic_isa_alloc_resources(device_t dev)
6952417Sluoqi{
7052417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
7152417Sluoqi	int rid;
7252417Sluoqi
7352417Sluoqi	sc->sc_port = sc->sc_irq = sc->sc_drq = 0;
7452417Sluoqi
7552417Sluoqi	rid = 0;
7652417Sluoqi	sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
7752417Sluoqi					0ul, ~0ul, AIC_ISA_PORTSIZE, RF_ACTIVE);
7874370Sken	if (!sc->sc_port) {
7974370Sken		device_printf(dev, "I/O port allocation failed\n");
8052417Sluoqi		return (ENOMEM);
8174370Sken	}
8252417Sluoqi
8352417Sluoqi	if (isa_get_irq(dev) != -1) {
8452417Sluoqi		rid = 0;
85127135Snjl		sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
86127135Snjl						    RF_ACTIVE);
8752417Sluoqi		if (!sc->sc_irq) {
8874370Sken			device_printf(dev, "IRQ allocation failed\n");
8952417Sluoqi			aic_isa_release_resources(dev);
9052417Sluoqi			return (ENOMEM);
9152417Sluoqi		}
9252417Sluoqi	}
9352417Sluoqi
9452417Sluoqi	if (isa_get_drq(dev) != -1) {
9552417Sluoqi		rid = 0;
96127135Snjl		sc->sc_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid,
97127135Snjl						    RF_ACTIVE);
9852417Sluoqi		if (!sc->sc_drq) {
9974370Sken			device_printf(dev, "DRQ allocation failed\n");
10052417Sluoqi			aic_isa_release_resources(dev);
10152417Sluoqi			return (ENOMEM);
10252417Sluoqi		}
10352417Sluoqi	}
10452417Sluoqi
10552417Sluoqi	sc->sc_aic.unit = device_get_unit(dev);
10652417Sluoqi	sc->sc_aic.tag = rman_get_bustag(sc->sc_port);
10752417Sluoqi	sc->sc_aic.bsh = rman_get_bushandle(sc->sc_port);
10852417Sluoqi	return (0);
10952417Sluoqi}
11052417Sluoqi
11152417Sluoqistatic void
11252417Sluoqiaic_isa_release_resources(device_t dev)
11352417Sluoqi{
11452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
11552417Sluoqi
11652417Sluoqi	if (sc->sc_port)
11752417Sluoqi		bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port);
11852417Sluoqi	if (sc->sc_irq)
11952417Sluoqi		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq);
12052417Sluoqi	if (sc->sc_drq)
12152417Sluoqi		bus_release_resource(dev, SYS_RES_DRQ, 0, sc->sc_drq);
12252417Sluoqi	sc->sc_port = sc->sc_irq = sc->sc_drq = 0;
12352417Sluoqi}
12452417Sluoqi
12552417Sluoqistatic int
12652417Sluoqiaic_isa_probe(device_t dev)
12752417Sluoqi{
12852417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
12952417Sluoqi	struct aic_softc *aic = &sc->sc_aic;
13052417Sluoqi	int numports, i;
13152417Sluoqi	u_int port, *ports;
13252417Sluoqi	u_int8_t porta;
13352417Sluoqi
13477844Simp	if (ISA_PNP_PROBE(device_get_parent(dev), dev, aic_ids) == ENXIO)
13552417Sluoqi		return (ENXIO);
13652417Sluoqi
13752417Sluoqi	port = isa_get_port(dev);
13852417Sluoqi	if (port != -1) {
13952417Sluoqi		ports = &port;
14052417Sluoqi		numports = 1;
14152417Sluoqi	} else {
14252417Sluoqi		ports = aic_isa_ports;
14352417Sluoqi		numports = AIC_ISA_NUMPORTS;
14452417Sluoqi	}
14552417Sluoqi
14652417Sluoqi	for (i = 0; i < numports; i++) {
14752417Sluoqi		if (bus_set_resource(dev, SYS_RES_IOPORT, 0, ports[i],
14852417Sluoqi				     AIC_ISA_PORTSIZE))
14952417Sluoqi			continue;
15052417Sluoqi		if (aic_isa_alloc_resources(dev))
15152417Sluoqi			continue;
15252417Sluoqi		if (!aic_probe(aic)) {
15352417Sluoqi			aic_isa_release_resources(dev);
15452417Sluoqi			break;
15552417Sluoqi		}
15652417Sluoqi		aic_isa_release_resources(dev);
15752417Sluoqi	}
15852417Sluoqi
15952417Sluoqi	if (i == numports)
16052417Sluoqi		return (ENXIO);
16152417Sluoqi
16252417Sluoqi	porta = aic_inb(aic, PORTA);
16352417Sluoqi	if (isa_get_irq(dev) == -1)
16452417Sluoqi		bus_set_resource(dev, SYS_RES_IRQ, 0, PORTA_IRQ(porta), 1);
16552417Sluoqi	if ((aic->flags & AIC_DMA_ENABLE) && isa_get_drq(dev) == -1)
16652417Sluoqi		bus_set_resource(dev, SYS_RES_DRQ, 0, PORTA_DRQ(porta), 1);
16754136Sluoqi	device_set_desc(dev, "Adaptec 6260/6360 SCSI controller");
16852417Sluoqi	return (0);
16952417Sluoqi}
17052417Sluoqi
17152417Sluoqistatic int
17252417Sluoqiaic_isa_attach(device_t dev)
17352417Sluoqi{
17452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
17552417Sluoqi	struct aic_softc *aic = &sc->sc_aic;
17652417Sluoqi	int error;
17752417Sluoqi
17852417Sluoqi	error = aic_isa_alloc_resources(dev);
17952417Sluoqi	if (error) {
18052417Sluoqi		device_printf(dev, "resource allocation failed\n");
18152417Sluoqi		return (error);
18252417Sluoqi	}
18352417Sluoqi
18452417Sluoqi	error = aic_attach(aic);
18552417Sluoqi	if (error) {
18652417Sluoqi		device_printf(dev, "attach failed\n");
18752417Sluoqi		aic_isa_release_resources(dev);
18852417Sluoqi		return (error);
18952417Sluoqi	}
19052417Sluoqi
19173280Smarkm	error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_CAM|INTR_ENTROPY,
19273280Smarkm				aic_intr, aic, &sc->sc_ih);
19352417Sluoqi	if (error) {
19452417Sluoqi		device_printf(dev, "failed to register interrupt handler\n");
19552417Sluoqi		aic_isa_release_resources(dev);
19652417Sluoqi		return (error);
19752417Sluoqi	}
19852417Sluoqi	return (0);
19952417Sluoqi}
20052417Sluoqi
20152417Sluoqistatic int
20252417Sluoqiaic_isa_detach(device_t dev)
20352417Sluoqi{
20452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
20552417Sluoqi	struct aic_softc *aic = &sc->sc_aic;
20652417Sluoqi	int error;
20752417Sluoqi
20852417Sluoqi	error = aic_detach(aic);
20952417Sluoqi	if (error) {
21052417Sluoqi		device_printf(dev, "detach failed\n");
21152417Sluoqi		return (error);
21252417Sluoqi	}
21352417Sluoqi
21452417Sluoqi	error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
21552417Sluoqi	if (error) {
21652417Sluoqi		device_printf(dev, "failed to unregister interrupt handler\n");
21752417Sluoqi	}
21852417Sluoqi
21952417Sluoqi	aic_isa_release_resources(dev);
22052417Sluoqi	return (0);
22152417Sluoqi}
22252417Sluoqi
22352417Sluoqistatic device_method_t aic_isa_methods[] = {
22452417Sluoqi	/* Device interface */
22552417Sluoqi	DEVMETHOD(device_probe,		aic_isa_probe),
22652417Sluoqi	DEVMETHOD(device_attach,	aic_isa_attach),
22752417Sluoqi	DEVMETHOD(device_detach,	aic_isa_detach),
22852417Sluoqi	{ 0, 0 }
22952417Sluoqi};
23052417Sluoqi
23152417Sluoqistatic driver_t aic_isa_driver = {
23252417Sluoqi	"aic",
23352417Sluoqi	aic_isa_methods, sizeof(struct aic_isa_softc),
23452417Sluoqi};
23552417Sluoqi
23655997Simpextern devclass_t aic_devclass;
23752417Sluoqi
23869960SimpMODULE_DEPEND(aic, cam, 1,1,1);
23952417SluoqiDRIVER_MODULE(aic, isa, aic_isa_driver, aic_devclass, 0, 0);
240