Get rid of bus_{disable,enable}_intr(), it wasn't generic enough for
[dragonfly.git] / sys / net / 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  *      isic - I4B Siemens ISDN Chipset Driver for ELSA MicroLink ISDN/PCI
28  *      ==================================================================
29  *
30  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_elsa_qs1p.c,v 1.6.2.1 2001/08/10 14:08:38 obrien Exp $
31  * $DragonFly: src/sys/net/i4b/layer1/isic/i4b_elsa_qs1p.c,v 1.5 2005/05/24 20:59:05 dillon Exp $
32  *
33  *      last edit-date: [Wed Jan 24 09:09:28 2001]
34  *
35  *      Note: ELSA Quickstep 1000pro PCI = ELSA MicroLink ISDN/PCI
36  *
37  *---------------------------------------------------------------------------*/
38
39 #include "use_isic.h"
40 #include "use_pci.h"
41 #include "opt_i4b.h"
42
43 #if (NISIC > 0) && (NPCI > 0) && defined(ELSA_QS1PCI)
44
45 #include <sys/param.h>
46 #include <sys/kernel.h>
47 #include <sys/systm.h>
48 #include <sys/socket.h>
49
50 #include <net/if.h>
51
52 #include <machine/bus.h>
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55
56 #include <bus/pci/pcireg.h>
57 #include <bus/pci/pcivar.h>
58
59 #include <net/i4b/include/machine/i4b_ioctl.h>
60
61 #include "i4b_isic.h"
62 #include "i4b_ipac.h"
63
64 #define MEM0_MAPOFF     0
65 #define PORT0_MAPOFF    4
66 #define PORT1_MAPOFF    12
67
68 #define ELSA_PORT0_MAPOFF       (PCIR_MAPS+PORT0_MAPOFF)
69 #define ELSA_PORT1_MAPOFF       (PCIR_MAPS+PORT1_MAPOFF)
70
71 #define PCI_QS1000_DID  0x1000
72 #define PCI_QS1000_VID  0x1048
73
74 /* masks for register encoded in base addr */
75
76 #define ELSA_BASE_MASK          0x0ffff
77 #define ELSA_OFF_MASK           0xf0000
78
79 /* register id's to be encoded in base addr */
80
81 #define ELSA_IDISAC             0x00000
82 #define ELSA_IDHSCXA            0x10000
83 #define ELSA_IDHSCXB            0x20000
84 #define ELSA_IDIPAC             0x40000
85
86 /* offsets from base address */
87
88 #define ELSA_OFF_ALE            0x00
89 #define ELSA_OFF_RW             0x01
90
91
92 static int eqs1p_pci_probe(device_t dev);
93 static int eqs1p_pci_attach(device_t dev);
94
95 static device_method_t eqs1p_pci_methods[] = {
96         /* Device interface */
97         DEVMETHOD(device_probe,         eqs1p_pci_probe),
98         DEVMETHOD(device_attach,        eqs1p_pci_attach),
99         { 0, 0 }
100 };
101
102 static driver_t eqs1p_pci_driver = {
103         "isic",
104         eqs1p_pci_methods,
105         0
106 };
107
108 static devclass_t eqs1p_pci_devclass;
109
110 DRIVER_MODULE(eqs1p, pci, eqs1p_pci_driver, eqs1p_pci_devclass, 0, 0);
111
112 /*---------------------------------------------------------------------------*
113  *      ELSA MicroLink ISDN/PCI fifo read routine
114  *---------------------------------------------------------------------------*/
115 static void
116 eqs1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
117 {
118         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
119         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
120
121         switch(what)
122         {
123                 case ISIC_WHAT_ISAC:
124                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
125                         bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
126                         break;
127                 case ISIC_WHAT_HSCXA:
128                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
129                         bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
130                         break;
131                 case ISIC_WHAT_HSCXB:
132                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
133                         bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
134                         break;
135         }
136 }
137
138 /*---------------------------------------------------------------------------*
139  *      ELSA MicroLink ISDN/PCI fifo write routine
140  *---------------------------------------------------------------------------*/
141 static void
142 eqs1pp_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
143 {
144         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
145         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
146
147         switch(what)
148         {
149                 case ISIC_WHAT_ISAC:
150                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
151                         bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
152                         break;
153                 case ISIC_WHAT_HSCXA:
154                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
155                         bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
156                         break;
157                 case ISIC_WHAT_HSCXB:
158                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
159                         bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
160                         break;
161         }
162 }
163
164 /*---------------------------------------------------------------------------*
165  *      ELSA MicroLink ISDN/PCI register write routine
166  *---------------------------------------------------------------------------*/
167 static void
168 eqs1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
169 {
170         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
171         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
172
173         switch(what)
174         {
175                 case ISIC_WHAT_ISAC:
176                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
177                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
178                         break;
179                 case ISIC_WHAT_HSCXA:
180                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
181                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
182                         break;
183                 case ISIC_WHAT_HSCXB:
184                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
185                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
186                         break;
187                 case ISIC_WHAT_IPAC:
188                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
189                         bus_space_write_1(t, h, ELSA_OFF_RW, data);
190                         break;
191         }
192 }
193
194 /*---------------------------------------------------------------------------*
195  *      ELSA MicroLink ISDN/PCI register read routine
196  *---------------------------------------------------------------------------*/
197 static u_int8_t
198 eqs1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
199 {
200         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[1]);
201         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
202
203         switch(what)
204         {
205                 case ISIC_WHAT_ISAC:
206                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
207                         return bus_space_read_1(t, h, ELSA_OFF_RW);
208                 case ISIC_WHAT_HSCXA:
209                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
210                         return bus_space_read_1(t, h, ELSA_OFF_RW);
211                 case ISIC_WHAT_HSCXB:
212                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
213                         return bus_space_read_1(t, h, ELSA_OFF_RW);
214                 case ISIC_WHAT_IPAC:
215                         bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
216                         return bus_space_read_1(t, h, ELSA_OFF_RW);
217         }
218         return 0;
219 }
220
221 /*---------------------------------------------------------------------------*
222  *      avma1pp_probe - probe for a card
223  *---------------------------------------------------------------------------*/
224 static int
225 eqs1p_pci_probe(device_t dev)
226 {
227         if((pci_get_vendor(dev) == PCI_QS1000_VID) &&
228            (pci_get_device(dev) == PCI_QS1000_DID))
229         {
230                 device_set_desc(dev, "ELSA MicroLink ISDN/PCI");
231                 return(0);
232         }
233         return(ENXIO);
234 }
235
236 /*---------------------------------------------------------------------------*
237  *      isic_attach_Eqs1pp - attach for ELSA MicroLink ISDN/PCI
238  *---------------------------------------------------------------------------*/
239 static int
240 eqs1p_pci_attach(device_t dev)
241 {
242         bus_space_tag_t t;
243         bus_space_handle_t h;
244         struct l1_softc *sc;
245         void *ih = 0;
246         int unit = device_get_unit(dev);
247         
248         /* check max unit range */
249         
250         if(unit >= ISIC_MAXUNIT)
251         {
252                 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA MicroLink ISDN/PCI!\n",
253                                 unit, unit);
254                 return(ENXIO);  
255         }       
256
257         sc = &l1_sc[unit];              /* get softc */ 
258         
259         sc->sc_unit = unit;
260
261         /* get io_base */
262
263         sc->sc_resources.io_rid[0] = ELSA_PORT0_MAPOFF;
264         
265         if(!(sc->sc_resources.io_base[0] =
266                         bus_alloc_resource(dev, SYS_RES_IOPORT,
267                                                 &sc->sc_resources.io_rid[0],
268                                                 0UL, ~0UL, 1, RF_ACTIVE)))
269         {
270                 printf("isic%d: Couldn't get first iobase for ELSA MicroLink ISDN/PCI!\n", unit);
271                 return(ENXIO);                                       
272         }
273
274         sc->sc_resources.io_rid[1] = ELSA_PORT1_MAPOFF;
275         
276         if(!(sc->sc_resources.io_base[1] =
277                         bus_alloc_resource(dev, SYS_RES_IOPORT,
278                                                 &sc->sc_resources.io_rid[1],
279                                                 0UL, ~0UL, 1, RF_ACTIVE)))
280         {
281                 printf("isic%d: Couldn't get second iobase for ELSA MicroLink ISDN/PCI!\n", unit);
282                 isic_detach_common(dev);
283                 return(ENXIO);                                       
284         }
285
286         sc->sc_port = rman_get_start(sc->sc_resources.io_base[1]);
287
288         if(!(sc->sc_resources.irq =
289                         bus_alloc_resource(dev, SYS_RES_IRQ,
290                                            &sc->sc_resources.irq_rid,
291                                            0UL, ~0UL, 1, RF_ACTIVE | RF_SHAREABLE)))
292         {
293                 printf("isic%d: Could not get irq for ELSA MicroLink ISDN/PCI!\n",unit);
294                 isic_detach_common(dev);
295                 return(ENXIO);                                       
296         }
297         
298         sc->sc_irq = rman_get_start(sc->sc_resources.irq);
299
300         /* setup access routines */
301
302         sc->clearirq = NULL;
303         sc->readreg = eqs1pp_read_reg;
304         sc->writereg = eqs1pp_write_reg;
305
306         sc->readfifo = eqs1pp_read_fifo;
307         sc->writefifo = eqs1pp_write_fifo;
308
309         /* setup card type */
310         
311         sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
312
313         /* setup IOM bus type */
314         
315         sc->sc_bustyp = BUS_TYPE_IOM2;
316
317         /* setup chip type = IPAC ! */
318         
319         sc->sc_ipac = 1;
320         sc->sc_bfifolen = IPAC_BFIFO_LEN;
321
322         if(isic_attach_common(dev))
323         {
324                 isic_detach_common(dev);
325                 return(ENXIO);
326         }
327
328         if (bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
329                                 (void(*)(void*))isicintr,
330                                 sc, &ih, NULL))
331         {
332                 printf("isic%d: Couldn't set up irq for ELSA MicroLink ISDN/PCI!\n", unit);
333                 isic_detach_common(dev);
334                 return(ENXIO);
335         }
336
337         /* enable hscx/isac irq's */
338
339         IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
340
341         IPAC_WRITE(IPAC_ACFG, 0);       /* outputs are open drain */
342         IPAC_WRITE(IPAC_AOE,            /* aux 5..2 are inputs, 7, 6 outputs */
343                 (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
344         IPAC_WRITE(IPAC_ATX, 0xff);     /* set all output lines high */
345
346         t = rman_get_bustag(sc->sc_resources.io_base[0]);
347         h = rman_get_bushandle(sc->sc_resources.io_base[0]);
348         
349         bus_space_write_1(t, h, 0x4c, 0x41);    /* enable card interrupt */
350         
351         return(0);
352 }
353
354 #endif /* (NISIC > 0) && (NPCI > 0) && defined(ELSA_QS1PCI) */