aic_isa.c revision 55997
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 * $FreeBSD: head/sys/dev/aic/aic_isa.c 55997 2000-01-14 23:42:36Z imp $
2752417Sluoqi */
2852417Sluoqi
2952417Sluoqi#include <sys/param.h>
3052417Sluoqi#include <sys/systm.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
5252417Sluoqistatic int aic_isa_alloc_resources __P((device_t));
5352417Sluoqistatic void aic_isa_release_resources __P((device_t));
5454136Sluoqistatic int aic_isa_probe __P((device_t));
5554136Sluoqistatic int aic_isa_attach __P((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
6152417Sluoqistatic int
6252417Sluoqiaic_isa_alloc_resources(device_t dev)
6352417Sluoqi{
6452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
6552417Sluoqi	int rid;
6652417Sluoqi
6752417Sluoqi	sc->sc_port = sc->sc_irq = sc->sc_drq = 0;
6852417Sluoqi
6952417Sluoqi	rid = 0;
7052417Sluoqi	sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
7152417Sluoqi					0ul, ~0ul, AIC_ISA_PORTSIZE, RF_ACTIVE);
7252417Sluoqi	if (!sc->sc_port)
7352417Sluoqi		return (ENOMEM);
7452417Sluoqi
7552417Sluoqi	if (isa_get_irq(dev) != -1) {
7652417Sluoqi		rid = 0;
7752417Sluoqi		sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
7852417Sluoqi						0ul, ~0ul, 1, RF_ACTIVE);
7952417Sluoqi		if (!sc->sc_irq) {
8052417Sluoqi			aic_isa_release_resources(dev);
8152417Sluoqi			return (ENOMEM);
8252417Sluoqi		}
8352417Sluoqi	}
8452417Sluoqi
8552417Sluoqi	if (isa_get_drq(dev) != -1) {
8652417Sluoqi		rid = 0;
8752417Sluoqi		sc->sc_drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid,
8852417Sluoqi						0ul, ~0ul, 1, RF_ACTIVE);
8952417Sluoqi		if (!sc->sc_drq) {
9052417Sluoqi			aic_isa_release_resources(dev);
9152417Sluoqi			return (ENOMEM);
9252417Sluoqi		}
9352417Sluoqi	}
9452417Sluoqi
9552417Sluoqi	sc->sc_aic.unit = device_get_unit(dev);
9652417Sluoqi	sc->sc_aic.tag = rman_get_bustag(sc->sc_port);
9752417Sluoqi	sc->sc_aic.bsh = rman_get_bushandle(sc->sc_port);
9852417Sluoqi	return (0);
9952417Sluoqi}
10052417Sluoqi
10152417Sluoqistatic void
10252417Sluoqiaic_isa_release_resources(device_t dev)
10352417Sluoqi{
10452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
10552417Sluoqi
10652417Sluoqi	if (sc->sc_port)
10752417Sluoqi		bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port);
10852417Sluoqi	if (sc->sc_irq)
10952417Sluoqi		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq);
11052417Sluoqi	if (sc->sc_drq)
11152417Sluoqi		bus_release_resource(dev, SYS_RES_DRQ, 0, sc->sc_drq);
11252417Sluoqi	sc->sc_port = sc->sc_irq = sc->sc_drq = 0;
11352417Sluoqi}
11452417Sluoqi
11552417Sluoqistatic int
11652417Sluoqiaic_isa_probe(device_t dev)
11752417Sluoqi{
11852417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
11952417Sluoqi	struct aic_softc *aic = &sc->sc_aic;
12052417Sluoqi	int numports, i;
12152417Sluoqi	u_int port, *ports;
12252417Sluoqi	u_int8_t porta;
12352417Sluoqi
12452417Sluoqi	if (isa_get_vendorid(dev))
12552417Sluoqi		return (ENXIO);
12652417Sluoqi
12752417Sluoqi	port = isa_get_port(dev);
12852417Sluoqi	if (port != -1) {
12952417Sluoqi		ports = &port;
13052417Sluoqi		numports = 1;
13152417Sluoqi	} else {
13252417Sluoqi		ports = aic_isa_ports;
13352417Sluoqi		numports = AIC_ISA_NUMPORTS;
13452417Sluoqi	}
13552417Sluoqi
13652417Sluoqi	for (i = 0; i < numports; i++) {
13752417Sluoqi		if (bus_set_resource(dev, SYS_RES_IOPORT, 0, ports[i],
13852417Sluoqi				     AIC_ISA_PORTSIZE))
13952417Sluoqi			continue;
14052417Sluoqi		if (aic_isa_alloc_resources(dev))
14152417Sluoqi			continue;
14252417Sluoqi		if (!aic_probe(aic)) {
14352417Sluoqi			aic_isa_release_resources(dev);
14452417Sluoqi			break;
14552417Sluoqi		}
14652417Sluoqi		aic_isa_release_resources(dev);
14752417Sluoqi	}
14852417Sluoqi
14952417Sluoqi	if (i == numports)
15052417Sluoqi		return (ENXIO);
15152417Sluoqi
15252417Sluoqi	porta = aic_inb(aic, PORTA);
15352417Sluoqi	if (isa_get_irq(dev) == -1)
15452417Sluoqi		bus_set_resource(dev, SYS_RES_IRQ, 0, PORTA_IRQ(porta), 1);
15552417Sluoqi	if ((aic->flags & AIC_DMA_ENABLE) && isa_get_drq(dev) == -1)
15652417Sluoqi		bus_set_resource(dev, SYS_RES_DRQ, 0, PORTA_DRQ(porta), 1);
15754136Sluoqi	device_set_desc(dev, "Adaptec 6260/6360 SCSI controller");
15852417Sluoqi	return (0);
15952417Sluoqi}
16052417Sluoqi
16152417Sluoqistatic int
16252417Sluoqiaic_isa_attach(device_t dev)
16352417Sluoqi{
16452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
16552417Sluoqi	struct aic_softc *aic = &sc->sc_aic;
16652417Sluoqi	int error;
16752417Sluoqi
16852417Sluoqi	error = aic_isa_alloc_resources(dev);
16952417Sluoqi	if (error) {
17052417Sluoqi		device_printf(dev, "resource allocation failed\n");
17152417Sluoqi		return (error);
17252417Sluoqi	}
17352417Sluoqi
17452417Sluoqi	error = aic_attach(aic);
17552417Sluoqi	if (error) {
17652417Sluoqi		device_printf(dev, "attach failed\n");
17752417Sluoqi		aic_isa_release_resources(dev);
17852417Sluoqi		return (error);
17952417Sluoqi	}
18052417Sluoqi
18152417Sluoqi	error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_CAM, aic_intr,
18252417Sluoqi				aic, &sc->sc_ih);
18352417Sluoqi	if (error) {
18452417Sluoqi		device_printf(dev, "failed to register interrupt handler\n");
18552417Sluoqi		aic_isa_release_resources(dev);
18652417Sluoqi		return (error);
18752417Sluoqi	}
18852417Sluoqi	return (0);
18952417Sluoqi}
19052417Sluoqi
19152417Sluoqistatic int
19252417Sluoqiaic_isa_detach(device_t dev)
19352417Sluoqi{
19452417Sluoqi	struct aic_isa_softc *sc = device_get_softc(dev);
19552417Sluoqi	struct aic_softc *aic = &sc->sc_aic;
19652417Sluoqi	int error;
19752417Sluoqi
19852417Sluoqi	error = aic_detach(aic);
19952417Sluoqi	if (error) {
20052417Sluoqi		device_printf(dev, "detach failed\n");
20152417Sluoqi		return (error);
20252417Sluoqi	}
20352417Sluoqi
20452417Sluoqi	error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
20552417Sluoqi	if (error) {
20652417Sluoqi		device_printf(dev, "failed to unregister interrupt handler\n");
20752417Sluoqi	}
20852417Sluoqi
20952417Sluoqi	aic_isa_release_resources(dev);
21052417Sluoqi	return (0);
21152417Sluoqi}
21252417Sluoqi
21352417Sluoqistatic device_method_t aic_isa_methods[] = {
21452417Sluoqi	/* Device interface */
21552417Sluoqi	DEVMETHOD(device_probe,		aic_isa_probe),
21652417Sluoqi	DEVMETHOD(device_attach,	aic_isa_attach),
21752417Sluoqi	DEVMETHOD(device_detach,	aic_isa_detach),
21852417Sluoqi	{ 0, 0 }
21952417Sluoqi};
22052417Sluoqi
22152417Sluoqistatic driver_t aic_isa_driver = {
22252417Sluoqi	"aic",
22352417Sluoqi	aic_isa_methods, sizeof(struct aic_isa_softc),
22452417Sluoqi};
22552417Sluoqi
22655997Simpextern devclass_t aic_devclass;
22752417Sluoqi
22852417SluoqiDRIVER_MODULE(aic, isa, aic_isa_driver, aic_devclass, 0, 0);
229