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