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