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