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