No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / isa / isic_isa_itk_ix1.c
blobf7caff1bc486897c892ddbe62ec0796201e5d965
1 /*-
2 * Copyright (c) 2002 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Martin Husemann <martin@NetBSD.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: isic_isa_itk_ix1.c,v 1.16 2008/04/08 20:08:50 cegger Exp $");
33 #include "opt_isicisa.h"
36 * The ITK ix1 micro ISDN card is an ISA card with one region
37 * of four io ports mapped and a fixed irq all jumpered on the card.
38 * Access to the board is straight forward and simmilar to
39 * the ELSA and DYNALINK cards. If a PCI version of this card
40 * exists all we need is probably a pci-bus attachment, all
41 * this low level routines should work immediately.
43 * To reset the card:
44 * - write 0x01 to ITK_CONFIG
45 * - wait >= 10 ms
46 * - write 0x00 to ITK_CONFIG
48 * To read or write data:
49 * - write address to ITK_ALE port
50 * - read data from or write data to ITK_ISAC_DATA port or ITK_HSCX_DATA port
51 * The two HSCX channel registers are offset by HSCXA (0x00) and HSCXB (0x40).
53 * The probe routine was derived by trial and error from a representative
54 * sample of two cards ;-) The standard way (checking HSCX versions)
55 * was extended by reading a zero from a non existent HSCX register (register
56 * 0xff). Reading the config register gives varying results, so this doesn't
57 * seem to be used as an id register (like the Teles S0/16.3).
59 * If the probe fails for your card use "options ITK_PROBE_DEBUG" to get
60 * additional debug output.
64 #ifdef ISICISA_ITKIX1
66 #include <sys/param.h>
67 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
68 #include <sys/ioccom.h>
69 #else
70 #include <sys/ioctl.h>
71 #endif
72 #include <sys/kernel.h>
73 #include <sys/systm.h>
74 #include <sys/mbuf.h>
76 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
77 #include <sys/callout.h>
78 #endif
80 #ifdef __FreeBSD__
81 #include <machine/clock.h>
82 #include <i386/isa/isa_device.h>
83 #else
84 #include <sys/bus.h>
85 #include <sys/device.h>
86 #endif
88 #include <sys/socket.h>
89 #include <net/if.h>
91 #ifdef __FreeBSD__
92 #include <machine/i4b_debug.h>
93 #include <machine/i4b_ioctl.h>
94 #else
95 #include <netisdn/i4b_global.h>
96 #include <netisdn/i4b_debug.h>
97 #include <netisdn/i4b_ioctl.h>
98 #include <netisdn/i4b_l2.h>
99 #include <netisdn/i4b_l1l2.h>
100 #endif
102 #include <dev/ic/isic_l1.h>
103 #include <dev/ic/isac.h>
104 #include <dev/ic/hscx.h>
106 #include <netisdn/i4b_global.h>
108 /* Register offsets */
109 #define ITK_ISAC_DATA 0
110 #define ITK_HSCX_DATA 1
111 #define ITK_ALE 2
112 #define ITK_CONFIG 3
114 /* Size of IO range to allocate for this card */
115 #define ITK_IO_SIZE 4
117 /* Register offsets for the two HSCX channels */
118 #define HSCXA 0
119 #define HSCXB 0x40
122 * Local function prototypes
124 #ifdef __FreeBSD__
125 /* FreeBSD version */
126 static void itkix1_read_fifo(void *buf, const void *base, size_t len);
127 static void itkix1_write_fifo(void *base, const void *buf, size_t len);
128 static void itkix1_write_reg(u_char *base, u_int offset, u_int v);
129 static u_char itkix1_read_reg(u_char *base, u_int offset);
130 #else
131 /* NetBSD/OpenBSD version */
132 static void itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
133 static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
134 static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
135 static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
136 #endif
139 * Probe for card
141 #ifdef __FreeBSD__
143 isic_probe_itkix1(struct isa_device *dev)
145 u_int8_t hd, hv1, hv2, saveale;
146 int ret;
148 /* save old value of this port, we're stomping over it */
149 saveale = inb(dev->id_iobase + ITK_ALE);
151 /* select invalid register */
152 outb(dev->id_iobase + ITK_ALE, 0xff);
153 /* get HSCX data for this non existent register */
154 hd = inb(dev->id_iobase + ITK_HSCX_DATA);
155 /* get HSCX version info */
156 outb(dev->id_iobase + ITK_ALE, HSCXA + H_VSTR);
157 hv1 = inb(dev->id_iobase + ITK_HSCX_DATA);
158 outb(dev->id_iobase + ITK_ALE, HSCXB + H_VSTR);
159 hv2 = inb(dev->id_iobase + ITK_HSCX_DATA);
161 /* succeed if version bits are OK and we got a zero from the
162 * non existent register. we found verison 0x05 and 0x04
163 * out there... */
164 ret = (hd == 0)
165 && (((hv1 & 0x0f) == 0x05) || ((hv1 & 0x0f) == 0x04))
166 && (((hv2 & 0x0f) == 0x05) || ((hv2 & 0x0f) == 0x04));
168 /* retstore save value if we fail (if we succeed the old value
169 * has no meaning) */
170 if (!ret)
171 outb(dev->id_iobase + ITK_ALE, saveale);
173 #ifdef ITK_PROBE_DEBUG
174 printf("\nITK ix1 micro probe: hscx = 0x%02x, v1 = 0x%02x, v2 = 0x%02x, would have %s\n",
175 hd, hv1, hv2, ret ? "succeeded" : "failed");
176 return 1;
177 #else
178 return ret;
179 #endif
181 #else
183 isic_probe_itkix1(struct isic_attach_args *ia)
185 bus_space_tag_t t = ia->ia_maps[0].t;
186 bus_space_handle_t h = ia->ia_maps[0].h;
187 u_int8_t hd, hv1, hv2, saveale;
188 int ret;
190 /* save old value of this port, we're stomping over it */
191 saveale = bus_space_read_1(t, h, ITK_ALE);
193 /* select invalid register */
194 bus_space_write_1(t, h, ITK_ALE, 0xff);
195 /* get HSCX data for this non existent register */
196 hd = bus_space_read_1(t, h, ITK_HSCX_DATA);
197 /* get HSCX version info */
198 bus_space_write_1(t, h, ITK_ALE, HSCXA + H_VSTR);
199 hv1 = bus_space_read_1(t, h, ITK_HSCX_DATA);
200 bus_space_write_1(t, h, ITK_ALE, HSCXB + H_VSTR);
201 hv2 = bus_space_read_1(t, h, ITK_HSCX_DATA);
203 ret = (hd == 0) && ((hv1 & 0x0f) == 0x05) && ((hv2 & 0x0f) == 0x05);
204 /* succeed if version bits are OK and we got a zero from the
205 * non existent register. we found verison 0x05 and 0x04
206 * out there... */
207 ret = (hd == 0)
208 && (((hv1 & 0x0f) == 0x05) || ((hv1 & 0x0f) == 0x04))
209 && (((hv2 & 0x0f) == 0x05) || ((hv2 & 0x0f) == 0x04));
211 /* retstore save value if we fail (if we succeed the old value
212 * has no meaning) */
213 if (!ret)
214 bus_space_write_1(t, h, ITK_ALE, saveale);
216 #ifdef ITK_PROBE_DEBUG
217 printf("\nITK ix1 micro probe: hscx = 0x%02x, v1 = 0x%02x, v2 = 0x%02x, would have %s\n",
218 hd, hv1, hv2, ret ? "succeeded" : "failed");
219 return 1;
220 #else
221 return ret;
222 #endif
224 #endif
227 * Attach card
229 #ifdef __FreeBSD__
231 isic_attach_itkix1(struct isa_device *dev)
233 struct isic_softc *sc = &l1_sc[dev->id_unit];
234 u_int8_t hv1, hv2;
236 sc->sc_irq = dev->id_irq;
238 dev->id_msize = 0;
240 /* check if we got an iobase */
241 sc->sc_port = dev->id_iobase;
243 /* setup access routines */
244 sc->clearirq = NULL;
245 sc->readreg = itkix1_read_reg;
246 sc->writereg = itkix1_write_reg;
247 sc->readfifo = itkix1_read_fifo;
248 sc->writefifo = itkix1_write_fifo;
250 /* setup card type */
251 sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
253 /* setup IOM bus type */
254 sc->sc_bustyp = BUS_TYPE_IOM2;
256 sc->sc_ipac = 0;
257 sc->sc_bfifolen = HSCX_FIFO_LEN;
259 /* setup ISAC and HSCX base addr */
260 ISAC_BASE = (void *) sc->sc_port;
261 HSCX_A_BASE = (void *) sc->sc_port + 1;
262 HSCX_B_BASE = (void *) sc->sc_port + 2;
264 /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
265 hv1 = HSCX_READ(0, H_VSTR) & 0xf;
266 hv2 = HSCX_READ(1, H_VSTR) & 0xf;
267 if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
269 printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n",
270 dev->id_unit);
271 printf("isic%d: HSC0: VSTR: %#x\n",
272 dev->id_unit, HSCX_READ(0, H_VSTR));
273 printf("isic%d: HSC1: VSTR: %#x\n",
274 dev->id_unit, HSCX_READ(1, H_VSTR));
275 return (0);
278 outb((dev->id_iobase)+ITK_CONFIG, 1);
279 DELAY(SEC_DELAY / 10);
280 outb((dev->id_iobase)+ITK_CONFIG, 0);
281 DELAY(SEC_DELAY / 10);
282 return(1);
285 #else
287 int isic_attach_itkix1(struct isic_softc *sc)
289 u_int8_t hv1, hv2;
291 /* setup access routines */
292 sc->clearirq = NULL;
293 sc->readreg = itkix1_read_reg;
294 sc->writereg = itkix1_write_reg;
295 sc->readfifo = itkix1_read_fifo;
296 sc->writefifo = itkix1_write_fifo;
298 /* setup card type */
299 sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
301 /* setup IOM bus type */
302 sc->sc_bustyp = BUS_TYPE_IOM2;
304 sc->sc_ipac = 0;
305 sc->sc_bfifolen = HSCX_FIFO_LEN;
307 /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
308 hv1 = HSCX_READ(0, H_VSTR) & 0xf;
309 hv2 = HSCX_READ(1, H_VSTR) & 0xf;
310 if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
312 printf("%s: HSCX VSTR test failed for ITK ix1 micro\n",
313 device_xname(&sc->sc_dev));
314 printf("%s: HSC0: VSTR: %#x\n",
315 device_xname(&sc->sc_dev), HSCX_READ(0, H_VSTR));
316 printf("%s: HSC1: VSTR: %#x\n",
317 device_xname(&sc->sc_dev), HSCX_READ(1, H_VSTR));
318 return 0;
321 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 1);
322 DELAY(SEC_DELAY / 10);
323 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 0);
324 DELAY(SEC_DELAY / 10);
325 return 1;
328 #endif
330 #ifdef __FreeBSD__
331 static void
332 itkix1_read_fifo(void *buf, const void *base, size_t len)
334 u_int port = (u_int)base & ~0x0003;
335 switch ((u_int)base & 3) {
336 case 0: /* ISAC */
337 outb(port+ITK_ALE, 0);
338 insb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
339 break;
340 case 1: /* HSCXA */
341 outb(port+ITK_ALE, HSCXA);
342 insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
343 break;
344 case 2: /* HSCXB */
345 outb(port+ITK_ALE, HSCXB);
346 insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
347 break;
350 #else
351 static void
352 itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
354 bus_space_tag_t t = sc->sc_maps[0].t;
355 bus_space_handle_t h = sc->sc_maps[0].h;
356 switch (what) {
357 case ISIC_WHAT_ISAC:
358 bus_space_write_1(t, h, ITK_ALE, 0);
359 bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size);
360 break;
361 case ISIC_WHAT_HSCXA:
362 bus_space_write_1(t, h, ITK_ALE, HSCXA);
363 bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
364 break;
365 case ISIC_WHAT_HSCXB:
366 bus_space_write_1(t, h, ITK_ALE, HSCXB);
367 bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
368 break;
371 #endif
373 #ifdef __FreeBSD__
374 static void
375 itkix1_write_fifo(void *base, const void *buf, size_t len)
377 u_int port = (u_int)base & ~0x0003;
378 switch ((u_int)base & 3) {
379 case 0: /* ISAC */
380 outb(port+ITK_ALE, 0);
381 outsb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
382 break;
383 case 1: /* HSCXA */
384 outb(port+ITK_ALE, HSCXA);
385 outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
386 break;
387 case 2: /* HSCXB */
388 outb(port+ITK_ALE, HSCXB);
389 outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
390 break;
393 #else
394 static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
396 bus_space_tag_t t = sc->sc_maps[0].t;
397 bus_space_handle_t h = sc->sc_maps[0].h;
398 switch (what) {
399 case ISIC_WHAT_ISAC:
400 bus_space_write_1(t, h, ITK_ALE, 0);
401 bus_space_write_multi_1(t, h, ITK_ISAC_DATA, buf, size);
402 break;
403 case ISIC_WHAT_HSCXA:
404 bus_space_write_1(t, h, ITK_ALE, HSCXA);
405 bus_space_write_multi_1(t, h, ITK_HSCX_DATA, buf, size);
406 break;
407 case ISIC_WHAT_HSCXB:
408 bus_space_write_1(t, h, ITK_ALE, HSCXB);
409 bus_space_write_multi_1(t, h, ITK_HSCX_DATA, buf, size);
410 break;
413 #endif
415 #ifdef __FreeBSD__
416 static void
417 itkix1_write_reg(u_char *base, u_int offset, u_int v)
419 u_int port = (u_int)base & ~0x0003;
420 switch ((u_int)base & 3) {
421 case 0: /* ISAC */
422 outb(port+ITK_ALE, offset);
423 outb(port+ITK_ISAC_DATA, (u_char)v);
424 break;
425 case 1: /* HSCXA */
426 outb(port+ITK_ALE, HSCXA+offset);
427 outb(port+ITK_HSCX_DATA, (u_char)v);
428 break;
429 case 2: /* HSCXB */
430 outb(port+ITK_ALE, HSCXB+offset);
431 outb(port+ITK_HSCX_DATA, (u_char)v);
432 break;
435 #else
436 static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
438 bus_space_tag_t t = sc->sc_maps[0].t;
439 bus_space_handle_t h = sc->sc_maps[0].h;
440 switch (what) {
441 case ISIC_WHAT_ISAC:
442 bus_space_write_1(t, h, ITK_ALE, offs);
443 bus_space_write_1(t, h, ITK_ISAC_DATA, data);
444 break;
445 case ISIC_WHAT_HSCXA:
446 bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
447 bus_space_write_1(t, h, ITK_HSCX_DATA, data);
448 break;
449 case ISIC_WHAT_HSCXB:
450 bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
451 bus_space_write_1(t, h, ITK_HSCX_DATA, data);
452 break;
455 #endif
457 #ifdef __FreeBSD__
458 static u_char
459 itkix1_read_reg(u_char *base, u_int offset)
461 u_int port = (u_int)base & ~0x0003;
462 switch ((u_int)base & 3) {
463 case 0: /* ISAC */
464 outb(port+ITK_ALE, offset);
465 return (inb(port+ITK_ISAC_DATA));
466 case 1: /* HSCXA */
467 outb(port+ITK_ALE, HSCXA+offset);
468 return (inb(port+ITK_HSCX_DATA));
469 case 2: /* HSCXB */
470 outb(port+ITK_ALE, HSCXB+offset);
471 return (inb(port+ITK_HSCX_DATA));
474 #else
475 static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
477 bus_space_tag_t t = sc->sc_maps[0].t;
478 bus_space_handle_t h = sc->sc_maps[0].h;
479 switch (what) {
480 case ISIC_WHAT_ISAC:
481 bus_space_write_1(t, h, ITK_ALE, offs);
482 return bus_space_read_1(t, h, ITK_ISAC_DATA);
483 case ISIC_WHAT_HSCXA:
484 bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
485 return bus_space_read_1(t, h, ITK_HSCX_DATA);
486 case ISIC_WHAT_HSCXB:
487 bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
488 return bus_space_read_1(t, h, ITK_HSCX_DATA);
490 return 0;
492 #endif
494 #endif /* ISICISA_ITKIX1 */