159078Smdodd/*-
259078Smdodd * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net>
359078Smdodd * All rights reserved.
459078Smdodd *
559078Smdodd * Redistribution and use in source and binary forms, with or without
659078Smdodd * modification, are permitted provided that the following conditions
759078Smdodd * are met:
859078Smdodd * 1. Redistributions of source code must retain the above copyright
959078Smdodd *    notice, this list of conditions and the following disclaimer.
1059078Smdodd * 2. Redistributions in binary form must reproduce the above copyright
1159078Smdodd *    notice, this list of conditions and the following disclaimer in the
1259078Smdodd *    documentation and/or other materials provided with the distribution.
1359078Smdodd *
1459078Smdodd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1559078Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1659078Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1759078Smdodd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1859078Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1959078Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2059078Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2159078Smdodd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2259078Smdodd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2359078Smdodd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2459078Smdodd * SUCH DAMAGE.
2559078Smdodd *
2659078Smdodd */
2759078Smdodd
28119418Sobrien#include <sys/cdefs.h>
29119418Sobrien__FBSDID("$FreeBSD$");
30119418Sobrien
3159078Smdodd#include <sys/param.h>
3259078Smdodd#include <sys/systm.h>
3359078Smdodd#include <sys/kernel.h>
34241593Sjhb#include <sys/lock.h>
3559078Smdodd#include <sys/module.h>
36241593Sjhb#include <sys/mutex.h>
3759078Smdodd#include <sys/bus.h>
3859078Smdodd
3959078Smdodd#include <machine/bus.h>
4059078Smdodd#include <machine/resource.h>
4159078Smdodd#include <sys/rman.h>
4259078Smdodd
4359078Smdodd#include <isa/isavar.h>
4459078Smdodd
4559078Smdodd#include <cam/scsi/scsi_all.h>
4659078Smdodd
4759078Smdodd#include <dev/dpt/dpt.h>
4859078Smdodd
49112795Smdodd#ifdef notyet
50112780Smdoddstatic void	dpt_isa_identify	(driver_t *, device_t);
51112795Smdodd#endif
5259078Smdoddstatic int	dpt_isa_probe		(device_t);
5359078Smdoddstatic int	dpt_isa_attach		(device_t);
54112780Smdoddstatic int	dpt_isa_detach		(device_t);
5559078Smdodd
56112780Smdoddstatic int	dpt_isa_valid_irq	(int);
57112780Smdoddstatic int	dpt_isa_valid_ioport	(int);
58112780Smdodd
5959078Smdoddstatic int
60112780Smdodddpt_isa_valid_irq (int irq)
61112780Smdodd{
62112780Smdodd	switch (irq) {
63112780Smdodd		case 11:
64112780Smdodd		case 12:
65112780Smdodd		case 14:
66112780Smdodd		case 15:
67112780Smdodd			return (0);
68112780Smdodd		default:
69112780Smdodd			return (1);
70112780Smdodd	};
71112780Smdodd	return (1);
72112780Smdodd}
73112780Smdodd
74112780Smdoddstatic int
75112780Smdodddpt_isa_valid_ioport (int ioport)
76112780Smdodd{
77112780Smdodd	switch (ioport) {
78112780Smdodd		case 0x170:
79112780Smdodd		case 0x1f0:
80112780Smdodd		case 0x230:
81112780Smdodd		case 0x330:
82112780Smdodd			return (0);
83112780Smdodd		default:
84112780Smdodd			return (1);
85112780Smdodd	};
86112780Smdodd	return (1);
87112780Smdodd}
88112780Smdodd
89112795Smdodd#ifdef notyet
90112780Smdoddstatic void
91112780Smdodddpt_isa_identify (driver_t *driver, device_t parent)
92112780Smdodd{
93112780Smdodd	device_t	child;
94112780Smdodd	dpt_conf_t *	conf;
95112780Smdodd	int		isa_bases[] = { 0x1f0, 0x170, 0x330, 0x230, 0 };
96112780Smdodd	int		i;
97112780Smdodd
98112780Smdodd	for (i = 0; isa_bases[i]; i++) {
99112780Smdodd		conf = dpt_pio_get_conf(isa_bases[i]);
100112780Smdodd	        if (!conf) {
101112780Smdodd			if (bootverbose)
102112780Smdodd				device_printf(parent, "dpt: dpt_pio_get_conf(%x) failed.\n",
103112780Smdodd					isa_bases[i]);
104112780Smdodd			continue;
105112780Smdodd		}
106112780Smdodd
107112780Smdodd		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "dpt", -1);
108112780Smdodd		if (child == 0) {
109112780Smdodd			device_printf(parent, "dpt: BUS_ADD_CHILD() failed!\n");
110112780Smdodd			continue;
111112780Smdodd		}
112112780Smdodd		device_set_driver(child, driver);
113112780Smdodd		bus_set_resource(child, SYS_RES_IOPORT, 0, isa_bases[i], 0x9);
114112780Smdodd	}
115112780Smdodd	return;
116112780Smdodd}
117112795Smdodd#endif
118112780Smdodd
119112780Smdoddstatic int
12059078Smdodddpt_isa_probe (device_t dev)
12159078Smdodd{
12259078Smdodd	dpt_conf_t *	conf;
12359078Smdodd	u_int32_t	io_base;
12459078Smdodd
12559078Smdodd	/* No pnp support */
12659078Smdodd	if (isa_get_vendorid(dev))
12759078Smdodd		return (ENXIO);
12859078Smdodd
12959078Smdodd	if ((io_base = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
13059078Smdodd		return (ENXIO);
13159078Smdodd
132112780Smdodd	if (dpt_isa_valid_ioport(io_base))
133112780Smdodd		;
134112780Smdodd
13559078Smdodd	conf = dpt_pio_get_conf(io_base);
136112780Smdodd	if (!conf) {
137112780Smdodd		printf("dpt: dpt_pio_get_conf() failed.\n");
138112780Smdodd		return (ENXIO);
139112780Smdodd	}
14059078Smdodd
141112780Smdodd	if (dpt_isa_valid_irq(conf->IRQ))
142112780Smdodd		;
143112780Smdodd
14459078Smdodd	device_set_desc(dev, "ISA DPT SCSI controller");
14559078Smdodd	bus_set_resource(dev, SYS_RES_IRQ, 0, conf->IRQ, 1);
14659078Smdodd	bus_set_resource(dev, SYS_RES_DRQ, 0, ((8 - conf->DMA_channel) & 7), 1);
14759078Smdodd
14859078Smdodd	return 0;
14959078Smdodd}
15059078Smdodd
15159078Smdoddstatic int
15259078Smdodddpt_isa_attach (device_t dev)
15359078Smdodd{
154112780Smdodd	dpt_softc_t *	dpt;
15559078Smdodd	int		error = 0;
15659078Smdodd
157112780Smdodd	dpt = device_get_softc(dev);
158170872Sscottl	dpt->dev = dev;
159241593Sjhb	dpt_alloc(dev);
16059078Smdodd
161112780Smdodd	dpt->io_rid = 0;
162112780Smdodd	dpt->io_type = SYS_RES_IOPORT;
163112780Smdodd	dpt->irq_rid = 0;
164112780Smdodd
165112780Smdodd	error = dpt_alloc_resources(dev);
166112780Smdodd	if (error) {
16759078Smdodd		goto bad;
16859078Smdodd	}
16959078Smdodd
170112780Smdodd	dpt->drq_rid = 0;
171127135Snjl	dpt->drq_res = bus_alloc_resource_any(dev, SYS_RES_DRQ, &dpt->drq_rid,
172127135Snjl					RF_ACTIVE);
173112780Smdodd	if (!dpt->drq_res) {
174112780Smdodd		device_printf(dev, "No DRQ!\n");
17559078Smdodd		error = ENOMEM;
17659078Smdodd		goto bad;
17759078Smdodd	}
178112780Smdodd	isa_dma_acquire(rman_get_start(dpt->drq_res));
179112780Smdodd	isa_dmacascade(rman_get_start(dpt->drq_res));
18059078Smdodd
18159078Smdodd	/* Allocate a dmatag representing the capabilities of this attachment */
182241593Sjhb	if (bus_dma_tag_create( /* parent    */	bus_get_dma_tag(dev),
18359078Smdodd				/* alignemnt */	1,
18459078Smdodd				/* boundary  */	0,
185112780Smdodd				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
18659078Smdodd				/* highaddr  */	BUS_SPACE_MAXADDR,
18759078Smdodd				/* filter    */	NULL,
18859078Smdodd				/* filterarg */	NULL,
18959078Smdodd				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
190104710Speter				/* nsegments */	~0,
19159078Smdodd				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
19259078Smdodd				/* flags     */	0,
193241593Sjhb				/* lockfunc  */ NULL,
194241593Sjhb				/* lockarg   */ NULL,
19559078Smdodd				&dpt->parent_dmat) != 0) {
19659078Smdodd		error = ENXIO;
19759078Smdodd		goto bad;
19859078Smdodd	}
19959078Smdodd
20059078Smdodd	if (dpt_init(dpt) != 0) {
20159078Smdodd		error = ENXIO;
20259078Smdodd		goto bad;
20359078Smdodd	}
20459078Smdodd
20559078Smdodd	/* Register with the XPT */
20659078Smdodd	dpt_attach(dpt);
20759078Smdodd
208241593Sjhb	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY |
209241593Sjhb	    INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) {
21059078Smdodd		device_printf(dev, "Unable to register interrupt handler\n");
21159078Smdodd		error = ENXIO;
21259078Smdodd		goto bad;
21359078Smdodd	}
21459078Smdodd
21559078Smdodd	return (error);
21659078Smdodd
21759078Smdodd bad:
218112780Smdodd	if (dpt->drq_res) {
219112780Smdodd		isa_dma_release(rman_get_start(dpt->drq_res));
220112780Smdodd	}
221112780Smdodd
222112780Smdodd	dpt_release_resources(dev);
223112780Smdodd
22459078Smdodd	if (dpt)
22559078Smdodd		dpt_free(dpt);
22659078Smdodd
22759078Smdodd	return (error);
22859078Smdodd}
22959078Smdodd
230112780Smdoddstatic int
231112780Smdodddpt_isa_detach (device_t dev)
232112780Smdodd{
233112780Smdodd	dpt_softc_t *	dpt;
234112780Smdodd	int		dma;
235112780Smdodd	int		error;
236112780Smdodd
237112780Smdodd	dpt = device_get_softc(dev);
238112780Smdodd
239112780Smdodd	dma = rman_get_start(dpt->drq_res);
240112780Smdodd	error = dpt_detach(dev);
241112780Smdodd	isa_dma_release(dma);
242112780Smdodd
243112780Smdodd	return (error);
244112780Smdodd}
245112780Smdodd
246112780Smdodd
24759078Smdoddstatic device_method_t dpt_isa_methods[] = {
24859078Smdodd	/* Device interface */
249112780Smdodd#ifdef notyet
250112780Smdodd	DEVMETHOD(device_identify,	dpt_isa_identify),
251112780Smdodd#endif
25259078Smdodd	DEVMETHOD(device_probe,		dpt_isa_probe),
25359078Smdodd	DEVMETHOD(device_attach,	dpt_isa_attach),
254112780Smdodd	DEVMETHOD(device_detach,	dpt_isa_detach),
25559078Smdodd
25659078Smdodd	{ 0, 0 }
25759078Smdodd};
25859078Smdodd
25959078Smdoddstatic driver_t dpt_isa_driver = {
26059078Smdodd	"dpt",
26159078Smdodd	dpt_isa_methods,
26259078Smdodd	sizeof(dpt_softc_t),
26359078Smdodd};
26459078Smdodd
26559078SmdoddDRIVER_MODULE(dpt, isa, dpt_isa_driver, dpt_devclass, 0, 0);
266165102SmjacobMODULE_DEPEND(dpt, isa, 1, 1, 1);
267165102SmjacobMODULE_DEPEND(dpt, cam, 1, 1, 1);
268