Annotation of sys/arch/vax/boot/boot/if_qe.c, Revision 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