if_de.c revision 1.6 1 /* $NetBSD: if_de.c,v 1.6 2009/03/18 16:00:15 cegger Exp $ */
2
3 /*
4 * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed at Ludd, University of
17 * Lule}, Sweden and its contributors.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * Standalone routine for the DEUNA Ethernet controller.
33 */
34
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/queue.h>
39
40 #include <net/if.h>
41 #include <net/if_ether.h>
42
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45
46 #include <lib/libsa/netif.h>
47 #include <lib/libsa/stand.h>
48
49 #include "lib/libkern/libkern.h"
50
51 #include <dev/qbus/if_dereg.h>
52
53 #include "arch/vax/include/sid.h"
54 #include "arch/vax/include/rpb.h"
55 #include "arch/vax/include/pte.h"
56
57 #include "vaxstand.h"
58
59 static int de_get(struct iodesc *, void *, size_t, saseconds_t);
60 static int de_put(struct iodesc *, void *, size_t);
61 static void dewait(char *);
62
63 struct netif_driver de_driver = {
64 0, 0, 0, 0, de_get, de_put,
65 };
66
67 #define NRCV 8 /* allocate 8 receive descriptors */
68 #define NXMT 4 /* and 4 transmit - must be >1 */
69
70 struct de_cdata {
71 /* the following structures are always mapped in */
72 struct de_pcbb dc_pcbb; /* port control block */
73 struct de_ring dc_xrent[NXMT]; /* transmit ring entrys */
74 struct de_ring dc_rrent[NRCV]; /* receive ring entrys */
75 struct de_udbbuf dc_udbbuf; /* UNIBUS data buffer */
76 char dc_rbuf[NRCV][ETHER_MAX_LEN];
77 char dc_xbuf[NXMT][ETHER_MAX_LEN];
78 /* end mapped area */
79 };
80
81 static volatile struct de_cdata *dc, *pdc;
82 static volatile char *addr;
83 static int crx, ctx;
84 #define DE_WCSR(csr, val) *(volatile u_short *)(addr + (csr)) = (val)
85 #define DE_WLOW(val) *(volatile u_char *)(addr + DE_PCSR0) = (val)
86 #define DE_WHIGH(val) *(volatile u_char *)(addr + DE_PCSR0 + 1) = (val)
87 #define DE_RCSR(csr) *(volatile u_short *)(addr + (csr))
88 #define LOWORD(x) ((u_int)(x) & 0xffff)
89 #define HIWORD(x) (((u_int)(x) >> 16) & 0x3)
90 #define dereg(x) ((x) & 017777)
91
92 int
93 deopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
94 {
95 int i, cdata, *map, npgs;
96 u_char eaddr[6];
97
98 /* point to the device in memory */
99 if (askname == 0) /* Override if autoboot */
100 addr = (char *)bootrpb.csrphy;
101 else {
102 addr = (char *)csrbase + dereg(0174510);
103 bootrpb.csrphy = (int)addr;
104 }
105 #ifdef DEV_DEBUG
106 printf("deopen: csrbase %x addr %p nexaddr %x\n",
107 csrbase, addr, nexaddr);
108 #endif
109 /* reset the device and wait for completion */
110 DE_WCSR(DE_PCSR0, 0);
111 {volatile int j = 100; while (--j);}
112 DE_WCSR(DE_PCSR0, PCSR0_RSET);
113 dewait("reset");
114
115 /* Map in the control structures and buffers */
116 dc = alloc(sizeof(struct de_cdata));
117 pdc = (struct de_cdata *)((int)dc & VAX_PGOFSET);
118 map = (int *)nexaddr + 512;
119 npgs = (sizeof(struct de_cdata) >> VAX_PGSHIFT) + 1;
120 cdata = (int)dc >> VAX_PGSHIFT;
121 for (i = 0; i < npgs; i++) {
122 map[i] = PG_V | (cdata + i);
123 }
124
125 memset((char *)dc, 0, sizeof(struct de_cdata));
126
127 /* Tell the DEUNA about our PCB */
128 DE_WCSR(DE_PCSR2, LOWORD(pdc));
129 DE_WCSR(DE_PCSR3, HIWORD(pdc));
130 DE_WLOW(CMD_GETPCBB);
131 dewait("pcbb");
132
133 /* Get our address */
134 dc->dc_pcbb.pcbb0 = FC_RDPHYAD;
135 DE_WLOW(CMD_GETCMD);
136 dewait("read physaddr");
137 bcopy((char *)&dc->dc_pcbb.pcbb2, eaddr, 6);
138
139 /* Create and link the descriptors */
140 for (i=0; i < NRCV; i++) {
141 volatile struct de_ring *rp = &dc->dc_rrent[i];
142
143 rp->r_lenerr = 0;
144 rp->r_segbl = LOWORD(&pdc->dc_rbuf[i][0]);
145 rp->r_segbh = HIWORD(&pdc->dc_rbuf[i][0]);
146 rp->r_flags = RFLG_OWN;
147 rp->r_slen = ETHER_MAX_LEN;
148 }
149 for (i=0; i < NXMT; i++) {
150 volatile struct de_ring *rp = &dc->dc_xrent[i];
151
152 rp->r_segbl = LOWORD(&pdc->dc_xbuf[i][0]);
153 rp->r_segbh = HIWORD(&pdc->dc_xbuf[i][0]);
154 rp->r_tdrerr = 0;
155 rp->r_flags = 0;
156 }
157 crx = ctx = 0;
158
159 /* set the transmit and receive ring header addresses */
160 dc->dc_pcbb.pcbb0 = FC_WTRING;
161 dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf);
162 dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf);
163
164 dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]);
165 dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]);
166 dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t);
167 dc->dc_udbbuf.b_trlen = NXMT;
168 dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]);
169 dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]);
170 dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t);
171 dc->dc_udbbuf.b_rrlen = NRCV;
172
173 DE_WLOW(CMD_GETCMD);
174 dewait("wtring");
175
176 dc->dc_pcbb.pcbb0 = FC_WTMODE;
177 dc->dc_pcbb.pcbb2 = MOD_DRDC|MOD_TPAD|MOD_HDX;
178 DE_WLOW(CMD_GETCMD);
179 dewait("wtmode");
180
181 DE_WLOW(CMD_START);
182 dewait("start");
183
184 DE_WLOW(CMD_PDMD);
185 dewait("initpoll");
186 /* Should be running by now */
187
188 net_devinit(f, &de_driver, eaddr);
189
190 return 0;
191 }
192
193 int
194 de_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timeout)
195 {
196 volatile int to = 100000 * timeout;
197 int len, csr0;
198
199 if ((csr0 = DE_RCSR(DE_PCSR0)) & PCSR0_INTR)
200 DE_WHIGH(csr0 >> 8);
201 retry:
202 if (to-- == 0)
203 return 0;
204
205 if (dc->dc_rrent[crx].r_flags & RFLG_OWN)
206 goto retry;
207
208 if (dc->dc_rrent[crx].r_flags & RFLG_ERRS)
209 len = 0;
210 else
211 len = dc->dc_rrent[crx].r_lenerr & RERR_MLEN;
212
213 if (len > maxlen)
214 len = maxlen;
215 if (len)
216 bcopy((char *)&dc->dc_rbuf[crx][0], pkt, len);
217
218 dc->dc_rrent[crx].r_flags = RFLG_OWN;
219 dc->dc_rrent[crx].r_lenerr = 0;
220 #ifdef DEV_DEBUG
221 printf("Got packet: len %d idx %d maxlen %ld\n", len, crx, maxlen);
222 #endif
223 if (++crx == NRCV)
224 crx = 0;
225
226 if (len == 0)
227 goto retry;
228 return len;
229 }
230
231
232 int
233 de_put(struct iodesc *desc, void *pkt, size_t len)
234 {
235 volatile int to = 100000;
236 int csr0;
237
238 if ((csr0 = DE_RCSR(DE_PCSR0)) & PCSR0_INTR)
239 DE_WHIGH(csr0 >> 8);
240 #ifdef DEV_DEBUG
241 printf("de_put: len %ld\n", len);
242 #endif
243 retry:
244 if (to-- == 0)
245 return -1;
246
247 if (dc->dc_xrent[ctx].r_flags & RFLG_OWN)
248 goto retry;
249
250 bcopy(pkt, (char *)&dc->dc_xbuf[ctx][0], len);
251
252 dc->dc_xrent[ctx].r_slen = len;
253 dc->dc_xrent[ctx].r_tdrerr = 0;
254 dc->dc_xrent[ctx].r_flags = XFLG_OWN|XFLG_STP|XFLG_ENP;
255
256 DE_WLOW(CMD_PDMD);
257 dewait("start");
258
259 if (++ctx == NXMT)
260 ctx = 0;
261 return len;
262 }
263
264 int
265 declose(struct open_file *f)
266 {
267 DE_WCSR(DE_PCSR0, PCSR0_RSET);
268 dewait("close");
269 return 0;
270 }
271
272 void
273 dewait(char *fn)
274 {
275 int csr0;
276
277 #ifdef DEV_DEBUG
278 printf("dewait: %s...", fn);
279 #endif
280 while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
281 ;
282 csr0 = DE_RCSR(DE_PCSR0);
283 DE_WHIGH(csr0 >> 8);
284 #ifdef DEV_DEBUG
285 if (csr0 & PCSR0_PCEI)
286 printf("failed! CSR0 %x", csr0);
287 else
288 printf("done");
289 printf(", PCSR1 %x\n", DE_RCSR(DE_PCSR1));
290 #endif
291 }
292