adv_isa.c revision 112782
1/*
2 * Device probe and attach routines for the following
3 * Advanced Systems Inc. SCSI controllers:
4 *
5 *   Connectivity Products:
6 *	ABP510/5150 - Bus-Master ISA (240 CDB) *
7 *	ABP5140 - Bus-Master ISA PnP (16 CDB) * **
8 *	ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) ***
9 *
10 *   Single Channel Products:
11 *	ABP542 - Bus-Master ISA with floppy (240 CDB)
12 *	ABP842 - Bus-Master VL (240 CDB)
13 *
14 *   Dual Channel Products:
15 *	ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
16 *
17 *    * This board has been shipped by HP with the 4020i CD-R drive.
18 *      The board has no BIOS so it cannot control a boot device, but
19 *      it can control any secondary SCSI device.
20 *   ** This board has been sold by SIIG as the i540 SpeedMaster.
21 *  *** This board has been sold by SIIG as the i542 SpeedMaster.
22 *
23 * Copyright (c) 1996, 1997 Justin T. Gibbs.
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 *    notice, this list of conditions, and the following disclaimer,
31 *    without modification, immediately at the beginning of the file.
32 * 2. The name of the author may not be used to endorse or promote products
33 *    derived from this software without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
39 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 *
47 * $FreeBSD: head/sys/dev/advansys/adv_isa.c 112782 2003-03-29 09:46:10Z mdodd $
48 */
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/kernel.h>
53
54#include <machine/bus_pio.h>
55#include <machine/bus.h>
56#include <machine/resource.h>
57#include <sys/bus.h>
58#include <sys/rman.h>
59
60#include <isa/isavar.h>
61
62#include <dev/advansys/advansys.h>
63
64#include <cam/scsi/scsi_all.h>
65
66#define ADV_ISA_MAX_DMA_ADDR    (0x00FFFFFFL)
67#define ADV_ISA_MAX_DMA_COUNT   (0x00FFFFFFL)
68
69#define ADV_VL_MAX_DMA_ADDR     (0x07FFFFFFL)
70#define ADV_VL_MAX_DMA_COUNT    (0x07FFFFFFL)
71
72/*
73 * The overrun buffer shared amongst all ISA/VL adapters.
74 */
75static	u_int8_t*	overrun_buf;
76static	bus_dma_tag_t	overrun_dmat;
77static	bus_dmamap_t	overrun_dmamap;
78static	bus_addr_t	overrun_physbase;
79
80/* Possible port addresses an ISA or VL adapter can live at */
81static u_int16_t adv_isa_ioports[] =
82{
83	0x100,
84	0x110,	/* First selection in BIOS setup */
85	0x120,
86	0x130,	/* Second selection in BIOS setup */
87	0x140,
88	0x150,	/* Third selection in BIOS setup */
89	0x190,	/* Fourth selection in BIOS setup */
90	0x210,	/* Fifth selection in BIOS setup */
91	0x230,	/* Sixth selection in BIOS setup */
92	0x250,	/* Seventh selection in BIOS setup */
93	0x330 	/* Eighth and default selection in BIOS setup */
94};
95
96#define MAX_ISA_IOPORT_INDEX (sizeof(adv_isa_ioports)/sizeof(u_int16_t) - 1)
97
98static	int	adv_isa_probe(device_t dev);
99static  int	adv_isa_attach(device_t dev);
100static	void	adv_set_isapnp_wait_for_key(void);
101static	int	adv_get_isa_dma_channel(struct adv_softc *adv);
102static	int	adv_set_isa_dma_settings(struct adv_softc *adv);
103
104static int
105adv_isa_probe(device_t dev)
106{
107	int	port_index;
108	int	max_port_index;
109	u_long	iobase, iocount, irq;
110	int	user_iobase = 0;
111	int	rid = 0;
112	void	*ih;
113	struct resource	*iores, *irqres;
114
115	/*
116	 * Default to scanning all possible device locations.
117	 */
118	port_index = 0;
119	max_port_index = MAX_ISA_IOPORT_INDEX;
120
121	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, &iocount) == 0) {
122		user_iobase = 1;
123		for (;port_index <= max_port_index; port_index++)
124			if (iobase <= adv_isa_ioports[port_index])
125				break;
126		if ((port_index > max_port_index)
127		 || (iobase != adv_isa_ioports[port_index])) {
128			if (bootverbose)
129			    printf("adv%d: Invalid baseport of 0x%lx specified. "
130				"Nearest valid baseport is 0x%x.  Failing "
131				"probe.\n", device_get_unit(dev), iobase,
132				(port_index <= max_port_index) ?
133					adv_isa_ioports[port_index] :
134					adv_isa_ioports[max_port_index]);
135			return ENXIO;
136		}
137		max_port_index = port_index;
138	}
139
140	/* Perform the actual probing */
141	adv_set_isapnp_wait_for_key();
142	for (;port_index <= max_port_index; port_index++) {
143		u_int16_t port_addr = adv_isa_ioports[port_index];
144		bus_size_t maxsegsz;
145		bus_size_t maxsize;
146		bus_addr_t lowaddr;
147		int error;
148		struct adv_softc *adv;
149
150		if (port_addr == 0)
151			/* Already been attached */
152			continue;
153
154		if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port_addr, 1))
155			continue;
156
157		/* XXX what is the real portsize? */
158		iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
159					   RF_ACTIVE);
160		if (iores == NULL)
161			continue;
162
163		if (adv_find_signature(rman_get_bustag(iores),
164				       rman_get_bushandle(iores)) == 0) {
165			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
166			continue;
167		}
168
169		/*
170		 * Got one.  Now allocate our softc
171		 * and see if we can initialize the card.
172		 */
173		adv = adv_alloc(dev, rman_get_bustag(iores),
174				rman_get_bushandle(iores));
175		if (adv == NULL) {
176			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
177			break;
178		}
179
180		/*
181		 * Stop the chip.
182		 */
183		ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
184		ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
185		/*
186		 * Determine the chip version.
187		 */
188		adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
189		if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL)
190		    && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) {
191			adv->type = ADV_VL;
192			maxsegsz = ADV_VL_MAX_DMA_COUNT;
193			maxsize = BUS_SPACE_MAXSIZE_32BIT;
194			lowaddr = ADV_VL_MAX_DMA_ADDR;
195			bus_delete_resource(dev, SYS_RES_DRQ, 0);
196		} else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA)
197			   && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) {
198			if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) {
199				adv->type = ADV_ISAPNP;
200				ADV_OUTB(adv, ADV_REG_IFC,
201					 ADV_IFC_INIT_DEFAULT);
202			} else {
203				adv->type = ADV_ISA;
204			}
205			maxsegsz = ADV_ISA_MAX_DMA_COUNT;
206			maxsize = BUS_SPACE_MAXSIZE_24BIT;
207			lowaddr = ADV_ISA_MAX_DMA_ADDR;
208			adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED;
209			adv->isa_dma_channel = adv_get_isa_dma_channel(adv);
210			bus_set_resource(dev, SYS_RES_DRQ, 0,
211					 adv->isa_dma_channel, 1);
212		} else {
213			panic("advisaprobe: Unknown card revision\n");
214		}
215
216		/*
217		 * Allocate a parent dmatag for all tags created
218		 * by the MI portions of the advansys driver
219		 */
220		/* XXX Should be a child of the ISA bus dma tag */
221		error = bus_dma_tag_create(
222				/* parent	*/ NULL,
223				/* alignemnt	*/ 1,
224				/* boundary	*/ 0,
225				/* lowaddr	*/ lowaddr,
226				/* highaddr	*/ BUS_SPACE_MAXADDR,
227				/* filter	*/ NULL,
228				/* filterarg	*/ NULL,
229				/* maxsize	*/ maxsize,
230				/* nsegments	*/ ~0,
231				/* maxsegsz	*/ maxsegsz,
232				/* flags	*/ 0,
233				&adv->parent_dmat);
234
235		if (error != 0) {
236			printf("%s: Could not allocate DMA tag - error %d\n",
237			       adv_name(adv), error);
238			adv_free(adv);
239			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
240			break;
241		}
242
243		adv->init_level += 2;
244
245		if (overrun_buf == NULL) {
246			/* Need to allocate our overrun buffer */
247			if (bus_dma_tag_create(
248				/* parent	*/ adv->parent_dmat,
249				/* alignment	*/ 8,
250				/* boundary	*/ 0,
251				/* lowaddr	*/ ADV_ISA_MAX_DMA_ADDR,
252				/* highaddr	*/ BUS_SPACE_MAXADDR,
253				/* filter	*/ NULL,
254				/* filterarg	*/ NULL,
255				/* maxsize	*/ ADV_OVERRUN_BSIZE,
256				/* nsegments	*/ 1,
257				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
258				/* flags	*/ 0,
259				&overrun_dmat) != 0) {
260				adv_free(adv);
261				bus_release_resource(dev, SYS_RES_IOPORT, 0,
262						     iores);
263				break;
264			}
265			if (bus_dmamem_alloc(overrun_dmat,
266					     (void **)&overrun_buf,
267					     BUS_DMA_NOWAIT,
268					     &overrun_dmamap) != 0) {
269				bus_dma_tag_destroy(overrun_dmat);
270				adv_free(adv);
271				bus_release_resource(dev, SYS_RES_IOPORT, 0,
272						     iores);
273				break;
274			}
275			/* And permanently map it in */
276			bus_dmamap_load(overrun_dmat, overrun_dmamap,
277					overrun_buf, ADV_OVERRUN_BSIZE,
278					adv_map, &overrun_physbase,
279					/*flags*/0);
280		}
281
282		adv->overrun_physbase = overrun_physbase;
283
284		if (adv_init(adv) != 0) {
285			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
286			bus_dmamem_free(overrun_dmat, overrun_buf,
287			    overrun_dmamap);
288			bus_dma_tag_destroy(overrun_dmat);
289			adv_free(adv);
290			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
291			break;
292		}
293
294		switch (adv->type) {
295		case ADV_ISAPNP:
296			if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG) {
297				adv->bug_fix_control
298				    |= ADV_BUG_FIX_ASYN_USE_SYN;
299				adv->fix_asyn_xfer = ~0;
300			}
301			/* Fall Through */
302		case ADV_ISA:
303			adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT;
304			adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR;
305			adv_set_isa_dma_settings(adv);
306			break;
307
308		case ADV_VL:
309			adv->max_dma_count = ADV_VL_MAX_DMA_COUNT;
310			adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR;
311			break;
312		default:
313			panic("advisaprobe: Invalid card type\n");
314		}
315
316		/* Determine our IRQ */
317		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL))
318			bus_set_resource(dev, SYS_RES_IRQ, 0,
319					 adv_get_chip_irq(adv), 1);
320		else
321			adv_set_chip_irq(adv, irq);
322
323		irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
324					    RF_ACTIVE);
325		if (irqres == NULL ||
326		    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY,
327				   adv_intr, adv, &ih)) {
328			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
329			bus_dmamem_free(overrun_dmat, overrun_buf,
330			    overrun_dmamap);
331			bus_dma_tag_destroy(overrun_dmat);
332			adv_free(adv);
333			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
334			break;
335		}
336
337		/* Mark as probed */
338		adv_isa_ioports[port_index] = 0;
339		return 0;
340	}
341
342	if (user_iobase)
343		bus_set_resource(dev, SYS_RES_IOPORT, 0, iobase, iocount);
344	else
345		bus_delete_resource(dev, SYS_RES_IOPORT, 0);
346
347	return ENXIO;
348}
349
350static int
351adv_isa_attach(device_t dev)
352{
353	struct adv_softc *adv = device_get_softc(dev);
354
355	return (adv_attach(adv));
356}
357
358static int
359adv_get_isa_dma_channel(struct adv_softc *adv)
360{
361	int channel;
362
363	channel = ADV_INW(adv, ADV_CONFIG_LSW) & ADV_CFG_LSW_ISA_DMA_CHANNEL;
364	if (channel == 0x03)
365		return (0);
366	else if (channel == 0x00)
367		return (7);
368	return (channel + 4);
369}
370
371static int
372adv_set_isa_dma_settings(struct adv_softc *adv)
373{
374	u_int16_t cfg_lsw;
375	u_int8_t  value;
376
377	if ((adv->isa_dma_channel >= 5) && (adv->isa_dma_channel <= 7)) {
378	        if (adv->isa_dma_channel == 7)
379			value = 0x00;
380		else
381			value = adv->isa_dma_channel - 4;
382		cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW)
383			& ~ADV_CFG_LSW_ISA_DMA_CHANNEL;
384		cfg_lsw |= value;
385		ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
386
387		adv->isa_dma_speed &= 0x07;
388		adv_set_bank(adv, 1);
389		ADV_OUTB(adv, ADV_DMA_SPEED, adv->isa_dma_speed);
390		adv_set_bank(adv, 0);
391		isa_dmacascade(adv->isa_dma_channel);
392	}
393	return (0);
394}
395
396static void
397adv_set_isapnp_wait_for_key(void)
398{
399	static	int isapnp_wait_set = 0;
400	if (isapnp_wait_set == 0) {
401		outb(ADV_ISA_PNP_PORT_ADDR, 0x02);
402		outb(ADV_ISA_PNP_PORT_WRITE, 0x02);
403		isapnp_wait_set++;
404	}
405}
406
407static device_method_t adv_isa_methods[] = {
408	/* Device interface */
409	DEVMETHOD(device_probe,		adv_isa_probe),
410	DEVMETHOD(device_attach,	adv_isa_attach),
411	{ 0, 0 }
412};
413
414static driver_t adv_isa_driver = {
415	"adv", adv_isa_methods, sizeof(struct adv_softc)
416};
417
418static devclass_t adv_isa_devclass;
419DRIVER_MODULE(adv, isa, adv_isa_driver, adv_isa_devclass, 0, 0);
420