1/*-
2 * Copyright (c) 2002 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Martin Husemann <martin@NetBSD.org>.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: isic_pcmcia_sbspeedstar2.c,v 1.11 2007/10/19 12:01:06 ad Exp $");
32
33#include "opt_isicpcmcia.h"
34#ifdef ISICPCMCIA_SBSPEEDSTAR2
35
36/*
37 * Card format:
38 *
39 * iobase + 0 : reset on (0x03), off (0x0)
40 * iobase + 1 : isac read/write
41 * iobase + 2 : hscx read/write ( offset 0-0x3f    hscx0 ,
42 *                                offset 0x40-0x7f hscx1 )
43 * iobase + 4 : address register
44 *
45 */
46
47#define SBSS_RESET  0 /* reset on / off           */
48#define SBSS_ISAC   1 /* ISAC                     */
49#define SBSS_HSCX   2 /* HSCX0                    */
50#define SBSS_RW     4 /* indirect access register */
51
52#define SBSS_REGS   8 /* we use an area of 8 bytes for io */
53
54#include <sys/param.h>
55#include <sys/callout.h>
56#include <sys/kernel.h>
57#include <sys/systm.h>
58#include <sys/mbuf.h>
59#include <sys/device.h>
60#include <sys/bus.h>
61#include <sys/socket.h>
62#include <net/if.h>
63#include <netisdn/i4b_debug.h>
64#include <netisdn/i4b_ioctl.h>
65#include <netisdn/i4b_l2.h>
66#include <netisdn/i4b_l1l2.h>
67
68#include <dev/ic/isic_l1.h>
69#include <dev/ic/isac.h>
70#include <dev/ic/hscx.h>
71
72#include <netisdn/i4b_global.h>
73#include <netisdn/i4b_l1l2.h>
74#include <netisdn/i4b_mbuf.h>
75#include <dev/pcmcia/pcmciareg.h>
76#include <dev/pcmcia/pcmciavar.h>
77
78#include <dev/pcmcia/isic_pcmcia.h>
79
80/*---------------------------------------------------------------------------*
81 *      Sedlbauer SpeedStar ISAC get fifo routine
82 *---------------------------------------------------------------------------*/
83
84static void
85sws_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
86{
87	bus_space_tag_t t = sc->sc_maps[0].t;
88	bus_space_handle_t h = sc->sc_maps[0].h;
89	switch (what) {
90		case ISIC_WHAT_ISAC:
91			bus_space_write_1(t, h, SBSS_RW, 0);
92			bus_space_read_multi_1(t, h, SBSS_ISAC, buf, size);
93			break;
94		case ISIC_WHAT_HSCXA:
95			bus_space_write_1(t, h, SBSS_RW, 0);
96			bus_space_read_multi_1(t, h, SBSS_HSCX, buf, size);
97			break;
98		case ISIC_WHAT_HSCXB:
99			bus_space_write_1(t, h, SBSS_RW, 0x40);
100			bus_space_read_multi_1(t, h, SBSS_HSCX, buf, size);
101			break;
102	}
103}
104
105/*---------------------------------------------------------------------------*
106 *      Sedlbauer SpeedStar ISAC put fifo routine
107 *---------------------------------------------------------------------------*/
108
109static void
110sws_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
111{
112	bus_space_tag_t t = sc->sc_maps[0].t;
113	bus_space_handle_t h = sc->sc_maps[0].h;
114	switch (what) {
115		case ISIC_WHAT_ISAC:
116			bus_space_write_1(t, h, SBSS_RW, 0);
117			bus_space_write_multi_1(t, h, SBSS_ISAC, buf, size);
118			break;
119		case ISIC_WHAT_HSCXA:
120			bus_space_write_1(t, h, SBSS_RW, 0);
121			bus_space_write_multi_1(t, h, SBSS_HSCX, buf, size);
122			break;
123		case ISIC_WHAT_HSCXB:
124			bus_space_write_1(t, h, SBSS_RW, 0x40);
125			bus_space_write_multi_1(t, h, SBSS_HSCX, buf, size);
126			break;
127	}
128}
129
130/*---------------------------------------------------------------------------*
131 *      Sedlbauer SpeedStar ISAC put register routine
132 *---------------------------------------------------------------------------*/
133
134static void
135sws_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
136{
137	bus_space_tag_t t = sc->sc_maps[0].t;
138	bus_space_handle_t h = sc->sc_maps[0].h;
139	switch (what) {
140		case ISIC_WHAT_ISAC:
141			bus_space_write_1(t, h, SBSS_RW, offs);
142			bus_space_write_1(t, h, SBSS_ISAC, data);
143			break;
144		case ISIC_WHAT_HSCXA:
145			bus_space_write_1(t, h, SBSS_RW, offs);
146			bus_space_write_1(t, h, SBSS_HSCX, data);
147			break;
148		case ISIC_WHAT_HSCXB:
149			bus_space_write_1(t, h, SBSS_RW, 0x40+offs);
150			bus_space_write_1(t, h, SBSS_HSCX, data);
151			break;
152	}
153}
154
155/*---------------------------------------------------------------------------*
156 *	Sedlbauer SpeedStar ISAC get register routine
157 *---------------------------------------------------------------------------*/
158
159static u_int8_t
160sws_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
161{
162	bus_space_tag_t t = sc->sc_maps[0].t;
163	bus_space_handle_t h = sc->sc_maps[0].h;
164	switch (what) {
165		case ISIC_WHAT_ISAC:
166			bus_space_write_1(t, h, SBSS_RW, offs);
167			return bus_space_read_1(t, h, SBSS_ISAC);
168		case ISIC_WHAT_HSCXA:
169			bus_space_write_1(t, h, SBSS_RW, offs);
170			return bus_space_read_1(t, h, SBSS_HSCX);
171		case ISIC_WHAT_HSCXB:
172			bus_space_write_1(t, h, SBSS_RW, 0x40+offs);
173			return bus_space_read_1(t, h, SBSS_HSCX);
174	}
175	return 0;
176}
177
178/*
179 * XXX - one time only! Some of this has to go into an enable
180 * function, with apropriate counterpart in disable, so a card
181 * could be removed an inserted again.
182 */
183int
184isic_attach_sbspeedstar2(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
185{
186	struct isic_softc * sc = &psc->sc_isic;
187	bus_space_tag_t t;
188	bus_space_handle_t h;
189
190	/* Validate config info */
191	if (cfe->num_memspace != 0)
192		printf(": unexpected number of memory spaces %d should be 0\n",
193			cfe->num_memspace);
194	if (cfe->num_iospace != 1)
195		printf(": unexpected number of memory spaces %d should be 1\n",
196			cfe->num_iospace);
197
198	/* Allocate pcmcia space */
199	if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
200			    cfe->iospace[0].length, &psc->sc_pcioh))
201		printf(": can't allocate i/o space\n");
202
203	/* map them */
204	if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
205	    PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), &psc->sc_pcioh,
206	    &psc->sc_io_window)) {
207		printf(": can't map i/o space\n");
208		return 0;
209	}
210
211	/* Setup bus space maps */
212	sc->sc_num_mappings = 1;
213	MALLOC_MAPS(sc);
214
215	/* Copy our handles/tags to the MI maps */
216	sc->sc_maps[0].t = psc->sc_pcioh.iot;
217	sc->sc_maps[0].h = psc->sc_pcioh.ioh;
218	sc->sc_maps[0].offset = 0;
219	sc->sc_maps[0].size = 0;	/* not our mapping */
220
221	t = sc->sc_maps[0].t;
222	h = sc->sc_maps[0].h;
223
224	/* setup access routines */
225
226	sc->readreg   = sws_read_reg;
227	sc->writereg  = sws_write_reg;
228
229	sc->readfifo  = sws_read_fifo;
230	sc->writefifo = sws_write_fifo;
231
232	/* setup IOM bus type */
233
234	sc->sc_bustyp = BUS_TYPE_IOM2;
235
236	sc->sc_ipac = 0;
237	sc->sc_bfifolen = HSCX_FIFO_LEN;
238
239	/* reset card */
240        {
241        	bus_space_tag_t t1 = sc->sc_maps[0].t;
242        	bus_space_handle_t h1 = sc->sc_maps[0].h;
243        	bus_space_write_1(t1, h1, SBSS_RESET, 0x3);
244		DELAY(SEC_DELAY / 5);
245		bus_space_write_1(t1, h1, SBSS_RESET, 0);
246		DELAY(SEC_DELAY / 5);
247	}
248
249	return 1;
250}
251
252#endif /* ISICPCMCIA_SBSPEEDSTAR2 */
253