dpt_isa.c revision 112795
1/*-
2 * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: head/sys/dev/dpt/dpt_isa.c 112795 2003-03-29 14:50:14Z mdodd $
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/kernel.h>
32#include <sys/module.h>
33#include <sys/bus.h>
34
35#include <machine/bus_pio.h>
36#include <machine/bus.h>
37#include <machine/resource.h>
38#include <sys/rman.h>
39
40#include <isa/isavar.h>
41
42#include <cam/scsi/scsi_all.h>
43
44#include <dev/dpt/dpt.h>
45
46#ifdef notyet
47static void	dpt_isa_identify	(driver_t *, device_t);
48#endif
49static int	dpt_isa_probe		(device_t);
50static int	dpt_isa_attach		(device_t);
51static int	dpt_isa_detach		(device_t);
52
53static int	dpt_isa_valid_irq	(int);
54static int	dpt_isa_valid_ioport	(int);
55
56static int
57dpt_isa_valid_irq (int irq)
58{
59	switch (irq) {
60		case 11:
61		case 12:
62		case 14:
63		case 15:
64			return (0);
65		default:
66			return (1);
67	};
68	return (1);
69}
70
71static int
72dpt_isa_valid_ioport (int ioport)
73{
74	switch (ioport) {
75		case 0x170:
76		case 0x1f0:
77		case 0x230:
78		case 0x330:
79			return (0);
80		default:
81			return (1);
82	};
83	return (1);
84}
85
86#ifdef notyet
87static void
88dpt_isa_identify (driver_t *driver, device_t parent)
89{
90	device_t	child;
91	dpt_conf_t *	conf;
92	int		isa_bases[] = { 0x1f0, 0x170, 0x330, 0x230, 0 };
93	int		i;
94
95	for (i = 0; isa_bases[i]; i++) {
96		conf = dpt_pio_get_conf(isa_bases[i]);
97	        if (!conf) {
98			if (bootverbose)
99				device_printf(parent, "dpt: dpt_pio_get_conf(%x) failed.\n",
100					isa_bases[i]);
101			continue;
102		}
103
104		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "dpt", -1);
105		if (child == 0) {
106			device_printf(parent, "dpt: BUS_ADD_CHILD() failed!\n");
107			continue;
108		}
109		device_set_driver(child, driver);
110		bus_set_resource(child, SYS_RES_IOPORT, 0, isa_bases[i], 0x9);
111	}
112	return;
113}
114#endif
115
116static int
117dpt_isa_probe (device_t dev)
118{
119	dpt_conf_t *	conf;
120	u_int32_t	io_base;
121
122	/* No pnp support */
123	if (isa_get_vendorid(dev))
124		return (ENXIO);
125
126	if ((io_base = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
127		return (ENXIO);
128
129	if (dpt_isa_valid_ioport(io_base))
130		;
131
132	conf = dpt_pio_get_conf(io_base);
133	if (!conf) {
134		printf("dpt: dpt_pio_get_conf() failed.\n");
135		return (ENXIO);
136	}
137
138	if (dpt_isa_valid_irq(conf->IRQ))
139		;
140
141	device_set_desc(dev, "ISA DPT SCSI controller");
142	bus_set_resource(dev, SYS_RES_IRQ, 0, conf->IRQ, 1);
143	bus_set_resource(dev, SYS_RES_DRQ, 0, ((8 - conf->DMA_channel) & 7), 1);
144
145	return 0;
146}
147
148static int
149dpt_isa_attach (device_t dev)
150{
151	dpt_softc_t *	dpt;
152	int		s;
153	int		error = 0;
154
155	dpt = device_get_softc(dev);
156
157
158	dpt->io_rid = 0;
159	dpt->io_type = SYS_RES_IOPORT;
160	dpt->irq_rid = 0;
161
162	error = dpt_alloc_resources(dev);
163	if (error) {
164		goto bad;
165	}
166
167	dpt->drq_rid = 0;
168	dpt->drq_res = bus_alloc_resource(dev, SYS_RES_DRQ, &dpt->drq_rid,
169					0, ~0, 1, RF_ACTIVE);
170	if (!dpt->drq_res) {
171		device_printf(dev, "No DRQ!\n");
172		error = ENOMEM;
173		goto bad;
174	}
175	isa_dma_acquire(rman_get_start(dpt->drq_res));
176	isa_dmacascade(rman_get_start(dpt->drq_res));
177
178	dpt_alloc(dev);
179
180	/* Allocate a dmatag representing the capabilities of this attachment */
181	if (bus_dma_tag_create( /* parent    */	NULL,
182				/* alignemnt */	1,
183				/* boundary  */	0,
184				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
185				/* highaddr  */	BUS_SPACE_MAXADDR,
186				/* filter    */	NULL,
187				/* filterarg */	NULL,
188				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
189				/* nsegments */	~0,
190				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
191				/* flags     */	0,
192				&dpt->parent_dmat) != 0) {
193		error = ENXIO;
194		goto bad;
195	}
196
197	s = splcam();
198
199	if (dpt_init(dpt) != 0) {
200		splx(s);
201		error = ENXIO;
202		goto bad;
203	}
204
205	/* Register with the XPT */
206	dpt_attach(dpt);
207
208	splx(s);
209
210	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY,
211			   dpt_intr, dpt, &dpt->ih)) {
212		device_printf(dev, "Unable to register interrupt handler\n");
213		error = ENXIO;
214		goto bad;
215	}
216
217	return (error);
218
219 bad:
220	if (dpt->drq_res) {
221		isa_dma_release(rman_get_start(dpt->drq_res));
222	}
223
224	dpt_release_resources(dev);
225
226	if (dpt)
227		dpt_free(dpt);
228
229	return (error);
230}
231
232static int
233dpt_isa_detach (device_t dev)
234{
235	dpt_softc_t *	dpt;
236	int		dma;
237	int		error;
238
239	dpt = device_get_softc(dev);
240
241	dma = rman_get_start(dpt->drq_res);
242	error = dpt_detach(dev);
243	isa_dma_release(dma);
244
245	return (error);
246}
247
248
249static device_method_t dpt_isa_methods[] = {
250	/* Device interface */
251#ifdef notyet
252	DEVMETHOD(device_identify,	dpt_isa_identify),
253#endif
254	DEVMETHOD(device_probe,		dpt_isa_probe),
255	DEVMETHOD(device_attach,	dpt_isa_attach),
256	DEVMETHOD(device_detach,	dpt_isa_detach),
257
258	{ 0, 0 }
259};
260
261static driver_t dpt_isa_driver = {
262	"dpt",
263	dpt_isa_methods,
264	sizeof(dpt_softc_t),
265};
266
267DRIVER_MODULE(dpt, isa, dpt_isa_driver, dpt_devclass, 0, 0);
268