]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/isic/i4b_tel_s08.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer1 / isic / i4b_tel_s08.c
1 /*-
2  *   Copyright (c) 1996 Arne Helme. All rights reserved.
3  *   Copyright (c) 1996 Gary Jennejohn. All rights reserved. 
4  *   Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *   1. Redistributions of source code must retain the above copyright
11  *      notice, this list of conditions and the following disclaimer.
12  *   2. Redistributions in binary form must reproduce the above copyright
13  *      notice, this list of conditions and the following disclaimer in the
14  *      documentation and/or other materials provided with the distribution.
15  *   3. Neither the name of the author nor the names of any co-contributors
16  *      may be used to endorse or promote products derived from this software
17  *      without specific prior written permission.
18  *   4. Altered versions must be plainly marked as such, and must not be
19  *      misrepresented as being the original software and/or documentation.
20  *   
21  *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  *   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  *   SUCH DAMAGE.
32  */
33
34 /*---------------------------------------------------------------------------
35  *
36  *      isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones
37  *      ================================================================
38  *      last edit-date: [Wed Jan 24 09:27:58 2001]
39  *
40  *---------------------------------------------------------------------------*/
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44
45 #include "opt_i4b.h"
46
47 #if defined(TEL_S0_8)
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/socket.h>
52 #include <net/if.h>
53
54 #include <machine/md_var.h>
55 #include <i4b/include/i4b_ioctl.h>
56 #include <i4b/include/i4b_trace.h>
57
58 #include <i4b/layer1/i4b_l1.h>
59 #include <i4b/layer1/isic/i4b_isic.h>
60 #include <i4b/layer1/isic/i4b_hscx.h>
61
62 #define TELES_S08_MEMSIZE 0x1000
63
64 static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
65
66 /*---------------------------------------------------------------------------*
67  *      Teles S0/8 write register routine
68  *---------------------------------------------------------------------------*/
69 static void
70 tels08_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
71 {
72         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
73         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
74
75         offs += offset[what];
76
77         if (offs & 0x01)
78                 offs |= 0x200;
79
80         bus_space_write_1(t, h, offs, data);
81 }
82
83 /*---------------------------------------------------------------------------*
84  *      Teles S0/8 read register routine
85  *---------------------------------------------------------------------------*/
86 static u_int8_t
87 tels08_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
88 {
89         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
90         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
91
92         offs += offset[what];
93
94         if (offs & 0x01)
95                 offs |= 0x200;
96
97         return bus_space_read_1(t, h, offs);
98 }
99
100 /*---------------------------------------------------------------------------*
101  *      Teles S0/8 fifo write access
102  *---------------------------------------------------------------------------*/
103 static void
104 tels08_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
105 {
106         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
107         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
108         bus_space_write_region_1(t, h, offset[what], data, size);
109 }
110
111 /*---------------------------------------------------------------------------*
112  *      Teles S0/8 fifo read access
113  *---------------------------------------------------------------------------*/
114 static void
115 tels08_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
116 {
117         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
118         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
119         bus_space_read_region_1(t, h, offset[what], buf, size);
120 }
121
122 /*---------------------------------------------------------------------------*
123  *      isic_probe_s08 - probe for Teles S0/8 and compatibles
124  *---------------------------------------------------------------------------*/
125 int
126 isic_probe_s08(device_t dev)
127 {
128         size_t unit = device_get_unit(dev);     /* get unit */
129         struct l1_softc *sc = 0;                /* pointer to softc */
130         void *ih = 0;                           /* dummy */
131
132         /* check max unit range */
133
134         if(unit >= ISIC_MAXUNIT)
135         {
136                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
137                                 unit, unit);
138                 return(ENXIO);  
139         }
140
141         sc = &l1_sc[unit];              /* get pointer to softc */
142         sc->sc_unit = unit;             /* set unit */
143
144         /* see if an io base was supplied */
145
146         if((sc->sc_resources.io_base[0] =
147                         bus_alloc_resource_any(dev, SYS_RES_IOPORT,
148                                                &sc->sc_resources.io_rid[0],
149                                                RF_ACTIVE)))
150         {
151                 /* the S0/8 is completely memory mapped ! */
152                 
153                 bus_release_resource(dev,SYS_RES_IOPORT,
154                                      sc->sc_resources.io_rid[0],
155                                      sc->sc_resources.io_base[0]);
156                 printf("isic%d: Error, iobase specified for Teles S0/8!\n", unit);
157                 return(ENXIO);
158         }
159
160         /* allocate memory */
161
162         if(!(sc->sc_resources.mem =
163                 bus_alloc_resource(dev, SYS_RES_MEMORY,
164                                 &sc->sc_resources.mem_rid,
165                                 0ul, ~0ul, TELES_S08_MEMSIZE, RF_ACTIVE)))
166         {
167                 printf("isic%d: Could not allocate memory for Teles S0/8!\n", unit);
168                 return(ENXIO);
169         }
170
171         /* 
172          * get virtual addr. it's just needed to see if it is in
173          * the valid range
174          */
175
176         sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem);
177                 
178         /* check if inside memory range of 0xA0000 .. 0xDF000 */
179
180         if((kvtop(sc->sc_vmem_addr) < 0xa0000) ||
181            (kvtop(sc->sc_vmem_addr) > 0xdf000))
182         {
183                 printf("isic%d: Error, mem addr 0x%x outside 0xA0000-0xDF000 for Teles S0/8!\n",
184                                 unit, kvtop(sc->sc_vmem_addr));
185                 bus_release_resource(dev,SYS_RES_MEMORY,
186                                      sc->sc_resources.mem_rid,
187                                      sc->sc_resources.mem);
188                 sc->sc_resources.mem = 0;
189                 return(ENXIO);
190         }
191         
192         /* setup ISAC access routines */
193
194         sc->clearirq = NULL;
195
196         sc->readreg = tels08_read_reg;
197         sc->writereg = tels08_write_reg;
198
199         sc->readfifo = tels08_read_fifo;
200         sc->writefifo = tels08_write_fifo;
201
202         sc->sc_cardtyp = CARD_TYPEP_8;          /* setup card type */
203         
204         sc->sc_bustyp = BUS_TYPE_IOM1;          /* setup IOM bus type */
205
206         sc->sc_ipac = 0;
207         sc->sc_bfifolen = HSCX_FIFO_LEN;
208
209         /* setup ISAC base addr, though we don't really need it */
210         
211         ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100);
212
213         /* setup HSCX base addr */
214         
215         HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180);
216         HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0);
217
218         /* allocate our irq */
219
220         if(!(sc->sc_resources.irq =
221                         bus_alloc_resource_any(dev, SYS_RES_IRQ,
222                                                &sc->sc_resources.irq_rid,
223                                                RF_ACTIVE)))
224         {
225                 printf("isic%d: Could not allocate irq for Teles S0/8!\n",unit);
226
227                 bus_release_resource(dev,SYS_RES_MEMORY,
228                                      sc->sc_resources.mem_rid,
229                                      sc->sc_resources.mem);
230
231                 sc->sc_resources.mem = 0;
232                 return ENXIO;
233         }
234
235         /* get the irq number */
236
237         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
238         
239         /* check IRQ validity */
240
241         switch(sc->sc_irq)
242         {
243                 case 2:
244                 case 9:         /* XXX */
245                 case 3:
246                 case 4:
247                 case 5:
248                 case 6:
249                 case 7:
250                         break;
251                         
252                 default:
253                         printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n",
254                                 unit, sc->sc_irq);
255                         bus_release_resource(dev,SYS_RES_IRQ,
256                                              sc->sc_resources.irq_rid,
257                                              sc->sc_resources.irq);
258                         sc->sc_resources.irq = 0;
259                         bus_release_resource(dev,SYS_RES_MEMORY,
260                                              sc->sc_resources.mem_rid,
261                                              sc->sc_resources.mem);
262                         sc->sc_resources.mem = 0;
263                         return(ENXIO);
264                         break;
265         }
266
267         /* register interrupt routine */
268
269         bus_setup_intr(dev, sc->sc_resources.irq,
270                         INTR_TYPE_NET,
271                         NULL, (void(*)(void *))(isicintr),
272                         sc, &ih);
273
274         return (0);
275 }
276
277 /*---------------------------------------------------------------------------*
278  *      isic_attach_s08 - attach Teles S0/8 and compatibles
279  *---------------------------------------------------------------------------*/
280 int
281 isic_attach_s08(device_t dev)
282 {
283         struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
284         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
285         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
286
287         /* set card off */
288
289         bus_space_write_1(t, h, 0x80, 0);
290
291         DELAY(SEC_DELAY / 5);
292
293         /* set card on */
294
295         bus_space_write_1(t, h, 0x80, 1);
296
297         DELAY(SEC_DELAY / 5);
298
299         return 0;
300 }
301
302 #endif /* defined(TEL_S0_8) */