]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i4b/layer1/i4b_tel_s016.c
This commit was generated by cvs2svn to compensate for changes in r63516,
[FreeBSD/FreeBSD.git] / sys / i4b / layer1 / i4b_tel_s016.c
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/16 and clones
38  *      =================================================================
39  *
40  *      $Id: i4b_tel_s016.c,v 1.3 1999/12/13 21:25:26 hm Exp $ 
41  *
42  * $FreeBSD$
43  *
44  *      last edit-date: [Mon Dec 13 22:02:47 1999]
45  *
46  *---------------------------------------------------------------------------*/
47
48 #include "isic.h"
49 #include "opt_i4b.h"
50
51 #if NISIC > 0 && defined(TEL_S0_16)
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/mbuf.h>
56 #include <sys/socket.h>
57
58 #include <machine/clock.h>
59 #include <machine/md_var.h>
60
61 #include <net/if.h>
62
63 #include <machine/i4b_debug.h>
64 #include <machine/i4b_ioctl.h>
65
66 #include <i4b/layer1/i4b_l1.h>
67 #include <i4b/layer1/i4b_isac.h>
68 #include <i4b/layer1/i4b_hscx.h>
69
70 #include <i4b/include/i4b_global.h>
71 #include <i4b/include/i4b_l1l2.h>
72 #include <i4b/include/i4b_mbuf.h>
73
74 #define TELES_S016_MEMSIZE 0x1000
75
76 static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
77 static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
78
79 /*---------------------------------------------------------------------------*
80  *      Teles S0/16 write register routine
81  *---------------------------------------------------------------------------*/
82 static void
83 tels016_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
84 {
85         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.mem);
86         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
87
88         offs += offset[what];
89
90         if (offs & 0x01)
91                 offs |= 0x200;
92
93         bus_space_write_1(t, h, offs, data);
94 }
95
96 /*---------------------------------------------------------------------------*
97  *      Teles S0/16 read register routine
98  *---------------------------------------------------------------------------*/
99 static u_int8_t
100 tels016_read_reg(struct l1_softc *sc,   int what, bus_size_t offs)
101 {
102         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.mem);
103         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
104
105         offs += offset[what];
106
107         if(offs & 0x01)
108                 offs |= 0x200;
109
110         return bus_space_read_1(t, h, offs);
111 }
112
113 /*---------------------------------------------------------------------------*
114  *      Teles S0/16 fifo write routine
115  *---------------------------------------------------------------------------*/
116 static void
117 tels016_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
118 {
119         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.mem);
120         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
121         bus_space_write_region_1(t, h, offset[what], data, size);
122 }
123
124 /*---------------------------------------------------------------------------*
125  *      Teles S0/16 fifo read routine
126  *---------------------------------------------------------------------------*/
127 static void
128 tels016_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
129 {
130         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.mem);
131         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
132         bus_space_read_region_1(t, h, offset[what], buf, size);
133 }
134
135 /*---------------------------------------------------------------------------*
136  *      isic_probe_s016 - probe for Teles S0/16 and compatibles
137  *---------------------------------------------------------------------------*/
138 int
139 isic_probe_s016(device_t dev)
140 {
141         size_t unit = device_get_unit(dev);     /* get unit */
142         struct l1_softc *sc = 0;                /* softc */
143         void *ih = 0;                           /* dummy */
144         u_int8_t b0,b1,b2;                      /* for signature */
145         bus_space_tag_t    t;                   /* bus things */
146         bus_space_handle_t h;
147
148         /* check max unit range */
149
150         if(unit >= ISIC_MAXUNIT)
151         {
152                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n",
153                                 unit, unit);
154                 return(ENXIO);  
155         }
156
157         sc = &l1_sc[unit];                      /* get pointer to softc */
158
159         sc->sc_unit = unit;                     /* set unit */
160
161         sc->sc_flags = FLAG_TELES_S0_16;        /* set flags */
162
163         /* see if an io base was supplied */
164
165         if(!(sc->sc_resources.io_base[0] =
166                         bus_alloc_resource(dev, SYS_RES_IOPORT,
167                                            &sc->sc_resources.io_rid[0],
168                                            0ul, ~0ul, 1, RF_ACTIVE)))
169         {
170                 printf("isic%d: Could not allocate i/o port for Teles S0/16.\n", unit);
171                 return(ENXIO);
172         }
173
174         sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
175
176         /*
177          * check if the provided io port is valid
178          */
179
180         switch(sc->sc_port)
181         {
182                 case 0xd80:
183                 case 0xe80:
184                 case 0xf80:
185                         break;
186
187                 default:
188                         printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n",
189                                 unit, sc->sc_port);
190                         isic_detach_common(dev);
191                         return(ENXIO);
192                         break;
193         }
194
195         /* allocate memory resource */
196
197         if(!(sc->sc_resources.mem =
198                         bus_alloc_resource(dev, SYS_RES_MEMORY,
199                                         &sc->sc_resources.mem_rid,
200                                         0ul, ~0ul, TELES_S016_MEMSIZE,
201                                         RF_ACTIVE)))
202         {
203                 printf("isic%d: Could not allocate memory for Teles S0/16.\n", unit);
204                 isic_detach_common(dev);
205                 return(ENXIO);
206         }
207
208         /* 
209          * get virtual addr.
210          */
211         sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem);
212
213         /*
214          * check for valid adresses
215          */
216         switch(kvtop(sc->sc_vmem_addr))
217         {
218                 case 0xc0000:
219                 case 0xc2000:
220                 case 0xc4000:
221                 case 0xc6000:
222                 case 0xc8000:
223                 case 0xca000:
224                 case 0xcc000:
225                 case 0xce000:
226                 case 0xd0000:
227                 case 0xd2000:
228                 case 0xd4000:
229                 case 0xd6000:
230                 case 0xd8000:
231                 case 0xda000:
232                 case 0xdc000:
233                 case 0xde000:
234                         break;
235
236                 default:
237                         printf("isic%d: Error, invalid memory address 0x%lx for Teles S0/16!\n",
238                                 unit, kvtop(sc->sc_vmem_addr));
239                         isic_detach_common(dev);
240                         return(ENXIO);
241                         break;
242         }               
243         
244         /* setup ISAC access routines */
245
246         sc->clearirq = NULL;
247
248         sc->readreg = tels016_read_reg;
249         sc->writereg = tels016_write_reg;
250
251         sc->readfifo = tels016_read_fifo;
252         sc->writefifo = tels016_write_fifo;
253
254         /* setup card type */
255         sc->sc_cardtyp = CARD_TYPEP_16;
256
257         /* setup IOM bus type */
258         
259         sc->sc_bustyp = BUS_TYPE_IOM1;
260
261         sc->sc_ipac = 0;
262         sc->sc_bfifolen = HSCX_FIFO_LEN;
263
264         /* setup ISAC base addr, though we don't really need it */
265         
266         ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100);
267
268         /* setup HSCX base addr */
269         
270         HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180);
271         HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0);
272
273         t = rman_get_bustag(sc->sc_resources.io_base[0]);
274         h = rman_get_bushandle(sc->sc_resources.io_base[0]);
275
276         /* get signature bytes */
277         b0 = bus_space_read_1(t, h, 0);
278         b1 = bus_space_read_1(t, h, 1);
279         b2 = bus_space_read_1(t, h, 2);
280
281         /* check signature bytes */
282         if(b0 != 0x51)
283         {
284                 printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n",
285                         unit, b0);
286                 isic_detach_common(dev);
287                 return(ENXIO);
288         }
289         
290         if(b1 != 0x93)
291         {
292                 printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n",
293                         unit, b1);
294                 isic_detach_common(dev);
295                 return(ENXIO);
296         }
297         
298         if((b2 != 0x1e) && (b2 != 0x1f))
299         {
300                 printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n",
301                         unit, b2);
302                 isic_detach_common(dev);
303                 return(ENXIO);
304         }
305
306         /* get our irq */
307
308         if(!(sc->sc_resources.irq =
309                         bus_alloc_resource(dev, SYS_RES_IRQ,
310                                                 &sc->sc_resources.irq_rid,
311                                                 0ul, ~0ul, 1, RF_ACTIVE)))
312         {
313                 printf("isic%d: Could not allocate irq for Teles S0/16.\n", unit);
314                 isic_detach_common(dev);
315                 return ENXIO;
316         }
317
318         /* register interupt routine */
319
320         bus_setup_intr(dev, sc->sc_resources.irq,
321                         INTR_TYPE_NET,
322                         (void(*)(void *))(isicintr),
323                         sc, &ih);
324
325         /* get the irq number */
326         
327         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
328
329         /* check IRQ validity */
330
331         if((intr_no[sc->sc_irq]) == 1)
332         {
333                 printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n",
334                         unit, sc->sc_irq);
335                 isic_detach_common(dev);
336                 return(ENXIO);
337         }
338         
339         return (0);
340 }
341
342 /*---------------------------------------------------------------------------*
343  *      isic_attach_s016 - attach Teles S0/16 and compatibles
344  *---------------------------------------------------------------------------*/
345 int
346 isic_attach_s016(device_t dev)
347 {
348         struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
349         u_long irq;
350
351         bus_space_tag_t    ta = rman_get_bustag(sc->sc_resources.mem);
352         bus_space_handle_t ha = rman_get_bushandle(sc->sc_resources.mem);
353         bus_space_tag_t    tb = rman_get_bustag(sc->sc_resources.io_base[0]);
354         bus_space_handle_t hb = rman_get_bushandle(sc->sc_resources.io_base[0]);
355
356         /* is this right for FreeBSD or off by one ? */
357         irq = intr_no[sc->sc_irq];
358
359         /* configure IRQ */
360
361         irq |= ((u_long) sc->sc_vmem_addr) >> 9;
362
363         DELAY(SEC_DELAY / 10);
364         bus_space_write_1(tb, hb, 4, irq);
365
366         DELAY(SEC_DELAY / 10);
367         bus_space_write_1(tb, hb, 4, irq | 0x01);
368
369         DELAY(SEC_DELAY / 5);
370
371         /* set card bit off */
372
373         bus_space_write_1(ta, ha, 0x80, 0);
374         DELAY(SEC_DELAY / 5);
375
376         /* set card bit on */
377         
378         bus_space_write_1(ta, ha, 0x80, 1);
379         DELAY(SEC_DELAY / 5);
380
381         return 0;
382 }
383 #endif /* ISIC > 0 */