adv_isa.c revision 41048
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 *      $Id: adv_isa.c,v 1.6 1998/10/12 18:53:33 imp Exp $
48 */
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/malloc.h>
53
54#include <machine/bus_pio.h>
55#include <machine/bus.h>
56
57#include <i386/isa/isa.h>
58#include <i386/isa/isa_device.h>
59
60#include <dev/advansys/advansys.h>
61
62#include <cam/scsi/scsi_all.h>
63
64#define ADV_ISA_MAX_DMA_ADDR    (0x00FFFFFFL)
65#define ADV_ISA_MAX_DMA_COUNT   (0x00FFFFFFL)
66
67#define ADV_VL_MAX_DMA_ADDR     (0x07FFFFFFL)
68#define ADV_VL_MAX_DMA_COUNT    (0x07FFFFFFL)
69
70/*
71 * The overrun buffer shared amongst all ISA/VL adapters.
72 */
73static	u_int8_t*	overrun_buf;
74bus_dma_tag_t		overrun_dmat;
75bus_dmamap_t		overrun_dmamap;
76bus_addr_t		overrun_physbase;
77
78/* Possible port addresses an ISA or VL adapter can live at */
79u_int16_t adv_isa_ioports[] =
80{
81	0x100,
82	0x110,	/* First selection in BIOS setup */
83	0x120,
84	0x130,	/* Second selection in BIOS setup */
85	0x140,
86	0x150,	/* Third selection in BIOS setup */
87	0x190,	/* Fourth selection in BIOS setup */
88	0x210,	/* Fifth selection in BIOS setup */
89	0x230,	/* Sixth selection in BIOS setup */
90	0x250,	/* Seventh selection in BIOS setup */
91	0x330 	/* Eighth and default selection in BIOS setup */
92};
93
94#define MAX_ISA_IOPORT_INDEX (sizeof(adv_isa_ioports)/sizeof(u_int16_t) - 1)
95
96static	int	advisaprobe(struct isa_device *id);
97static  int	advisaattach(struct isa_device *id);
98static	void	adv_set_isapnp_wait_for_key(void);
99static	int	adv_get_isa_dma_channel(struct adv_softc *adv);
100static	int	adv_set_isa_dma_settings(struct adv_softc *adv);
101
102void	adv_isa_intr(void *unit);
103
104struct isa_driver advdriver =
105{
106	advisaprobe,
107	advisaattach,
108	"adv"
109};
110
111static int
112advisaprobe(struct isa_device *id)
113{
114	int	port_index;
115	int	max_port_index;
116
117	/*
118	 * Default to scanning all possible device locations.
119	 */
120	port_index = 0;
121	max_port_index = MAX_ISA_IOPORT_INDEX;
122
123	if (id->id_iobase > 0) {
124		for (;port_index <= max_port_index; port_index++)
125			if (id->id_iobase <= adv_isa_ioports[port_index])
126				break;
127		if ((port_index > max_port_index)
128		 || (id->id_iobase != adv_isa_ioports[port_index])) {
129			printf("adv%d: Invalid baseport of 0x%x specified. "
130				"Neerest valid baseport is 0x%x.  Failing "
131				"probe.\n", id->id_unit, id->id_iobase,
132				(port_index <= max_port_index) ?
133					adv_isa_ioports[port_index] :
134					adv_isa_ioports[max_port_index]);
135			return 0;
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
149		if (port_addr == 0)
150			/* Already been attached */
151			continue;
152		id->id_iobase = port_addr;
153		if (haveseen_isadev(id, CC_IOADDR | CC_QUIET))
154			continue;
155
156		if (adv_find_signature(I386_BUS_SPACE_IO, port_addr)) {
157			/*
158			 * Got one.  Now allocate our softc
159			 * and see if we can initialize the card.
160			 */
161			struct adv_softc *adv;
162			adv = adv_alloc(id->id_unit, I386_BUS_SPACE_IO,
163					port_addr);
164			if (adv == NULL)
165				return (0);
166
167			adv_unit++;
168
169			id->id_iobase = adv->bsh;
170
171			/*
172			 * Stop the chip.
173			 */
174			ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
175			ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
176			/*
177			 * Determine the chip version.
178			 */
179			adv->chip_version = ADV_INB(adv,
180						    ADV_NONEISA_CHIP_REVISION);
181			if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL)
182			 && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) {
183				adv->type = ADV_VL;
184				maxsegsz = ADV_VL_MAX_DMA_COUNT;
185				maxsize = BUS_SPACE_MAXSIZE_32BIT;
186				lowaddr = ADV_VL_MAX_DMA_ADDR;
187				id->id_drq = -1;
188			} else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA)
189				&& (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) {
190				if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) {
191					adv->type = ADV_ISAPNP;
192					ADV_OUTB(adv, ADV_REG_IFC,
193						 ADV_IFC_INIT_DEFAULT);
194				} else {
195					adv->type = ADV_ISA;
196				}
197				maxsegsz = ADV_ISA_MAX_DMA_COUNT;
198				maxsize = BUS_SPACE_MAXSIZE_24BIT;
199				lowaddr = ADV_ISA_MAX_DMA_ADDR;
200				adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED;
201				adv->isa_dma_channel =
202				    adv_get_isa_dma_channel(adv);
203				id->id_drq = adv->isa_dma_channel;
204			} else {
205				panic("advisaprobe: Unknown card revision\n");
206			}
207
208			/*
209			 * Allocate a parent dmatag for all tags created
210			 * by the MI portions of the advansys driver
211			 */
212			/* XXX Should be a child of the ISA bus dma tag */
213			error =
214			    bus_dma_tag_create(/*parent*/NULL,
215					       /*alignemnt*/0,
216					       /*boundary*/0,
217					       lowaddr,
218					       /*highaddr*/BUS_SPACE_MAXADDR,
219					       /*filter*/NULL,
220					       /*filterarg*/NULL,
221					       maxsize,
222					       /*nsegs*/BUS_SPACE_UNRESTRICTED,
223					       maxsegsz,
224					       /*flags*/0,
225					       &adv->parent_dmat);
226
227			if (error != 0) {
228				printf("%s: Could not allocate DMA tag - error %d\n",
229				       adv_name(adv), error);
230				adv_free(adv);
231				return (0);
232			}
233
234			adv->init_level++;
235
236			if (overrun_buf == NULL) {
237				/* Need to allocate our overrun buffer */
238				if (bus_dma_tag_create(adv->parent_dmat,
239						       /*alignment*/8,
240						       /*boundary*/0,
241						       ADV_ISA_MAX_DMA_ADDR,
242						       BUS_SPACE_MAXADDR,
243						       /*filter*/NULL,
244						       /*filterarg*/NULL,
245						       ADV_OVERRUN_BSIZE,
246						       /*nsegments*/1,
247						       BUS_SPACE_MAXSIZE_32BIT,
248						       /*flags*/0,
249						       &overrun_dmat) != 0) {
250					adv_free(adv);
251					return (0);
252        			}
253				if (bus_dmamem_alloc(overrun_dmat,
254						     (void **)&overrun_buf,
255						     BUS_DMA_NOWAIT,
256						     &overrun_dmamap) != 0) {
257					bus_dma_tag_destroy(overrun_dmat);
258					adv_free(adv);
259					return (0);
260				}
261				/* And permanently map it in */
262				bus_dmamap_load(overrun_dmat, overrun_dmamap,
263						overrun_buf, ADV_OVERRUN_BSIZE,
264                        			adv_map, &overrun_physbase,
265						/*flags*/0);
266			}
267
268			adv->overrun_physbase = overrun_physbase;
269
270			if (adv_init(adv) != 0) {
271				adv_free(adv);
272				return (0);
273			}
274
275			switch (adv->type) {
276			case ADV_ISAPNP:
277				if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG){
278					adv->bug_fix_control
279					    |= ADV_BUG_FIX_ASYN_USE_SYN;
280					adv->fix_asyn_xfer = ~0;
281				}
282				/* Fall Through */
283			case ADV_ISA:
284				adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT;
285				adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR;
286				adv_set_isa_dma_settings(adv);
287				break;
288
289			case ADV_VL:
290				adv->max_dma_count = ADV_VL_MAX_DMA_COUNT;
291				adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR;
292				break;
293			default:
294				panic("advisaprobe: Invalid card type\n");
295			}
296
297			/* Determine our IRQ */
298			if (id->id_irq == 0 /* irq ? */)
299				id->id_irq = 1 << adv_get_chip_irq(adv);
300			else
301				adv_set_chip_irq(adv, ffs(id->id_irq) - 1);
302
303			id->id_intr = adv_isa_intr;
304
305			/* Mark as probed */
306			adv_isa_ioports[port_index] = 0;
307			return 1;
308		}
309	}
310
311	return 0;
312}
313
314static int
315advisaattach(struct isa_device *id)
316{
317	struct adv_softc *adv;
318
319	adv = advsoftcs[id->id_unit];
320	return (adv_attach(adv));
321}
322
323static int
324adv_get_isa_dma_channel(struct adv_softc *adv)
325{
326	int channel;
327
328	channel = ADV_INW(adv, ADV_CONFIG_LSW) & ADV_CFG_LSW_ISA_DMA_CHANNEL;
329	if (channel == 0x03)
330		return (0);
331	else if (channel == 0x00)
332		return (7);
333	return (channel + 4);
334}
335
336static int
337adv_set_isa_dma_settings(struct adv_softc *adv)
338{
339	u_int16_t cfg_lsw;
340	u_int8_t  value;
341
342	if ((adv->isa_dma_channel >= 5) && (adv->isa_dma_channel <= 7)) {
343	        if (adv->isa_dma_channel == 7)
344			value = 0x00;
345		else
346			value = adv->isa_dma_channel - 4;
347		cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW)
348			& ~ADV_CFG_LSW_ISA_DMA_CHANNEL;
349		cfg_lsw |= value;
350		ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
351
352		adv->isa_dma_speed &= 0x07;
353		adv_set_bank(adv, 1);
354		ADV_OUTB(adv, ADV_DMA_SPEED, adv->isa_dma_speed);
355		adv_set_bank(adv, 0);
356		isa_dmacascade(adv->isa_dma_channel);
357	}
358	return (0);
359}
360
361static void
362adv_set_isapnp_wait_for_key(void)
363{
364	static	int isapnp_wait_set = 0;
365	if (isapnp_wait_set == 0) {
366		outb(ADV_ISA_PNP_PORT_ADDR, 0x02);
367		outb(ADV_ISA_PNP_PORT_WRITE, 0x02);
368		isapnp_wait_set++;
369	}
370	return;
371}
372
373/*
374 * Handle an ISA interrupt.
375 * XXX should go away as soon as ISA interrupt handlers
376 * take a (void *) arg.
377 */
378void
379adv_isa_intr(void *unit)
380{
381	struct adv_softc *arg = advsoftcs[(int)unit];
382	adv_intr((void *)arg);
383}
384