Home | History | Annotate | Line # | Download | only in boot
      1 /*	$NetBSD: if_qe.c,v 1.10 2018/03/20 13:30:40 ragge Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1998 Roar Throns.  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 Throns.
     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