xref: /NextBSD/sys/dev/ct/ct_isa.c (revision 287e3b14e9552995def1802ec9c5034f4adf28ec)
1 /*	$NecBSD: ct_isa.c,v 1.6 1999/07/26 06:32:01 honda Exp $	*/
2 
3 #include <sys/cdefs.h>
4 __FBSDID("$FreeBSD$");
5 /*	$NetBSD$	*/
6 
7 /*-
8  * [NetBSD for NEC PC-98 series]
9  *  Copyright (c) 1995, 1996, 1997, 1998
10  *	NetBSD/pc98 porting staff. All rights reserved.
11  *
12  *  Redistribution and use in source and binary forms, with or without
13  *  modification, are permitted provided that the following conditions
14  *  are met:
15  *  1. Redistributions of source code must retain the above copyright
16  *     notice, this list of conditions and the following disclaimer.
17  *  2. Redistributions in binary form must reproduce the above copyright
18  *     notice, this list of conditions and the following disclaimer in the
19  *     documentation and/or other materials provided with the distribution.
20  *  3. The name of the author may not be used to endorse or promote products
21  *     derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #define	SCSIBUS_RESCAN
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/bio.h>
42 #include <sys/buf.h>
43 #include <sys/queue.h>
44 #include <sys/malloc.h>
45 #include <sys/bus.h>
46 #include <sys/module.h>
47 #include <sys/errno.h>
48 
49 #include <vm/vm.h>
50 
51 #include <machine/bus.h>
52 #include <machine/resource.h>
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55 #include <machine/md_var.h>
56 
57 #include <pc98/cbus/cbus.h>
58 #include <isa/isavar.h>
59 
60 #include <compat/netbsd/dvcfg.h>
61 
62 #include <cam/scsi/scsi_low.h>
63 
64 #include <dev/ic/wd33c93reg.h>
65 #include <dev/ct/ctvar.h>
66 #include <dev/ct/bshwvar.h>
67 
68 #define	BSHW_IOSZ	0x08
69 #define	BSHW_IOBASE 	0xcc0
70 #define	BSHW_MEMSZ	(PAGE_SIZE * 2)
71 
72 static int ct_isa_match(device_t);
73 static int ct_isa_attach(device_t);
74 static int ct_space_map(device_t, struct bshw *,
75 			struct resource **, struct resource **);
76 static void ct_space_unmap(device_t, struct ct_softc *);
77 static struct bshw *ct_find_hw(device_t);
78 static void ct_dmamap(void *, bus_dma_segment_t *, int, int);
79 static void ct_isa_bus_access_weight(struct ct_bus_access_handle *);
80 static void ct_isa_dmasync_before(struct ct_softc *);
81 static void ct_isa_dmasync_after(struct ct_softc *);
82 
83 struct ct_isa_softc {
84 	struct ct_softc sc_ct;
85 	struct bshw_softc sc_bshw;
86 };
87 
88 static struct isa_pnp_id ct_pnp_ids[] = {
89 	{ 0x0100e7b1,	"Logitec LHA-301" },
90 	{ 0x110154dc,	"I-O DATA SC-98III" },
91 	{ 0x4120acb4,	"MELCO IFC-NN" },
92 	{ 0,		NULL }
93 };
94 
95 static device_method_t ct_isa_methods[] = {
96 	/* Device interface */
97 	DEVMETHOD(device_probe,		ct_isa_match),
98 	DEVMETHOD(device_attach,	ct_isa_attach),
99 	{ 0, 0 }
100 };
101 
102 static driver_t ct_isa_driver = {
103 	"ct", ct_isa_methods, sizeof(struct ct_isa_softc),
104 };
105 
106 static devclass_t ct_devclass;
107 
108 DRIVER_MODULE(ct, isa, ct_isa_driver, ct_devclass, 0, 0);
109 
110 static int
ct_isa_match(device_t dev)111 ct_isa_match(device_t dev)
112 {
113 	struct bshw *hw;
114 	struct resource *port_res, *mem_res;
115 	struct ct_bus_access_handle ch;
116 	int rv;
117 
118 	if (ISA_PNP_PROBE(device_get_parent(dev), dev, ct_pnp_ids) == ENXIO)
119 		return ENXIO;
120 
121 	switch (isa_get_logicalid(dev)) {
122 	case 0x0100e7b1:	/* LHA-301 */
123 	case 0x110154dc:	/* SC-98III */
124 	case 0x4120acb4:	/* IFC-NN */
125 		/* XXX - force to SMIT mode */
126 		device_set_flags(dev, device_get_flags(dev) | 0x40000);
127 		break;
128 	}
129 
130 	if (isa_get_port(dev) == -1)
131 		bus_set_resource(dev, SYS_RES_IOPORT, 0,
132 				 BSHW_IOBASE, BSHW_IOSZ);
133 
134 	if ((hw = ct_find_hw(dev)) == NULL)
135 		return ENXIO;
136 	if (ct_space_map(dev, hw, &port_res, &mem_res) != 0)
137 		return ENXIO;
138 
139 	bzero(&ch, sizeof(ch));
140 	ch.ch_io = port_res;
141 	ch.ch_bus_weight = ct_isa_bus_access_weight;
142 
143 	rv = ctprobesubr(&ch, 0, BSHW_DEFAULT_HOSTID,
144 			 BSHW_DEFAULT_CHIPCLK, NULL);
145 	if (rv != 0)
146 	{
147 		struct bshw_softc bshw_tab;
148 		struct bshw_softc *bs = &bshw_tab;
149 
150 		memset(bs, 0, sizeof(*bs));
151 		bshw_read_settings(&ch, bs);
152 		bus_set_resource(dev, SYS_RES_IRQ, 0, bs->sc_irq, 1);
153 		bus_set_resource(dev, SYS_RES_DRQ, 0, bs->sc_drq, 1);
154 	}
155 
156 	bus_release_resource(dev, SYS_RES_IOPORT, 0, port_res);
157 	if (mem_res != NULL)
158 		bus_release_resource(dev, SYS_RES_MEMORY, 0, mem_res);
159 
160 	if (rv != 0)
161 		return (BUS_PROBE_DEFAULT);
162 	return ENXIO;
163 }
164 
165 static int
ct_isa_attach(device_t dev)166 ct_isa_attach(device_t dev)
167 {
168 	struct ct_isa_softc *pct = device_get_softc(dev);
169 	struct ct_softc *ct = &pct->sc_ct;
170 	struct ct_bus_access_handle *chp = &ct->sc_ch;
171 	struct scsi_low_softc *slp = &ct->sc_sclow;
172 	struct bshw_softc *bs = &pct->sc_bshw;
173 	struct bshw *hw;
174 	int irq_rid, drq_rid, chiprev;
175 	u_int8_t *vaddr;
176 	bus_addr_t addr;
177 
178 	hw = ct_find_hw(dev);
179 	if (ct_space_map(dev, hw, &ct->port_res, &ct->mem_res) != 0) {
180 		device_printf(dev, "bus io mem map failed\n");
181 		return ENXIO;
182 	}
183 
184 	chp->ch_io = ct->port_res;
185 	chp->ch_mem = ct->mem_res;
186 	chp->ch_bus_weight = ct_isa_bus_access_weight;
187 
188 	irq_rid = 0;
189 	ct->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid,
190 					     RF_ACTIVE);
191 	drq_rid = 0;
192 	ct->drq_res = bus_alloc_resource_any(dev, SYS_RES_DRQ, &drq_rid,
193 					     RF_ACTIVE);
194 	if (ct->irq_res == NULL || ct->drq_res == NULL) {
195 		ct_space_unmap(dev, ct);
196 		return ENXIO;
197 	}
198 
199 	if (ctprobesubr(chp, 0, BSHW_DEFAULT_HOSTID,
200 			BSHW_DEFAULT_CHIPCLK, &chiprev) == 0)
201 	{
202 		device_printf(dev, "hardware missing\n");
203 		ct_space_unmap(dev, ct);
204 		return ENXIO;
205 	}
206 
207 	/* setup DMA map */
208 	if (bus_dma_tag_create(NULL, 1, 0,
209 			       BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR,
210 			       NULL, NULL, DFLTPHYS, 1,
211 			       BUS_SPACE_MAXSIZE_32BIT,
212 			       BUS_DMA_ALLOCNOW, NULL, NULL,
213 			       &ct->sc_dmat) != 0) {
214 		device_printf(dev, "can't set up ISA DMA map\n");
215 		ct_space_unmap(dev, ct);
216 		return ENXIO;
217 	}
218 
219 	if (bus_dmamem_alloc(ct->sc_dmat, (void **)&vaddr, BUS_DMA_NOWAIT,
220 			     &ct->sc_dmamapt) != 0) {
221 		device_printf(dev, "can't set up ISA DMA map\n");
222 		ct_space_unmap(dev, ct);
223 		return ENXIO;
224 	}
225 
226 	bus_dmamap_load(ct->sc_dmat, ct->sc_dmamapt, vaddr, DFLTPHYS,
227 			ct_dmamap, &addr, BUS_DMA_NOWAIT);
228 
229 	/* setup machdep softc */
230 	bs->sc_hw = hw;
231 	bs->sc_io_control = 0;
232 	bs->sc_bounce_phys = (u_int8_t *)addr;
233 	bs->sc_bounce_addr = vaddr;
234 	bs->sc_bounce_size = DFLTPHYS;
235 	bs->sc_minphys = (1 << 24);
236 	bs->sc_dmasync_before = ct_isa_dmasync_before;
237 	bs->sc_dmasync_after = ct_isa_dmasync_after;
238 	bshw_read_settings(chp, bs);
239 
240 	/* setup ct driver softc */
241 	ct->ct_hw = bs;
242 	ct->ct_dma_xfer_start = bshw_dma_xfer_start;
243 	ct->ct_pio_xfer_start = bshw_smit_xfer_start;
244 	ct->ct_dma_xfer_stop = bshw_dma_xfer_stop;
245 	ct->ct_pio_xfer_stop = bshw_smit_xfer_stop;
246 	ct->ct_bus_reset = bshw_bus_reset;
247 	ct->ct_synch_setup = bshw_synch_setup;
248 
249 	ct->sc_xmode = CT_XMODE_DMA;
250 	if (chp->ch_mem != NULL)
251 		ct->sc_xmode |= CT_XMODE_PIO;
252 
253 	ct->sc_chiprev = chiprev;
254 	switch (chiprev)
255 	{
256 	case CT_WD33C93:
257 		/* s = "WD33C93"; */
258 		ct->sc_chipclk = 8;
259 		break;
260 	case CT_WD33C93_A:
261 		if (DVCFG_MAJOR(device_get_flags(dev)) > 0)
262 		{
263 			/* s = "AM33C93_A"; */
264 			ct->sc_chipclk = 20;
265 			ct->sc_chiprev = CT_AM33C93_A;
266 		}
267 		else
268 		{
269 			/* s = "WD33C93_A"; */
270 			ct->sc_chipclk = 10;
271 		}
272 		break;
273 
274 	case CT_AM33C93_A:
275 		/* s = "AM33C93_A"; */
276 		ct->sc_chipclk = 20;
277 		break;
278 
279 	default:
280 	case CT_WD33C93_B:
281 		/* s = "WD33C93_B"; */
282 		ct->sc_chipclk = 20;
283 		break;
284 	}
285 #if	0
286 	printf("%s: chiprev %s chipclk %d MHz\n",
287 		slp->sl_dev.dv_xname, s, ct->sc_chipclk);
288 #endif
289 
290 	slp->sl_dev = dev;
291 	slp->sl_hostid = bs->sc_hostid;
292 	slp->sl_cfgflags = device_get_flags(dev);
293 	mtx_init(&slp->sl_lock, "ct", NULL, MTX_DEF);
294 
295 	ctattachsubr(ct);
296 
297 	if (bus_setup_intr(dev, ct->irq_res, INTR_TYPE_CAM | INTR_MPSAFE,
298 			   NULL, ctintr, ct, &ct->sc_ih)) {
299 		ct_space_unmap(dev, ct);
300 		return ENXIO;
301 	}
302 
303 	return 0;
304 }
305 
306 static struct bshw *
ct_find_hw(device_t dev)307 ct_find_hw(device_t dev)
308 {
309 	return DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(device_get_flags(dev)));
310 }
311 
312 static int
ct_space_map(device_t dev,struct bshw * hw,struct resource ** iohp,struct resource ** memhp)313 ct_space_map(device_t dev, struct bshw *hw,
314 	     struct resource **iohp, struct resource **memhp)
315 {
316 	int port_rid, mem_rid;
317 
318 	*memhp = NULL;
319 
320 	port_rid = 0;
321 	*iohp = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid, 0ul, ~0ul,
322 				   BSHW_IOSZ, RF_ACTIVE);
323 	if (*iohp == NULL)
324 		return ENXIO;
325 
326 	if ((hw->hw_flags & BSHW_SMFIFO) == 0 || isa_get_maddr(dev) == -1)
327 		return 0;
328 
329 	mem_rid = 0;
330 	*memhp = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid, 0ul, ~0ul,
331 				    BSHW_MEMSZ, RF_ACTIVE);
332 	if (*memhp == NULL) {
333 		bus_release_resource(dev, SYS_RES_IOPORT, port_rid, *iohp);
334 		return ENXIO;
335 	}
336 
337 	return 0;
338 }
339 
340 static void
ct_space_unmap(device_t dev,struct ct_softc * ct)341 ct_space_unmap(device_t dev, struct ct_softc *ct)
342 {
343 	if (ct->port_res != NULL)
344 		bus_release_resource(dev, SYS_RES_IOPORT, 0, ct->port_res);
345 	if (ct->mem_res != NULL)
346 		bus_release_resource(dev, SYS_RES_MEMORY, 0, ct->mem_res);
347 	if (ct->irq_res != NULL)
348 		bus_release_resource(dev, SYS_RES_IRQ, 0, ct->irq_res);
349 	if (ct->drq_res != NULL)
350 		bus_release_resource(dev, SYS_RES_DRQ, 0, ct->drq_res);
351 }
352 
353 static void
ct_dmamap(void * arg,bus_dma_segment_t * seg,int nseg,int error)354 ct_dmamap(void *arg, bus_dma_segment_t *seg, int nseg, int error)
355 {
356 	bus_addr_t *addr = (bus_addr_t *)arg;
357 
358 	*addr = seg->ds_addr;
359 }
360 
361 static void
ct_isa_bus_access_weight(struct ct_bus_access_handle * chp)362 ct_isa_bus_access_weight(struct ct_bus_access_handle *chp)
363 {
364 
365 	outb(0x5f, 0);
366 }
367 
368 static void
ct_isa_dmasync_before(struct ct_softc * ct)369 ct_isa_dmasync_before(struct ct_softc *ct)
370 {
371 
372 	if (need_pre_dma_flush)
373 		wbinvd();
374 }
375 
376 static void
ct_isa_dmasync_after(struct ct_softc * ct)377 ct_isa_dmasync_after(struct ct_softc *ct)
378 {
379 
380 	if (need_post_dma_flush)
381 		invd();
382 }
383