1 /* $NetBSD: if_de.c,v 1.10 2018/03/19 15:43:45 ragge Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Ludd, University of Lule}, Sweden. 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 * Standalone routine for the DEUNA Ethernet controller. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <sys/queue.h> 33 34 #include <net/if.h> 35 #include <net/if_ether.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_dereg.h> 46 47 #include "arch/vax/include/sid.h" 48 #include "arch/vax/include/rpb.h" 49 #include "arch/vax/include/pte.h" 50 51 #include "vaxstand.h" 52 53 static int de_get(struct iodesc *, void *, size_t, saseconds_t); 54 static int de_put(struct iodesc *, void *, size_t); 55 static void dewait(char *); 56 57 struct netif_driver de_driver = { 58 0, 0, 0, 0, de_get, de_put, 59 }; 60 61 #define NRCV 8 /* allocate 8 receive descriptors */ 62 #define NXMT 4 /* and 4 transmit - must be >1 */ 63 64 struct de_cdata { 65 /* the following structures are always mapped in */ 66 struct de_pcbb dc_pcbb; /* port control block */ 67 struct de_ring dc_xrent[NXMT]; /* transmit ring entrys */ 68 struct de_ring dc_rrent[NRCV]; /* receive ring entrys */ 69 struct de_udbbuf dc_udbbuf; /* UNIBUS data buffer */ 70 char dc_rbuf[NRCV][ETHER_MAX_LEN]; 71 char dc_xbuf[NXMT][ETHER_MAX_LEN]; 72 /* end mapped area */ 73 }; 74 75 static volatile struct de_cdata *dc, *pdc; 76 static volatile char *addr; 77 static int crx, ctx; 78 #define DE_WCSR(csr, val) *(volatile u_short *)(addr + (csr)) = (val) 79 #define DE_WLOW(val) *(volatile u_char *)(addr + DE_PCSR0) = (val) 80 #define DE_WHIGH(val) *(volatile u_char *)(addr + DE_PCSR0 + 1) = (val) 81 #define DE_RCSR(csr) *(volatile u_short *)(addr + (csr)) 82 #define LOWORD(x) ((u_int)(x) & 0xffff) 83 #define HIWORD(x) (((u_int)(x) >> 16) & 0x3) 84 #define dereg(x) ((x) & 017777) 85 86 int 87 deopen(struct open_file *f, int adapt, int ctlr, int unit, int part) 88 { 89 int i; 90 u_char eaddr[6]; 91 92 /* point to the device in memory */ 93 if (askname == 0) /* Override if autoboot */ 94 addr = (char *)bootrpb.csrphy; 95 else { 96 addr = (char *)csrbase + dereg(0174510); 97 bootrpb.csrphy = (int)addr; 98 } 99 #ifdef DEV_DEBUG 100 printf("deopen: csrbase %x addr %p nexaddr %x\n", 101 csrbase, addr, nexaddr); 102 #endif 103 /* reset the device and wait for completion */ 104 DE_WCSR(DE_PCSR0, 0); 105 {volatile int j = 100; while (--j);} 106 DE_WCSR(DE_PCSR0, PCSR0_RSET); 107 dewait("reset"); 108 109 /* Map in the control structures and buffers */ 110 dc = alloc(sizeof(struct de_cdata)); 111 112 pdc = (struct de_cdata *)ubmap(0, (int)dc, sizeof(struct de_cdata)); 113 memset((char *)dc, 0, sizeof(struct de_cdata)); 114 115 /* Tell the DEUNA about our PCB */ 116 DE_WCSR(DE_PCSR2, LOWORD(pdc)); 117 DE_WCSR(DE_PCSR3, HIWORD(pdc)); 118 DE_WLOW(CMD_GETPCBB); 119 dewait("pcbb"); 120 121 /* Get our address */ 122 dc->dc_pcbb.pcbb0 = FC_RDPHYAD; 123 DE_WLOW(CMD_GETCMD); 124 dewait("read physaddr"); 125 memcpy(eaddr, (char *)&dc->dc_pcbb.pcbb2, 6); 126 127 /* Create and link the descriptors */ 128 for (i=0; i < NRCV; i++) { 129 volatile struct de_ring *rp = &dc->dc_rrent[i]; 130 131 rp->r_lenerr = 0; 132 rp->r_segbl = LOWORD(&pdc->dc_rbuf[i][0]); 133 rp->r_segbh = HIWORD(&pdc->dc_rbuf[i][0]); 134 rp->r_flags = RFLG_OWN; 135 rp->r_slen = ETHER_MAX_LEN; 136 } 137 for (i=0; i < NXMT; i++) { 138 volatile struct de_ring *rp = &dc->dc_xrent[i]; 139 140 rp->r_segbl = LOWORD(&pdc->dc_xbuf[i][0]); 141 rp->r_segbh = HIWORD(&pdc->dc_xbuf[i][0]); 142 rp->r_tdrerr = 0; 143 rp->r_flags = 0; 144 } 145 crx = ctx = 0; 146 147 /* set the transmit and receive ring header addresses */ 148 dc->dc_pcbb.pcbb0 = FC_WTRING; 149 dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf); 150 dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf); 151 152 dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]); 153 dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]); 154 dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t); 155 dc->dc_udbbuf.b_trlen = NXMT; 156 dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]); 157 dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]); 158 dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t); 159 dc->dc_udbbuf.b_rrlen = NRCV; 160 161 DE_WLOW(CMD_GETCMD); 162 dewait("wtring"); 163 164 dc->dc_pcbb.pcbb0 = FC_WTMODE; 165 dc->dc_pcbb.pcbb2 = MOD_DRDC|MOD_TPAD|MOD_HDX; 166 DE_WLOW(CMD_GETCMD); 167 dewait("wtmode"); 168 169 DE_WLOW(CMD_START); 170 dewait("start"); 171 172 DE_WLOW(CMD_PDMD); 173 dewait("initpoll"); 174 /* Should be running by now */ 175 176 net_devinit(f, &de_driver, eaddr); 177 178 return 0; 179 } 180 181 int 182 de_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timeout) 183 { 184 volatile int to = 100000 * timeout; 185 int len, csr0; 186 187 if ((csr0 = DE_RCSR(DE_PCSR0)) & PCSR0_INTR) 188 DE_WHIGH(csr0 >> 8); 189 retry: 190 if (to-- == 0) 191 return 0; 192 193 if (dc->dc_rrent[crx].r_flags & RFLG_OWN) 194 goto retry; 195 196 if (dc->dc_rrent[crx].r_flags & RFLG_ERRS) 197 len = 0; 198 else 199 len = dc->dc_rrent[crx].r_lenerr & RERR_MLEN; 200 201 if (len > maxlen) 202 len = maxlen; 203 if (len) 204 memcpy(pkt, (char *)&dc->dc_rbuf[crx][0], len); 205 206 dc->dc_rrent[crx].r_flags = RFLG_OWN; 207 dc->dc_rrent[crx].r_lenerr = 0; 208 #ifdef DEV_DEBUG 209 printf("Got packet: len %d idx %d maxlen %ld\n", len, crx, maxlen); 210 #endif 211 if (++crx == NRCV) 212 crx = 0; 213 214 if (len == 0) 215 goto retry; 216 return len; 217 } 218 219 220 int 221 de_put(struct iodesc *desc, void *pkt, size_t len) 222 { 223 volatile int to = 100000; 224 int csr0; 225 226 if ((csr0 = DE_RCSR(DE_PCSR0)) & PCSR0_INTR) 227 DE_WHIGH(csr0 >> 8); 228 #ifdef DEV_DEBUG 229 printf("de_put: len %ld\n", len); 230 #endif 231 retry: 232 if (to-- == 0) 233 return -1; 234 235 if (dc->dc_xrent[ctx].r_flags & RFLG_OWN) 236 goto retry; 237 238 memcpy((char *)&dc->dc_xbuf[ctx][0], pkt, len); 239 240 dc->dc_xrent[ctx].r_slen = len; 241 dc->dc_xrent[ctx].r_tdrerr = 0; 242 dc->dc_xrent[ctx].r_flags = XFLG_OWN|XFLG_STP|XFLG_ENP; 243 244 DE_WLOW(CMD_PDMD); 245 dewait("start"); 246 247 if (++ctx == NXMT) 248 ctx = 0; 249 return len; 250 } 251 252 int 253 declose(struct open_file *f) 254 { 255 DE_WCSR(DE_PCSR0, PCSR0_RSET); 256 dewait("close"); 257 return 0; 258 } 259 260 void 261 dewait(char *fn) 262 { 263 int csr0; 264 265 #ifdef DEV_DEBUG 266 printf("dewait: %s...", fn); 267 #endif 268 while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0) 269 ; 270 csr0 = DE_RCSR(DE_PCSR0); 271 DE_WHIGH(csr0 >> 8); 272 #ifdef DEV_DEBUG 273 if (csr0 & PCSR0_PCEI) 274 printf("failed! CSR0 %x", csr0); 275 else 276 printf("done"); 277 printf(", PCSR1 %x\n", DE_RCSR(DE_PCSR1)); 278 #endif 279 } 280