1 1.5 andvar /* $NetBSD: enic.c,v 1.5 2023/01/22 21:36:12 andvar Exp $ */ 2 1.1 pooka 3 1.1 pooka /*- 4 1.1 pooka * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 1.1 pooka * All rights reserved. 6 1.1 pooka * 7 1.1 pooka * This code was written by Alessandro Forin and Neil Pittman 8 1.1 pooka * at Microsoft Research and contributed to The NetBSD Foundation 9 1.1 pooka * by Microsoft Corporation. 10 1.1 pooka * 11 1.1 pooka * Redistribution and use in source and binary forms, with or without 12 1.1 pooka * modification, are permitted provided that the following conditions 13 1.1 pooka * are met: 14 1.1 pooka * 1. Redistributions of source code must retain the above copyright 15 1.1 pooka * notice, this list of conditions and the following disclaimer. 16 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 pooka * notice, this list of conditions and the following disclaimer in the 18 1.1 pooka * documentation and/or other materials provided with the distribution. 19 1.1 pooka * 20 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 pooka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 pooka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 pooka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 pooka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 pooka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 pooka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 pooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 pooka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 pooka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 pooka * POSSIBILITY OF SUCH DAMAGE. 31 1.1 pooka */ 32 1.1 pooka 33 1.1 pooka /* -------------------------------------------------------------------------- 34 1.1 pooka * 35 1.1 pooka * Module: 36 1.1 pooka * 37 1.1 pooka * enic.c 38 1.1 pooka * 39 1.1 pooka * Purpose: 40 1.1 pooka * 41 1.1 pooka * Driver for the Microsoft eNIC (eMIPS system) Ethernet 42 1.1 pooka * 43 1.1 pooka * Author: 44 1.1 pooka * A. Forin (sandrof) 45 1.1 pooka * 46 1.1 pooka * References: 47 1.1 pooka * Internal Microsoft specifications, file eNIC_Design.docx titled 48 1.1 pooka * "eNIC: a simple Ethernet" Revision 4/30/99 49 1.1 pooka * 50 1.1 pooka * Giano simulation module, file Peripherals\enic.cpp 51 1.1 pooka * 52 1.1 pooka * Various other drivers I wrote for said hardware 53 1.1 pooka * -------------------------------------------------------------------------- 54 1.1 pooka */ 55 1.1 pooka 56 1.1 pooka #include <sys/param.h> 57 1.1 pooka #include <sys/types.h> 58 1.1 pooka 59 1.1 pooka #include <net/if_ether.h> 60 1.1 pooka #include <netinet/in.h> 61 1.1 pooka #include <netinet/in_systm.h> 62 1.1 pooka #include <netinet/ip.h> 63 1.1 pooka 64 1.1 pooka #include <lib/libsa/stand.h> 65 1.1 pooka #include <lib/libsa/net.h> 66 1.1 pooka #include <lib/libsa/netif.h> 67 1.1 pooka #include <lib/libkern/libkern.h> 68 1.1 pooka 69 1.2 martin 70 1.1 pooka #include <machine/emipsreg.h> 71 1.3 christos 72 1.3 christos #include "start.h" 73 1.3 christos #include "common.h" 74 1.3 christos 75 1.1 pooka #define the_enic ((struct _Enic *)ETHERNET_DEFAULT_ADDRESS) 76 1.1 pooka 77 1.1 pooka /* forward declarations */ 78 1.1 pooka static int enicprobe (struct netif *, void *); 79 1.1 pooka static int enicmatch (struct netif *, void *); 80 1.1 pooka static void enicinit (struct iodesc *, void *); 81 1.1 pooka static int enicget (struct iodesc *, void *, size_t, saseconds_t); 82 1.1 pooka static int enicput (struct iodesc *, void *, size_t); 83 1.1 pooka static void enicend (struct netif *); 84 1.1 pooka 85 1.1 pooka #ifdef NET_DEBUG 86 1.1 pooka static void dump_packet(void *, int); 87 1.1 pooka #endif 88 1.1 pooka 89 1.1 pooka /* BUGBUG do we have this? */ 90 1.1 pooka #define kvtophys(_v_) ((paddr_t)(_v_) & ~0x80000000) 91 1.1 pooka 92 1.1 pooka #define rpostone(_r_,_p_,_s_) \ 93 1.1 pooka (_r_)->SizeAndFlags = ES_F_RECV | (_s_); \ 94 1.1 pooka (_r_)->BufferAddressHi32 = 0; \ 95 1.1 pooka (_r_)->BufferAddressLo32 = _p_; 96 1.1 pooka #define tpostone(_r_,_p_,_s_) \ 97 1.1 pooka (_r_)->SizeAndFlags = ES_F_XMIT | (_s_); \ 98 1.1 pooka (_r_)->BufferAddressHi32 = 0; \ 99 1.1 pooka (_r_)->BufferAddressLo32 = _p_; 100 1.1 pooka 101 1.1 pooka 102 1.1 pooka /* Send a packet 103 1.1 pooka */ 104 1.3 christos static int 105 1.3 christos enic_putpkt(struct _Enic *regs, void *buf, int bytes) 106 1.1 pooka { 107 1.1 pooka paddr_t phys = kvtophys(buf); 108 1.1 pooka 109 1.1 pooka tpostone(regs,phys,bytes); 110 1.1 pooka 111 1.1 pooka /* poll till done? */ 112 1.1 pooka //printf("\tenic: sent %d at %x\n",bytes,phys); 113 1.1 pooka return bytes; 114 1.1 pooka } 115 1.1 pooka 116 1.1 pooka /* Get a packet 117 1.1 pooka */ 118 1.3 christos static int 119 1.3 christos enic_getpkt(struct _Enic *regs, void *buf, int bytes, int timeo) 120 1.1 pooka { 121 1.1 pooka paddr_t phys; 122 1.1 pooka unsigned int isr, saf, hi, lo, fl; 123 1.1 pooka 124 1.1 pooka phys = kvtophys(buf); 125 1.1 pooka rpostone(regs,phys,bytes); 126 1.1 pooka 127 1.1 pooka //printf("\tenic: recv %d at %x\n",bytes,phys); 128 1.1 pooka 129 1.1 pooka /* poll till we get some */ 130 1.1 pooka timeo += getsecs(); 131 1.1 pooka 132 1.1 pooka for (;;) { 133 1.1 pooka 134 1.1 pooka /* anything there? */ 135 1.1 pooka isr = regs->Control; 136 1.1 pooka 137 1.1 pooka if (isr & EC_ERROR) { 138 1.1 pooka printf("enic: internal error %x\n", isr); 139 1.1 pooka regs->Control = EC_RESET; 140 1.1 pooka break; 141 1.1 pooka } 142 1.1 pooka 143 1.1 pooka //printf("isr %x ",isr); 144 1.1 pooka 145 1.1 pooka if ((isr & (EC_DONE|EC_OF_EMPTY)) == EC_DONE) { 146 1.1 pooka 147 1.1 pooka /* beware, order matters */ 148 1.1 pooka saf = regs->SizeAndFlags; 149 1.3 christos hi = regs->BufferAddressHi32; /* BUGBUG 64bit */ 150 1.3 christos lo = regs->BufferAddressLo32; /* this pops the fifo */ 151 1.3 christos __USE(hi); 152 1.1 pooka 153 1.1 pooka fl = saf & (ES_F_MASK &~ ES_F_DONE); 154 1.1 pooka 155 1.1 pooka if (fl == ES_F_RECV) 156 1.1 pooka { 157 1.1 pooka /* and we are done? */ 158 1.1 pooka if (phys == lo) 159 1.1 pooka return saf & ES_S_MASK; 160 1.1 pooka } else if (fl == ES_F_XMIT) 161 1.1 pooka { 162 1.1 pooka ;/* nothing */ 163 1.1 pooka } else if (fl != ES_F_CMD) 164 1.1 pooka { 165 1.2 martin printf("enic: invalid saf=x%x (lo=%x, hi=%x)\n", saf, lo, hi); 166 1.1 pooka } 167 1.1 pooka } 168 1.1 pooka 169 1.1 pooka if (getsecs() >= timeo) { 170 1.1 pooka //printf("enic: timeout\n"); 171 1.1 pooka regs->Control = EC_RESET; 172 1.1 pooka break; 173 1.1 pooka } 174 1.1 pooka } 175 1.1 pooka 176 1.1 pooka return 0; 177 1.1 pooka } 178 1.1 pooka 179 1.1 pooka /* 180 1.1 pooka */ 181 1.1 pooka static int enic_getmac(struct _Enic *regs, uint8_t *mac) 182 1.1 pooka { 183 1.1 pooka uint8_t buffer[8]; 184 1.1 pooka paddr_t phys = kvtophys(&buffer[0]); 185 1.1 pooka int i; 186 1.1 pooka 187 1.1 pooka regs->Control = EC_RESET; 188 1.1 pooka Delay(1); 189 1.3 christos regs->Control = regs->Control & (~EC_RXDIS); 190 1.1 pooka 191 1.1 pooka buffer[0] = ENIC_CMD_GET_ADDRESS; 192 1.1 pooka 193 1.1 pooka //printf("%x:%x:%x:%x:%x:%x\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]); 194 1.1 pooka 195 1.1 pooka regs->SizeAndFlags = (sizeof buffer) | ES_F_CMD; 196 1.1 pooka regs->BufferAddressHi32 = 0; 197 1.1 pooka regs->BufferAddressLo32 = phys; /* go! */ 198 1.1 pooka 199 1.1 pooka for (i = 0; i < 100; i++) { 200 1.1 pooka Delay(100); 201 1.1 pooka if (0 == (regs->Control & EC_OF_EMPTY)) 202 1.1 pooka break; 203 1.1 pooka } 204 1.1 pooka if (i == 100) 205 1.1 pooka return 0; 206 1.1 pooka 207 1.1 pooka //printf("%x:%x:%x:%x:%x:%x\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]); 208 1.1 pooka 209 1.1 pooka memcpy(mac,buffer,6); 210 1.1 pooka return 1; 211 1.1 pooka } 212 1.1 pooka 213 1.1 pooka /* Exported interface 214 1.1 pooka */ 215 1.3 christos int 216 1.3 christos enic_present(int unit) 217 1.1 pooka { 218 1.3 christos if ((unit != 0) || (the_enic->Tag != PMTTAG_ETHERNET)) 219 1.3 christos return 0; 220 1.1 pooka 221 1.1 pooka return 1; 222 1.1 pooka } 223 1.1 pooka 224 1.1 pooka extern int try_bootp; 225 1.1 pooka 226 1.1 pooka extern struct netif_stats enicstats[]; 227 1.1 pooka struct netif_dif enicifs[] = { 228 1.1 pooka /* dif_unit dif_nsel dif_stats dif_private */ 229 1.1 pooka { 0, 1, &enicstats[0], the_enic, }, 230 1.1 pooka }; 231 1.1 pooka #define NENICIFS (sizeof(enicifs) / sizeof(enicifs[0])) 232 1.1 pooka struct netif_stats enicstats[NENICIFS]; 233 1.1 pooka 234 1.1 pooka struct netif_driver enic_netif_driver = { 235 1.1 pooka "enic", /* netif_bname */ 236 1.1 pooka enicmatch, /* netif_match */ 237 1.1 pooka enicprobe, /* netif_probe */ 238 1.1 pooka enicinit, /* netif_init */ 239 1.1 pooka enicget, /* netif_get */ 240 1.1 pooka enicput, /* netif_put */ 241 1.1 pooka enicend, /* netif_end */ 242 1.1 pooka enicifs, /* netif_ifs */ 243 1.1 pooka NENICIFS /* netif_nifs */ 244 1.1 pooka }; 245 1.1 pooka 246 1.1 pooka static int 247 1.1 pooka enicmatch(struct netif *nif, void *machdep_hint) 248 1.1 pooka { 249 1.1 pooka return (1); 250 1.1 pooka } 251 1.1 pooka 252 1.1 pooka /* NB: We refuse anything but unit==0 253 1.1 pooka */ 254 1.1 pooka static int 255 1.1 pooka enicprobe(struct netif *nif, void *machdep_hint) 256 1.1 pooka { 257 1.1 pooka int unit = nif->nif_unit; 258 1.1 pooka #ifdef NET_DEBUG 259 1.1 pooka printf("enic%d: probe\n", unit); 260 1.1 pooka #endif 261 1.1 pooka return (enic_present(unit) ? 0 : 1); 262 1.1 pooka } 263 1.1 pooka 264 1.1 pooka static void 265 1.1 pooka enicinit(struct iodesc *desc, void *machdep_hint) 266 1.1 pooka { 267 1.1 pooka #ifdef NET_DEBUG 268 1.1 pooka struct netif *nif = (struct netif *)desc->io_netif; 269 1.1 pooka int unit = nif->nif_driver->netif_ifs->dif_unit; 270 1.1 pooka printf("enic%d: init %s\n", unit, machdep_hint); 271 1.1 pooka #endif 272 1.1 pooka 273 1.1 pooka /* 274 1.5 andvar * Yes we want DHCP and this is our MAC 275 1.1 pooka */ 276 1.1 pooka try_bootp = 1; 277 1.1 pooka enic_getmac(the_enic,desc->myea); 278 1.1 pooka desc->xid = 0xfe63d095; 279 1.1 pooka } 280 1.1 pooka 281 1.1 pooka 282 1.1 pooka static int 283 1.1 pooka enicput(struct iodesc *desc, void *pkt, size_t len) 284 1.1 pooka { 285 1.1 pooka #ifdef NET_DEBUG 286 1.1 pooka if (debug) 287 1.1 pooka dump_packet(pkt,len); 288 1.1 pooka #endif 289 1.1 pooka 290 1.1 pooka return enic_putpkt(the_enic,pkt,len); 291 1.1 pooka } 292 1.1 pooka 293 1.1 pooka 294 1.1 pooka int 295 1.1 pooka enicget(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) 296 1.1 pooka { 297 1.1 pooka #ifdef NET_DEBUG 298 1.1 pooka printf("enicget: %lx %lx\n",len,timeout); 299 1.1 pooka #endif 300 1.1 pooka return enic_getpkt(the_enic,pkt,len,timeout); 301 1.1 pooka } 302 1.1 pooka 303 1.1 pooka 304 1.1 pooka static void 305 1.1 pooka enicend(struct netif *nif) 306 1.1 pooka { 307 1.1 pooka /* BUGBUG stop it in reset? */ 308 1.1 pooka } 309 1.1 pooka 310 1.1 pooka #ifdef NET_DEBUG 311 1.1 pooka static void dump_packet(void *pkt, int len) 312 1.1 pooka { 313 1.1 pooka struct ether_header *eh = (struct ether_header *)pkt; 314 1.1 pooka struct ip *ih = (struct ip *)(eh + 1); 315 1.1 pooka 316 1.1 pooka printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost)); 317 1.1 pooka printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost)); 318 1.1 pooka printf("ether_type = 0x%x\n", ntohs(eh->ether_type)); 319 1.1 pooka 320 1.1 pooka if (ntohs(eh->ether_type) == 0x0800) { 321 1.1 pooka printf("ip packet version %d\n", ih->ip_v); 322 1.1 pooka printf("source ip: 0x%x\n", ih->ip_src.s_addr); 323 1.1 pooka printf("dest ip: 0x%x\n", ih->ip_dst.s_addr); 324 1.1 pooka 325 1.1 pooka } 326 1.1 pooka } 327 1.1 pooka #endif 328