kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / net / i4b / layer1 / isic / i4b_diva.c
1 /*
2  *   Copyright (c) 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  *      Eicon Diehl DIVA 2.0 or 2.02 (ISA PnP) support for isic driver
28  *      --------------------------------------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_diva.c,v 1.1.2.1 2001/08/10 14:08:38 obrien Exp $
31  * $DragonFly: src/sys/net/i4b/layer1/isic/i4b_diva.c,v 1.3 2003/08/07 21:17:26 dillon Exp $
32  *
33  *      last edit-date: [Fri Jan 26 13:57:10 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_isic.h"
38 #include "opt_i4b.h"
39
40 #if NISIC > 0 && defined EICON_DIVA
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/socket.h>
45
46 #include <net/if.h>
47
48 #include <machine/i4b_ioctl.h>
49
50 #include "i4b_isic.h"
51 #include "i4b_ipac.h"
52 #include "i4b_isic.h"
53 #include "i4b_hscx.h"
54
55 /* offsets from base address */
56
57 #define DIVA_IPAC_OFF_ALE       0x00
58 #define DIVA_IPAC_OFF_RW        0x01
59
60 #define DIVA_ISAC_OFF_RW        0x02
61 #define DIVA_ISAC_OFF_ALE       0x06
62
63 #define DIVA_HSCX_OFF_RW        0x00
64 #define DIVA_HSCX_OFF_ALE       0x04
65
66 #define DIVA_CTRL_OFF           0x07
67 #define         DIVA_CTRL_RDIST 0x01
68 #define         DIVA_CTRL_WRRST 0x08
69 #define         DIVA_CTRL_WRLDA 0x20
70 #define         DIVA_CTRL_WRLDB 0x40
71 #define         DIVA_CTRL_WRICL 0x80
72
73 /* HSCX channel base offsets */
74
75 #define DIVA_HSCXA              0x00
76 #define DIVA_HSCXB              0x40
77
78 /*---------------------------------------------------------------------------*
79  *      Eicon Diehl DIVA 2.02
80  *---------------------------------------------------------------------------*/
81 static void 
82 diva_ipac_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
83 {
84         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
85         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
86
87         switch ( what )
88         {
89                 case ISIC_WHAT_ISAC:
90                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_ISAC_OFF);
91                         bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size);
92                         break;
93                 case ISIC_WHAT_HSCXA:
94                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXA_OFF);
95                         bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size);
96                         break;
97                 case ISIC_WHAT_HSCXB:
98                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXB_OFF);
99                         bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size);
100                         break;
101         }
102 }
103
104 /*---------------------------------------------------------------------------*
105  *      Eicon Diehl DIVA 2.02
106  *---------------------------------------------------------------------------*/
107 static void 
108 diva_ipac_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
109 {
110         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
111         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
112
113         switch ( what )
114         {
115                 case ISIC_WHAT_ISAC:
116                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_ISAC_OFF);
117                         bus_space_write_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size);
118                         break;
119                 case ISIC_WHAT_HSCXA:
120                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXA_OFF);
121                         bus_space_write_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size);
122                         break;
123                 case ISIC_WHAT_HSCXB:
124                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXB_OFF);
125                         bus_space_write_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size);
126                         break;
127         }
128 }
129
130 /*---------------------------------------------------------------------------*
131  *      Eicon Diehl DIVA 2.02
132  *---------------------------------------------------------------------------*/
133 static void
134 diva_ipac_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data)
135 {
136         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
137         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
138
139         switch ( what )
140         {
141                 case ISIC_WHAT_ISAC:
142                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_ISAC_OFF);
143                         bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data);
144                         break;
145                 case ISIC_WHAT_HSCXA:
146                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXA_OFF);
147                         bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data);
148                         break;
149                 case ISIC_WHAT_HSCXB:
150                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXB_OFF);
151                         bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data);
152                         break;
153                 case ISIC_WHAT_IPAC:
154                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_IPAC_OFF);
155                         bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data);
156                         break;
157         }
158 }
159
160 /*---------------------------------------------------------------------------*
161  *      Eicon Diehl DIVA 2.02
162  *---------------------------------------------------------------------------*/
163 static u_int8_t
164 diva_ipac_read_reg(struct l1_softc *sc,int what,bus_size_t reg)
165 {
166         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
167         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
168
169         switch ( what )
170         {
171                 case ISIC_WHAT_ISAC:
172                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_ISAC_OFF);
173                         return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW);
174                 case ISIC_WHAT_HSCXA:
175                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXA_OFF);
176                         return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW);
177                 case ISIC_WHAT_HSCXB:
178                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXB_OFF);
179                         return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW);
180                 case ISIC_WHAT_IPAC:
181                         bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_IPAC_OFF);
182                         return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW);
183                 default:
184                         return 0;
185         }
186 }
187
188 /*---------------------------------------------------------------------------*
189  *      Eicon Diehl DIVA 2.02
190  *---------------------------------------------------------------------------*/
191 int
192 isic_attach_diva_ipac(device_t dev)
193 {
194         int unit = device_get_unit(dev);
195         struct l1_softc *sc = &l1_sc[unit];     
196         
197         /* setup access routines */
198
199         sc->clearirq = NULL;
200         sc->readreg = diva_ipac_read_reg;
201         sc->writereg = diva_ipac_write_reg;
202
203         sc->readfifo = diva_ipac_read_fifo;
204         sc->writefifo = diva_ipac_write_fifo;
205
206         /* setup card type */
207         
208         sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA;
209
210         /* setup IOM bus type */
211         
212         sc->sc_bustyp = BUS_TYPE_IOM2;
213
214         /* setup chip type = IPAC */
215         
216         sc->sc_ipac = 1;
217         sc->sc_bfifolen = IPAC_BFIFO_LEN;
218
219         /* enable hscx/isac irq's */
220
221         IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
222
223         IPAC_WRITE(IPAC_ACFG, 0);       /* outputs are open drain */
224
225         IPAC_WRITE(IPAC_AOE,            /* aux 5..2 are inputs, 7, 6 outputs */
226                 (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
227
228         IPAC_WRITE(IPAC_ATX, 0xff);     /* set all output lines high */
229
230         return(0);
231 }
232
233 /*---------------------------------------------------------------------------*
234  *      Eicon Diehl DIVA 2.0
235  *---------------------------------------------------------------------------*/
236 static void 
237 diva_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
238 {
239         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
240         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
241
242         switch(what)
243         {
244                 case ISIC_WHAT_ISAC:
245                         bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,0);
246                         bus_space_read_multi_1(t,h,DIVA_ISAC_OFF_RW,buf,size);
247                         break;
248
249                 case ISIC_WHAT_HSCXA:
250                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXA);
251                         bus_space_read_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size);
252                         break;
253
254                 case ISIC_WHAT_HSCXB:
255                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXB);
256                         bus_space_read_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size);
257                         break;
258         }
259 }
260
261 /*---------------------------------------------------------------------------*
262  *      Eicon Diehl DIVA 2.0
263  *---------------------------------------------------------------------------*/
264 static void 
265 diva_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
266 {
267         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
268         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
269
270         switch(what)
271         {
272                 case ISIC_WHAT_ISAC:
273                         bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,0);
274                         bus_space_write_multi_1(t,h,DIVA_ISAC_OFF_RW,buf,size);
275                         break;
276
277                 case ISIC_WHAT_HSCXA:
278                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXA);
279                         bus_space_write_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size);
280                         break;
281
282                 case ISIC_WHAT_HSCXB:
283                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXB);
284                         bus_space_write_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size);
285                         break;
286         }
287 }
288
289 /*---------------------------------------------------------------------------*
290  *      Eicon Diehl DIVA 2.0
291  *---------------------------------------------------------------------------*/
292 static void
293 diva_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data)
294 {
295         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
296         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
297
298         switch(what)
299         {
300                 case ISIC_WHAT_ISAC:
301                         bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,reg);
302                         bus_space_write_1(t,h,DIVA_ISAC_OFF_RW,data);
303                         break;
304
305                 case ISIC_WHAT_HSCXA:
306                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXA);
307                         bus_space_write_1(t,h,DIVA_HSCX_OFF_RW,data);
308                         break;
309
310                 case ISIC_WHAT_HSCXB:
311                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXB);
312                         bus_space_write_1(t,h,DIVA_HSCX_OFF_RW,data);
313                         break;
314         }
315 }
316
317 /*---------------------------------------------------------------------------*
318  *      Eicon Diehl DIVA 2.0
319  *---------------------------------------------------------------------------*/
320 static u_int8_t
321 diva_read_reg(struct l1_softc *sc,int what,bus_size_t reg)
322 {
323         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
324         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
325
326         switch(what)
327         {
328                 case ISIC_WHAT_ISAC:
329                         bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,reg);
330                         return bus_space_read_1(t,h,DIVA_ISAC_OFF_RW);
331
332                 case ISIC_WHAT_HSCXA:
333                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXA);
334                         return bus_space_read_1(t,h,DIVA_HSCX_OFF_RW);
335
336                 case ISIC_WHAT_HSCXB:
337                         bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXB);
338                         return bus_space_read_1(t,h,DIVA_HSCX_OFF_RW);
339
340                 default:
341                         return 0;
342         }
343 }
344
345 /*---------------------------------------------------------------------------*
346  *      Eicon Diehl DIVA 2.0
347  *---------------------------------------------------------------------------*/
348 int
349 isic_attach_diva(device_t dev)
350 {
351         int unit = device_get_unit(dev);
352         struct l1_softc *sc = &l1_sc[unit];     
353         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
354         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
355         
356         /* setup access routines */
357
358         sc->clearirq = NULL;
359         sc->readreg = diva_read_reg;
360         sc->writereg = diva_write_reg;
361
362         sc->readfifo = diva_read_fifo;
363         sc->writefifo = diva_write_fifo;
364
365         /* setup card type */
366         
367         sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA;
368
369         /* setup IOM bus type */
370         
371         sc->sc_bustyp = BUS_TYPE_IOM2;
372
373         /* setup chip type = ISAC/HSCX */
374
375         sc->sc_ipac = 0;
376         sc->sc_bfifolen = HSCX_FIFO_LEN;
377
378         /* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
379
380         if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || 
381             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
382         {
383                 printf("isic%d: HSCX VSTR test failed for Eicon DIVA 2.0\n",
384                         sc->sc_unit);
385                 printf("isic%d: HSC0: VSTR: %#x\n",
386                         sc->sc_unit, HSCX_READ(0, H_VSTR));
387                 printf("isic%d: HSC1: VSTR: %#x\n",
388                         sc->sc_unit, HSCX_READ(1, H_VSTR));
389                 return ENXIO;
390         }
391         /* reset on */
392         bus_space_write_1(t,h,DIVA_CTRL_OFF,0);
393         DELAY(100);
394         /* reset off */
395         bus_space_write_1(t,h,DIVA_CTRL_OFF,DIVA_CTRL_WRRST);
396         return(0);
397 }
398
399 #endif /* NISIC > 0 && defined EICON_DIVA */