Home | History | Annotate | Line # | Download | only in boot
      1 /*	$NetBSD: if_le.c,v 1.13 2017/05/22 16:59:32 ragge Exp $ */
      2 /*
      3  * Copyright (c) 1997, 1999 Ludd, University of Lule}, Sweden.
      4  * 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  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 /*
     28  * Standalone routine for MicroVAX LANCE chip.
     29  */
     30 
     31 #include <sys/param.h>
     32 #include <sys/types.h>
     33 #include <sys/queue.h>
     34 #include <sys/socket.h>
     35 
     36 #include <net/if.h>
     37 #include <net/if_ether.h>
     38 
     39 #include <netinet/in.h>
     40 #include <netinet/in_systm.h>
     41 
     42 #include <../include/sid.h>
     43 #include <../include/rpb.h>
     44 
     45 #include <lib/libsa/netif.h>
     46 #include <lib/libsa/stand.h>
     47 
     48 #include <dev/ic/lancereg.h>
     49 #include <dev/ic/am7990reg.h>
     50 
     51 #include "vaxstand.h"
     52 
     53 /*
     54  * Buffer sizes.
     55  */
     56 #define TLEN    1
     57 #define NTBUF   (1 << TLEN)
     58 #define RLEN    3
     59 #define NRBUF   (1 << RLEN)
     60 #define BUFSIZE 1518
     61 
     62 #define	QW_ALLOC(x)	(((uintptr_t)alloc((x) + 7) + 7) & ~7)
     63 
     64 static int le_get(struct iodesc *, void *, size_t, saseconds_t);
     65 static int le_put(struct iodesc *, void *, size_t);
     66 static void copyout(void *from, int dest, int len);
     67 static void copyin(int src, void *to, int len);
     68 
     69 struct netif_driver le_driver = {
     70 	0, 0, 0, 0, le_get, le_put,
     71 };
     72 
     73 /*
     74  * Init block & buffer descriptors according to DEC system
     75  * specification documentation.
     76  */
     77 struct initblock {
     78 	short	ib_mode;
     79 	char	ib_padr[6]; /* Ethernet address */
     80 	int	ib_ladrf1;
     81 	int	ib_ladrf2;
     82 	int	ib_rdr; /* Receive address */
     83 	int	ib_tdr; /* Transmit address */
     84 } *initblock = NULL;
     85 
     86 struct nireg {
     87 	volatile u_short ni_rdp;       /* data port */
     88 	volatile short ni_pad0;
     89 	volatile short ni_rap;       /* register select port */
     90 } *nireg;
     91 
     92 
     93 volatile struct	buffdesc {
     94 	int	bd_adrflg;
     95 	short	bd_bcnt;
     96 	short	bd_mcnt;
     97 } *rdesc, *tdesc;
     98 
     99 static	int addoff, kopiera = 0;
    100 
    101 /* Flags in the address field */
    102 #define	BR_OWN	0x80000000
    103 #define	BR_ERR	0x40000000
    104 #define	BR_FRAM	0x20000000
    105 #define	BR_OFLO	0x10000000
    106 #define	BR_CRC	0x08000000
    107 #define	BR_BUFF	0x04000000
    108 #define	BR_STP	0x02000000
    109 #define	BR_ENP	0x01000000
    110 
    111 #define	BT_OWN	0x80000000
    112 #define	BT_ERR	0x40000000
    113 #define	BT_MORE	0x10000000
    114 #define	BT_ONE	0x08000000
    115 #define	BT_DEF	0x04000000
    116 #define	BT_STP	0x02000000
    117 #define	BT_ENP	0x01000000
    118 
    119 int	next_rdesc, next_tdesc;
    120 
    121 #define	LEWRCSR(port, val) { \
    122 	nireg->ni_rap = (port); \
    123 	nireg->ni_rdp = (val); \
    124 }
    125 
    126 #define	LERDCSR(port) \
    127 	(nireg->ni_rap = port, nireg->ni_rdp)
    128 
    129 int
    130 leopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
    131 {
    132 	int i, *ea;
    133 	volatile int to = 100000;
    134 	u_char eaddr[6];
    135 
    136 	next_rdesc = next_tdesc = 0;
    137 
    138 	if (vax_boardtype == VAX_BTYP_650 &&
    139 	    ((vax_siedata >> 8) & 0xff) == VAX_SIE_KA640) {
    140 		kopiera = 1;
    141 		ea = (void *)0x20084200;
    142 		nireg = (void *)0x20084400;
    143 	} else {
    144 		*(int *)0x20080014 = 0; /* Be sure we do DMA in low 16MB */
    145 		ea = (void *)0x20090000; /* XXX ethernetaddress */
    146 		nireg = (void *)0x200e0000;
    147 	}
    148 	if (askname == 0) /* Override if autoboot */
    149 		nireg = (void *)bootrpb.csrphy;
    150 	else /* Tell kernel from where we booted */
    151 		bootrpb.csrphy = (int)nireg;
    152 
    153 	if (vax_boardtype == VAX_BTYP_43)
    154 		addoff = 0x28000000;
    155 	else
    156 		addoff = 0;
    157 igen:
    158 	LEWRCSR(LE_CSR0, LE_C0_STOP);
    159 	while (to--)
    160 		;
    161 
    162 	for (i = 0; i < 6; i++)
    163 		eaddr[i] = ea[i] & 0377;
    164 
    165 	if (initblock == NULL) {
    166 		initblock = (struct initblock *)
    167 			(QW_ALLOC(sizeof(struct initblock)) + addoff);
    168 		initblock->ib_mode = LE_MODE_NORMAL;
    169 		memcpy(initblock->ib_padr, eaddr, 6);
    170 		initblock->ib_ladrf1 = 0;
    171 		initblock->ib_ladrf2 = 0;
    172 
    173 		rdesc = (struct buffdesc *)
    174 			(QW_ALLOC(sizeof(struct buffdesc) * NRBUF) + addoff);
    175 		initblock->ib_rdr = (RLEN << 29) | (int)rdesc;
    176 		if (kopiera)
    177 			initblock->ib_rdr -= (int)initblock;
    178 		tdesc = (struct buffdesc *)
    179 			(QW_ALLOC(sizeof(struct buffdesc) * NTBUF) + addoff);
    180 		initblock->ib_tdr = (TLEN << 29) | (int)tdesc;
    181 		if (kopiera)
    182 			initblock->ib_tdr -= (int)initblock;
    183 		if (kopiera)
    184 			copyout(initblock, 0, sizeof(struct initblock));
    185 
    186 		for (i = 0; i < NRBUF; i++) {
    187 			rdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE) | BR_OWN;
    188 			if (kopiera)
    189 				rdesc[i].bd_adrflg -= (int)initblock;
    190 			rdesc[i].bd_bcnt = -BUFSIZE;
    191 			rdesc[i].bd_mcnt = 0;
    192 		}
    193 		if (kopiera)
    194 			copyout((void *)rdesc, (int)rdesc - (int)initblock,
    195 			    sizeof(struct buffdesc) * NRBUF);
    196 
    197 		for (i = 0; i < NTBUF; i++) {
    198 			tdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE);
    199 			if (kopiera)
    200 				tdesc[i].bd_adrflg -= (int)initblock;
    201 			tdesc[i].bd_bcnt = 0xf000;
    202 			tdesc[i].bd_mcnt = 0;
    203 		}
    204 		if (kopiera)
    205 			copyout((void *)tdesc, (int)tdesc - (int)initblock,
    206 			    sizeof(struct buffdesc) * NTBUF);
    207 	}
    208 
    209 	if (kopiera) {
    210 		LEWRCSR(LE_CSR1, 0);
    211 		LEWRCSR(LE_CSR2, 0);
    212 	} else {
    213 		LEWRCSR(LE_CSR1, (int)initblock & 0xffff);
    214 		LEWRCSR(LE_CSR2, ((int)initblock >> 16) & 0xff);
    215 	}
    216 
    217 	LEWRCSR(LE_CSR0, LE_C0_INIT);
    218 
    219 	to = 100000;
    220 	while (to--) {
    221 		if (LERDCSR(LE_CSR0) & LE_C0_IDON)
    222 			break;
    223 		if (LERDCSR(LE_CSR0) & LE_C0_ERR) {
    224 			printf("lance init error: csr0 %x\n", LERDCSR(LE_CSR0));
    225 			goto igen;
    226 		}
    227 	}
    228 
    229 	LEWRCSR(LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON);
    230 
    231 	net_devinit(f, &le_driver, eaddr);
    232 	return 0;
    233 }
    234 
    235 int
    236 le_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timeout)
    237 {
    238 	int csr, len;
    239 	volatile int to = 100000 * timeout;
    240 
    241 retry:
    242 	if (to-- == 0)
    243 		return 0;
    244 
    245 	csr = LERDCSR(LE_CSR0);
    246 	LEWRCSR(LE_CSR0, csr & (LE_C0_BABL|LE_C0_MISS|LE_C0_MERR|LE_C0_RINT));
    247 
    248 	if (kopiera)
    249 		copyin((int)&rdesc[next_rdesc] - (int)initblock,
    250 		    (void *)&rdesc[next_rdesc], sizeof(struct buffdesc));
    251 	if (rdesc[next_rdesc].bd_adrflg & BR_OWN)
    252 		goto retry;
    253 
    254         if (rdesc[next_rdesc].bd_adrflg & BR_ERR)
    255                 len = 0;
    256         else {
    257 		if ((len = rdesc[next_rdesc].bd_mcnt - 4) > maxlen)
    258 			len = maxlen;
    259 
    260 		if (kopiera)
    261 			copyin((rdesc[next_rdesc].bd_adrflg&0xffffff),
    262 			    pkt, len);
    263 		else
    264 			memcpy(pkt,
    265 			    (char *)(rdesc[next_rdesc].bd_adrflg&0xffffff) +
    266 			    addoff, len);
    267 	}
    268 
    269 	rdesc[next_rdesc].bd_mcnt = 0;
    270 	rdesc[next_rdesc].bd_adrflg |= BR_OWN;
    271 	if (kopiera)
    272 		copyout((void *)&rdesc[next_rdesc], (int)&rdesc[next_rdesc] -
    273 		    (int)initblock, sizeof(struct buffdesc));
    274 	if (++next_rdesc >= NRBUF)
    275 		next_rdesc = 0;
    276 
    277 
    278 	if (len == 0)
    279 		goto retry;
    280 	return len;
    281 }
    282 
    283 int
    284 le_put(struct iodesc *desc, void *pkt, size_t len)
    285 {
    286 	volatile int to = 100000;
    287 	int csr;
    288 
    289 retry:
    290 	if (--to == 0)
    291 		return -1;
    292 
    293 	csr = LERDCSR(LE_CSR0);
    294 	LEWRCSR(LE_CSR0, csr & (LE_C0_MISS|LE_C0_CERR|LE_C0_TINT));
    295 
    296 	if (kopiera)
    297 		copyin((int)&tdesc[next_tdesc] - (int)initblock,
    298 		    (void *)&tdesc[next_tdesc], sizeof(struct buffdesc));
    299 	if (tdesc[next_tdesc].bd_adrflg & BT_OWN)
    300 		goto retry;
    301 
    302 	if (kopiera)
    303 		copyout(pkt, (tdesc[next_tdesc].bd_adrflg & 0xffffff), len);
    304 	else
    305 		memcpy((char *)(tdesc[next_tdesc].bd_adrflg & 0xffffff) +
    306 		    addoff, pkt, len);
    307 	tdesc[next_tdesc].bd_bcnt =
    308 	    (len < ETHER_MIN_LEN ? -ETHER_MIN_LEN : -len);
    309 	tdesc[next_tdesc].bd_mcnt = 0;
    310 	tdesc[next_tdesc].bd_adrflg |= BT_OWN | BT_STP | BT_ENP;
    311 	if (kopiera)
    312 		copyout((void *)&tdesc[next_tdesc], (int)&tdesc[next_tdesc] -
    313 		    (int)initblock, sizeof(struct buffdesc));
    314 
    315 	LEWRCSR(LE_CSR0, LE_C0_TDMD);
    316 
    317 	to = 100000;
    318 	while (((LERDCSR(LE_CSR0) & LE_C0_TINT) == 0) && --to)
    319 		;
    320 
    321 	LEWRCSR(LE_CSR0, LE_C0_TINT);
    322 	if (++next_tdesc >= NTBUF)
    323 		next_tdesc = 0;
    324 
    325 	if (to)
    326 		return len;
    327 
    328 	return -1;
    329 }
    330 
    331 int
    332 leclose(struct open_file *f)
    333 {
    334 	LEWRCSR(LE_CSR0, LE_C0_STOP);
    335 
    336 	return 0;
    337 }
    338 
    339 void
    340 copyout(void *f, int dest, int len)
    341 {
    342 	short *from = f;
    343 	short *toaddr;
    344 
    345 	toaddr = (short *)0x20120000 + dest;
    346 
    347 	while (len > 0) {
    348 		*toaddr = *from++;
    349 		toaddr += 2;
    350 		len -= 2;
    351 	}
    352 }
    353 
    354 void
    355 copyin(int src, void *f, int len)
    356 {
    357 	short *to = f;
    358 	short *fromaddr;
    359 
    360 	fromaddr = (short *)0x20120000 + src;
    361 
    362 	while (len > 0) {
    363 		*to++ = *fromaddr;
    364 		fromaddr += 2;
    365 		len -= 2;
    366 	}
    367 }
    368