Annotation of sys/arch/vax/boot/boot/if_qe.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_qe.c,v 1.3 2002/06/11 09:36:23 hugh Exp $ */
2: /* $NetBSD: if_qe.c,v 1.3 2000/05/20 13:30:03 ragge Exp $ */
3:
4: /*
5: * Copyright (c) 1998 Roar Thronęs. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Roar Thronęs.
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 DEQNA.
33: */
34:
35: #include <sys/param.h>
36: #include <sys/types.h>
37:
38: #include <netinet/in.h>
39: #include <netinet/in_systm.h>
40:
41: #include <lib/libsa/netif.h>
42: #include <lib/libsa/stand.h>
43:
44: #include <arch/vax/if/if_qereg.h>
45:
46: #include "../include/rpb.h"
47:
48: #include "vaxstand.h"
49:
50: static int qe_get(struct iodesc *desc, void *pkt, size_t, time_t timeout);
51: static int qe_put(struct iodesc *desc, void *pkt, size_t);
52: static void qe_init(u_char *eaddr);
53:
54: struct netif_driver qe_driver = {
55: 0, 0, 0, 0, qe_get, qe_put,
56: };
57:
58: #define NRCV 1 /* Receive descriptors */
59: #define NXMT 1 /* Transmit descriptors */
60:
61: #define QE_INTS (QE_RCV_INT | QE_XMIT_INT)
62: #define MAXPACKETSIZE 0x800 /* Because of (buggy) DEQNA */
63:
64: static struct qe_softc {
65: struct qe_ring rring[NRCV+2]; /* Receive ring descriptors */
66: struct qe_ring tring[NXMT+2]; /* Xmit ring descriptors */
67: u_char setup_pkt[16][8]; /* Setup packet */
68: char qein[2048], qeout[2048];/* Packet buffers */
69: } qe_softc;
70:
71: static struct qe_softc *sc = &qe_softc;
72: static int addr;
73:
74: #define QE_WCSR(csr, val) \
75: (*((volatile u_short *)(addr + (csr))) = (val))
76: #define QE_RCSR(csr) \
77: *((volatile u_short *)(addr + (csr)))
78: #define DELAY(x) {volatile int i = x;while (--i);}
79: #define LOWORD(x) ((int)(x) & 0xffff)
80: #define HIWORD(x) (((int)(x) >> 16) & 0x3f)
81: #define qereg(x) ((x) & 017777)
82:
83: int
84: qeopen(struct open_file *f, int adapt, int ctlr, int unit, int part) {
85: u_char eaddr[6];
86:
87: if (askname == 0)
88: addr = bootrpb.csrphy; /* Autoboot; use RPB instead */
89: else {
90: addr = 0x20000000;
91: if (unit == 0)
92: addr += qereg(0774440); /* XQA0 */
93: else if (unit == 1)
94: addr += qereg(0174460); /* XQB0 */
95: else
96: return ECTLR;
97: }
98:
99: qe_init(eaddr);
100:
101: net_devinit(f, &qe_driver, eaddr);
102: return 0;
103: }
104:
105: void
106: qe_init(u_char *eaddr)
107: {
108: int i,j;
109:
110: QE_WCSR(QE_CSR_CSR, QE_RESET);
111: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
112:
113: for (i = 0; i < 6; i++) {
114: sc->setup_pkt[i][1] = QE_RCSR(i * 2);
115: sc->setup_pkt[i+8][1] = QE_RCSR(i * 2);
116: sc->setup_pkt[i][2] = 0xff;
117: sc->setup_pkt[i+8][2] = QE_RCSR(i * 2);
118: for (j=3; j < 8; j++) {
119: sc->setup_pkt[i][j] = QE_RCSR(i * 2);
120: sc->setup_pkt[i+8][j] = QE_RCSR(i * 2);
121: }
122: eaddr[i] = QE_RCSR(i * 2);
123: }
124:
125: bzero((caddr_t)sc->rring, sizeof(struct qe_ring));
126: sc->rring->qe_buf_len = -64;
127: sc->rring->qe_addr_lo = (short)((int)sc->setup_pkt);
128: sc->rring->qe_addr_hi = (short)((int)sc->setup_pkt >> 16);
129:
130: bzero((caddr_t)sc->tring, sizeof(struct qe_ring));
131: sc->tring->qe_buf_len = -64;
132: sc->tring->qe_addr_lo = (short)((int)sc->setup_pkt);
133: sc->tring->qe_addr_hi = (short)((int)sc->setup_pkt >> 16);
134:
135: sc->rring[0].qe_flag = sc->rring[0].qe_status1 = QE_NOTYET;
136: sc->rring->qe_addr_hi |= QE_VALID;
137:
138: sc->tring[0].qe_flag = sc->tring[0].qe_status1 = QE_NOTYET;
139: sc->tring->qe_addr_hi |= QE_VALID | QE_SETUP | QE_EOMSG;
140:
141: QE_WCSR(QE_CSR_CSR, QE_XMIT_INT | QE_RCV_INT);
142:
143: QE_WCSR(QE_CSR_RCLL, LOWORD(sc->rring));
144: QE_WCSR(QE_CSR_RCLH, HIWORD(sc->rring));
145: QE_WCSR(QE_CSR_XMTL, LOWORD(sc->tring));
146: QE_WCSR(QE_CSR_XMTH, HIWORD(sc->tring));
147:
148: while ((QE_RCSR(QE_CSR_CSR) & QE_INTS) != QE_INTS)
149: ;
150: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_INTS);
151: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~(QE_INT_ENABLE|QE_ELOOP));
152: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_ILOOP);
153:
154: sc->rring[0].qe_addr_lo = (short)((int)sc->qein & 0xffff);
155: sc->rring[0].qe_addr_hi = (short)((int)sc->qein >> 16);
156: sc->rring[0].qe_buf_len=-MAXPACKETSIZE/2;
157: sc->rring[0].qe_addr_hi |= QE_VALID;
158: sc->rring[0].qe_flag=sc->rring[0].qe_status1=QE_NOTYET;
159: sc->rring[0].qe_status2=1;
160:
161: sc->rring[1].qe_addr_lo = 0;
162: sc->rring[1].qe_addr_hi = 0;
163: sc->rring[1].qe_flag=sc->rring[1].qe_status1=QE_NOTYET;
164: sc->rring[1].qe_status2=1;
165:
166: sc->tring[0].qe_addr_lo = (short)((int)sc->qeout & 0xffff);
167: sc->tring[0].qe_addr_hi = (short)((int)sc->qeout >> 16);
168: sc->tring[0].qe_buf_len=0;
169: sc->tring[0].qe_flag=sc->tring[0].qe_status1=QE_NOTYET;
170: sc->tring[0].qe_addr_hi |= QE_EOMSG|QE_VALID;
171:
172: sc->tring[1].qe_flag=sc->tring[1].qe_status1=QE_NOTYET;
173: sc->tring[1].qe_addr_lo = 0;
174: sc->tring[1].qe_addr_hi = 0;
175:
176: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_RCV_ENABLE);
177: QE_WCSR(QE_CSR_RCLL, LOWORD(sc->rring));
178: QE_WCSR(QE_CSR_RCLH, HIWORD(sc->rring));
179: }
180:
181: int
182: qe_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timeout) {
183: int len, j;
184:
185: retry:
186: for(j = 0x10000;j && (QE_RCSR(QE_CSR_CSR) & QE_RCV_INT) == 0; j--)
187: ;
188:
189: if ((QE_RCSR(QE_CSR_CSR) & QE_RCV_INT) == 0)
190: goto fail;
191:
192: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~(QE_RCV_ENABLE|QE_XMIT_INT));
193:
194: len= ((sc->rring[0].qe_status1 & QE_RBL_HI) |
195: (sc->rring[0].qe_status2 & QE_RBL_LO)) + 60;
196:
197: if (sc->rring[0].qe_status1 & 0xc000)
198: goto fail;
199:
200: if (len == 0)
201: goto retry;
202:
203: bcopy((void*)sc->qein,pkt,len);
204:
205:
206: end:
207: sc->rring[0].qe_status2 = sc->rring[1].qe_status2 = 1;
208: sc->rring[0].qe_flag=sc->rring[0].qe_status1=QE_NOTYET;
209: sc->rring[1].qe_flag=sc->rring[1].qe_status1=QE_NOTYET;
210: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_RCV_ENABLE);
211:
212: QE_WCSR(QE_CSR_RCLL, LOWORD(sc->rring));
213: QE_WCSR(QE_CSR_RCLH, HIWORD(sc->rring));
214: return len;
215:
216: fail: len = -1;
217: goto end;
218: }
219:
220: int
221: qe_put(struct iodesc *desc, void *pkt, size_t len) {
222: int j;
223:
224: bcopy(pkt, (char *)sc->qeout, len);
225: sc->tring[0].qe_buf_len=-len/2;
226: sc->tring[0].qe_flag=sc->tring[0].qe_status1=QE_NOTYET;
227: sc->tring[1].qe_flag=sc->tring[1].qe_status1=QE_NOTYET;
228:
229: QE_WCSR(QE_CSR_XMTL, LOWORD(sc->tring));
230: QE_WCSR(QE_CSR_XMTH, HIWORD(sc->tring));
231:
232: for(j = 0; (j < 0x10000) && ((QE_RCSR(QE_CSR_CSR) & QE_XMIT_INT) == 0); j++)
233: ;
234:
235: if ((QE_RCSR(QE_CSR_CSR) & QE_XMIT_INT) == 0) {
236: char eaddr[6];
237:
238: qe_init(eaddr);
239: return -1;
240: }
241: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RCV_INT);
242:
243: if (sc->tring[0].qe_status1 & 0xc000) {
244: char eaddr[6];
245:
246: qe_init(eaddr);
247: return -1;
248: }
249: return len;
250: }
251:
252: int
253: qeclose(struct open_file *nif)
254: {
255: QE_WCSR(QE_CSR_CSR, QE_RESET);
256: QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
257:
258: return 0;
259: }
CVSweb