dpt_isa.c revision 256281
1139731Simp/*-
299123Sobrien * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net>
399123Sobrien * All rights reserved.
499123Sobrien *
599123Sobrien * Redistribution and use in source and binary forms, with or without
699123Sobrien * modification, are permitted provided that the following conditions
799123Sobrien * are met:
899123Sobrien * 1. Redistributions of source code must retain the above copyright
999123Sobrien *    notice, this list of conditions and the following disclaimer.
1099123Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1199123Sobrien *    notice, this list of conditions and the following disclaimer in the
1299123Sobrien *    documentation and/or other materials provided with the distribution.
1399123Sobrien *
1499123Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1599123Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1699123Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1799123Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1899123Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1999123Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2099123Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2199123Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2299123Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2399123Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2499123Sobrien * SUCH DAMAGE.
2599123Sobrien *
2699123Sobrien */
2799123Sobrien
2899123Sobrien#include <sys/cdefs.h>
2999123Sobrien__FBSDID("$FreeBSD: stable/10/sys/dev/dpt/dpt_isa.c 241593 2012-10-15 16:29:08Z jhb $");
3099123Sobrien
3199123Sobrien#include <sys/param.h>
3299123Sobrien#include <sys/systm.h>
3399123Sobrien#include <sys/kernel.h>
3499123Sobrien#include <sys/lock.h>
3599123Sobrien#include <sys/module.h>
3699123Sobrien#include <sys/mutex.h>
3799123Sobrien#include <sys/bus.h>
3899123Sobrien
3999123Sobrien#include <machine/bus.h>
4099123Sobrien#include <machine/resource.h>
4199123Sobrien#include <sys/rman.h>
4299123Sobrien
43114349Speter#include <isa/isavar.h>
4499123Sobrien
4599123Sobrien#include <cam/scsi/scsi_all.h>
4699123Sobrien
4799123Sobrien#include <dev/dpt/dpt.h>
4899123Sobrien
4999123Sobrien#ifdef notyet
5099123Sobrienstatic void	dpt_isa_identify	(driver_t *, device_t);
5199123Sobrien#endif
5299123Sobrienstatic int	dpt_isa_probe		(device_t);
5399123Sobrienstatic int	dpt_isa_attach		(device_t);
5499123Sobrienstatic int	dpt_isa_detach		(device_t);
5599123Sobrien
5699123Sobrienstatic int	dpt_isa_valid_irq	(int);
5799123Sobrienstatic int	dpt_isa_valid_ioport	(int);
58114349Speter
5999123Sobrienstatic int
6099123Sobriendpt_isa_valid_irq (int irq)
6199123Sobrien{
6299123Sobrien	switch (irq) {
6399123Sobrien		case 11:
6499123Sobrien		case 12:
6599123Sobrien		case 14:
6699123Sobrien		case 15:
6799123Sobrien			return (0);
6899123Sobrien		default:
69154128Simp			return (1);
70154128Simp	};
71154128Simp	return (1);
7299123Sobrien}
7399123Sobrien
7499123Sobrienstatic int
7599123Sobriendpt_isa_valid_ioport (int ioport)
76114346Speter{
7799123Sobrien	switch (ioport) {
7899123Sobrien		case 0x170:
79114346Speter		case 0x1f0:
8099123Sobrien		case 0x230:
8199123Sobrien		case 0x330:
82177661Sjb			return (0);
83183525Sjhb		default:
84122849Speter			return (1);
8599123Sobrien	};
86122849Speter	return (1);
8799123Sobrien}
8899123Sobrien
8999123Sobrien#ifdef notyet
90115795Speterstatic void
9199123Sobriendpt_isa_identify (driver_t *driver, device_t parent)
92191278Srwatson{
93191278Srwatson	device_t	child;
94191278Srwatson	dpt_conf_t *	conf;
95191278Srwatson	int		isa_bases[] = { 0x1f0, 0x170, 0x330, 0x230, 0 };
96191276Srwatson	int		i;
97191276Srwatson
98191276Srwatson	for (i = 0; isa_bases[i]; i++) {
99191276Srwatson		conf = dpt_pio_get_conf(isa_bases[i]);
100115251Speter	        if (!conf) {
101114349Speter			if (bootverbose)
102114349Speter				device_printf(parent, "dpt: dpt_pio_get_conf(%x) failed.\n",
103115251Speter					isa_bases[i]);
10499123Sobrien			continue;
10599123Sobrien		}
10699123Sobrien
107114349Speter		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "dpt", -1);
108114349Speter		if (child == 0) {
109115251Speter			device_printf(parent, "dpt: BUS_ADD_CHILD() failed!\n");
110114349Speter			continue;
111114349Speter		}
112114349Speter		device_set_driver(child, driver);
113114349Speter		bus_set_resource(child, SYS_RES_IOPORT, 0, isa_bases[i], 0x9);
114114349Speter	}
115115251Speter	return;
116114349Speter}
117114349Speter#endif
118114349Speter
119114349Speterstatic int
120114349Speterdpt_isa_probe (device_t dev)
121115251Speter{
122130218Speter	dpt_conf_t *	conf;
123130218Speter	u_int32_t	io_base;
124130218Speter
12599123Sobrien	/* No pnp support */
12699123Sobrien	if (isa_get_vendorid(dev))
12799123Sobrien		return (ENXIO);
128118236Speter
129114349Speter	if ((io_base = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
130118236Speter		return (ENXIO);
131116355Salc
13299123Sobrien	if (dpt_isa_valid_ioport(io_base))
13399123Sobrien		;
134114349Speter
135114349Speter	conf = dpt_pio_get_conf(io_base);
136114349Speter	if (!conf) {
137114349Speter		printf("dpt: dpt_pio_get_conf() failed.\n");
138114349Speter		return (ENXIO);
139114349Speter	}
140114349Speter
141114349Speter	if (dpt_isa_valid_irq(conf->IRQ))
142114349Speter		;
143114349Speter
144114349Speter	device_set_desc(dev, "ISA DPT SCSI controller");
145114349Speter	bus_set_resource(dev, SYS_RES_IRQ, 0, conf->IRQ, 1);
146114349Speter	bus_set_resource(dev, SYS_RES_DRQ, 0, ((8 - conf->DMA_channel) & 7), 1);
147180623Salc
148114349Speter	return 0;
149114349Speter}
150114349Speter
15199123Sobrienstatic int
15299123Sobriendpt_isa_attach (device_t dev)
15399123Sobrien{
15499123Sobrien	dpt_softc_t *	dpt;
155114349Speter	int		error = 0;
156114349Speter
157181112Salc	dpt = device_get_softc(dev);
15899123Sobrien	dpt->dev = dev;
15999123Sobrien	dpt_alloc(dev);
16099123Sobrien
16199123Sobrien	dpt->io_rid = 0;
162114346Speter	dpt->io_type = SYS_RES_IOPORT;
163114346Speter	dpt->irq_rid = 0;
16499123Sobrien
165114349Speter	error = dpt_alloc_resources(dev);
16699123Sobrien	if (error) {
16799123Sobrien		goto bad;
16899123Sobrien	}
169
170	dpt->drq_rid = 0;
171	dpt->drq_res = bus_alloc_resource_any(dev, SYS_RES_DRQ, &dpt->drq_rid,
172					RF_ACTIVE);
173	if (!dpt->drq_res) {
174		device_printf(dev, "No DRQ!\n");
175		error = ENOMEM;
176		goto bad;
177	}
178	isa_dma_acquire(rman_get_start(dpt->drq_res));
179	isa_dmacascade(rman_get_start(dpt->drq_res));
180
181	/* Allocate a dmatag representing the capabilities of this attachment */
182	if (bus_dma_tag_create( /* parent    */	bus_get_dma_tag(dev),
183				/* alignemnt */	1,
184				/* boundary  */	0,
185				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
186				/* highaddr  */	BUS_SPACE_MAXADDR,
187				/* filter    */	NULL,
188				/* filterarg */	NULL,
189				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
190				/* nsegments */	~0,
191				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
192				/* flags     */	0,
193				/* lockfunc  */ NULL,
194				/* lockarg   */ NULL,
195				&dpt->parent_dmat) != 0) {
196		error = ENXIO;
197		goto bad;
198	}
199
200	if (dpt_init(dpt) != 0) {
201		error = ENXIO;
202		goto bad;
203	}
204
205	/* Register with the XPT */
206	dpt_attach(dpt);
207
208	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY |
209	    INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) {
210		device_printf(dev, "Unable to register interrupt handler\n");
211		error = ENXIO;
212		goto bad;
213	}
214
215	return (error);
216
217 bad:
218	if (dpt->drq_res) {
219		isa_dma_release(rman_get_start(dpt->drq_res));
220	}
221
222	dpt_release_resources(dev);
223
224	if (dpt)
225		dpt_free(dpt);
226
227	return (error);
228}
229
230static int
231dpt_isa_detach (device_t dev)
232{
233	dpt_softc_t *	dpt;
234	int		dma;
235	int		error;
236
237	dpt = device_get_softc(dev);
238
239	dma = rman_get_start(dpt->drq_res);
240	error = dpt_detach(dev);
241	isa_dma_release(dma);
242
243	return (error);
244}
245
246
247static device_method_t dpt_isa_methods[] = {
248	/* Device interface */
249#ifdef notyet
250	DEVMETHOD(device_identify,	dpt_isa_identify),
251#endif
252	DEVMETHOD(device_probe,		dpt_isa_probe),
253	DEVMETHOD(device_attach,	dpt_isa_attach),
254	DEVMETHOD(device_detach,	dpt_isa_detach),
255
256	{ 0, 0 }
257};
258
259static driver_t dpt_isa_driver = {
260	"dpt",
261	dpt_isa_methods,
262	sizeof(dpt_softc_t),
263};
264
265DRIVER_MODULE(dpt, isa, dpt_isa_driver, dpt_devclass, 0, 0);
266MODULE_DEPEND(dpt, isa, 1, 1, 1);
267MODULE_DEPEND(dpt, cam, 1, 1, 1);
268