]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/isic/i4b_elsa_qs1p.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer1 / isic / i4b_elsa_qs1p.c
1 /*-
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /*---------------------------------------------------------------------------
27  *
28  *      isic - I4B Siemens ISDN Chipset Driver for ELSA MicroLink ISDN/PCI
29  *      ==================================================================
30  *      last edit-date: [Wed Jan 24 09:09:28 2001]
31  *
32  *      Note: ELSA Quickstep 1000pro PCI = ELSA MicroLink ISDN/PCI
33  *
34  *---------------------------------------------------------------------------*/
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include "opt_i4b.h"
40
41 #if defined(ELSA_QS1PCI)
42
43 #include <sys/param.h>
44 #include <sys/kernel.h>
45 #include <sys/module.h>
46 #include <sys/systm.h>
47 #include <sys/socket.h>
48
49 #include <net/if.h>
50
51 #include <machine/bus.h>
52 #include <sys/bus.h>
53 #include <sys/rman.h>
54
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pcivar.h>
57
58 #include <i4b/include/i4b_ioctl.h>
59
60 #include <i4b/layer1/isic/i4b_isic.h>
61 #include <i4b/layer1/isic/i4b_ipac.h>
62
63 #define MEM0_BAR        0
64 #define PORT0_BAR       1
65 #define PORT1_BAR       3
66
67 #define ELSA_PORT0_MAPOFF       PCIR_BAR(PORT0_BAR)
68 #define ELSA_PORT1_MAPOFF       PCIR_BAR(PORT1_BAR)
69
70 #define PCI_QS1000_DID  0x1000
71 #define PCI_QS1000_VID  0x1048
72
73 /* masks for register encoded in base addr */
74
75 #define ELSA_BASE_MASK          0x0ffff
76 #define ELSA_OFF_MASK           0xf0000
77
78 /* register id's to be encoded in base addr */
79
80 #define ELSA_IDISAC             0x00000
81 #define ELSA_IDHSCXA            0x10000
82 #define ELSA_IDHSCXB            0x20000
83 #define ELSA_IDIPAC             0x40000
84
85 /* offsets from base address */
86
87 #define ELSA_OFF_ALE            0x00
88 #define ELSA_OFF_RW             0x01
89
90
91 static int eqs1p_pci_probe(device_t dev);
92 static int eqs1p_pci_attach(device_t dev);
93
94 static device_method_t eqs1p_pci_methods[] = {
95         /* Device interface */
96         DEVMETHOD(device_probe,         eqs1p_pci_probe),
97         DEVMETHOD(device_attach,        eqs1p_pci_attach),
98         { 0, 0 }
99 };
100
101 static driver_t eqs1p_pci_driver = {
102         "isic",
103         eqs1p_pci_methods,
104         0
105 };
106
107 static devclass_t eqs1p_pci_devclass;
108
109 DRIVER_MODULE(eqs1p, pci, eqs1p_pci_driver, eqs1p_pci_devclass, 0, 0);
110
111 /*---------------------------------------------------------------------------*
112  *      ELSA MicroLink ISDN/PCI fifo read routine
113  *---------------------------------------------------------------------------*/
114 static void
115 eqs1pp_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.io_base[1]);
118         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
119
120         switch(what)
121         {
122                 case ISIC_WHAT_ISAC:
123                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
124                         bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
125                         break;
126                 case ISIC_WHAT_HSCXA:
127                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
128                         bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
129                         break;
130                 case ISIC_WHAT_HSCXB:
131                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
132                         bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
133                         break;
134         }
135 }
136
137 /*---------------------------------------------------------------------------*
138  *      ELSA MicroLink ISDN/PCI fifo write routine
139  *---------------------------------------------------------------------------*/
140 static void
141 eqs1pp_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
142 {
143         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
144         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
145
146         switch(what)
147         {
148                 case ISIC_WHAT_ISAC:
149                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
150                         bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
151                         break;
152                 case ISIC_WHAT_HSCXA:
153                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
154                         bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
155                         break;
156                 case ISIC_WHAT_HSCXB:
157                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
158                         bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
159                         break;
160         }
161 }
162
163 /*---------------------------------------------------------------------------*
164  *      ELSA MicroLink ISDN/PCI register write routine
165  *---------------------------------------------------------------------------*/
166 static void
167 eqs1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
168 {
169         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
170         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
171
172         switch(what)
173         {
174                 case ISIC_WHAT_ISAC:
175                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
176                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
177                         break;
178                 case ISIC_WHAT_HSCXA:
179                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
180                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
181                         break;
182                 case ISIC_WHAT_HSCXB:
183                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
184                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
185                         break;
186                 case ISIC_WHAT_IPAC:
187                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
188                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
189                         break;
190         }
191 }
192
193 /*---------------------------------------------------------------------------*
194  *      ELSA MicroLink ISDN/PCI register read routine
195  *---------------------------------------------------------------------------*/
196 static u_int8_t
197 eqs1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
198 {
199         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
200         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
201
202         switch(what)
203         {
204                 case ISIC_WHAT_ISAC:
205                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
206                         return bus_space_read_1(t, h, ELSA_OFF_RW);
207                 case ISIC_WHAT_HSCXA:
208                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
209                         return bus_space_read_1(t, h, ELSA_OFF_RW);
210                 case ISIC_WHAT_HSCXB:
211                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
212                         return bus_space_read_1(t, h, ELSA_OFF_RW);
213                 case ISIC_WHAT_IPAC:
214                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
215                         return bus_space_read_1(t, h, ELSA_OFF_RW);
216         }
217         return 0;
218 }
219
220 /*---------------------------------------------------------------------------*
221  *      avma1pp_probe - probe for a card
222  *---------------------------------------------------------------------------*/
223 static int
224 eqs1p_pci_probe(device_t dev)
225 {
226         if((pci_get_vendor(dev) == PCI_QS1000_VID) &&
227            (pci_get_device(dev) == PCI_QS1000_DID))
228         {
229                 device_set_desc(dev, "ELSA MicroLink ISDN/PCI");
230                 return(0);
231         }
232         return(ENXIO);
233 }
234
235 /*---------------------------------------------------------------------------*
236  *      isic_attach_Eqs1pp - attach for ELSA MicroLink ISDN/PCI
237  *---------------------------------------------------------------------------*/
238 static int
239 eqs1p_pci_attach(device_t dev)
240 {
241         bus_space_tag_t t;
242         bus_space_handle_t h;
243         struct l1_softc *sc;
244         void *ih = 0;
245         int unit = device_get_unit(dev);
246         
247         /* check max unit range */
248         
249         if(unit >= ISIC_MAXUNIT)
250         {
251                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA MicroLink ISDN/PCI!\n",
252                                 unit, unit);
253                 return(ENXIO);  
254         }       
255
256         sc = &l1_sc[unit];              /* get softc */ 
257         
258         sc->sc_unit = unit;
259
260         /* get io_base */
261
262         sc->sc_resources.io_rid[0] = ELSA_PORT0_MAPOFF;
263         
264         if(!(sc->sc_resources.io_base[0] =
265                         bus_alloc_resource_any(dev, SYS_RES_IOPORT,
266                                                &sc->sc_resources.io_rid[0],
267                                                RF_ACTIVE)))
268         {
269                 printf("isic%d: Couldn't get first iobase for ELSA MicroLink ISDN/PCI!\n", unit);
270                 return(ENXIO);                                       
271         }
272
273         sc->sc_resources.io_rid[1] = ELSA_PORT1_MAPOFF;
274         
275         if(!(sc->sc_resources.io_base[1] =
276                         bus_alloc_resource_any(dev, SYS_RES_IOPORT,
277                                                &sc->sc_resources.io_rid[1],
278                                                RF_ACTIVE)))
279         {
280                 printf("isic%d: Couldn't get second iobase for ELSA MicroLink ISDN/PCI!\n", unit);
281                 isic_detach_common(dev);
282                 return(ENXIO);                                       
283         }
284
285         sc->sc_port = rman_get_start(sc->sc_resources.io_base[1]);
286
287         if(!(sc->sc_resources.irq =
288                         bus_alloc_resource_any(dev, SYS_RES_IRQ,
289                                                &sc->sc_resources.irq_rid,
290                                                RF_ACTIVE | RF_SHAREABLE)))
291         {
292                 printf("isic%d: Could not get irq for ELSA MicroLink ISDN/PCI!\n",unit);
293                 isic_detach_common(dev);
294                 return(ENXIO);                                       
295         }
296         
297         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
298
299         /* setup access routines */
300
301         sc->clearirq = NULL;
302         sc->readreg = eqs1pp_read_reg;
303         sc->writereg = eqs1pp_write_reg;
304
305         sc->readfifo = eqs1pp_read_fifo;
306         sc->writefifo = eqs1pp_write_fifo;
307
308         /* setup card type */
309         
310         sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
311
312         /* setup IOM bus type */
313         
314         sc->sc_bustyp = BUS_TYPE_IOM2;
315
316         /* setup chip type = IPAC ! */
317         
318         sc->sc_ipac = 1;
319         sc->sc_bfifolen = IPAC_BFIFO_LEN;
320
321         if(isic_attach_common(dev))
322         {
323                 isic_detach_common(dev);
324                 return(ENXIO);
325         }
326
327         if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
328                                 NULL, (void(*)(void*))isicintr,
329                                 sc, &ih))
330         {
331                 printf("isic%d: Couldn't set up irq for ELSA MicroLink ISDN/PCI!\n", unit);
332                 isic_detach_common(dev);
333                 return(ENXIO);
334         }
335
336         /* enable hscx/isac irq's */
337
338         IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
339
340         IPAC_WRITE(IPAC_ACFG, 0);       /* outputs are open drain */
341         IPAC_WRITE(IPAC_AOE,            /* aux 5..2 are inputs, 7, 6 outputs */
342                 (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
343         IPAC_WRITE(IPAC_ATX, 0xff);     /* set all output lines high */
344
345         t = rman_get_bustag(sc->sc_resources.io_base[0]);
346         h = rman_get_bushandle(sc->sc_resources.io_base[0]);
347         
348         bus_space_write_1(t, h, 0x4c, 0x41);    /* enable card interrupt */
349         
350         return(0);
351 }
352
353 #endif /* defined(ELSA_QS1PCI) */