if_cs.c revision 1.3 1 1.3 christos /* $NetBSD: if_cs.c,v 1.3 2005/12/11 12:17:34 christos Exp $ */
2 1.1 igy
3 1.1 igy /*
4 1.1 igy * Copyright (c) 2003 Naoto Shimazaki.
5 1.1 igy * All rights reserved.
6 1.1 igy *
7 1.1 igy * Redistribution and use in source and binary forms, with or without
8 1.1 igy * modification, are permitted provided that the following conditions
9 1.1 igy * are met:
10 1.1 igy * 1. Redistributions of source code must retain the above copyright
11 1.1 igy * notice, this list of conditions and the following disclaimer.
12 1.1 igy * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 igy * notice, this list of conditions and the following disclaimer in the
14 1.1 igy * documentation and/or other materials provided with the distribution.
15 1.1 igy *
16 1.1 igy * THIS SOFTWARE IS PROVIDED BY NAOTO SHIMAZAKI AND CONTRIBUTORS ``AS IS''
17 1.1 igy * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 1.1 igy * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 igy * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE NAOTO OR CONTRIBUTORS BE
20 1.1 igy * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 igy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 igy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 igy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 igy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 igy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 1.1 igy * THE POSSIBILITY OF SUCH DAMAGE.
27 1.1 igy */
28 1.1 igy #include <sys/cdefs.h>
29 1.3 christos __KERNEL_RCSID(0, "$NetBSD: if_cs.c,v 1.3 2005/12/11 12:17:34 christos Exp $");
30 1.1 igy
31 1.1 igy #include <sys/param.h>
32 1.1 igy #include <netinet/in.h>
33 1.1 igy
34 1.1 igy #include <lib/libsa/stand.h>
35 1.1 igy #include <lib/libsa/netif.h>
36 1.1 igy
37 1.1 igy #include <dev/ic/cs89x0reg.h>
38 1.1 igy
39 1.1 igy #include "extern.h"
40 1.1 igy
41 1.1 igy static int cs_match(struct netif *, void *);
42 1.1 igy static int cs_probe(struct netif *, void *);
43 1.1 igy static void cs_init(struct iodesc *, void *);
44 1.1 igy static int cs_get(struct iodesc *, void *, size_t, time_t);
45 1.1 igy static int cs_put(struct iodesc *, void *, size_t);
46 1.1 igy static void cs_end(struct netif *);
47 1.1 igy
48 1.1 igy static struct netif_stats cs_stats;
49 1.1 igy
50 1.1 igy static struct netif_dif cs_if = {
51 1.1 igy .dif_unit = 0,
52 1.1 igy .dif_nsel = 1,
53 1.1 igy .dif_stats = &cs_stats,
54 1.1 igy .dif_private = NULL,
55 1.1 igy .dif_used = 0,
56 1.1 igy };
57 1.1 igy
58 1.1 igy struct netif_driver cs_driver = {
59 1.1 igy .netif_bname = "cs",
60 1.1 igy .netif_match = cs_match,
61 1.1 igy .netif_probe = cs_probe,
62 1.1 igy .netif_init = cs_init,
63 1.1 igy .netif_get = cs_get,
64 1.1 igy .netif_put = cs_put,
65 1.1 igy .netif_end = cs_end,
66 1.1 igy .netif_ifs = &cs_if,
67 1.1 igy .netif_nifs = 1,
68 1.1 igy };
69 1.1 igy
70 1.1 igy #define CS_IO_BASE 0x14010300U
71 1.1 igy
72 1.1 igy #define CS_READ_1(off) REGREAD_1(CS_IO_BASE, (off))
73 1.1 igy #define CS_READ_2(off) REGREAD_2(CS_IO_BASE, (off))
74 1.1 igy #define CS_WRITE_1(off, val) REGWRITE_1(CS_IO_BASE, (off), (val))
75 1.1 igy #define CS_WRITE_2(off, val) REGWRITE_2(CS_IO_BASE, (off), (val))
76 1.1 igy #define CS_READ_PACKET_PAGE(off) \
77 1.1 igy (REGWRITE_2(CS_IO_BASE, PORT_PKTPG_PTR, (off)), \
78 1.1 igy REGREAD_2(CS_IO_BASE, PORT_PKTPG_DATA))
79 1.1 igy #define CS_WRITE_PACKET_PAGE(off, val) \
80 1.1 igy (REGWRITE_2(CS_IO_BASE, PORT_PKTPG_PTR, (off)), \
81 1.1 igy REGWRITE_2(CS_IO_BASE, PORT_PKTPG_DATA, (val)))
82 1.1 igy
83 1.1 igy static inline void
84 1.1 igy delay(int n)
85 1.1 igy {
86 1.1 igy int i = 33 * n;
87 1.1 igy
88 1.1 igy while (--i > 0)
89 1.1 igy ;
90 1.1 igy }
91 1.1 igy
92 1.1 igy time_t
93 1.1 igy getsecs(void)
94 1.1 igy {
95 1.1 igy return REGREAD_4(VRETIMEL, 0) >> 15;
96 1.1 igy }
97 1.1 igy
98 1.1 igy static int
99 1.1 igy cs_match(struct netif *nif, void *machdep_hint)
100 1.1 igy {
101 1.1 igy return 1;
102 1.1 igy }
103 1.1 igy
104 1.1 igy static int
105 1.1 igy cs_probe(struct netif *nif, void *machdep_hint)
106 1.1 igy {
107 1.1 igy return 0;
108 1.1 igy }
109 1.1 igy
110 1.1 igy static void
111 1.2 igy cs_get_eeprom(int offset, u_int16_t *result)
112 1.2 igy {
113 1.2 igy int timeo;
114 1.2 igy
115 1.2 igy for (timeo = MAXLOOP; timeo > 0; timeo--) {
116 1.2 igy if (!(CS_READ_PACKET_PAGE(PKTPG_SELF_ST)
117 1.2 igy & SELF_ST_SI_BUSY))
118 1.2 igy break;
119 1.2 igy }
120 1.2 igy if (timeo == 0)
121 1.2 igy goto eeprom_error;
122 1.2 igy
123 1.2 igy CS_WRITE_PACKET_PAGE(PKTPG_EEPROM_CMD, offset | EEPROM_CMD_READ);
124 1.2 igy
125 1.2 igy for (timeo = MAXLOOP; timeo > 0; timeo--) {
126 1.2 igy if (!(CS_READ_PACKET_PAGE(PKTPG_SELF_ST)
127 1.2 igy & SELF_ST_SI_BUSY))
128 1.2 igy break;
129 1.2 igy }
130 1.2 igy if (timeo == 0)
131 1.2 igy goto eeprom_error;
132 1.2 igy
133 1.2 igy *result = CS_READ_PACKET_PAGE(PKTPG_EEPROM_DATA);
134 1.2 igy
135 1.2 igy return;
136 1.2 igy
137 1.2 igy eeprom_error:
138 1.2 igy panic("cannot read mac addr");
139 1.2 igy }
140 1.2 igy
141 1.2 igy static void
142 1.1 igy cs_init(struct iodesc *desc, void *machdep_hint)
143 1.1 igy {
144 1.2 igy int i;
145 1.2 igy u_int16_t *myea;
146 1.1 igy
147 1.1 igy /* Issue a software reset command to the chip */
148 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_SELF_CTL, SELF_CTL_RESET);
149 1.1 igy
150 1.1 igy /* We cannot touch the chip until calibration is done */
151 1.1 igy delay(10000);
152 1.1 igy
153 1.1 igy /*
154 1.1 igy * Transition -SBHE H->L L->H is needed between reset and
155 1.1 igy * the first access to the chip's register.
156 1.1 igy */
157 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 0);
158 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 1);
159 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 0);
160 1.1 igy CS_READ_1(PORT_PKTPG_PTR + 1);
161 1.1 igy
162 1.1 igy /* wait for INIT_DONE */
163 1.1 igy for (i = 10000; i > 0; i--) {
164 1.1 igy u_int16_t s;
165 1.1 igy
166 1.1 igy s = CS_READ_PACKET_PAGE(PKTPG_SELF_ST);
167 1.1 igy if ((s & SELF_ST_INIT_DONE) && !(s & SELF_ST_SI_BUSY))
168 1.1 igy break;
169 1.1 igy }
170 1.1 igy if (i == 0)
171 1.1 igy panic("cannot reset netif");
172 1.1 igy
173 1.2 igy myea = (u_int16_t *) desc->myea;
174 1.1 igy
175 1.2 igy cs_get_eeprom(EEPROM_IND_ADDR_H, &myea[0]);
176 1.2 igy cs_get_eeprom(EEPROM_IND_ADDR_M, &myea[1]);
177 1.2 igy cs_get_eeprom(EEPROM_IND_ADDR_L, &myea[2]);
178 1.1 igy
179 1.2 igy for (i = 0; i < 3; i++)
180 1.2 igy CS_WRITE_PACKET_PAGE(PKTPG_IND_ADDR + (i << 1), myea[i]);
181 1.1 igy
182 1.1 igy /*
183 1.1 igy * Accepting frames:
184 1.1 igy * RX_CTL_RX_OK_A: correct crc, and valid length
185 1.1 igy * RX_CTL_IND_A: dest addr maches individual address
186 1.1 igy * RX_CTL_BCAST_A: dest addr maches broadcast address
187 1.1 igy */
188 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_RX_CTL,
189 1.1 igy RX_CTL_RX_OK_A | RX_CTL_IND_A | RX_CTL_BCAST_A);
190 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_LINE_CTL, LINE_CTL_RX_ON | LINE_CTL_TX_ON);
191 1.1 igy }
192 1.1 igy
193 1.1 igy static int
194 1.1 igy cs_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
195 1.1 igy {
196 1.1 igy time_t t;
197 1.1 igy int rlen;
198 1.1 igy int i;
199 1.1 igy u_int16_t *p;
200 1.1 igy
201 1.1 igy t = getsecs();
202 1.1 igy rlen = 0;
203 1.1 igy while (getsecs() - t < timeout && rlen == 0) {
204 1.1 igy if (!(CS_READ_PACKET_PAGE(PKTPG_RX_EVENT) & RX_EVENT_RX_OK))
205 1.1 igy continue;
206 1.1 igy
207 1.1 igy /* drop status */
208 1.1 igy CS_READ_2(PORT_RXTX_DATA);
209 1.1 igy
210 1.1 igy /* get frame length */
211 1.1 igy rlen = CS_READ_2(PORT_RXTX_DATA);
212 1.1 igy
213 1.1 igy if (rlen > len) {
214 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_RX_CFG, RX_CFG_SKIP);
215 1.1 igy rlen = 0;
216 1.1 igy continue;
217 1.1 igy }
218 1.1 igy
219 1.1 igy p = pkt;
220 1.1 igy for (i = rlen >> 1; i > 0; i--)
221 1.1 igy *p++ = CS_READ_2(PORT_RXTX_DATA);
222 1.1 igy if (rlen & 1)
223 1.1 igy *((u_int8_t *) p + 1) = CS_READ_1(PORT_RXTX_DATA);
224 1.1 igy
225 1.1 igy /* exit while loop */
226 1.1 igy }
227 1.1 igy
228 1.1 igy return rlen;
229 1.1 igy }
230 1.1 igy
231 1.1 igy static int
232 1.1 igy cs_put(struct iodesc *desc, void *pkt, size_t len)
233 1.1 igy {
234 1.1 igy int timeo;
235 1.1 igy int i;
236 1.1 igy u_int16_t *p;
237 1.1 igy
238 1.1 igy CS_WRITE_2(PORT_TX_CMD, TX_CMD_START_ALL);
239 1.1 igy CS_WRITE_2(PORT_TX_LENGTH, len);
240 1.1 igy
241 1.1 igy for (timeo = 1000000; timeo > 0; timeo--) {
242 1.1 igy if (CS_READ_PACKET_PAGE(PKTPG_BUS_ST) & BUS_ST_RDY4TXNOW)
243 1.1 igy break;
244 1.1 igy }
245 1.1 igy if (timeo == 0)
246 1.1 igy panic("cs: cannot send frame");
247 1.1 igy
248 1.1 igy p = pkt;
249 1.1 igy i = (len + 1) >> 1;
250 1.1 igy while (i > 0) {
251 1.1 igy CS_WRITE_2(PORT_RXTX_DATA, *p++);
252 1.1 igy i--;
253 1.1 igy }
254 1.1 igy
255 1.1 igy return len;
256 1.1 igy }
257 1.1 igy
258 1.1 igy static void
259 1.1 igy cs_end(struct netif *nif)
260 1.1 igy {
261 1.1 igy CS_WRITE_PACKET_PAGE(PKTPG_LINE_CTL, 0);
262 1.1 igy }
263