kernel: Use NULL for pointers.
[dragonfly.git] / sys / net / i4b / layer1 / isic / i4b_tel_s08.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, 2001 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  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_tel_s08.c,v 1.5.2.1 2001/08/10 14:08:39 obrien Exp $
41  *
42  *      last edit-date: [Wed Jan 24 09:27:58 2001]
43  *
44  *---------------------------------------------------------------------------*/
45
46 #include "use_isic.h"
47 #include "opt_i4b.h"
48
49 #if NISIC > 0 && defined(TEL_S0_8)
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/socket.h>
54 #include <net/if.h>
55
56 #include <machine/md_var.h>
57 #include <net/i4b/include/machine/i4b_ioctl.h>
58 #include <net/i4b/include/machine/i4b_trace.h>
59
60 #include "../i4b_l1.h"
61 #include "i4b_isic.h"
62 #include "i4b_hscx.h"
63
64 #define TELES_S08_MEMSIZE 0x1000
65
66 static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
67
68 /*---------------------------------------------------------------------------*
69  *      Teles S0/8 write register routine
70  *---------------------------------------------------------------------------*/
71 static void
72 tels08_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
73 {
74         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
75         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
76
77         offs += offset[what];
78
79         if (offs & 0x01)
80                 offs |= 0x200;
81
82         bus_space_write_1(t, h, offs, data);
83 }
84
85 /*---------------------------------------------------------------------------*
86  *      Teles S0/8 read register routine
87  *---------------------------------------------------------------------------*/
88 static u_int8_t
89 tels08_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
90 {
91         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
92         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
93
94         offs += offset[what];
95
96         if (offs & 0x01)
97                 offs |= 0x200;
98
99         return bus_space_read_1(t, h, offs);
100 }
101
102 /*---------------------------------------------------------------------------*
103  *      Teles S0/8 fifo write access
104  *---------------------------------------------------------------------------*/
105 static void
106 tels08_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
107 {
108         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
109         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
110         bus_space_write_region_1(t, h, offset[what], data, size);
111 }
112
113 /*---------------------------------------------------------------------------*
114  *      Teles S0/8 fifo read access
115  *---------------------------------------------------------------------------*/
116 static void
117 tels08_read_fifo(struct l1_softc *sc, int what, void *buf, 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_read_region_1(t, h, offset[what], buf, size);
122 }
123
124 /*---------------------------------------------------------------------------*
125  *      isic_probe_s08 - probe for Teles S0/8 and compatibles
126  *---------------------------------------------------------------------------*/
127 int
128 isic_probe_s08(device_t dev)
129 {
130         size_t unit = device_get_unit(dev);     /* get unit */
131         struct l1_softc *sc = NULL;             /* pointer to softc */
132         void *ih = NULL;                                /* dummy */
133
134         /* check max unit range */
135
136         if(unit >= ISIC_MAXUNIT)
137         {
138                 kprintf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
139                                 unit, unit);
140                 return(ENXIO);  
141         }
142
143         sc = &l1_sc[unit];              /* get pointer to softc */
144         sc->sc_unit = unit;             /* set unit */
145
146         /* see if an io base was supplied */
147
148         if((sc->sc_resources.io_base[0] =
149                         bus_alloc_resource(dev, SYS_RES_IOPORT,
150                                            &sc->sc_resources.io_rid[0],
151                                            0ul, ~0ul, 1, RF_ACTIVE)))
152         {
153                 /* the S0/8 is completely memory mapped ! */
154                 
155                 bus_release_resource(dev,SYS_RES_IOPORT,
156                                      sc->sc_resources.io_rid[0],
157                                      sc->sc_resources.io_base[0]);
158                 kprintf("isic%d: Error, iobase specified for Teles S0/8!\n", unit);
159                 return(ENXIO);
160         }
161
162         /* allocate memory */
163
164         if(!(sc->sc_resources.mem =
165                 bus_alloc_resource(dev, SYS_RES_MEMORY,
166                                 &sc->sc_resources.mem_rid,
167                                 0ul, ~0ul, TELES_S08_MEMSIZE, RF_ACTIVE)))
168         {
169                 kprintf("isic%d: Could not allocate memory for Teles S0/8!\n", unit);
170                 return(ENXIO);
171         }
172
173         /* 
174          * get virtual addr. it's just needed to see if it is in
175          * the valid range
176          */
177
178         sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem);
179                 
180         /* check if inside memory range of 0xA0000 .. 0xDF000 */
181
182         if((kvtop(sc->sc_vmem_addr) < 0xa0000) ||
183            (kvtop(sc->sc_vmem_addr) > 0xdf000))
184         {
185                 kprintf("isic%d: Error, mem addr 0x%llx outside 0xA0000-0xDF000 for Teles S0/8!\n",
186                                 unit, kvtop(sc->sc_vmem_addr));
187                 bus_release_resource(dev,SYS_RES_MEMORY,
188                                      sc->sc_resources.mem_rid,
189                                      sc->sc_resources.mem);
190                 sc->sc_resources.mem = 0;
191                 return(ENXIO);
192         }
193         
194         /* setup ISAC access routines */
195
196         sc->clearirq = NULL;
197
198         sc->readreg = tels08_read_reg;
199         sc->writereg = tels08_write_reg;
200
201         sc->readfifo = tels08_read_fifo;
202         sc->writefifo = tels08_write_fifo;
203
204         sc->sc_cardtyp = CARD_TYPEP_8;          /* setup card type */
205         
206         sc->sc_bustyp = BUS_TYPE_IOM1;          /* setup IOM bus type */
207
208         sc->sc_ipac = 0;
209         sc->sc_bfifolen = HSCX_FIFO_LEN;
210
211         /* setup ISAC base addr, though we don't really need it */
212         
213         ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100);
214
215         /* setup HSCX base addr */
216         
217         HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180);
218         HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0);
219
220         /* allocate our irq */
221
222         if(!(sc->sc_resources.irq =
223                         bus_alloc_resource(dev, SYS_RES_IRQ,
224                                                 &sc->sc_resources.irq_rid,
225                                                 0ul, ~0ul, 1, RF_ACTIVE)))
226         {
227                 kprintf("isic%d: Could not allocate irq for Teles S0/8!\n",unit);
228
229                 bus_release_resource(dev,SYS_RES_MEMORY,
230                                      sc->sc_resources.mem_rid,
231                                      sc->sc_resources.mem);
232
233                 sc->sc_resources.mem = 0;
234                 return ENXIO;
235         }
236
237         /* get the irq number */
238
239         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
240         
241         /* check IRQ validity */
242
243         switch(sc->sc_irq)
244         {
245                 case 2:
246                 case 9:         /* XXX */
247                 case 3:
248                 case 4:
249                 case 5:
250                 case 6:
251                 case 7:
252                         break;
253                         
254                 default:
255                         kprintf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n",
256                                 unit, sc->sc_irq);
257                         bus_release_resource(dev,SYS_RES_IRQ,
258                                              sc->sc_resources.irq_rid,
259                                              sc->sc_resources.irq);
260                         sc->sc_resources.irq = 0;
261                         bus_release_resource(dev,SYS_RES_MEMORY,
262                                              sc->sc_resources.mem_rid,
263                                              sc->sc_resources.mem);
264                         sc->sc_resources.mem = 0;
265                         return(ENXIO);
266                         break;
267         }
268
269         /* register interupt routine */
270
271         bus_setup_intr(dev, sc->sc_resources.irq,
272                         0, (void(*)(void *))(isicintr),
273                         sc, &ih, NULL);
274
275         return (0);
276 }
277
278 /*---------------------------------------------------------------------------*
279  *      isic_attach_s08 - attach Teles S0/8 and compatibles
280  *---------------------------------------------------------------------------*/
281 int
282 isic_attach_s08(device_t dev)
283 {
284         struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
285         bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
286         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
287
288         /* set card off */
289
290         bus_space_write_1(t, h, 0x80, 0);
291
292         DELAY(SEC_DELAY / 5);
293
294         /* set card on */
295
296         bus_space_write_1(t, h, 0x80, 1);
297
298         DELAY(SEC_DELAY / 5);
299
300         return 0;
301 }
302 #endif /* ISIC > 0 */