if_ze.c revision 1.9 1 1.9 matt /* $NetBSD: if_ze.c,v 1.9 2000/05/18 04:20:41 matt Exp $ */
2 1.1 ragge /*
3 1.1 ragge * Copyright (c) 1998 James R. Maynard III. All rights reserved.
4 1.1 ragge *
5 1.1 ragge * Redistribution and use in source and binary forms, with or without
6 1.1 ragge * modification, are permitted provided that the following conditions
7 1.1 ragge * are met:
8 1.1 ragge * 1. Redistributions of source code must retain the above copyright
9 1.1 ragge * notice, this list of conditions and the following disclaimer.
10 1.1 ragge * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 ragge * notice, this list of conditions and the following disclaimer in the
12 1.1 ragge * documentation and/or other materials provided with the distribution.
13 1.1 ragge * 3. All advertising materials mentioning features or use of this software
14 1.1 ragge * must display the following acknowledgement:
15 1.1 ragge * This product includes software developed by James R. Maynard III.
16 1.1 ragge * 4. The name of the author may not be used to endorse or promote products
17 1.1 ragge * derived from this software without specific prior written permission
18 1.1 ragge *
19 1.1 ragge * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.1 ragge * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.1 ragge * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.1 ragge * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.1 ragge * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.1 ragge * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.1 ragge * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.1 ragge * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.1 ragge * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.1 ragge * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.1 ragge *
30 1.1 ragge * Standalone routine for the SGEC Ethernet controller.
31 1.1 ragge */
32 1.1 ragge
33 1.1 ragge #include <sys/param.h>
34 1.1 ragge #include <sys/types.h>
35 1.3 ragge #include <sys/socket.h>
36 1.3 ragge #include <sys/queue.h>
37 1.3 ragge
38 1.3 ragge #include <net/if.h>
39 1.3 ragge #include <net/if_ether.h>
40 1.1 ragge
41 1.1 ragge #include <netinet/in.h>
42 1.1 ragge #include <netinet/in_systm.h>
43 1.1 ragge
44 1.1 ragge #include <lib/libkern/libkern.h>
45 1.1 ragge #include <lib/libsa/netif.h>
46 1.1 ragge #include <lib/libsa/stand.h>
47 1.1 ragge
48 1.5 ragge #include <dev/ic/sgecreg.h>
49 1.1 ragge
50 1.5 ragge #include "arch/vax/include/sid.h"
51 1.8 ragge #include "arch/vax/include/rpb.h"
52 1.8 ragge
53 1.8 ragge #include "vaxstand.h"
54 1.1 ragge
55 1.1 ragge int ze_probe(), ze_match(), ze_get(), ze_put();
56 1.4 ragge void ze_init(), ze_end();
57 1.1 ragge
58 1.1 ragge struct netif_stats ze_stats;
59 1.1 ragge
60 1.1 ragge struct netif_dif ze_ifs[] = {
61 1.1 ragge /* dif_unit dif_nsel dif_stats dif_private */
62 1.1 ragge { 0, 1, &ze_stats, },
63 1.1 ragge };
64 1.1 ragge
65 1.1 ragge struct netif_stats ze_stats;
66 1.1 ragge
67 1.1 ragge struct netif_driver ze_driver = {
68 1.4 ragge "ze", ze_match, ze_probe, ze_init, ze_get, ze_put, ze_end, ze_ifs, 1,
69 1.1 ragge };
70 1.1 ragge
71 1.9 matt #define NRCV 8 /* allocate 8 receive descriptors */
72 1.9 matt #define NXMT 4 /* and 4 transmit - must be >1 */
73 1.1 ragge #define SETUP_FRAME_LEN 128 /* length of the setup frame */
74 1.1 ragge
75 1.1 ragge /* allocate a buffer on an octaword boundary */
76 1.1 ragge #define OW_ALLOC(x) ((void *)((int)(alloc((x) + 15) + 15) & ~15))
77 1.1 ragge
78 1.1 ragge static volatile struct zedevice *addr;
79 1.1 ragge
80 1.1 ragge struct ze_tdes *ze_tdes_list; /* transmit desc list */
81 1.1 ragge struct ze_rdes *ze_rdes_list; /* and receive desc list */
82 1.1 ragge u_char ze_myaddr[ETHER_ADDR_LEN]; /* my Ethernet address */
83 1.1 ragge
84 1.1 ragge int
85 1.1 ragge ze_match(nif, machdep_hint)
86 1.1 ragge struct netif *nif;
87 1.1 ragge void *machdep_hint;
88 1.1 ragge {
89 1.1 ragge return strcmp(machdep_hint, "ze") == 0;
90 1.1 ragge }
91 1.1 ragge
92 1.1 ragge int
93 1.1 ragge ze_probe(nif, machdep_hint)
94 1.1 ragge struct netif *nif;
95 1.1 ragge void *machdep_hint;
96 1.1 ragge {
97 1.1 ragge return 0;
98 1.1 ragge }
99 1.1 ragge
100 1.1 ragge void
101 1.1 ragge ze_init(desc, machdep_hint)
102 1.1 ragge struct iodesc *desc;
103 1.1 ragge void *machdep_hint;
104 1.1 ragge {
105 1.1 ragge u_long nicsr0_work, *nisa_rom;
106 1.1 ragge int i;
107 1.1 ragge u_char *saved_buf;
108 1.1 ragge struct ze_tdes *ze_setup_tdes_list;
109 1.1 ragge
110 1.1 ragge /* point to the device in memory */
111 1.8 ragge addr = (struct zedevice *)rpb->csrphy;
112 1.1 ragge
113 1.1 ragge /* reset the device and wait for completion */
114 1.1 ragge addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_RE;
115 1.1 ragge while ((addr->ze_nicsr5 & ZE_NICSR5_ID) == 0)
116 1.1 ragge ;
117 1.1 ragge if (addr->ze_nicsr5 & ZE_NICSR5_SF) {
118 1.1 ragge printf("SGEC self-test failed...\n");
119 1.1 ragge }
120 1.1 ragge
121 1.1 ragge /* Get our Ethernet address */
122 1.5 ragge if (vax_boardtype == VAX_BTYP_49) {
123 1.5 ragge nisa_rom = (u_long *)0x27800000;
124 1.5 ragge for (i=0; i<ETHER_ADDR_LEN; i++)
125 1.5 ragge ze_myaddr[i] = nisa_rom[i] & 0377;
126 1.5 ragge } else {
127 1.5 ragge nisa_rom = (u_long *)0x20084000;
128 1.5 ragge for (i=0; i<ETHER_ADDR_LEN; i++)
129 1.7 ragge if (vax_boardtype == VAX_BTYP_660)
130 1.7 ragge ze_myaddr[i] = (nisa_rom[i] & 0xff000000) >> 24;
131 1.7 ragge else
132 1.7 ragge ze_myaddr[i] = (nisa_rom[i] & 0x0000ff00) >> 8;
133 1.5 ragge }
134 1.1 ragge bcopy(ze_myaddr,desc->myea,ETHER_ADDR_LEN);
135 1.1 ragge
136 1.1 ragge /* initialize SGEC operating mode */
137 1.1 ragge /* disable interrupts here */
138 1.1 ragge nicsr0_work = ZE_NICSR0_IPL14 | ZE_NICSR0_SA | ZE_NICSR0_MBO |
139 1.1 ragge (ZE_NICSR0_IV_MASK & 0x0108);
140 1.1 ragge while (addr->ze_nicsr0 != nicsr0_work)
141 1.1 ragge addr->ze_nicsr0 = nicsr0_work;
142 1.1 ragge if (addr->ze_nicsr5 & ZE_NICSR5_ME)
143 1.1 ragge addr->ze_nicsr5 |= ZE_NICSR5_ME;
144 1.1 ragge /* reenable interrupts here */
145 1.1 ragge
146 1.1 ragge /* Allocate space for descriptor lists and buffers,
147 1.1 ragge then initialize them. Set up both lists as a ring. */
148 1.1 ragge ze_rdes_list = OW_ALLOC((NRCV+1) * sizeof(struct ze_rdes));
149 1.1 ragge ze_tdes_list = OW_ALLOC((NXMT+1) * sizeof(struct ze_tdes));
150 1.1 ragge for (i=0; i < NRCV; i++) {
151 1.1 ragge bzero(ze_rdes_list+i,sizeof(struct ze_rdes));
152 1.1 ragge ze_rdes_list[i].ze_framelen = ZE_FRAMELEN_OW;
153 1.1 ragge ze_rdes_list[i].ze_bufsize = ETHER_MAX_LEN;
154 1.1 ragge ze_rdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
155 1.1 ragge }
156 1.1 ragge bzero(ze_rdes_list+NRCV,sizeof(struct ze_rdes));
157 1.1 ragge ze_rdes_list[NRCV].ze_framelen = ZE_FRAMELEN_OW;
158 1.1 ragge ze_rdes_list[NRCV].ze_rdes1 = ZE_RDES1_CA;
159 1.1 ragge ze_rdes_list[NRCV].ze_bufaddr = (u_char *)ze_rdes_list;
160 1.1 ragge for (i=0; i < NXMT; i++) {
161 1.1 ragge bzero(ze_tdes_list+i,sizeof(struct ze_tdes));
162 1.1 ragge ze_tdes_list[i].ze_tdes1 = ZE_TDES1_FS | ZE_TDES1_LS;
163 1.1 ragge ze_tdes_list[i].ze_bufsize = ETHER_MAX_LEN;
164 1.1 ragge ze_tdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
165 1.1 ragge }
166 1.1 ragge bzero(ze_tdes_list+NXMT,sizeof(struct ze_tdes));
167 1.1 ragge ze_tdes_list[NXMT].ze_tdes1 = ZE_TDES1_CA;
168 1.1 ragge ze_tdes_list[NXMT].ze_tdr = ZE_TDR_OW;
169 1.1 ragge ze_tdes_list[NXMT].ze_bufaddr = (u_char *)ze_tdes_list;
170 1.1 ragge
171 1.1 ragge /* Build setup frame. We set the SGEC to do a
172 1.1 ragge perfect filter on our own address. */
173 1.1 ragge ze_setup_tdes_list = OW_ALLOC(2*sizeof(struct ze_tdes));
174 1.1 ragge bzero(ze_setup_tdes_list+0,2*sizeof(struct ze_tdes));
175 1.1 ragge ze_setup_tdes_list[0].ze_tdr = ZE_TDR_OW;
176 1.1 ragge ze_setup_tdes_list[0].ze_tdes1 = ZE_TDES1_DT_SETUP;
177 1.1 ragge ze_setup_tdes_list[0].ze_bufsize = SETUP_FRAME_LEN;
178 1.1 ragge ze_setup_tdes_list[0].ze_bufaddr = alloc(SETUP_FRAME_LEN);
179 1.1 ragge bzero(ze_setup_tdes_list[0].ze_bufaddr,SETUP_FRAME_LEN);
180 1.1 ragge for (i=0; i < 16; i++)
181 1.1 ragge bcopy(ze_myaddr,ze_setup_tdes_list[0].ze_bufaddr+(8*i),
182 1.1 ragge ETHER_ADDR_LEN);
183 1.1 ragge ze_setup_tdes_list[1].ze_tdes1 = ZE_TDES1_CA;
184 1.1 ragge ze_setup_tdes_list[1].ze_bufaddr = (u_char *)ze_setup_tdes_list;
185 1.1 ragge
186 1.1 ragge /* Start the transmitter and initialize almost everything else. */
187 1.1 ragge addr->ze_nicsr4 = ze_setup_tdes_list;
188 1.1 ragge addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_SE | ZE_NICSR6_ST |
189 1.1 ragge ZE_NICSR6_DC | ZE_NICSR6_BL_4;
190 1.1 ragge while ((addr->ze_nicsr5 & ZE_NICSR5_TS) != ZE_NICSR5_TS_SUSP)
191 1.1 ragge ; /* wait for the frame to be processed */
192 1.1 ragge
193 1.1 ragge /* Setup frame is done processing, initialize the receiver and
194 1.1 ragge point the transmitter to the real tdes list. */
195 1.1 ragge addr->ze_nicsr4 = ze_tdes_list;
196 1.1 ragge addr->ze_nicsr3 = ze_rdes_list;
197 1.1 ragge addr->ze_nicsr6 |= ZE_NICSR6_SR;
198 1.1 ragge
199 1.1 ragge /* And away-y-y we go! */
200 1.1 ragge }
201 1.1 ragge
202 1.1 ragge int
203 1.1 ragge ze_get(desc, pkt, maxlen, timeout)
204 1.1 ragge struct iodesc *desc;
205 1.1 ragge void *pkt;
206 1.1 ragge int maxlen;
207 1.1 ragge time_t timeout;
208 1.1 ragge {
209 1.1 ragge int timeout_ctr=100000*timeout, len, rdes;
210 1.1 ragge
211 1.1 ragge while (timeout_ctr-- > 0) {
212 1.1 ragge
213 1.1 ragge /* If there's not a packet waiting for us, just decrement the
214 1.1 ragge timeout counter. */
215 1.1 ragge if (!(addr->ze_nicsr5 & ZE_NICSR5_RI))
216 1.1 ragge continue;
217 1.1 ragge
218 1.1 ragge /* Look through the receive descriptor list for the packet. */
219 1.1 ragge for (rdes=0; rdes<NRCV; rdes++) {
220 1.1 ragge if (ze_rdes_list[rdes].ze_framelen & ZE_FRAMELEN_OW)
221 1.1 ragge continue;
222 1.1 ragge
223 1.1 ragge /* If the packet has an error, ignore it. */
224 1.1 ragge if (ze_rdes_list[rdes].ze_rdes0 & ZE_RDES0_ES)
225 1.1 ragge len = 0;
226 1.1 ragge
227 1.1 ragge /* Copy the packet, up to the length supplied by the caller, to
228 1.1 ragge the caller's buffer. */
229 1.1 ragge else {
230 1.1 ragge if ((len = (ze_rdes_list[rdes].ze_framelen &
231 1.1 ragge (~ ZE_FRAMELEN_OW))) > maxlen)
232 1.1 ragge len = maxlen;
233 1.1 ragge bcopy((void *)ze_rdes_list[rdes].ze_bufaddr,
234 1.1 ragge pkt,len);
235 1.1 ragge }
236 1.1 ragge
237 1.1 ragge /* Give ownership of this descriptor back to the SGEC. */
238 1.1 ragge ze_rdes_list[rdes].ze_framelen = ZE_FRAMELEN_OW;
239 1.1 ragge
240 1.1 ragge /* If we actually got a good packet, reset the error flags and
241 1.1 ragge tell the SGEC to look for more before returning. */
242 1.1 ragge if (len > 0) {
243 1.1 ragge addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI |
244 1.1 ragge ZE_NICSR5_IS;
245 1.1 ragge addr->ze_nicsr2=ZE_NICSR2_RXPD;
246 1.1 ragge return len;
247 1.1 ragge }
248 1.1 ragge }
249 1.1 ragge }
250 1.1 ragge
251 1.1 ragge /* If we're going to return an error indication, at least reset the
252 1.1 ragge error flags and tell the SGEC to keep receiving first. */
253 1.1 ragge addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI | ZE_NICSR5_IS;
254 1.1 ragge addr->ze_nicsr2=ZE_NICSR2_RXPD;
255 1.1 ragge return 0;
256 1.1 ragge }
257 1.1 ragge
258 1.1 ragge int
259 1.1 ragge ze_put(desc, pkt, len)
260 1.1 ragge struct iodesc *desc;
261 1.1 ragge void *pkt;
262 1.1 ragge int len;
263 1.1 ragge {
264 1.1 ragge int timeout=100000;
265 1.1 ragge
266 1.1 ragge /* The SGEC maintains its position in the transmit descriptor list
267 1.1 ragge for the next frame to transmit. Unfortunately, there's no way to tell
268 1.1 ragge from software just where that is. We're forced to reset the position
269 1.1 ragge whenever we send a frame, which requires waiting for the previous
270 1.1 ragge frame to be sent. Argh. */
271 1.1 ragge while ((addr->ze_nicsr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN)
272 1.1 ragge ;
273 1.1 ragge
274 1.1 ragge /* Copy the packet to the buffer we allocated. */
275 1.1 ragge bcopy(pkt, (void *)ze_tdes_list[0].ze_bufaddr, len);
276 1.1 ragge
277 1.1 ragge /* Set the packet length in the descriptor, increasing it to the
278 1.1 ragge minimum size if needed. */
279 1.1 ragge ze_tdes_list[0].ze_bufsize = len;
280 1.1 ragge if (len < ETHER_MIN_LEN)
281 1.1 ragge ze_tdes_list[0].ze_bufsize = ETHER_MIN_LEN;
282 1.1 ragge
283 1.1 ragge /* Give ownership of the descriptor to the SGEC and tell it to start
284 1.1 ragge transmitting. */
285 1.1 ragge ze_tdes_list[0].ze_tdr = ZE_TDR_OW;
286 1.1 ragge addr->ze_nicsr4 = ze_tdes_list;
287 1.1 ragge addr->ze_nicsr1 = ZE_NICSR1_TXPD;
288 1.1 ragge
289 1.1 ragge /* Wait for the frame to be sent, but not too long. */
290 1.1 ragge timeout = 100000;
291 1.1 ragge while ((addr->ze_nicsr5 & ZE_NICSR5_TI == 0) && (--timeout>0))
292 1.1 ragge ;
293 1.1 ragge
294 1.1 ragge /* Reset the transmitter interrupt pending flag. */
295 1.1 ragge addr->ze_nicsr5 |= ZE_NICSR5_TI;
296 1.1 ragge
297 1.1 ragge /* Return good if we didn't timeout, or error if we did. */
298 1.1 ragge if (timeout>0) return len;
299 1.1 ragge return -1;
300 1.4 ragge }
301 1.4 ragge
302 1.4 ragge void
303 1.4 ragge ze_end()
304 1.4 ragge {
305 1.4 ragge addr->ze_nicsr6 = ZE_NICSR6_RE;
306 1.1 ragge }
307