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