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
48#include <sys/cdefs.h>
49__FBSDID("$FreeBSD$");
50
51#include <sys/param.h>
52#include <sys/systm.h>
53#include <sys/kernel.h>
54#include <sys/module.h>
55#include <sys/lock.h>
56#include <sys/mutex.h>
57
58#include <machine/bus.h>
59#include <machine/resource.h>
60#include <sys/bus.h>
61#include <sys/rman.h>
62
63#include <isa/isavar.h>
64
65#include <dev/advansys/advansys.h>
66
67#include <cam/scsi/scsi_all.h>
68
69#define ADV_ISA_MAX_DMA_ADDR    (0x00FFFFFFL)
70#define ADV_ISA_MAX_DMA_COUNT   (0x00FFFFFFL)
71
72#define ADV_VL_MAX_DMA_ADDR     (0x07FFFFFFL)
73#define ADV_VL_MAX_DMA_COUNT    (0x07FFFFFFL)
74
75/*
76 * The overrun buffer shared amongst all ISA/VL adapters.
77 */
78static	u_int8_t*	overrun_buf;
79static	bus_dma_tag_t	overrun_dmat;
80static	bus_dmamap_t	overrun_dmamap;
81static	bus_addr_t	overrun_physbase;
82
83/* Possible port addresses an ISA or VL adapter can live at */
84static u_int16_t adv_isa_ioports[] =
85{
86	0x100,
87	0x110,	/* First selection in BIOS setup */
88	0x120,
89	0x130,	/* Second selection in BIOS setup */
90	0x140,
91	0x150,	/* Third selection in BIOS setup */
92	0x190,	/* Fourth selection in BIOS setup */
93	0x210,	/* Fifth selection in BIOS setup */
94	0x230,	/* Sixth selection in BIOS setup */
95	0x250,	/* Seventh selection in BIOS setup */
96	0x330 	/* Eighth and default selection in BIOS setup */
97};
98
99#define MAX_ISA_IOPORT_INDEX (sizeof(adv_isa_ioports)/sizeof(u_int16_t) - 1)
100
101static	int	adv_isa_probe(device_t dev);
102static  int	adv_isa_attach(device_t dev);
103static	void	adv_set_isapnp_wait_for_key(void);
104static	int	adv_get_isa_dma_channel(struct adv_softc *adv);
105static	int	adv_set_isa_dma_settings(struct adv_softc *adv);
106
107static int
108adv_isa_probe(device_t dev)
109{
110	int	port_index;
111	int	max_port_index;
112	u_long	iobase, iocount, irq;
113	int	user_iobase = 0;
114	int	rid = 0;
115	void	*ih;
116	struct resource	*iores, *irqres;
117
118	/*
119	 * We don't know of any PnP ID's for these cards.
120	 */
121	if (isa_get_logicalid(dev) != 0)
122		return (ENXIO);
123
124	/*
125	 * Default to scanning all possible device locations.
126	 */
127	port_index = 0;
128	max_port_index = MAX_ISA_IOPORT_INDEX;
129
130	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, &iocount) == 0) {
131		user_iobase = 1;
132		for (;port_index <= max_port_index; port_index++)
133			if (iobase <= adv_isa_ioports[port_index])
134				break;
135		if ((port_index > max_port_index)
136		 || (iobase != adv_isa_ioports[port_index])) {
137			if (bootverbose)
138				device_printf(dev,
139				    "Invalid baseport of 0x%lx specified. "
140				    "Nearest valid baseport is 0x%x.  Failing "
141				    "probe.\n", iobase,
142				    (port_index <= max_port_index) ?
143				    adv_isa_ioports[port_index] :
144				    adv_isa_ioports[max_port_index]);
145			return ENXIO;
146		}
147		max_port_index = port_index;
148	}
149
150	/* Perform the actual probing */
151	adv_set_isapnp_wait_for_key();
152	for (;port_index <= max_port_index; port_index++) {
153		u_int16_t port_addr = adv_isa_ioports[port_index];
154		bus_size_t maxsegsz;
155		bus_size_t maxsize;
156		bus_addr_t lowaddr;
157		int error;
158		struct adv_softc *adv;
159
160		if (port_addr == 0)
161			/* Already been attached */
162			continue;
163
164		if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port_addr, 1))
165			continue;
166
167		/* XXX what is the real portsize? */
168		iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
169					       RF_ACTIVE);
170		if (iores == NULL)
171			continue;
172
173		if (adv_find_signature(iores) == 0) {
174			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
175			continue;
176		}
177
178		/*
179		 * Got one.  Now allocate our softc
180		 * and see if we can initialize the card.
181		 */
182		adv = adv_alloc(dev, iores, 0);
183		if (adv == NULL) {
184			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
185			break;
186		}
187
188		/*
189		 * Stop the chip.
190		 */
191		ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
192		ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
193		/*
194		 * Determine the chip version.
195		 */
196		adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
197		if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL)
198		    && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) {
199			adv->type = ADV_VL;
200			maxsegsz = ADV_VL_MAX_DMA_COUNT;
201			maxsize = BUS_SPACE_MAXSIZE_32BIT;
202			lowaddr = ADV_VL_MAX_DMA_ADDR;
203			bus_delete_resource(dev, SYS_RES_DRQ, 0);
204		} else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA)
205			   && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) {
206			if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) {
207				adv->type = ADV_ISAPNP;
208				ADV_OUTB(adv, ADV_REG_IFC,
209					 ADV_IFC_INIT_DEFAULT);
210			} else {
211				adv->type = ADV_ISA;
212			}
213			maxsegsz = ADV_ISA_MAX_DMA_COUNT;
214			maxsize = BUS_SPACE_MAXSIZE_24BIT;
215			lowaddr = ADV_ISA_MAX_DMA_ADDR;
216			adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED;
217			adv->isa_dma_channel = adv_get_isa_dma_channel(adv);
218			bus_set_resource(dev, SYS_RES_DRQ, 0,
219					 adv->isa_dma_channel, 1);
220		} else {
221			panic("advisaprobe: Unknown card revision\n");
222		}
223
224		/*
225		 * Allocate a parent dmatag for all tags created
226		 * by the MI portions of the advansys driver
227		 */
228		error = bus_dma_tag_create(
229				/* parent	*/ bus_get_dma_tag(dev),
230				/* alignemnt	*/ 1,
231				/* boundary	*/ 0,
232				/* lowaddr	*/ lowaddr,
233				/* highaddr	*/ BUS_SPACE_MAXADDR,
234				/* filter	*/ NULL,
235				/* filterarg	*/ NULL,
236				/* maxsize	*/ maxsize,
237				/* nsegments	*/ ~0,
238				/* maxsegsz	*/ maxsegsz,
239				/* flags	*/ 0,
240				/* lockfunc	*/ NULL,
241				/* lockarg	*/ NULL,
242				&adv->parent_dmat);
243
244		if (error != 0) {
245			device_printf(dev,
246			    "Could not allocate DMA tag - error %d\n", error);
247			adv_free(adv);
248			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
249			break;
250		}
251
252		adv->init_level += 2;
253
254		if (overrun_buf == NULL) {
255			/* Need to allocate our overrun buffer */
256			if (bus_dma_tag_create(
257				/* parent	*/ adv->parent_dmat,
258				/* alignment	*/ 8,
259				/* boundary	*/ 0,
260				/* lowaddr	*/ ADV_ISA_MAX_DMA_ADDR,
261				/* highaddr	*/ BUS_SPACE_MAXADDR,
262				/* filter	*/ NULL,
263				/* filterarg	*/ NULL,
264				/* maxsize	*/ ADV_OVERRUN_BSIZE,
265				/* nsegments	*/ 1,
266				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
267				/* flags	*/ 0,
268				/* lockfunc	*/ NULL,
269				/* lockarg	*/ NULL,
270				&overrun_dmat) != 0) {
271				adv_free(adv);
272				bus_release_resource(dev, SYS_RES_IOPORT, 0,
273						     iores);
274				break;
275			}
276			if (bus_dmamem_alloc(overrun_dmat,
277					     (void **)&overrun_buf,
278					     BUS_DMA_NOWAIT,
279					     &overrun_dmamap) != 0) {
280				bus_dma_tag_destroy(overrun_dmat);
281				adv_free(adv);
282				bus_release_resource(dev, SYS_RES_IOPORT, 0,
283						     iores);
284				break;
285			}
286			/* And permanently map it in */
287			bus_dmamap_load(overrun_dmat, overrun_dmamap,
288					overrun_buf, ADV_OVERRUN_BSIZE,
289					adv_map, &overrun_physbase,
290					/*flags*/0);
291		}
292
293		adv->overrun_physbase = overrun_physbase;
294
295		if (adv_init(adv) != 0) {
296			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
297			bus_dmamem_free(overrun_dmat, overrun_buf,
298			    overrun_dmamap);
299			bus_dma_tag_destroy(overrun_dmat);
300			adv_free(adv);
301			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
302			break;
303		}
304
305		switch (adv->type) {
306		case ADV_ISAPNP:
307			if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG) {
308				adv->bug_fix_control
309				    |= ADV_BUG_FIX_ASYN_USE_SYN;
310				adv->fix_asyn_xfer = ~0;
311			}
312			/* Fall Through */
313		case ADV_ISA:
314			adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT;
315			adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR;
316			adv_set_isa_dma_settings(adv);
317			break;
318
319		case ADV_VL:
320			adv->max_dma_count = ADV_VL_MAX_DMA_COUNT;
321			adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR;
322			break;
323		default:
324			panic("advisaprobe: Invalid card type\n");
325		}
326
327		/* Determine our IRQ */
328		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL))
329			bus_set_resource(dev, SYS_RES_IRQ, 0,
330					 adv_get_chip_irq(adv), 1);
331		else
332			adv_set_chip_irq(adv, irq);
333
334		irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
335						RF_ACTIVE);
336		if (irqres == NULL ||
337		    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|
338		    INTR_MPSAFE, NULL, adv_intr, adv, &ih) != 0) {
339			if (irqres != NULL)
340				bus_release_resource(dev, SYS_RES_IRQ, rid,
341				    irqres);
342			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
343			bus_dmamem_free(overrun_dmat, overrun_buf,
344			    overrun_dmamap);
345			bus_dma_tag_destroy(overrun_dmat);
346			adv_free(adv);
347			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
348			break;
349		}
350
351		/* Mark as probed */
352		adv_isa_ioports[port_index] = 0;
353		return 0;
354	}
355
356	if (user_iobase)
357		bus_set_resource(dev, SYS_RES_IOPORT, 0, iobase, iocount);
358	else
359		bus_delete_resource(dev, SYS_RES_IOPORT, 0);
360
361	return ENXIO;
362}
363
364static int
365adv_isa_attach(device_t dev)
366{
367	struct adv_softc *adv = device_get_softc(dev);
368
369	return (adv_attach(adv));
370}
371
372static int
373adv_get_isa_dma_channel(struct adv_softc *adv)
374{
375	int channel;
376
377	channel = ADV_INW(adv, ADV_CONFIG_LSW) & ADV_CFG_LSW_ISA_DMA_CHANNEL;
378	if (channel == 0x03)
379		return (0);
380	else if (channel == 0x00)
381		return (7);
382	return (channel + 4);
383}
384
385static int
386adv_set_isa_dma_settings(struct adv_softc *adv)
387{
388	u_int16_t cfg_lsw;
389	u_int8_t  value;
390
391	if ((adv->isa_dma_channel >= 5) && (adv->isa_dma_channel <= 7)) {
392	        if (adv->isa_dma_channel == 7)
393			value = 0x00;
394		else
395			value = adv->isa_dma_channel - 4;
396		cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW)
397			& ~ADV_CFG_LSW_ISA_DMA_CHANNEL;
398		cfg_lsw |= value;
399		ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
400
401		adv->isa_dma_speed &= 0x07;
402		adv_set_bank(adv, 1);
403		ADV_OUTB(adv, ADV_DMA_SPEED, adv->isa_dma_speed);
404		adv_set_bank(adv, 0);
405		isa_dmacascade(adv->isa_dma_channel);
406	}
407	return (0);
408}
409
410static void
411adv_set_isapnp_wait_for_key(void)
412{
413	static	int isapnp_wait_set = 0;
414	if (isapnp_wait_set == 0) {
415		outb(ADV_ISA_PNP_PORT_ADDR, 0x02);
416		outb(ADV_ISA_PNP_PORT_WRITE, 0x02);
417		isapnp_wait_set++;
418	}
419}
420
421static device_method_t adv_isa_methods[] = {
422	/* Device interface */
423	DEVMETHOD(device_probe,		adv_isa_probe),
424	DEVMETHOD(device_attach,	adv_isa_attach),
425	{ 0, 0 }
426};
427
428static driver_t adv_isa_driver = {
429	"adv", adv_isa_methods, sizeof(struct adv_softc)
430};
431
432static devclass_t adv_isa_devclass;
433DRIVER_MODULE(adv, isa, adv_isa_driver, adv_isa_devclass, 0, 0);
434MODULE_DEPEND(adv, isa, 1, 1, 1);
435