aha_isa.c revision 42887
1122394Sharti/*
2122394Sharti * Product specific probe and attach routines for:
3122394Sharti *      Adaptec 154x.
4122394Sharti *
5163820Sharti * Derived from code written by:
6163820Sharti *
7163820Sharti * Copyright (c) 1998 Justin T. Gibbs
8122394Sharti * All rights reserved.
9122394Sharti *
10133211Sharti * Redistribution and use in source and binary forms, with or without
11133211Sharti * modification, are permitted provided that the following conditions
12133211Sharti * are met:
13133211Sharti * 1. Redistributions of source code must retain the above copyright
14133211Sharti *    notice, this list of conditions, and the following disclaimer,
15133211Sharti *    without modification, immediately at the beginning of the file.
16122394Sharti * 2. The name of the author may not be used to endorse or promote products
17122394Sharti *    derived from this software without specific prior written permission.
18122394Sharti *
19133211Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23133211Sharti * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29133211Sharti * SUCH DAMAGE.
30133211Sharti *
31122394Sharti *	$Id: aha_isa.c,v 1.5 1998/11/10 06:44:54 gibbs Exp $
32163820Sharti */
33122394Sharti
34122394Sharti#include "pnp.h"
35122394Sharti
36122394Sharti#include <sys/param.h>
37216294Ssyrinx#include <sys/systm.h>
38122394Sharti#include <sys/kernel.h>
39122394Sharti
40163820Sharti#include <machine/bus_pio.h>
41122394Sharti#include <machine/bus.h>
42122394Sharti
43122394Sharti#include <i386/isa/isa_device.h>
44122394Sharti#include <dev/aha/ahareg.h>
45122394Sharti
46216294Ssyrinx#include <cam/scsi/scsi_all.h>
47122394Sharti
48122394Sharti#if NPNP > 0
49122394Sharti#include <i386/isa/pnp.h>
50122394Sharti#endif
51122394Sharti
52122394Shartistatic	int aha_isa_probe(struct isa_device *dev);
53122394Shartistatic	int aha_isa_attach(struct isa_device *dev);
54122394Shartistatic	void aha_isa_intr(void *unit);
55122394Sharti
56122394Shartistruct isa_driver ahadriver =
57163820Sharti{
58163820Sharti    aha_isa_probe,
59163820Sharti    aha_isa_attach,
60163820Sharti    "aha"
61163820Sharti};
62122394Sharti
63122394Sharti/*
64122394Sharti * Check if the device can be found at the port given
65122394Sharti * and if so, set it up ready for further work
66122394Sharti * as an argument, takes the isa_device structure from
67122394Sharti * autoconf.c
68122394Sharti */
69122394Shartistatic int
70122394Shartiaha_isa_probe(dev)
71122394Sharti	struct isa_device *dev;
72122394Sharti{
73122394Sharti	/*
74122394Sharti	 * find unit and check we have that many defined
75122394Sharti	 */
76122394Sharti	struct	aha_softc *aha;
77122394Sharti	int	port_index;
78122394Sharti	int	max_port_index;
79122394Sharti
80122394Sharti	aha = NULL;
81122394Sharti
82122394Sharti	/*
83122394Sharti	 * Bound our board search if the user has
84122394Sharti	 * specified an exact port.
85122394Sharti	 */
86122394Sharti	aha_find_probe_range(dev->id_iobase, &port_index, &max_port_index);
87122394Sharti
88122394Sharti	if (port_index < 0)
89122394Sharti		return 0;
90122394Sharti
91122394Sharti	/* Attempt to find an adapter */
92122394Sharti	for (;port_index <= max_port_index; port_index++) {
93122394Sharti		config_data_t config_data;
94122394Sharti		u_int ioport;
95122394Sharti		int error;
96122394Sharti
97122394Sharti		ioport = aha_iop_from_bio(port_index);
98122394Sharti
99122394Sharti		/*
100122394Sharti		 * Ensure this port has not already been claimed already
101122394Sharti		 * by a PCI, EISA or ISA adapter.
102122394Sharti		 */
103122394Sharti		if (aha_check_probed_iop(ioport) != 0)
104122394Sharti			continue;
105122394Sharti		dev->id_iobase = ioport;
106122394Sharti		if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET))
107122394Sharti			continue;
108122394Sharti
109122394Sharti		/* Allocate a softc for use during probing */
110122394Sharti		aha = aha_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
111122394Sharti
112122394Sharti		if (aha == NULL)
113122394Sharti			break;
114163820Sharti
115163820Sharti		/* We're going to attempt to probe it now, so mark it probed */
116122394Sharti		aha_mark_probed_bio(port_index);
117163820Sharti
118163820Sharti		/* See if there is really a card present */
119163820Sharti		if (aha_probe(aha) || aha_fetch_adapter_info(aha)) {
120163820Sharti			aha_free(aha);
121122394Sharti			continue;
122163820Sharti		}
123122394Sharti
124122394Sharti		/*
125163820Sharti		 * Determine our IRQ, and DMA settings and
126163820Sharti		 * export them to the configuration system.
127122394Sharti		 */
128163820Sharti		error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
129163820Sharti			       (u_int8_t*)&config_data, sizeof(config_data),
130122394Sharti			       DEFAULT_CMD_TIMEOUT);
131163820Sharti		if (error != 0) {
132163820Sharti			printf("aha_isa_probe: Could not determine IRQ or DMA "
133163820Sharti			       "settings for adapter at 0x%x.  Failing probe\n",
134163820Sharti			       ioport);
135122394Sharti			aha_free(aha);
136163820Sharti			continue;
137163820Sharti		}
138163820Sharti
139163820Sharti		switch (config_data.dma_chan) {
140163820Sharti		case DMA_CHAN_5:
141163820Sharti			dev->id_drq = 5;
142122394Sharti			break;
143163820Sharti		case DMA_CHAN_6:
144163820Sharti			dev->id_drq = 6;
145163820Sharti			break;
146163820Sharti		case DMA_CHAN_7:
147163820Sharti			dev->id_drq = 7;
148163820Sharti			break;
149163820Sharti		default:
150163820Sharti			printf("aha_isa_probe: Invalid DMA setting "
151163820Sharti				"detected for adapter at 0x%x.  "
152163820Sharti				"Failing probe\n", ioport);
153163820Sharti			return (0);
154163820Sharti		}
155163820Sharti		dev->id_irq = (config_data.irq << 9);
156163820Sharti		dev->id_intr = aha_isa_intr;
157163820Sharti		aha_unit++;
158163820Sharti		return (AHA_NREGS);
159163820Sharti	}
160163820Sharti
161163820Sharti	return (0);
162163820Sharti}
163163820Sharti
164122394Sharti/*
165122394Sharti * Attach all the sub-devices we can find
166122394Sharti */
167216294Ssyrinxstatic int
168216294Ssyrinxaha_isa_attach(dev)
169216294Ssyrinx	struct isa_device *dev;
170216294Ssyrinx{
171216294Ssyrinx	struct	aha_softc *aha;
172216294Ssyrinx	bus_dma_filter_t *filter;
173216294Ssyrinx	void		 *filter_arg;
174122394Sharti	bus_addr_t	 lowaddr;
175216294Ssyrinx
176216294Ssyrinx	aha = aha_softcs[dev->id_unit];
177216294Ssyrinx	if (dev->id_drq != -1)
178122394Sharti		isa_dmacascade(dev->id_drq);
179216294Ssyrinx
180216294Ssyrinx	/* Allocate our parent dmatag */
181216294Ssyrinx	filter = NULL;
182216294Ssyrinx	filter_arg = NULL;
183216294Ssyrinx	lowaddr = BUS_SPACE_MAXADDR_24BIT;
184216294Ssyrinx
185216294Ssyrinx	if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
186216294Ssyrinx                               lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
187216294Ssyrinx                               filter, filter_arg,
188216294Ssyrinx                               /*maxsize*/BUS_SPACE_MAXSIZE_24BIT,
189216294Ssyrinx                               /*nsegments*/BUS_SPACE_UNRESTRICTED,
190216294Ssyrinx                               /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
191216294Ssyrinx                               /*flags*/0, &aha->parent_dmat) != 0) {
192216294Ssyrinx                aha_free(aha);
193216294Ssyrinx                return (-1);
194216294Ssyrinx        }
195216294Ssyrinx
196216294Ssyrinx        if (aha_init(aha)) {
197216294Ssyrinx		printf("aha init failed\n");
198216294Ssyrinx                aha_free(aha);
199216294Ssyrinx                return (-1);
200216294Ssyrinx        }
201216294Ssyrinx
202216294Ssyrinx	return (aha_attach(aha));
203216294Ssyrinx}
204216294Ssyrinx
205216294Ssyrinx/*
206216294Ssyrinx * Handle an ISA interrupt.
207216294Ssyrinx * XXX should go away as soon as ISA interrupt handlers
208216294Ssyrinx * take a (void *) arg.
209216294Ssyrinx */
210216294Ssyrinxstatic void
211216294Ssyrinxaha_isa_intr(void *unit)
212216294Ssyrinx{
213216294Ssyrinx	struct aha_softc* arg = aha_softcs[(int)unit];
214216294Ssyrinx	aha_intr((void *)arg);
215216294Ssyrinx}
216216294Ssyrinx
217216294Ssyrinx/*
218216294Ssyrinx * support PnP cards if we are using 'em
219216294Ssyrinx */
220216294Ssyrinx
221216294Ssyrinx#if NPNP > 0
222216294Ssyrinx
223216294Ssyrinxstatic char *ahapnp_probe(u_long csn, u_long vend_id);
224216294Ssyrinxstatic void ahapnp_attach(u_long csn, u_long vend_id, char *name,
225216294Ssyrinx	struct isa_device *dev);
226216294Ssyrinxstatic u_long nahapnp = NAHA;
227216294Ssyrinx
228216294Ssyrinxstatic struct pnp_device ahapnp = {
229216294Ssyrinx	"ahapnp",
230216294Ssyrinx	ahapnp_probe,
231216294Ssyrinx	ahapnp_attach,
232216294Ssyrinx	&nahapnp,
233216294Ssyrinx	&bio_imask
234216294Ssyrinx};
235216294SsyrinxDATA_SET (pnpdevice_set, ahapnp);
236216294Ssyrinx
237216294Ssyrinxstatic char *
238216294Ssyrinxahapnp_probe(u_long csn, u_long vend_id)
239216294Ssyrinx{
240216294Ssyrinx	struct pnp_cinfo d;
241216294Ssyrinx	char *s = NULL;
242216294Ssyrinx
243216294Ssyrinx	if (vend_id != AHA1542_PNP && vend_id != AHA1542_PNPCOMPAT)
244216294Ssyrinx		return (NULL);
245122394Sharti
246122394Sharti	read_pnp_parms(&d, 0);
247122394Sharti	if (d.enable == 0 || d.flags & 1) {
248122394Sharti		printf("CSN %lu is disabled.\n", csn);
249122394Sharti		return (NULL);
250122394Sharti	}
251122394Sharti	s = "Adaptec 1542CP";
252122394Sharti
253122394Sharti	return (s);
254122394Sharti}
255122394Sharti
256122394Shartistatic void
257122394Shartiahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
258122394Sharti{
259122394Sharti	struct pnp_cinfo d;
260122394Sharti	struct isa_device *dvp;
261122394Sharti
262122394Sharti	if (dev->id_unit >= NAHATOT)
263122394Sharti		return;
264122394Sharti
265122394Sharti	if (read_pnp_parms(&d, 0) == 0) {
266122394Sharti		printf("failed to read pnp parms\n");
267122394Sharti		return;
268122394Sharti	}
269122394Sharti
270122394Sharti	write_pnp_parms(&d, 0);
271122394Sharti
272122394Sharti	enable_pnp_card();
273122394Sharti
274122394Sharti	dev->id_iobase = d.port[0];
275122394Sharti	dev->id_irq = (1 << d.irq[0]);
276122394Sharti	dev->id_intr = aha_intr;
277122394Sharti	dev->id_drq = d.drq[0];
278122394Sharti
279122394Sharti	if (dev->id_driver == NULL) {
280122394Sharti		dev->id_driver = &ahadriver;
281122394Sharti		dvp = find_isadev(isa_devtab_tty, &ahadriver, 0);
282122394Sharti		if (dvp != NULL)
283122394Sharti			dev->id_id = dvp->id_id;
284122394Sharti	}
285122394Sharti
286122394Sharti	if ((dev->id_alive = aha_isa_probe(dev)) != 0)
287122394Sharti		aha_isa_attach(dev);
288122394Sharti	else
289122394Sharti		printf("aha%d: probe failed\n", dev->id_unit);
290122394Sharti}
291122394Sharti#endif
292122394Sharti