1 /*
2 * Copyright (c) 1996 Arne Helme. All rights reserved.
3 *
4 * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
5 *
6 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
7 *
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 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the author nor the names of any co-contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 * 4. Altered versions must be plainly marked as such, and must not be
21 * misrepresented as being the original software and/or documentation.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *---------------------------------------------------------------------------
36 *
37 * isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones
38 * ================================================================
39 *
40 * $Id: isic_isa_tel_s08.c,v 1.4 2002/03/24 20:35:49 martin Exp $
41 *
42 * last edit-date: [Fri Jan 5 11:37:22 2001]
43 *
44 * -hm clean up
45 * -hm more cleanup
46 * -hm NetBSD patches from Martin
47 * -hm making it finally work (checked with board revision 1.2)
48 * -hm converting asm -> C
49 *
50 *---------------------------------------------------------------------------*/
51
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: isic_isa_tel_s08.c,v 1.4 2002/03/24 20:35:49 martin Exp $");
54
55 #include "opt_isicisa.h"
56 #ifdef ISICISA_TEL_S0_8
57
58 #include <sys/param.h>
59 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
60 #include <sys/ioccom.h>
61 #else
62 #include <sys/ioctl.h>
63 #endif
64 #include <sys/kernel.h>
65 #include <sys/systm.h>
66 #include <sys/mbuf.h>
67
68 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
69 #include <sys/callout.h>
70 #endif
71
72 #ifdef __FreeBSD__
73 #include <machine/clock.h>
74 #include <machine/md_var.h>
75 #include <i386/isa/isa_device.h>
76 #else
77 #include <machine/bus.h>
78 #include <sys/device.h>
79 #endif
80
81 #include <sys/socket.h>
82 #include <net/if.h>
83
84 #ifdef __FreeBSD__
85 #include <machine/i4b_debug.h>
86 #include <machine/i4b_ioctl.h>
87 #else
88 #include <netisdn/i4b_debug.h>
89 #include <netisdn/i4b_ioctl.h>
90 #endif
91
92 #include <netisdn/i4b_global.h>
93 #include <netisdn/i4b_debug.h>
94 #include <netisdn/i4b_l2.h>
95 #include <netisdn/i4b_l1l2.h>
96 #include <netisdn/i4b_mbuf.h>
97
98 #include <dev/ic/isic_l1.h>
99 #include <dev/ic/isac.h>
100 #include <dev/ic/hscx.h>
101
102 #ifndef __FreeBSD__
103 static u_int8_t tels08_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
104 static void tels08_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
105 static void tels08_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
106 static void tels08_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
107 #endif
108
109 /*---------------------------------------------------------------------------*
110 * Teles S0/8 write register routine
111 *---------------------------------------------------------------------------*/
112 #ifdef __FreeBSD__
113
114 static void
115 tels08_write_reg(u_char *base, u_int i, u_int v)
116 {
117 if(i & 0x01)
118 i |= 0x200;
119 base[i] = v;
120 }
121
122 #else
123
124 static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
125
126 static void
127 tels08_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
128 {
129 bus_space_tag_t t = sc->sc_maps[0].t;
130 bus_space_handle_t h = sc->sc_maps[0].h;
131
132 offs += offset[what];
133
134 if (offs & 0x01)
135 offs |= 0x200;
136
137 bus_space_write_1(t, h, offs, data);
138 }
139 #endif
140
141 /*---------------------------------------------------------------------------*
142 * Teles S0/8 read register routine
143 *---------------------------------------------------------------------------*/
144 #ifdef __FreeBSD__
145
146 static u_char
147 tels08_read_reg(u_char *base, u_int i)
148 {
149 if(i & 0x1)
150 i |= 0x200;
151 return(base[i]);
152 }
153
154 #else
155
156 static u_int8_t
157 tels08_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
158 {
159 bus_space_tag_t t = sc->sc_maps[0].t;
160 bus_space_handle_t h = sc->sc_maps[0].h;
161
162 offs += offset[what];
163
164 if (offs & 0x01)
165 offs |= 0x200;
166
167 return bus_space_read_1(t, h, offs);
168 }
169 #endif
170
171 /*---------------------------------------------------------------------------*
172 * Teles S0/8 fifo read/write access
173 *---------------------------------------------------------------------------*/
174 #ifdef __FreeBSD__
175
176 static void
177 tels08_memcpyb(void *to, const void *from, size_t len)
178 {
179 for(;len > 0; len--)
180 *((unsigned char *)to)++ = *((unsigned char *)from)++;
181 }
182
183 #else
184
185 static void
186 tels08_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size)
187 {
188 bus_space_tag_t t = sc->sc_maps[0].t;
189 bus_space_handle_t h = sc->sc_maps[0].h;
190 bus_space_write_region_1(t, h, offset[what], data, size);
191 }
192
193 static void
194 tels08_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
195 {
196 bus_space_tag_t t = sc->sc_maps[0].t;
197 bus_space_handle_t h = sc->sc_maps[0].h;
198 bus_space_read_region_1(t, h, offset[what], buf, size);
199 }
200 #endif
201
202 /*---------------------------------------------------------------------------*
203 * isic_probe_s08 - probe for Teles S0/8 and compatibles
204 *---------------------------------------------------------------------------*/
205 #ifdef __FreeBSD__
206
207 int
208 isic_probe_s08(struct isa_device *dev)
209 {
210 struct isic_softc *sc = &l1_sc[dev->id_unit];
211
212 /* check max unit range */
213
214 if(dev->id_unit >= ISIC_MAXUNIT)
215 {
216 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
217 dev->id_unit, dev->id_unit);
218 return(0);
219 }
220 sc->sc_unit = dev->id_unit;
221
222 /* check IRQ validity */
223
224 switch(ffs(dev->id_irq)-1)
225 {
226 case 2:
227 case 9: /* XXX */
228 case 3:
229 case 4:
230 case 5:
231 case 6:
232 case 7:
233 break;
234
235 default:
236 printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n",
237 dev->id_unit, ffs(dev->id_irq)-1);
238 return(0);
239 break;
240 }
241 sc->sc_irq = dev->id_irq;
242
243 /* check if we got an iobase */
244
245 if(dev->id_iobase > 0)
246 {
247 printf("isic%d: Error, iobase specified for Teles S0/8!\n",
248 dev->id_unit);
249 return(0);
250 }
251
252 /* check if inside memory range of 0xA0000 .. 0xDF000 */
253
254 if( (kvtop(dev->id_maddr) < 0xa0000) ||
255 (kvtop(dev->id_maddr) > 0xdf000) )
256 {
257 printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n",
258 dev->id_unit, kvtop(dev->id_maddr));
259 return(0);
260 }
261
262 sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
263 dev->id_msize = 0x1000;
264
265 /* setup ISAC access routines */
266
267 sc->clearirq = NULL;
268 sc->readreg = tels08_read_reg;
269 sc->writereg = tels08_write_reg;
270
271 sc->readfifo = tels08_memcpyb;
272 sc->writefifo = tels08_memcpyb;
273
274 /* setup card type */
275
276 sc->sc_cardtyp = CARD_TYPEP_8;
277
278 /* setup IOM bus type */
279
280 sc->sc_bustyp = BUS_TYPE_IOM1;
281
282 sc->sc_ipac = 0;
283 sc->sc_bfifolen = HSCX_FIFO_LEN;
284
285 /* setup ISAC base addr */
286
287 ISAC_BASE = (caddr_t)((dev->id_maddr) + 0x100);
288
289 /* setup HSCX base addr */
290
291 HSCX_A_BASE = (caddr_t)((dev->id_maddr) + 0x180);
292 HSCX_B_BASE = (caddr_t)((dev->id_maddr) + 0x1c0);
293
294 return (1);
295 }
296
297 #else
298
299 int
300 isic_probe_s08(struct isic_attach_args *ia)
301 {
302 /* no real sensible probe is easy - write to fifo memory
303 and read back to verify there is memory doesn't work,
304 because you talk to tx fifo and rcv fifo. So, just check
305 HSCX version, which at least fails if no card present
306 at the given location. */
307 bus_space_tag_t t = ia->ia_maps[0].t;
308 bus_space_handle_t h = ia->ia_maps[0].h;
309 u_int8_t v1, v2;
310
311 /* HSCX A VSTR */
312 v1 = bus_space_read_1(t, h, offset[1] + H_VSTR) & 0x0f;
313 if (v1 != HSCX_VA1 && v1 != HSCX_VA2 && v1 != HSCX_VA3 && v1 != HSCX_V21)
314 return 0;
315
316 /* HSCX B VSTR */
317 v2 = bus_space_read_1(t, h, offset[2] + H_VSTR) & 0x0f;
318 if (v2 != HSCX_VA1 && v2 != HSCX_VA2 && v2 != HSCX_VA3 && v2 != HSCX_V21)
319 return 0;
320
321 /* both HSCX channels should have the same version... */
322 if (v1 != v2)
323 return 0;
324
325 return 1;
326 }
327 #endif
328
329 /*---------------------------------------------------------------------------*
330 * isic_attach_s08 - attach Teles S0/8 and compatibles
331 *---------------------------------------------------------------------------*/
332 int
333 #ifdef __FreeBSD__
334 isic_attach_s08(struct isa_device *dev)
335 #else
336 isic_attach_s08(struct isic_softc *sc)
337 #endif
338 {
339 #ifdef __FreeBSD__
340 struct isic_softc *sc = &l1_sc[dev->id_unit];
341 #else
342 bus_space_tag_t t = sc->sc_maps[0].t;
343 bus_space_handle_t h = sc->sc_maps[0].h;
344 #endif
345
346 /* set card off */
347
348 #ifdef __FreeBSD__
349 sc->sc_vmem_addr[0x80] = 0;
350 #else
351 bus_space_write_1(t, h, 0x80, 0);
352 #endif
353
354 DELAY(SEC_DELAY / 5);
355
356 /* set card on */
357
358 #ifdef __FreeBSD__
359 sc->sc_vmem_addr[0x80] = 1;
360 #else
361 bus_space_write_1(t, h, 0x80, 1);
362 #endif
363
364 DELAY(SEC_DELAY / 5);
365
366 #ifndef __FreeBSD__
367
368 /* setup ISAC access routines */
369
370 sc->clearirq = NULL;
371 sc->readreg = tels08_read_reg;
372 sc->writereg = tels08_write_reg;
373 sc->readfifo = tels08_read_fifo;
374 sc->writefifo = tels08_write_fifo;
375
376 /* setup card type */
377
378 sc->sc_cardtyp = CARD_TYPEP_8;
379
380 /* setup IOM bus type */
381
382 sc->sc_bustyp = BUS_TYPE_IOM1;
383
384 sc->sc_ipac = 0;
385 sc->sc_bfifolen = HSCX_FIFO_LEN;
386
387 #endif
388
389 return (1);
390 }
391
392 #endif /* ISICISA_TEL_S0_8 */
393
Cache object: fba4bd3756d17603637d1b15b67ddf84
|