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 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 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 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 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 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