Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / net / i4b / layer1 / isic / i4b_sws.c
1 /*
2  *   Copyright (c) 1998, 2000 German Tischler. 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  *
8  *   1. Redistributions of source code must retain the above copyright
9  *      notice, this list of conditions and the following disclaimer.
10  *   2. Redistributions in binary form must reproduce the above copyright
11  *      notice, this list of conditions and the following disclaimer in the
12  *      documentation and/or other materials provided with the distribution.
13  *   3. Neither the name of the author nor the names of any co-contributors
14  *      may be used to endorse or promote products derived from this software
15  *      without specific prior written permission.
16  *   4. Altered versions must be plainly marked as such, and must not be
17  *      misrepresented as being the original software and/or documentation.
18  *   
19  *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  *   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  *   SUCH DAMAGE.
30  *
31  *---------------------------------------------------------------------------
32  *
33  * Card format:
34  * 
35  * iobase + 0 : reset on  (0x03)
36  * iobase + 1 : reset off (0x0)
37  * iobase + 2 : isac read/write
38  * iobase + 3 : hscx read/write ( offset 0-0x3f    hscx0 , 
39  *                                offset 0x40-0x7f hscx1 )
40  * iobase + 4 : offset for indirect adressing
41  *
42  *---------------------------------------------------------------------------
43  *
44  *      isic - I4B Siemens ISDN Chipset Driver for SWS cards
45  *      ====================================================
46  *
47  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_sws.c,v 1.5.2.1 2001/08/10 14:08:38 obrien Exp $
48  *
49  *      last edit-date: [Wed Jan 24 08:58:57 2001]
50  *
51  *---------------------------------------------------------------------------*/
52
53 #include "isic.h"
54 #include "opt_i4b.h"
55
56 #if defined (SEDLBAUER) && NISIC > 0
57
58 #define SWS_RESON  0 /* reset on                 */
59 #define SWS_RESOFF 1 /* reset off                */
60 #define SWS_ISAC   2 /* ISAC                     */
61 #define SWS_HSCX0  3 /* HSCX0                    */
62 #define SWS_RW     4 /* indirect access register */
63 #define SWS_HSCX1  5 /* this is for fakeing that we mean hscx1, though */
64                      /* access is done through hscx0                   */
65
66 #define SWS_REGS   8 /* we use an area of 8 bytes for io */
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/socket.h>
71 #include <net/if.h>
72
73 #include <machine/i4b_ioctl.h>
74 #include <machine/i4b_trace.h>
75 #include <i4b/layer1/i4b_l1.h>
76 #include <i4b/layer1/isic/i4b_isic.h>
77 #include <i4b/layer1/isic/i4b_hscx.h>
78
79 /*---------------------------------------------------------------------------*
80  *      SWS P&P ISAC get fifo routine
81  *---------------------------------------------------------------------------*/
82 static void
83 sws_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) {
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                 case ISIC_WHAT_ISAC:
89                         bus_space_write_1(t,h,SWS_RW,0x0);
90                         bus_space_read_multi_1(t,h,SWS_ISAC,buf,size);
91                         break;
92                 case ISIC_WHAT_HSCXA:
93                         bus_space_write_1(t,h,SWS_RW,0x0);
94                         bus_space_read_multi_1(t,h,SWS_HSCX0,buf,size);
95                         break;
96                 case ISIC_WHAT_HSCXB:
97                         bus_space_write_1(t,h,SWS_RW,0x0+0x40);
98                         bus_space_read_multi_1(t,h,SWS_HSCX0,buf,size);
99                         break;
100         }
101 }
102
103 static void
104 sws_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) {
105         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
106         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
107
108         switch ( what ) {
109                 case ISIC_WHAT_ISAC:
110                         bus_space_write_1(t,h,SWS_RW,0x0);
111                         bus_space_write_multi_1(t,h,SWS_ISAC,buf,size);
112                         break;
113                 case ISIC_WHAT_HSCXA:
114                         bus_space_write_1(t,h,SWS_RW,0x0);
115                         bus_space_write_multi_1(t,h,SWS_HSCX0,buf,size);
116                         break;
117                 case ISIC_WHAT_HSCXB:
118                         bus_space_write_1(t,h,SWS_RW,0x0+0x40);
119                         bus_space_write_multi_1(t,h,SWS_HSCX0,buf,size);
120                         break;
121         }
122 }
123
124 static void
125 sws_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) {
126         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
127         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
128
129         switch ( what ) {
130                 case ISIC_WHAT_ISAC:
131                         bus_space_write_1(t,h,SWS_RW,reg);
132                         bus_space_write_1(t,h,SWS_ISAC,data);
133                         break;
134                 case ISIC_WHAT_HSCXA:
135                         bus_space_write_1(t,h,SWS_RW,reg);
136                         bus_space_write_1(t,h,SWS_HSCX0,data);
137                         break;
138                 case ISIC_WHAT_HSCXB:
139                         bus_space_write_1(t,h,SWS_RW,reg+0x40);
140                         bus_space_write_1(t,h,SWS_HSCX0,data);
141                         break;
142         }
143 }
144
145 static u_char
146 sws_read_reg (struct l1_softc *sc,int what,bus_size_t reg) {
147         bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
148         bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
149
150         switch ( what ) {
151                 case ISIC_WHAT_ISAC:
152                         bus_space_write_1(t,h,SWS_RW,reg);
153                         return bus_space_read_1(t,h,SWS_ISAC);
154                 case ISIC_WHAT_HSCXA:
155                         bus_space_write_1(t,h,SWS_RW,reg);
156                         return bus_space_read_1(t,h,SWS_HSCX0);
157                 case ISIC_WHAT_HSCXB:
158                         bus_space_write_1(t,h,SWS_RW,reg+0x40);
159                         return bus_space_read_1(t,h,SWS_HSCX0);
160                 default:
161                         return 0;
162         }
163 }
164
165 /* attach callback routine */
166 int
167 isic_attach_sws(device_t dev)
168 {
169         int unit = device_get_unit(dev);
170         struct l1_softc *sc = &l1_sc[unit];     
171         
172         struct i4b_info * info = &(sc->sc_resources);
173         bus_space_tag_t    t = rman_get_bustag(info->io_base[0]);
174         bus_space_handle_t h = rman_get_bushandle(info->io_base[0]);
175
176         /* fill in l1_softc structure */
177         sc->readreg     = sws_read_reg;
178         sc->writereg    = sws_write_reg;
179         sc->readfifo    = sws_read_fifo;
180         sc->writefifo   = sws_write_fifo;
181         sc->clearirq    = NULL;
182         sc->sc_cardtyp  = CARD_TYPEP_SWS;
183         sc->sc_bustyp   = BUS_TYPE_IOM2;
184         sc->sc_ipac     = 0;
185         sc->sc_bfifolen = HSCX_FIFO_LEN;
186
187         /* 
188          * Read HSCX A/B VSTR.  Expected value for the SWS PnP card is
189          * 0x05 ( = version 2.1 ) in the least significant bits.
190          */
191
192         if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
193             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
194         {
195                 printf("isic%d: HSCX VSTR test failed for SWS PnP\n",
196                         sc->sc_unit);
197                 printf("isic%d: HSC0: VSTR: %#x\n",
198                         sc->sc_unit, HSCX_READ(0, H_VSTR));
199                 printf("isic%d: HSC1: VSTR: %#x\n",
200                         sc->sc_unit, HSCX_READ(1, H_VSTR));
201                 return (ENXIO);
202         }                   
203
204         /* reset card */
205         bus_space_write_1(t,h,SWS_RESON,0x3);
206         DELAY(SEC_DELAY / 5);
207         bus_space_write_1(t,h,SWS_RESOFF,0x0);
208         DELAY(SEC_DELAY / 5);
209
210         return(0);
211 }
212 #endif /* defined(SEDLBAUER) && NISIC > 0 */