1 1.57 andvar /* $NetBSD: if_ie.c,v 1.57 2025/08/18 20:59:55 andvar Exp $ */ 2 1.1 reinoud 3 1.1 reinoud /* 4 1.1 reinoud * Copyright (c) 1995 Melvin Tang-Richardson. 5 1.1 reinoud * All rights reserved. 6 1.1 reinoud * 7 1.1 reinoud * This driver is a major hash up of src/sys/dev/isa/if_ie.c and 8 1.1 reinoud * src/sys/arch/acorn32/podulebus/kgdb_ie.c Please refer to copyright 9 1.1 reinoud * notices from them too. 10 1.1 reinoud * 11 1.1 reinoud * Redistribution and use in source and binary forms, with or without 12 1.1 reinoud * modification, are permitted provided that the following conditions 13 1.1 reinoud * are met: 14 1.1 reinoud * 1. Redistributions of source code must retain the above copyright 15 1.1 reinoud * notice, this list of conditions and the following disclaimer. 16 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 reinoud * notice, this list of conditions and the following disclaimer in the 18 1.1 reinoud * documentation and/or other materials provided with the distribution. 19 1.1 reinoud * 3. All advertising materials mentioning features or use of this software 20 1.1 reinoud * must display the following acknowledgement: 21 1.1 reinoud * This product includes software developed by RiscBSD. 22 1.1 reinoud * 4. The name of the company nor the name of the author may be used to 23 1.1 reinoud * endorse or promote products derived from this software without specific 24 1.1 reinoud * prior written permission. 25 1.1 reinoud * 26 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED 27 1.1 reinoud * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 1.1 reinoud * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 1.1 reinoud * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 30 1.1 reinoud * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 1.1 reinoud * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 1.1 reinoud * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 1.1 reinoud * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 1.1 reinoud * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 1.1 reinoud * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 1.1 reinoud * SUCH DAMAGE. 37 1.1 reinoud * 38 1.1 reinoud * RiscBSD kernel project 39 1.1 reinoud * 40 1.1 reinoud * if_ie.c 41 1.1 reinoud * 42 1.1 reinoud * Ether 1 podule driver 43 1.1 reinoud * 44 1.1 reinoud * Created : 26/06/95 45 1.1 reinoud */ 46 1.1 reinoud 47 1.1 reinoud /* 48 1.33 snj * This driver is at its last beta release. It should not cause 49 1.1 reinoud * any problems (Touch wood) 50 1.1 reinoud * 51 1.1 reinoud * If it passes field tests again. This will constitute the realse 52 1.1 reinoud * version. 53 1.1 reinoud */ 54 1.1 reinoud 55 1.13 lukem #include <sys/cdefs.h> 56 1.57 andvar __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.57 2025/08/18 20:59:55 andvar Exp $"); 57 1.13 lukem 58 1.1 reinoud #define IGNORE_ETHER1_IDROM_CHECKSUM 59 1.1 reinoud 60 1.1 reinoud /* Standard podule includes */ 61 1.1 reinoud 62 1.1 reinoud #include "opt_inet.h" 63 1.1 reinoud #include "opt_ns.h" 64 1.1 reinoud 65 1.1 reinoud #include <sys/param.h> 66 1.5 bjh21 67 1.1 reinoud #include <sys/systm.h> 68 1.1 reinoud #include <sys/kernel.h> 69 1.1 reinoud #include <sys/conf.h> 70 1.1 reinoud #include <sys/device.h> 71 1.1 reinoud #include <machine/io.h> 72 1.3 thorpej #include <machine/intr.h> 73 1.1 reinoud #include <acorn32/podulebus/podulebus.h> 74 1.1 reinoud #include <dev/podulebus/podules.h> 75 1.1 reinoud 76 1.1 reinoud /* Include for interface to the net and ethernet subsystems */ 77 1.1 reinoud 78 1.1 reinoud #include <sys/socket.h> 79 1.1 reinoud #include <sys/syslog.h> 80 1.1 reinoud #include <sys/ioctl.h> 81 1.1 reinoud #include <sys/mbuf.h> 82 1.1 reinoud 83 1.1 reinoud #include <net/if.h> 84 1.1 reinoud #include <net/if_types.h> 85 1.1 reinoud #include <net/if_dl.h> 86 1.1 reinoud #include <net/if_ether.h> 87 1.1 reinoud 88 1.1 reinoud #ifdef INET 89 1.1 reinoud #include <netinet/in.h> 90 1.1 reinoud #include <netinet/in_systm.h> 91 1.1 reinoud #include <netinet/in_var.h> 92 1.1 reinoud #include <netinet/ip.h> 93 1.1 reinoud #include <netinet/if_inarp.h> 94 1.1 reinoud #endif 95 1.1 reinoud 96 1.49 andvar /* Import our data structures */ 97 1.1 reinoud 98 1.1 reinoud #include "if_iereg.h" 99 1.1 reinoud 100 1.1 reinoud /* BPF support */ 101 1.1 reinoud 102 1.1 reinoud #include <net/bpf.h> 103 1.1 reinoud 104 1.1 reinoud /* Some useful defines and macros */ 105 1.1 reinoud 106 1.1 reinoud #define PODULE_IRQ_PENDING (1) 107 1.1 reinoud #define NFRAMES (16) /* number of frame to allow for receive */ 108 1.1 reinoud #define NRXBUF (48) /* number of receive buffers to allocate */ 109 1.1 reinoud #define IE_RXBUF_SIZE (256) /* receive buf size */ 110 1.1 reinoud #define NTXBUF (2) /* number of transmit buffers to allocate */ 111 1.1 reinoud #define IE_TXBUF_SIZE (1522) /* size of tx buffer */ 112 1.1 reinoud 113 1.1 reinoud #define PWriteShort(a,b) WriteWord(a,(b)<<16|(b)) 114 1.1 reinoud 115 1.1 reinoud #define xoffsetof(type, member) (offsetof(type, member) << 1) 116 1.1 reinoud 117 1.51 msaitoh /* Some data structures local to this file */ 118 1.1 reinoud 119 1.1 reinoud struct ie_softc { 120 1.32 chs device_t sc_dev; 121 1.1 reinoud int sc_podule_number; 122 1.1 reinoud podule_t *sc_podule; 123 1.1 reinoud irqhandler_t sc_ih; 124 1.1 reinoud int sc_flags; 125 1.1 reinoud #define IE_BROKEN 1 126 1.1 reinoud int sc_iobase; 127 1.1 reinoud int sc_fastbase; 128 1.1 reinoud int sc_rom; 129 1.1 reinoud int sc_ram; 130 1.1 reinoud int sc_control; 131 1.1 reinoud struct ethercom sc_ethercom; 132 1.44 msaitoh u_short promisc; 133 1.1 reinoud int sc_irqmode; 134 1.1 reinoud 135 1.1 reinoud u_long rframes[NFRAMES]; 136 1.1 reinoud u_long rbuffs[NRXBUF]; 137 1.1 reinoud u_long cbuffs[NRXBUF]; 138 1.1 reinoud int rfhead, rftail, rbhead, rbtail; 139 1.1 reinoud 140 1.1 reinoud u_long xmit_cmds[NTXBUF]; 141 1.1 reinoud u_long xmit_buffs[NTXBUF]; 142 1.1 reinoud u_long xmit_cbuffs[NTXBUF]; 143 1.1 reinoud int xmit_count; 144 1.1 reinoud int xmit_free; 145 1.1 reinoud int xchead; 146 1.1 reinoud int xctail; 147 1.1 reinoud }; 148 1.1 reinoud 149 1.1 reinoud /* Function and data prototypes */ 150 1.1 reinoud 151 1.21 dsl static void host2ie( struct ie_softc *sc, void *src, u_long dest, int size ); 152 1.21 dsl static void ie2host( struct ie_softc *sc, u_long src, void *dest, int size ); 153 1.21 dsl static void iezero( struct ie_softc *sc, u_long p, int size ); 154 1.21 dsl void iereset( struct ie_softc *sc ); 155 1.21 dsl void iewatchdog( struct ifnet *ifp ); 156 1.21 dsl int ieioctl( struct ifnet *ifp, u_long cmd, void *data ); 157 1.21 dsl void iestart( struct ifnet *ifp ); 158 1.21 dsl int iestop( struct ie_softc *sc ); 159 1.21 dsl int ieinit( struct ie_softc *sc ); 160 1.21 dsl int ieintr( void *arg ); 161 1.21 dsl void ietint( struct ie_softc *sc ); 162 1.1 reinoud 163 1.1 reinoud /* A whopper of a function */ 164 1.21 dsl static int command_and_wait( struct ie_softc *sc, u_short cmd, 165 1.1 reinoud struct ie_sys_ctl_block *pscb, 166 1.21 dsl void *pcmd, int ocmd, int scmd, int mask ); 167 1.1 reinoud 168 1.30 matt int ieprobe(device_t, cfdata_t, void *); 169 1.30 matt void ieattach(device_t, device_t, void *); 170 1.1 reinoud 171 1.15 perry static inline void ie_cli(struct ie_softc *); 172 1.15 perry static inline void ieattn(struct ie_softc *); 173 1.15 perry static inline void setpage(struct ie_softc *, u_long); 174 1.5 bjh21 static void ie_ack(struct ie_softc *, u_short); 175 1.5 bjh21 void PWriteShorts(char *, char *, int); 176 1.5 bjh21 void ReadShorts(char *, char *, int); 177 1.5 bjh21 static void run_tdr(struct ie_softc *); 178 1.5 bjh21 u_long setup_rfa(struct ie_softc *, u_long); 179 1.15 perry static inline int ie_buflen(struct ie_softc *, int); 180 1.15 perry static inline int ie_packet_len(struct ie_softc *); 181 1.5 bjh21 struct mbuf *ieget(struct ie_softc *, int *); 182 1.5 bjh21 void ie_drop_packet_buffer(struct ie_softc *); 183 1.5 bjh21 void ie_read_frame(struct ie_softc *, int num); 184 1.5 bjh21 void ierint(struct ie_softc *); 185 1.5 bjh21 void iexmit(struct ie_softc *); 186 1.5 bjh21 static void start_receiver(struct ie_softc *); 187 1.5 bjh21 188 1.5 bjh21 189 1.1 reinoud /* 190 1.1 reinoud * Our cfattach structure for the autoconfig system to chew on 191 1.1 reinoud */ 192 1.1 reinoud 193 1.32 chs CFATTACH_DECL_NEW(ie, sizeof(struct ie_softc), 194 1.10 thorpej ieprobe, ieattach, NULL, NULL); 195 1.1 reinoud 196 1.1 reinoud /* Let's go! */ 197 1.1 reinoud 198 1.1 reinoud /* 199 1.1 reinoud * Clear all pending interrupts from the i82586 chip 200 1.1 reinoud */ 201 1.1 reinoud 202 1.15 perry static inline void 203 1.22 dsl ie_cli(struct ie_softc *sc) 204 1.1 reinoud { 205 1.1 reinoud WriteByte(sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI); 206 1.1 reinoud } 207 1.1 reinoud 208 1.46 skrll /* 209 1.1 reinoud * Wake the i82586 chip up and get it to do something 210 1.1 reinoud */ 211 1.1 reinoud 212 1.15 perry static inline void 213 1.22 dsl ieattn(struct ie_softc *sc) 214 1.1 reinoud { 215 1.1 reinoud WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN ); 216 1.1 reinoud } 217 1.1 reinoud 218 1.1 reinoud /* 219 1.1 reinoud * Set the podule page register to bring a given address into view 220 1.1 reinoud */ 221 1.1 reinoud 222 1.15 perry static inline void 223 1.22 dsl setpage(struct ie_softc *sc, u_long off) 224 1.1 reinoud { 225 1.1 reinoud WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) ); 226 1.1 reinoud } 227 1.1 reinoud 228 1.1 reinoud /* 229 1.1 reinoud * Ack the i82586 230 1.1 reinoud */ 231 1.1 reinoud 232 1.1 reinoud static void 233 1.22 dsl ie_ack(struct ie_softc *sc, u_short mask) 234 1.1 reinoud { 235 1.1 reinoud u_short stat; 236 1.1 reinoud int i; 237 1.1 reinoud setpage(sc, IE_IBASE + IE_SCB_OFF ); 238 1.1 reinoud 239 1.1 reinoud stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 240 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 241 1.1 reinoud 242 1.1 reinoud PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 243 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_command)), 244 1.1 reinoud stat & mask ); 245 1.1 reinoud 246 1.1 reinoud ieattn(sc); 247 1.1 reinoud 248 1.1 reinoud for ( i=4000; --i>=0; ) { 249 1.1 reinoud if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 250 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_command))) ) 251 1.1 reinoud break; 252 1.1 reinoud delay(100); 253 1.1 reinoud } 254 1.1 reinoud 255 1.1 reinoud if ( i<=0 ) 256 1.1 reinoud printf ( "ie: command timed out\n" ); 257 1.1 reinoud ie_cli(sc); 258 1.1 reinoud } 259 1.1 reinoud 260 1.1 reinoud /* 261 1.1 reinoud * This routine does the checksumming for the idrom 262 1.1 reinoud */ 263 1.1 reinoud 264 1.1 reinoud #ifndef IGNORE_ETHER1_IDROM_CHECKSUM 265 1.1 reinoud static u_long 266 1.22 dsl crc32(u_char *p, int l) 267 1.1 reinoud { 268 1.1 reinoud u_long crc=-1; 269 1.1 reinoud int i, b; 270 1.1 reinoud while ( --l >= 0 ) { 271 1.1 reinoud b = *p++; 272 1.1 reinoud for ( i=8; --i >= 0; b>>=1 ) 273 1.1 reinoud if ((b&1)^(crc>>31)) 274 1.1 reinoud crc=(crc<<1)^0x4c11db7; 275 1.1 reinoud else 276 1.1 reinoud crc<<=1; 277 1.1 reinoud } 278 1.1 reinoud return crc; 279 1.1 reinoud } 280 1.1 reinoud #endif 281 1.1 reinoud 282 1.1 reinoud /* 283 1.1 reinoud * Probe for the ether1 card. return 1 on success 0 on failure 284 1.1 reinoud */ 285 1.1 reinoud 286 1.1 reinoud int 287 1.30 matt ieprobe(device_t parent, cfdata_t cf, void *aux) 288 1.1 reinoud { 289 1.30 matt struct podule_attach_args *pa = aux; 290 1.1 reinoud 291 1.1 reinoud /* Look for a network slot interface */ 292 1.1 reinoud 293 1.6 bjh21 return (pa->pa_product == PODULE_ETHER1); 294 1.1 reinoud } 295 1.1 reinoud 296 1.1 reinoud /* 297 1.1 reinoud * Attach our driver to the interfaces it uses 298 1.1 reinoud */ 299 1.46 skrll 300 1.32 chs void 301 1.32 chs ieattach(device_t parent, device_t self, void *aux) 302 1.1 reinoud { 303 1.30 matt struct ie_softc *sc = device_private(self); 304 1.30 matt struct podule_attach_args *pa = aux; 305 1.1 reinoud struct ifnet *ifp = &sc->sc_ethercom.ec_if; 306 1.1 reinoud int i; 307 1.1 reinoud char idrom[32]; 308 1.31 skrll uint8_t hwaddr[ETHER_ADDR_LEN]; 309 1.1 reinoud 310 1.1 reinoud /* Check a few things about the attach args */ 311 1.1 reinoud 312 1.1 reinoud if (pa->pa_podule_number == -1) 313 1.1 reinoud panic("Podule has disappeared !"); 314 1.1 reinoud 315 1.32 chs sc->sc_dev = self; 316 1.1 reinoud sc->sc_podule_number = pa->pa_podule_number; 317 1.1 reinoud sc->sc_podule = pa->pa_podule; 318 1.1 reinoud podules[sc->sc_podule_number].attached = 1; 319 1.1 reinoud 320 1.1 reinoud /* 321 1.1 reinoud * MESS MESS MESS 322 1.1 reinoud * 323 1.1 reinoud * This needs a serious clean up. Alot of this code was in the probe function 324 1.1 reinoud * but required the softc structure. As a temporary measure until I rewrite it 325 1.1 reinoud * I have just bolted in the probe code here. 326 1.1 reinoud */ 327 1.1 reinoud 328 1.1 reinoud /* Index some podule areas */ 329 1.1 reinoud sc->sc_iobase = sc->sc_podule->sync_base; /* OBSOLETE */ 330 1.1 reinoud sc->sc_fastbase = sc->sc_podule->fast_base; /* OBSOLETE */ 331 1.1 reinoud sc->sc_rom = sc->sc_podule->sync_base; 332 1.1 reinoud sc->sc_control = sc->sc_podule->fast_base; 333 1.1 reinoud sc->sc_ram = sc->sc_podule->fast_base + IE_MEMOFF; 334 1.1 reinoud 335 1.1 reinoud /* Set the page mask to something know and neutral */ 336 1.1 reinoud setpage(sc, IE_SCB_OFF); 337 1.1 reinoud 338 1.1 reinoud /* Fetch the first part of the idrom */ 339 1.1 reinoud for ( i=0; i<16; i++ ) 340 1.1 reinoud idrom[i] = ReadByte ( sc->sc_rom + (i<<2) ); 341 1.1 reinoud 342 1.1 reinoud /* Verify the podulebus probe incase RiscOS lied */ 343 1.1 reinoud if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) { 344 1.52 andvar printf(": Ether1 ROM probably broken. ECID corrupt\n"); 345 1.1 reinoud sc->sc_flags |= IE_BROKEN; 346 1.1 reinoud return; 347 1.1 reinoud } 348 1.1 reinoud 349 1.1 reinoud /* Reset the 82586 */ 350 1.1 reinoud WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET ); 351 1.1 reinoud delay(1000); 352 1.1 reinoud WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 ); 353 1.1 reinoud delay(10000); 354 1.1 reinoud 355 1.1 reinoud /* Clear pending interrupts */ 356 1.1 reinoud ie_cli (sc); 357 1.1 reinoud 358 1.1 reinoud /* Setup SCP */ 359 1.1 reinoud { 360 1.1 reinoud struct ie_sys_conf_ptr scp; 361 1.1 reinoud bzero (&scp, sizeof(scp) ); 362 1.17 christos scp.ie_iscp_ptr = (void *)IE_ISCP_ADDR; 363 1.1 reinoud host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) ); 364 1.1 reinoud } 365 1.1 reinoud 366 1.1 reinoud /* Setup ISCP */ 367 1.1 reinoud { 368 1.1 reinoud struct ie_int_sys_conf_ptr iscp; 369 1.1 reinoud bzero ( &iscp, sizeof(iscp) ); 370 1.1 reinoud iscp.ie_busy = 1; 371 1.17 christos iscp.ie_base = (void *)IE_IBASE; 372 1.1 reinoud iscp.ie_scb_offset = IE_SCB_OFF; 373 1.1 reinoud host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) ); 374 1.1 reinoud } 375 1.1 reinoud 376 1.1 reinoud /* Initialise the control block */ 377 1.1 reinoud iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) ); 378 1.1 reinoud ieattn(sc); 379 1.1 reinoud 380 1.1 reinoud /* Wait for not busy */ 381 1.1 reinoud setpage ( sc, IE_ISCP_ADDR ); 382 1.1 reinoud for ( i=10000; --i>=0; ) { 383 1.1 reinoud if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) + 384 1.1 reinoud ( xoffsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) ) 385 1.1 reinoud break; 386 1.1 reinoud delay (10); 387 1.1 reinoud } 388 1.1 reinoud 389 1.1 reinoud /* If the busy didn't go low, the i82586 is broken or too slow */ 390 1.1 reinoud if ( i<=0 ) { 391 1.1 reinoud printf ( ": ether1 chipset didn't respond\n" ); 392 1.1 reinoud sc->sc_flags |= IE_BROKEN; 393 1.1 reinoud return; 394 1.1 reinoud } 395 1.1 reinoud 396 1.1 reinoud /* Ensure that the podule sends interrupts */ 397 1.1 reinoud for ( i=1000; --i>=0 ; ) { 398 1.1 reinoud if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING ) 399 1.1 reinoud break; 400 1.1 reinoud delay (10); 401 1.1 reinoud } 402 1.1 reinoud 403 1.1 reinoud /* If we didn't see the interrupt then the IRQ line is broken */ 404 1.1 reinoud if ( i<=0 ) { 405 1.1 reinoud printf ( ": interrupt from chipset didn't reach host\n" ); 406 1.1 reinoud sc->sc_flags |= IE_BROKEN; 407 1.1 reinoud return; 408 1.1 reinoud } 409 1.1 reinoud 410 1.1 reinoud /* Ack our little test operation */ 411 1.1 reinoud ie_ack(sc,IE_ST_WHENCE); 412 1.1 reinoud ie_cli (sc); 413 1.1 reinoud 414 1.1 reinoud /* Get second part of idrom */ 415 1.1 reinoud for ( i=16; i<32; i++ ) 416 1.1 reinoud idrom[i] = ReadByte ( sc->sc_rom + (i<<2) ); 417 1.1 reinoud 418 1.1 reinoud /* This checksum always fails. For some reason the first 16 */ 419 1.1 reinoud /* bytes are duplicated in the second 16 bytes, the checksum */ 420 1.1 reinoud /* should be at location 28 it is clearly not */ 421 1.1 reinoud 422 1.1 reinoud /* It is possible that this ether1 card is buggered */ 423 1.1 reinoud 424 1.1 reinoud #ifndef IGNORE_ETHER1_IDROM_CHECKSUM 425 1.1 reinoud if ( crc32(idrom,28) != *(u_long *)(idrom+28) ) 426 1.1 reinoud { 427 1.1 reinoud printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n", 428 1.1 reinoud crc32(idrom,28), *(u_long *)(idrom+28)); 429 1.1 reinoud for ( i=0; i<32; i+=8 ) { 430 1.1 reinoud printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n", 431 1.46 skrll idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i], 432 1.1 reinoud idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] ); 433 1.1 reinoud } 434 1.1 reinoud printf ( "ie: I'll ignore this fact for now!\n" ); 435 1.1 reinoud } 436 1.1 reinoud #endif 437 1.1 reinoud 438 1.1 reinoud /* Get our ethernet address. Do explicit copy */ 439 1.1 reinoud for ( i=0; i<ETHER_ADDR_LEN; i++ ) 440 1.1 reinoud hwaddr[i] = idrom[9+i]; 441 1.1 reinoud 442 1.1 reinoud /* Fill in my application form to attach to the inet system */ 443 1.1 reinoud 444 1.32 chs memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 445 1.1 reinoud ifp->if_softc = sc; 446 1.1 reinoud ifp->if_start = iestart; 447 1.1 reinoud ifp->if_ioctl = ieioctl; 448 1.1 reinoud ifp->if_watchdog = iewatchdog; 449 1.43 msaitoh ifp->if_flags = IFF_BROADCAST; 450 1.46 skrll 451 1.1 reinoud /* Signed, dated then sent */ 452 1.1 reinoud if_attach (ifp); 453 1.39 nonaka if_deferred_start_init(ifp, NULL); 454 1.1 reinoud ether_ifattach(ifp, hwaddr); 455 1.1 reinoud 456 1.1 reinoud /* "Hmm," said nuts, "what if the attach fails" */ 457 1.46 skrll 458 1.50 andvar /* Write some pretty things on the announcement line */ 459 1.1 reinoud printf ( ": %s using %dk card ram", 460 1.1 reinoud ether_sprintf(hwaddr), 461 1.1 reinoud ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 ); 462 1.1 reinoud 463 1.1 reinoud sc->sc_ih.ih_func = ieintr; 464 1.1 reinoud sc->sc_ih.ih_arg = sc; 465 1.1 reinoud sc->sc_ih.ih_level = IPL_NET; 466 1.1 reinoud sc->sc_ih.ih_name = "net: ie"; 467 1.1 reinoud sc->sc_ih.ih_maskaddr = sc->sc_podule->irq_addr; 468 1.1 reinoud sc->sc_ih.ih_maskbits = sc->sc_podule->irq_mask; 469 1.1 reinoud 470 1.1 reinoud if (irq_claim(sc->sc_podule->interrupt, &sc->sc_ih)) { 471 1.1 reinoud sc->sc_irqmode = 0; 472 1.1 reinoud printf(" POLLED"); 473 1.32 chs panic("%s: Cannot install IRQ handler", device_xname(sc->sc_dev)); 474 1.1 reinoud } else { 475 1.1 reinoud sc->sc_irqmode = 1; 476 1.1 reinoud printf(" IRQ"); 477 1.1 reinoud } 478 1.1 reinoud 479 1.1 reinoud printf("\n"); 480 1.1 reinoud } 481 1.46 skrll 482 1.46 skrll 483 1.1 reinoud /* 484 1.1 reinoud * Oh no!! Where's my shorts!!! I'm sure I put them on this morning 485 1.1 reinoud */ 486 1.1 reinoud 487 1.1 reinoud void 488 1.22 dsl PWriteShorts(char *src, char *dest, int cnt) 489 1.1 reinoud { 490 1.1 reinoud for (cnt /= 2; --cnt >= 0; ) { 491 1.1 reinoud PWriteShort(dest, *(u_short *)src); 492 1.1 reinoud src+=2; 493 1.1 reinoud dest+=4; 494 1.1 reinoud } 495 1.1 reinoud } 496 1.1 reinoud 497 1.1 reinoud void 498 1.22 dsl ReadShorts(char *src, char *dest, int cnt) 499 1.1 reinoud { 500 1.1 reinoud for (cnt /= 2; --cnt >= 0; ) { 501 1.1 reinoud *(u_short *)dest = ReadShort(src); 502 1.1 reinoud src+=4; 503 1.1 reinoud dest+=2; 504 1.1 reinoud } 505 1.1 reinoud } 506 1.1 reinoud 507 1.1 reinoud /* 508 1.1 reinoud * A bcopy or memcpy to adapter ram. It handles the page register for you 509 1.1 reinoud * so you dont have to worry about the ram windowing 510 1.1 reinoud */ 511 1.1 reinoud 512 1.1 reinoud static void 513 1.22 dsl host2ie(struct ie_softc *sc, void *src, u_long dest, int size) 514 1.1 reinoud { 515 1.1 reinoud int cnt; 516 1.1 reinoud char *sptr = src; 517 1.1 reinoud 518 1.1 reinoud #ifdef DIAGNOSTIC 519 1.1 reinoud if (size & 1) 520 1.1 reinoud panic("host2ie"); 521 1.1 reinoud #endif 522 1.1 reinoud 523 1.1 reinoud while (size > 0) { 524 1.1 reinoud cnt = IE_PAGESIZE - dest % IE_PAGESIZE; 525 1.1 reinoud if (cnt > size) 526 1.1 reinoud cnt = size; 527 1.1 reinoud setpage(sc, dest); 528 1.1 reinoud PWriteShorts(sptr, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt); 529 1.1 reinoud sptr+=cnt; 530 1.1 reinoud dest+=cnt; 531 1.1 reinoud size-=cnt; 532 1.1 reinoud } 533 1.1 reinoud } 534 1.1 reinoud 535 1.1 reinoud static void 536 1.22 dsl ie2host(struct ie_softc *sc, u_long src, void *dest, int size) 537 1.1 reinoud { 538 1.1 reinoud int cnt; 539 1.1 reinoud char *dptr = dest; 540 1.1 reinoud 541 1.1 reinoud #ifdef DIAGNOSTIC 542 1.1 reinoud if (size & 1) 543 1.1 reinoud panic ( "ie2host" ); 544 1.1 reinoud #endif 545 1.1 reinoud 546 1.1 reinoud while (size > 0) { 547 1.1 reinoud cnt = IE_PAGESIZE - src % IE_PAGESIZE; 548 1.1 reinoud if (cnt > size) 549 1.1 reinoud cnt = size; 550 1.1 reinoud setpage(sc, src); 551 1.1 reinoud ReadShorts((char *)sc->sc_ram + IE_COFF2POFF(src), dptr, cnt); 552 1.1 reinoud src+=cnt; 553 1.1 reinoud dptr+=cnt; 554 1.1 reinoud size-=cnt; 555 1.1 reinoud } 556 1.1 reinoud } 557 1.1 reinoud 558 1.1 reinoud /* 559 1.1 reinoud * Like a bzero or memset 0 for adapter memory. It handles the page 560 1.1 reinoud * register so you dont have to worry about it 561 1.1 reinoud */ 562 1.1 reinoud 563 1.1 reinoud static void 564 1.22 dsl iezero(struct ie_softc *sc, u_long p, int size) 565 1.1 reinoud { 566 1.1 reinoud int cnt; 567 1.1 reinoud 568 1.1 reinoud while (size > 0) { 569 1.1 reinoud cnt = IE_PAGESIZE - p % IE_PAGESIZE; 570 1.1 reinoud if (cnt > size) 571 1.1 reinoud cnt=size; 572 1.1 reinoud setpage(sc, p); 573 1.24 cegger memset((char *)sc->sc_ram + IE_COFF2POFF(p), 0, 2*cnt); 574 1.1 reinoud p += cnt; 575 1.1 reinoud size -= cnt; 576 1.1 reinoud } 577 1.1 reinoud } 578 1.1 reinoud 579 1.1 reinoud /* 580 1.1 reinoud * I/O Control interface to the kernel, entry point here 581 1.1 reinoud */ 582 1.1 reinoud 583 1.1 reinoud int 584 1.20 dyoung ieioctl(struct ifnet *ifp, unsigned long cmd, void *data) 585 1.1 reinoud { 586 1.1 reinoud struct ie_softc *sc = ifp->if_softc; 587 1.1 reinoud struct ifaddr *ifa = (struct ifaddr *)data; 588 1.1 reinoud int s; 589 1.1 reinoud int error=0; 590 1.1 reinoud 591 1.1 reinoud s=splnet(); 592 1.1 reinoud 593 1.1 reinoud switch ( cmd ) 594 1.1 reinoud { 595 1.20 dyoung case SIOCINITIFADDR: 596 1.1 reinoud ifp->if_flags |= IFF_UP; 597 1.20 dyoung switch (ifa->ifa_addr->sa_family ) { 598 1.1 reinoud #ifdef INET 599 1.1 reinoud case AF_INET: 600 1.1 reinoud ieinit(sc); 601 1.1 reinoud arp_ifinit(ifp, ifa ); 602 1.1 reinoud break; 603 1.1 reinoud #endif 604 1.1 reinoud default: 605 1.1 reinoud ieinit(sc); 606 1.1 reinoud break; 607 1.1 reinoud } 608 1.1 reinoud break; 609 1.1 reinoud 610 1.1 reinoud #define IZSET(a,b) ((a->if_flags&b)!=0) 611 1.1 reinoud #define IZCLR(a,b) ((a->if_flags&b)==0) 612 1.1 reinoud #define DOSET(a,b) (a->if_flags|=b) 613 1.1 reinoud #define DOCLR(a,b) (a->if_flags&=~b) 614 1.1 reinoud 615 1.1 reinoud case SIOCSIFFLAGS: 616 1.20 dyoung if ((error = ifioctl_common(ifp, cmd, data)) != 0) 617 1.40 maxv break; 618 1.1 reinoud sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI ); 619 1.1 reinoud 620 1.1 reinoud if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) 621 1.1 reinoud { 622 1.1 reinoud /* Interface was marked down and its running so stop it */ 623 1.1 reinoud iestop(sc); 624 1.1 reinoud DOCLR(ifp,IFF_RUNNING); 625 1.1 reinoud } 626 1.1 reinoud else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) 627 1.1 reinoud { 628 1.1 reinoud /* Just marked up and we're not running so start it */ 629 1.1 reinoud ieinit(sc); 630 1.1 reinoud } 631 1.1 reinoud else 632 1.1 reinoud { 633 1.1 reinoud /* else reset to invoke changes in other registers */ 634 1.1 reinoud iestop(sc); 635 1.1 reinoud ieinit(sc); 636 1.1 reinoud } 637 1.1 reinoud 638 1.1 reinoud default: 639 1.20 dyoung error = ether_ioctl(ifp, cmd, data); 640 1.20 dyoung break; 641 1.1 reinoud } 642 1.1 reinoud (void)splx(s); 643 1.1 reinoud return error; 644 1.1 reinoud } 645 1.1 reinoud 646 1.1 reinoud /* 647 1.1 reinoud * Reset the card. Completely. 648 1.1 reinoud */ 649 1.1 reinoud 650 1.1 reinoud void 651 1.22 dsl iereset(struct ie_softc *sc) 652 1.1 reinoud { 653 1.1 reinoud struct ie_sys_ctl_block scb; 654 1.1 reinoud int s = splnet(); 655 1.1 reinoud 656 1.1 reinoud iestop(sc); 657 1.1 reinoud 658 1.1 reinoud ie2host(sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb); 659 1.1 reinoud 660 1.1 reinoud if (command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0)) 661 1.1 reinoud printf("ie0: abort commands timed out\n"); 662 1.1 reinoud 663 1.1 reinoud if (command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0)) 664 1.1 reinoud printf("ie0: abort commands timed out\n"); 665 1.1 reinoud 666 1.1 reinoud ieinit(sc); 667 1.1 reinoud 668 1.1 reinoud (void)splx(s); 669 1.1 reinoud } 670 1.1 reinoud 671 1.1 reinoud /* 672 1.1 reinoud * Watchdog entry point. This is the entry for the kernel to call us 673 1.1 reinoud */ 674 1.1 reinoud 675 1.1 reinoud void 676 1.22 dsl iewatchdog(struct ifnet *ifp) 677 1.1 reinoud { 678 1.1 reinoud struct ie_softc *sc = ifp->if_softc; 679 1.1 reinoud 680 1.32 chs log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 681 1.47 skrll if_statinc(ifp, if_oerrors); 682 1.1 reinoud iereset(sc); 683 1.1 reinoud } 684 1.1 reinoud 685 1.46 skrll /* 686 1.1 reinoud * Start the time-domain-refloctometer running 687 1.1 reinoud */ 688 1.1 reinoud 689 1.1 reinoud static void 690 1.22 dsl run_tdr(struct ie_softc *sc) 691 1.1 reinoud { 692 1.1 reinoud struct ie_sys_ctl_block scb; 693 1.1 reinoud u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; 694 1.1 reinoud struct ie_tdr_cmd cmd; 695 1.1 reinoud int result; 696 1.1 reinoud 697 1.1 reinoud bzero ( &scb, sizeof(scb) ); 698 1.1 reinoud bzero ( &cmd, sizeof(cmd) ); 699 1.1 reinoud 700 1.1 reinoud cmd.com.ie_cmd_status = 0; 701 1.1 reinoud cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST; 702 1.1 reinoud cmd.com.ie_cmd_link = 0xffff; 703 1.1 reinoud cmd.ie_tdr_time = 0; 704 1.1 reinoud 705 1.1 reinoud scb.ie_command_list = (u_short)ptr; 706 1.1 reinoud 707 1.1 reinoud result=0; 708 1.1 reinoud if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, 709 1.1 reinoud IE_STAT_COMPL) ) 710 1.1 reinoud { 711 1.1 reinoud result = 0x10000; 712 1.1 reinoud } 713 1.1 reinoud else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 714 1.1 reinoud { 715 1.1 reinoud result = 0x10000; 716 1.1 reinoud } 717 1.1 reinoud 718 1.1 reinoud if ( result==0 ) 719 1.1 reinoud result = cmd.ie_tdr_time; 720 1.1 reinoud 721 1.1 reinoud ie_ack ( sc, IE_ST_WHENCE ); 722 1.1 reinoud 723 1.1 reinoud if (result & IE_TDR_SUCCESS ) 724 1.1 reinoud return; 725 1.1 reinoud 726 1.1 reinoud /* Very messy. I'll tidy it later */ 727 1.1 reinoud 728 1.1 reinoud if ( result & 0x10000 ) 729 1.1 reinoud { 730 1.1 reinoud printf ( "ie: TDR command failed\n" ); 731 1.1 reinoud } 732 1.1 reinoud else if ( result & IE_TDR_XCVR ) 733 1.1 reinoud { 734 1.57 andvar printf ( "ie: transceiver problem. Is it plugged in?\n" ); 735 1.1 reinoud } 736 1.1 reinoud else if ( result & IE_TDR_OPEN ) 737 1.1 reinoud { 738 1.1 reinoud if ((result & IE_TDR_TIME)>0) 739 1.1 reinoud printf ( "ie: TDR detected an open %d clocks away.\n", 740 1.1 reinoud result & IE_TDR_TIME ); 741 1.1 reinoud } 742 1.1 reinoud else if ( result & IE_TDR_SHORT ) 743 1.1 reinoud { 744 1.1 reinoud if ((result & IE_TDR_TIME)>0) 745 1.1 reinoud printf ( "ie: TDR detected a short %d clock away.\n", 746 1.1 reinoud result & IE_TDR_TIME ); 747 1.1 reinoud } 748 1.1 reinoud else 749 1.1 reinoud { 750 1.1 reinoud printf ( "ie: TDR returned unknown status %x\n", result ); 751 1.1 reinoud } 752 1.1 reinoud } 753 1.1 reinoud 754 1.1 reinoud u_long 755 1.22 dsl setup_rfa(struct ie_softc *sc, u_long ptr) 756 1.1 reinoud { 757 1.1 reinoud int i; 758 1.1 reinoud { 759 1.1 reinoud /* Receive frame descriptors */ 760 1.1 reinoud struct ie_recv_frame_desc rfd; 761 1.24 cegger memset( &rfd, 0, sizeof rfd ); 762 1.1 reinoud for ( i=0; i<NFRAMES; i++ ) 763 1.1 reinoud { 764 1.1 reinoud sc->rframes[i] = ptr; 765 1.1 reinoud rfd.ie_fd_next = ptr + sizeof rfd; 766 1.1 reinoud host2ie(sc, (char *)&rfd, ptr, sizeof rfd); 767 1.1 reinoud ptr += sizeof rfd; 768 1.1 reinoud } 769 1.1 reinoud rfd.ie_fd_next = sc->rframes[0]; 770 1.1 reinoud rfd.ie_fd_last |= IE_FD_LAST; 771 1.1 reinoud host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd ); 772 1.1 reinoud 773 1.1 reinoud ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd ); 774 1.1 reinoud rfd.ie_fd_buf_desc = (u_short) ptr; 775 1.1 reinoud host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd ); 776 1.1 reinoud } 777 1.1 reinoud 778 1.1 reinoud { 779 1.1 reinoud /* Receive frame descriptors */ 780 1.1 reinoud struct ie_recv_buf_desc rbd; 781 1.24 cegger memset(&rbd, 0, sizeof rbd); 782 1.1 reinoud for ( i=0; i<NRXBUF; i++ ) 783 1.1 reinoud { 784 1.1 reinoud sc->rbuffs[i] = ptr; 785 1.1 reinoud rbd.ie_rbd_length = IE_RXBUF_SIZE; 786 1.17 christos rbd.ie_rbd_buffer = (void *)(ptr + sizeof rbd); 787 1.1 reinoud rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE); 788 1.1 reinoud host2ie(sc, &rbd, ptr, sizeof rbd); 789 1.1 reinoud ptr+=sizeof rbd; 790 1.1 reinoud 791 1.46 skrll sc->cbuffs[i] = ptr; 792 1.1 reinoud ptr+=IE_RXBUF_SIZE; 793 1.1 reinoud } 794 1.1 reinoud rbd.ie_rbd_next = sc->rbuffs[0]; 795 1.1 reinoud rbd.ie_rbd_length |= IE_RBD_LAST; 796 1.1 reinoud host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd); 797 1.1 reinoud } 798 1.1 reinoud 799 1.1 reinoud sc->rfhead = 0; 800 1.1 reinoud sc->rftail = NFRAMES-1; 801 1.1 reinoud sc->rbhead = 0; 802 1.1 reinoud sc->rbtail = NRXBUF-1; 803 1.1 reinoud 804 1.1 reinoud { 805 1.1 reinoud struct ie_sys_ctl_block scb; 806 1.1 reinoud bzero ( &scb, sizeof scb ); 807 1.1 reinoud scb.ie_recv_list = (u_short)sc->rframes[0]; 808 1.1 reinoud host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); 809 1.1 reinoud } 810 1.1 reinoud return ptr; 811 1.1 reinoud } 812 1.1 reinoud 813 1.1 reinoud static void 814 1.22 dsl start_receiver(struct ie_softc *sc) 815 1.1 reinoud { 816 1.1 reinoud struct ie_sys_ctl_block scb; 817 1.1 reinoud ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 818 1.1 reinoud scb.ie_recv_list = (u_short)sc->rframes[0]; 819 1.1 reinoud command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); 820 1.1 reinoud ie_ack(sc, IE_ST_WHENCE ); 821 1.1 reinoud } 822 1.1 reinoud 823 1.1 reinoud /* 824 1.1 reinoud * Take our configuration and update all the other data structures that 825 1.1 reinoud * require information from the driver. 826 1.1 reinoud * 827 1.1 reinoud * CALL AT SPLIMP OR HIGHER 828 1.1 reinoud */ 829 1.1 reinoud 830 1.1 reinoud int 831 1.22 dsl ieinit(struct ie_softc *sc) 832 1.1 reinoud { 833 1.1 reinoud struct ifnet *ifp; 834 1.1 reinoud struct ie_sys_ctl_block scb; 835 1.1 reinoud struct ie_config_cmd cmd; 836 1.1 reinoud struct ie_iasetup_cmd iasetup_cmd; 837 1.1 reinoud u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; 838 1.1 reinoud int n; 839 1.1 reinoud 840 1.1 reinoud ifp = &sc->sc_ethercom.ec_if; 841 1.1 reinoud 842 1.1 reinoud bzero ( &scb, sizeof(scb) ); 843 1.1 reinoud 844 1.1 reinoud /* Send the configure command */ 845 1.1 reinoud 846 1.1 reinoud cmd.com.ie_cmd_status = 0; 847 1.1 reinoud cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST; 848 1.1 reinoud cmd.com.ie_cmd_link = 0xffff; 849 1.1 reinoud 850 1.1 reinoud cmd.ie_config_count = 0x0c; 851 1.1 reinoud cmd.ie_fifo = 8; 852 1.1 reinoud cmd.ie_save_bad = 0x40; 853 1.1 reinoud cmd.ie_addr_len = 0x2e; 854 1.1 reinoud cmd.ie_priority = 0; 855 1.1 reinoud cmd.ie_ifs = 0x60; 856 1.1 reinoud cmd.ie_slot_low = 0; 857 1.1 reinoud cmd.ie_slot_high = 0xf2; 858 1.1 reinoud cmd.ie_promisc = 0; /* Hey nuts, look at this! */ 859 1.1 reinoud cmd.ie_crs_cdt = 0; 860 1.1 reinoud cmd.ie_min_len = 64; 861 1.1 reinoud cmd.ie_junk = 0xff; 862 1.1 reinoud 863 1.1 reinoud scb.ie_command_list = (u_short)ptr; 864 1.1 reinoud 865 1.1 reinoud if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, 866 1.1 reinoud IE_STAT_COMPL) ) 867 1.1 reinoud { 868 1.32 chs printf ( "%s: command failed: timeout\n", device_xname(sc->sc_dev)); 869 1.1 reinoud return 0; 870 1.1 reinoud } 871 1.1 reinoud 872 1.1 reinoud if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 873 1.1 reinoud { 874 1.32 chs printf ( "%s: command failed: !IE_STAT_OK\n", device_xname(sc->sc_dev)); 875 1.1 reinoud return 0; 876 1.1 reinoud } 877 1.1 reinoud 878 1.1 reinoud /* Individual address setup command */ 879 1.1 reinoud 880 1.1 reinoud iasetup_cmd.com.ie_cmd_status = 0; 881 1.1 reinoud iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST; 882 1.1 reinoud iasetup_cmd.com.ie_cmd_link = 0xffff; 883 1.1 reinoud 884 1.18 dyoung bcopy ( CLLADDR(ifp->if_sadl), (void *) &iasetup_cmd.ie_address, 885 1.1 reinoud sizeof (iasetup_cmd.ie_address) ); 886 1.1 reinoud 887 1.1 reinoud if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd, 888 1.1 reinoud IE_STAT_COMPL) ) 889 1.1 reinoud { 890 1.32 chs printf ( "%s: iasetup failed : timeout\n", device_xname(sc->sc_dev)); 891 1.1 reinoud return 0; 892 1.1 reinoud } 893 1.1 reinoud 894 1.1 reinoud if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 895 1.1 reinoud { 896 1.32 chs printf ( "%s: iasetup failed : !IE_STAT_OK\n", device_xname(sc->sc_dev)); 897 1.1 reinoud return 0; 898 1.1 reinoud } 899 1.1 reinoud 900 1.1 reinoud ie_ack ( sc, IE_ST_WHENCE ); 901 1.1 reinoud 902 1.1 reinoud /* Run the time-domain refloctometer */ 903 1.1 reinoud run_tdr ( sc ); 904 1.1 reinoud 905 1.1 reinoud ie_ack ( sc, IE_ST_WHENCE ); 906 1.1 reinoud 907 1.1 reinoud /* meminit */ 908 1.1 reinoud ptr = setup_rfa(sc, ptr); 909 1.1 reinoud 910 1.1 reinoud ifp->if_flags |= IFF_RUNNING; 911 1.1 reinoud 912 1.1 reinoud /* Setup transmit buffers */ 913 1.1 reinoud 914 1.1 reinoud for ( n=0; n<NTXBUF; n++ ) { 915 1.1 reinoud sc->xmit_cmds[n] = ptr; 916 1.1 reinoud iezero(sc, ptr, sizeof(struct ie_xmit_cmd) ); 917 1.1 reinoud ptr += sizeof(struct ie_xmit_cmd); 918 1.1 reinoud 919 1.1 reinoud sc->xmit_buffs[n] = ptr; 920 1.1 reinoud iezero(sc, ptr, sizeof(struct ie_xmit_buf)); 921 1.1 reinoud ptr += sizeof(struct ie_xmit_buf); 922 1.1 reinoud } 923 1.1 reinoud 924 1.1 reinoud for ( n=0; n<NTXBUF; n++ ) { 925 1.1 reinoud sc->xmit_cbuffs[n] = ptr; 926 1.1 reinoud ptr += IE_TXBUF_SIZE; 927 1.1 reinoud } 928 1.1 reinoud 929 1.1 reinoud sc->xmit_free = NTXBUF; 930 1.1 reinoud sc->xchead = sc->xctail = 0; 931 1.1 reinoud 932 1.1 reinoud { 933 1.1 reinoud struct ie_xmit_cmd xmcmd; 934 1.1 reinoud bzero ( &xmcmd, sizeof xmcmd ); 935 1.1 reinoud xmcmd.ie_xmit_status = IE_STAT_COMPL; 936 1.1 reinoud host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd); 937 1.1 reinoud } 938 1.1 reinoud 939 1.1 reinoud start_receiver (sc); 940 1.1 reinoud 941 1.1 reinoud return 0; 942 1.1 reinoud } 943 1.1 reinoud 944 1.1 reinoud int 945 1.22 dsl iestop(struct ie_softc *sc) 946 1.1 reinoud { 947 1.1 reinoud struct ie_sys_ctl_block scb; 948 1.1 reinoud int s = splnet(); 949 1.1 reinoud 950 1.1 reinoud ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 951 1.1 reinoud 952 1.1 reinoud if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) ) 953 1.1 reinoud printf ( "ie0: abort commands timed out\n" ); 954 1.1 reinoud 955 1.1 reinoud (void)splx(s); 956 1.1 reinoud return(0); 957 1.1 reinoud } 958 1.1 reinoud 959 1.1 reinoud /* 960 1.33 snj * Send a command to the card and await its completion. 961 1.1 reinoud * Timeout if it's taking too long 962 1.1 reinoud */ 963 1.1 reinoud 964 1.1 reinoud /*CAW*/ 965 1.1 reinoud 966 1.1 reinoud static int 967 1.23 dsl command_and_wait(struct ie_softc *sc, u_short cmd, struct ie_sys_ctl_block *pscb, void *pcmd, int ocmd, int scmd, int mask) 968 1.1 reinoud { 969 1.1 reinoud int i=0; 970 1.1 reinoud 971 1.1 reinoud /* Copy the command to the card */ 972 1.1 reinoud 973 1.1 reinoud if ( pcmd ) 974 1.1 reinoud host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */ 975 1.1 reinoud 976 1.1 reinoud /* Copy the scb to the card */ 977 1.1 reinoud 978 1.1 reinoud if ( pscb ) { 979 1.1 reinoud pscb->ie_command = cmd; 980 1.1 reinoud host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb); 981 1.1 reinoud } 982 1.1 reinoud else 983 1.1 reinoud { 984 1.1 reinoud setpage ( sc, IE_IBASE + IE_SCB_OFF ); 985 1.1 reinoud PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 986 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_command)), cmd ); 987 1.1 reinoud } 988 1.1 reinoud 989 1.1 reinoud /* Prod the card to act on the newly loaded command */ 990 1.1 reinoud ieattn(sc); 991 1.1 reinoud 992 1.1 reinoud /* Wait for the command to complete */ 993 1.1 reinoud if ( IE_ACTION_COMMAND(cmd) && pcmd ) 994 1.1 reinoud { 995 1.1 reinoud setpage(sc,ocmd); 996 1.1 reinoud for ( i=4000; --i>=0; ) { 997 1.1 reinoud if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) + 998 1.1 reinoud (xoffsetof(struct ie_config_cmd, ie_config_status))) & mask) 999 1.1 reinoud break; 1000 1.1 reinoud delay(100); 1001 1.1 reinoud } 1002 1.1 reinoud } 1003 1.1 reinoud else 1004 1.1 reinoud { 1005 1.1 reinoud for ( i=4000; --i>=0; ) { 1006 1.1 reinoud if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1007 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_command))) ) 1008 1.1 reinoud break; 1009 1.1 reinoud delay(100); 1010 1.1 reinoud } 1011 1.1 reinoud } 1012 1.1 reinoud 1013 1.1 reinoud /* Update the host structures to reflect the state on the card */ 1014 1.1 reinoud if ( pscb ) 1015 1.1 reinoud ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb ); 1016 1.1 reinoud if ( pcmd ) 1017 1.1 reinoud ie2host(sc, ocmd, pcmd, scmd); 1018 1.1 reinoud 1019 1.1 reinoud return i < 0; 1020 1.1 reinoud } 1021 1.1 reinoud 1022 1.1 reinoud #define READ_MEMBER(sc,type,member,ptr,dest) \ 1023 1.1 reinoud setpage(sc, ptr); \ 1024 1.1 reinoud dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ 1025 1.1 reinoud (xoffsetof(type, member)) ); 1026 1.1 reinoud 1027 1.1 reinoud #define WRITE_MEMBER(sc,type,member,ptr,dest) \ 1028 1.1 reinoud setpage(sc, ptr); \ 1029 1.1 reinoud PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ 1030 1.1 reinoud (xoffsetof(type, member)), dest ); 1031 1.1 reinoud 1032 1.15 perry static inline int 1033 1.22 dsl ie_buflen(struct ie_softc *sc, int head) 1034 1.1 reinoud { 1035 1.1 reinoud int actual; 1036 1.1 reinoud 1037 1.1 reinoud READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1038 1.1 reinoud sc->rbuffs[head], actual ); 1039 1.1 reinoud 1040 1.1 reinoud return(actual & (IE_RXBUF_SIZE | (IE_RXBUF_SIZE-1))) ; 1041 1.1 reinoud } 1042 1.1 reinoud 1043 1.15 perry static inline int 1044 1.22 dsl ie_packet_len(struct ie_softc *sc) 1045 1.1 reinoud { 1046 1.1 reinoud int i; 1047 1.1 reinoud int actual; 1048 1.1 reinoud int head = sc->rbhead; 1049 1.1 reinoud int acc=0; 1050 1.1 reinoud 1051 1.1 reinoud do { 1052 1.1 reinoud READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1053 1.1 reinoud sc->rbuffs[sc->rbhead], actual ); 1054 1.1 reinoud if (!(actual&IE_RBD_USED)) 1055 1.1 reinoud { 1056 1.1 reinoud return (-1); 1057 1.1 reinoud } 1058 1.1 reinoud 1059 1.1 reinoud READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1060 1.1 reinoud sc->rbuffs[head], i ); 1061 1.1 reinoud i = i & IE_RBD_LAST; 1062 1.1 reinoud 1063 1.1 reinoud acc += ie_buflen(sc, head); 1064 1.1 reinoud head = (head+1) % NRXBUF; 1065 1.1 reinoud } while (!i); 1066 1.1 reinoud 1067 1.1 reinoud return acc; 1068 1.1 reinoud } 1069 1.1 reinoud 1070 1.1 reinoud struct mbuf * 1071 1.1 reinoud ieget(struct ie_softc *sc, int *to_bpf ) 1072 1.1 reinoud { 1073 1.1 reinoud struct mbuf *top, **mp, *m; 1074 1.1 reinoud int head; 1075 1.1 reinoud int resid, totlen, thisrboff, thismboff; 1076 1.1 reinoud int len; 1077 1.1 reinoud struct ether_header eh; 1078 1.1 reinoud 1079 1.1 reinoud totlen = ie_packet_len(sc); 1080 1.1 reinoud 1081 1.1 reinoud if ( totlen > ETHER_MAX_LEN ) 1082 1.1 reinoud { 1083 1.1 reinoud printf ( "ie: Gosh that packet was s-o-o-o big.\n" ); 1084 1.1 reinoud return 0; 1085 1.1 reinoud } 1086 1.1 reinoud 1087 1.1 reinoud if ( totlen<=0 ) 1088 1.1 reinoud return 0; 1089 1.1 reinoud 1090 1.1 reinoud head = sc->rbhead; 1091 1.1 reinoud 1092 1.1 reinoud /* Read the ethernet header */ 1093 1.17 christos ie2host ( sc, sc->cbuffs[head], (void *)&eh, sizeof eh ); 1094 1.1 reinoud 1095 1.1 reinoud /* Check if the packet is for us */ 1096 1.1 reinoud 1097 1.1 reinoud resid = totlen; 1098 1.1 reinoud 1099 1.1 reinoud MGETHDR ( m, M_DONTWAIT, MT_DATA ); 1100 1.1 reinoud if ( m==0 ) 1101 1.1 reinoud return 0; 1102 1.1 reinoud 1103 1.37 ozaki m_set_rcvif(m, &sc->sc_ethercom.ec_if); 1104 1.1 reinoud m->m_pkthdr.len = totlen; 1105 1.1 reinoud len = MHLEN; 1106 1.1 reinoud top = 0; 1107 1.1 reinoud mp = ⊤ 1108 1.1 reinoud 1109 1.1 reinoud /* 1110 1.1 reinoud * This loop goes through and allocates mbufs for all the data we will 1111 1.1 reinoud * be copying in. It does not actually do the copying yet. 1112 1.1 reinoud */ 1113 1.1 reinoud while (totlen > 0) { 1114 1.1 reinoud if (top) { 1115 1.1 reinoud MGET(m, M_DONTWAIT, MT_DATA); 1116 1.1 reinoud if (m == 0) { 1117 1.1 reinoud m_freem(top); 1118 1.1 reinoud return 0; 1119 1.1 reinoud } 1120 1.1 reinoud len = MLEN; 1121 1.1 reinoud } 1122 1.1 reinoud if (totlen >= MINCLSIZE) { 1123 1.1 reinoud MCLGET(m, M_DONTWAIT); 1124 1.1 reinoud if (m->m_flags & M_EXT) 1125 1.1 reinoud len = MCLBYTES; 1126 1.1 reinoud } 1127 1.1 reinoud 1128 1.1 reinoud if (mp == &top) { 1129 1.17 christos void *newdata = (void *) 1130 1.1 reinoud ALIGN(m->m_data + sizeof(struct ether_header)) - 1131 1.1 reinoud sizeof(struct ether_header); 1132 1.46 skrll len -= newdata - m->m_data; 1133 1.1 reinoud m->m_data = newdata; 1134 1.1 reinoud } 1135 1.1 reinoud 1136 1.1 reinoud m->m_len = len = min(totlen, len); 1137 1.1 reinoud 1138 1.1 reinoud totlen -= len; 1139 1.1 reinoud *mp = m; 1140 1.1 reinoud mp = &m->m_next; 1141 1.1 reinoud } 1142 1.1 reinoud 1143 1.1 reinoud m = top; 1144 1.1 reinoud thismboff = 0; 1145 1.1 reinoud 1146 1.1 reinoud /* 1147 1.1 reinoud * Copy the Ethernet header into the mbuf chain. 1148 1.1 reinoud */ 1149 1.17 christos memcpy(mtod(m, void *), &eh, sizeof(struct ether_header)); 1150 1.1 reinoud thismboff = sizeof(struct ether_header); 1151 1.1 reinoud thisrboff = sizeof(struct ether_header); 1152 1.1 reinoud resid -= sizeof(struct ether_header); 1153 1.1 reinoud 1154 1.1 reinoud /* 1155 1.1 reinoud * Now we take the mbuf chain (hopefully only one mbuf most of the 1156 1.1 reinoud * time) and stuff the data into it. There are no possible failures at 1157 1.1 reinoud * or after this point. 1158 1.1 reinoud */ 1159 1.1 reinoud while (resid > 0) { 1160 1.1 reinoud int thisrblen = ie_buflen(sc, head) - thisrboff, 1161 1.1 reinoud thismblen = m->m_len - thismboff; 1162 1.1 reinoud len = min(thisrblen, thismblen); 1163 1.1 reinoud 1164 1.17 christos /* bcopy((void *)(sc->cbuffs[head] + thisrboff), 1165 1.17 christos mtod(m, void *) + thismboff, (u_int)len); */ 1166 1.1 reinoud 1167 1.1 reinoud 1168 1.1 reinoud if ( len&1 ) 1169 1.1 reinoud { 1170 1.1 reinoud ie2host(sc, sc->cbuffs[head]+thisrboff, 1171 1.17 christos mtod(m, void *) + thismboff, (u_int)len+1); 1172 1.1 reinoud } 1173 1.1 reinoud else 1174 1.1 reinoud { 1175 1.1 reinoud ie2host(sc, sc->cbuffs[head]+thisrboff, 1176 1.17 christos mtod(m, void *) + thismboff, (u_int)len); 1177 1.1 reinoud } 1178 1.1 reinoud 1179 1.1 reinoud resid -= len; 1180 1.1 reinoud 1181 1.1 reinoud if (len == thismblen) { 1182 1.1 reinoud m = m->m_next; 1183 1.1 reinoud thismboff = 0; 1184 1.1 reinoud } else 1185 1.1 reinoud thismboff += len; 1186 1.1 reinoud 1187 1.1 reinoud if (len == thisrblen) { 1188 1.1 reinoud head = (head + 1) % NRXBUF; 1189 1.1 reinoud thisrboff = 0; 1190 1.1 reinoud } else 1191 1.1 reinoud thisrboff += len; 1192 1.1 reinoud } 1193 1.1 reinoud 1194 1.1 reinoud 1195 1.1 reinoud return top; 1196 1.1 reinoud } 1197 1.1 reinoud 1198 1.1 reinoud void 1199 1.22 dsl ie_drop_packet_buffer(struct ie_softc *sc) 1200 1.1 reinoud { 1201 1.1 reinoud int i, actual, last; 1202 1.1 reinoud 1203 1.1 reinoud do { 1204 1.1 reinoud READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1205 1.1 reinoud sc->rbuffs[sc->rbhead], actual ); 1206 1.1 reinoud if (!(actual&IE_RBD_USED)) 1207 1.1 reinoud { 1208 1.1 reinoud iereset(sc); 1209 1.1 reinoud return; 1210 1.1 reinoud } 1211 1.1 reinoud 1212 1.1 reinoud i = actual & IE_RBD_LAST; 1213 1.1 reinoud 1214 1.1 reinoud READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1215 1.1 reinoud sc->rbuffs[sc->rbhead], last ); 1216 1.1 reinoud last |= IE_RBD_LAST; 1217 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1218 1.1 reinoud sc->rbuffs[sc->rbhead], last ); 1219 1.1 reinoud 1220 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual, 1221 1.1 reinoud sc->rbuffs[sc->rbhead], 0 ); 1222 1.1 reinoud 1223 1.1 reinoud sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF; 1224 1.1 reinoud 1225 1.1 reinoud READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1226 1.1 reinoud sc->rbuffs[sc->rbtail], last ); 1227 1.1 reinoud last &= ~IE_RBD_LAST; 1228 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1229 1.1 reinoud sc->rbuffs[sc->rbtail], last ); 1230 1.1 reinoud 1231 1.1 reinoud sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF; 1232 1.1 reinoud } while (!i); 1233 1.1 reinoud } 1234 1.1 reinoud 1235 1.1 reinoud void 1236 1.22 dsl ie_read_frame(struct ie_softc *sc, int num) 1237 1.1 reinoud { 1238 1.1 reinoud int status; 1239 1.1 reinoud struct ie_recv_frame_desc rfd; 1240 1.1 reinoud struct mbuf *m=0; 1241 1.1 reinoud struct ifnet *ifp; 1242 1.1 reinoud int last; 1243 1.1 reinoud 1244 1.1 reinoud ifp = &sc->sc_ethercom.ec_if; 1245 1.1 reinoud 1246 1.1 reinoud ie2host(sc, sc->rframes[num], &rfd, sizeof rfd ); 1247 1.1 reinoud status = rfd.ie_fd_status; 1248 1.1 reinoud 1249 1.1 reinoud /* Advance the RFD list, since we're done with this descriptor */ 1250 1.1 reinoud 1251 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, 1252 1.1 reinoud sc->rframes[num], 0 ); 1253 1.1 reinoud 1254 1.1 reinoud READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1255 1.1 reinoud sc->rframes[num], last ); 1256 1.1 reinoud last |= IE_FD_LAST; 1257 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1258 1.1 reinoud sc->rframes[num], last ); 1259 1.1 reinoud 1260 1.1 reinoud READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1261 1.1 reinoud sc->rframes[sc->rftail], last ); 1262 1.1 reinoud last &= ~IE_FD_LAST; 1263 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1264 1.1 reinoud sc->rframes[sc->rftail], last ); 1265 1.1 reinoud 1266 1.1 reinoud sc->rftail = ( sc->rftail + 1 ) % NFRAMES; 1267 1.1 reinoud sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES; 1268 1.1 reinoud 1269 1.1 reinoud if ( status & IE_FD_OK ) { 1270 1.1 reinoud m = ieget(sc, 0); 1271 1.1 reinoud ie_drop_packet_buffer(sc); 1272 1.1 reinoud } 1273 1.1 reinoud 1274 1.1 reinoud if ( m==0 ) { 1275 1.45 skrll if_statinc(ifp, if_ierrors); 1276 1.1 reinoud return; 1277 1.1 reinoud } 1278 1.1 reinoud 1279 1.36 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1280 1.1 reinoud } 1281 1.1 reinoud 1282 1.1 reinoud void 1283 1.22 dsl ierint(struct ie_softc *sc) 1284 1.1 reinoud { 1285 1.1 reinoud int i; 1286 1.1 reinoud int times_thru = 1024; 1287 1.1 reinoud struct ie_sys_ctl_block scb; 1288 1.1 reinoud int status; 1289 1.1 reinoud int safety_catch = 0; 1290 1.1 reinoud 1291 1.1 reinoud i = sc->rfhead; 1292 1.1 reinoud for (;;) { 1293 1.1 reinoud 1294 1.1 reinoud if ( (safety_catch++)>100 ) 1295 1.1 reinoud { 1296 1.1 reinoud printf ( "ie: ierint safety catch tripped\n" ); 1297 1.1 reinoud iereset(sc); 1298 1.1 reinoud return; 1299 1.1 reinoud } 1300 1.1 reinoud 1301 1.1 reinoud READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, 1302 1.1 reinoud sc->rframes[i],status); 1303 1.1 reinoud 1304 1.1 reinoud if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) { 1305 1.1 reinoud if ( !--times_thru ) { 1306 1.1 reinoud printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" ); 1307 1.1 reinoud ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1308 1.1 reinoud sc->sc_ethercom.ec_if.if_ierrors += scb.ie_err_crc + 1309 1.1 reinoud scb.ie_err_align + 1310 1.1 reinoud scb.ie_err_resource + 1311 1.1 reinoud scb.ie_err_overrun; 1312 1.1 reinoud scb.ie_err_crc = scb.ie_err_align = 0; 1313 1.1 reinoud scb.ie_err_resource = scb.ie_err_overrun = 0; 1314 1.1 reinoud host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) ); 1315 1.1 reinoud } 1316 1.1 reinoud ie_read_frame(sc, i); 1317 1.1 reinoud } else { 1318 1.1 reinoud ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1319 1.1 reinoud 1320 1.1 reinoud if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) ) 1321 1.1 reinoud { 1322 1.1 reinoud WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc, 1323 1.1 reinoud sc->rframes[0], sc->rbuffs[0] ); 1324 1.1 reinoud 1325 1.1 reinoud scb.ie_recv_list = sc->rframes[0]; 1326 1.1 reinoud host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) ); 1327 1.1 reinoud command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); 1328 1.1 reinoud } 1329 1.1 reinoud break; 1330 1.1 reinoud } 1331 1.1 reinoud i = (i + 1) % NFRAMES; 1332 1.1 reinoud } 1333 1.1 reinoud } 1334 1.1 reinoud 1335 1.1 reinoud static int in_intr = 0; 1336 1.1 reinoud 1337 1.1 reinoud int 1338 1.22 dsl ieintr(void *arg) 1339 1.1 reinoud { 1340 1.1 reinoud struct ie_softc *sc = arg; 1341 1.1 reinoud u_short status; 1342 1.1 reinoud int safety_catch = 0; 1343 1.1 reinoud static int safety_net = 0; 1344 1.1 reinoud 1345 1.1 reinoud if (in_intr == 1) 1346 1.1 reinoud panic ( "ie: INTERRUPT REENTERED\n" ); 1347 1.1 reinoud 1348 1.55 andvar /* Clear the interrupt */ 1349 1.1 reinoud ie_cli (sc); 1350 1.1 reinoud 1351 1.1 reinoud setpage(sc, IE_IBASE + IE_SCB_OFF ); 1352 1.1 reinoud status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1353 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 1354 1.1 reinoud 1355 1.1 reinoud status = status & IE_ST_WHENCE; 1356 1.1 reinoud 1357 1.1 reinoud if (status == 0) { 1358 1.1 reinoud in_intr = 0; 1359 1.1 reinoud return(0); 1360 1.1 reinoud } 1361 1.1 reinoud 1362 1.1 reinoud loop: 1363 1.1 reinoud 1364 1.1 reinoud ie_ack(sc, status); 1365 1.1 reinoud 1366 1.1 reinoud if (status & (IE_ST_FR | IE_ST_RNR)) 1367 1.1 reinoud ierint(sc); 1368 1.1 reinoud 1369 1.1 reinoud if (status & IE_ST_CX) 1370 1.1 reinoud ietint(sc); 1371 1.1 reinoud 1372 1.1 reinoud if (status & IE_ST_RNR) { 1373 1.1 reinoud printf ( "ie: receiver not ready\n" ); 1374 1.1 reinoud sc->sc_ethercom.ec_if.if_ierrors++; 1375 1.1 reinoud iereset(sc); 1376 1.1 reinoud } 1377 1.1 reinoud 1378 1.1 reinoud setpage(sc, IE_IBASE + IE_SCB_OFF ); 1379 1.1 reinoud status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1380 1.1 reinoud (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 1381 1.1 reinoud status = status & IE_ST_WHENCE; 1382 1.1 reinoud 1383 1.1 reinoud ie_cli(sc); 1384 1.1 reinoud 1385 1.1 reinoud if (status == 0) { 1386 1.1 reinoud in_intr = 0; 1387 1.1 reinoud return(0); 1388 1.1 reinoud } 1389 1.1 reinoud 1390 1.56 andvar /* This is perhaps a little over cautious */ 1391 1.1 reinoud if ( safety_catch++ > 10 ) 1392 1.1 reinoud { 1393 1.1 reinoud printf ( "ie: Interrupt couldn't be cleared\n" ); 1394 1.1 reinoud delay ( 1000 ); 1395 1.1 reinoud ie_cli(sc); 1396 1.1 reinoud if ( safety_net++ > 50 ) 1397 1.1 reinoud { 1398 1.1 reinoud /* printf ( "ie: safety net catches driver, shutting down\n" ); 1399 1.1 reinoud disable_irq ( IRQ_PODULE );*/ 1400 1.1 reinoud } 1401 1.1 reinoud in_intr = 0; 1402 1.1 reinoud return(0); 1403 1.1 reinoud } 1404 1.1 reinoud 1405 1.1 reinoud goto loop; 1406 1.1 reinoud } 1407 1.1 reinoud 1408 1.1 reinoud void 1409 1.22 dsl iexmit(struct ie_softc *sc) 1410 1.1 reinoud { 1411 1.1 reinoud /* int actual;*/ 1412 1.1 reinoud struct ie_sys_ctl_block scb; 1413 1.1 reinoud 1414 1.1 reinoud struct ie_xmit_cmd xc; 1415 1.1 reinoud struct ie_xmit_buf xb; 1416 1.46 skrll 1417 1.1 reinoud ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb ); 1418 1.1 reinoud xb.ie_xmit_flags |= IE_XMIT_LAST; 1419 1.1 reinoud xb.ie_xmit_next = 0xffff; 1420 1.17 christos xb.ie_xmit_buf = (void *)sc->xmit_cbuffs[sc->xctail]; 1421 1.1 reinoud host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb ); 1422 1.1 reinoud 1423 1.1 reinoud bzero ( &xc, sizeof xc ); 1424 1.1 reinoud xc.com.ie_cmd_link = 0xffff; 1425 1.1 reinoud xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST; 1426 1.1 reinoud xc.ie_xmit_status = 0x0000; 1427 1.1 reinoud xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail]; 1428 1.1 reinoud host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc ); 1429 1.1 reinoud 1430 1.1 reinoud ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1431 1.1 reinoud scb.ie_command_list = sc->xmit_cmds[sc->xctail]; 1432 1.1 reinoud host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); 1433 1.1 reinoud 1434 1.1 reinoud command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail] 1435 1.1 reinoud , sizeof xc, IE_STAT_COMPL); 1436 1.1 reinoud 1437 1.1 reinoud sc->sc_ethercom.ec_if.if_timer = 5; 1438 1.1 reinoud } 1439 1.1 reinoud /* 1440 1.1 reinoud * Start sending all the queued buffers. 1441 1.1 reinoud */ 1442 1.1 reinoud 1443 1.1 reinoud void 1444 1.22 dsl iestart(struct ifnet *ifp) 1445 1.1 reinoud { 1446 1.1 reinoud struct ie_softc *sc = ifp->if_softc; 1447 1.1 reinoud struct mbuf *m0, *m; 1448 1.1 reinoud u_char *buffer; 1449 1.1 reinoud u_short len; 1450 1.1 reinoud char txbuf[IE_TXBUF_SIZE]; 1451 1.1 reinoud int safety_catch = 0; 1452 1.1 reinoud 1453 1.53 thorpej while (sc->xmit_free != 0) { 1454 1.1 reinoud if ( (safety_catch++)>100 ) 1455 1.1 reinoud { 1456 1.1 reinoud printf ( "ie: iestart safety catch tripped\n" ); 1457 1.1 reinoud iereset(sc); 1458 1.1 reinoud return; 1459 1.1 reinoud } 1460 1.1 reinoud 1461 1.1 reinoud IF_DEQUEUE(&ifp->if_snd, m); 1462 1.1 reinoud if (!m) 1463 1.1 reinoud break; 1464 1.1 reinoud 1465 1.1 reinoud /* TODO: Write directly to the card */ 1466 1.1 reinoud len = 0; 1467 1.1 reinoud /* buffer = sc->xmit_cbuffs[sc->xchead]; */ 1468 1.1 reinoud buffer = txbuf; 1469 1.1 reinoud 1470 1.1 reinoud for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE; 1471 1.1 reinoud m = m->m_next) { 1472 1.27 cegger memcpy(buffer, mtod(m, void *), m->m_len); 1473 1.1 reinoud buffer += m->m_len; 1474 1.1 reinoud len += m->m_len; 1475 1.1 reinoud } 1476 1.1 reinoud 1477 1.42 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 1478 1.4 thorpej 1479 1.4 thorpej m_freem(m0); 1480 1.11 bouyer if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) { 1481 1.11 bouyer memset(buffer, 0, ETHER_MIN_LEN - ETHER_CRC_LEN - len); 1482 1.11 bouyer len = ETHER_MIN_LEN - ETHER_CRC_LEN; 1483 1.11 bouyer buffer += ETHER_MIN_LEN - ETHER_CRC_LEN; 1484 1.11 bouyer } 1485 1.46 skrll 1486 1.1 reinoud /* When we write directly to the card we dont need this */ 1487 1.1 reinoud if (len&1) 1488 1.1 reinoud host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 ); 1489 1.1 reinoud else 1490 1.1 reinoud host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len ); 1491 1.1 reinoud 1492 1.1 reinoud /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */ 1493 1.46 skrll 1494 1.1 reinoud WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags, 1495 1.1 reinoud sc->xmit_buffs[sc->xchead], len) 1496 1.1 reinoud 1497 1.1 reinoud /* Start the first packet transmitting. */ 1498 1.1 reinoud if (sc->xmit_free == NTXBUF) 1499 1.1 reinoud iexmit(sc); 1500 1.1 reinoud 1501 1.1 reinoud sc->xchead = (sc->xchead + 1) % NTXBUF; 1502 1.1 reinoud sc->xmit_free--; 1503 1.1 reinoud } 1504 1.1 reinoud } 1505 1.1 reinoud 1506 1.1 reinoud void 1507 1.22 dsl ietint(struct ie_softc *sc) 1508 1.1 reinoud { 1509 1.1 reinoud struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1510 1.1 reinoud 1511 1.1 reinoud int status; 1512 1.1 reinoud 1513 1.1 reinoud ifp->if_timer=0; 1514 1.46 skrll 1515 1.1 reinoud READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status, 1516 1.1 reinoud sc->xmit_cmds[sc->xctail], status ); 1517 1.1 reinoud 1518 1.1 reinoud if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) ) 1519 1.1 reinoud printf ( "ietint: command still busy!\n" ); 1520 1.46 skrll 1521 1.1 reinoud if ( status & IE_STAT_OK ) { 1522 1.45 skrll if_statinc(ifp, if_opackets); 1523 1.45 skrll if_statadd(ifp, if_collisions, status & IE_XS_MAXCOLL); 1524 1.1 reinoud } else { 1525 1.45 skrll if_statinc(ifp, if_oerrors); 1526 1.1 reinoud if ( status & IE_STAT_ABORT ) 1527 1.1 reinoud printf ( "ie: send aborted\n" ); 1528 1.1 reinoud if ( status & IE_XS_LATECOLL ) 1529 1.1 reinoud printf ( "ie: late collision\n" ); 1530 1.1 reinoud if ( status & IE_XS_NOCARRIER ) 1531 1.1 reinoud printf ( "ie: no carrier\n" ); 1532 1.1 reinoud if ( status & IE_XS_LOSTCTS ) 1533 1.1 reinoud printf ( "ie: lost CTS\n" ); 1534 1.1 reinoud if ( status & IE_XS_UNDERRUN ) 1535 1.1 reinoud printf ( "ie: DMA underrun\n" ); 1536 1.1 reinoud if ( status & IE_XS_EXCMAX ) 1537 1.1 reinoud printf ( "ie: too many collisions\n" ); 1538 1.48 skrll if_statadd(ifp, if_collisions, 16); 1539 1.1 reinoud } 1540 1.1 reinoud /* Done with the buffer */ 1541 1.1 reinoud sc->xmit_free++; 1542 1.1 reinoud sc->xctail = (sc->xctail + 1 ) % NTXBUF; 1543 1.46 skrll 1544 1.1 reinoud /* Start the next packet transmitting, if any */ 1545 1.1 reinoud if ( sc->xmit_free<NTXBUF ) 1546 1.1 reinoud iexmit(sc); 1547 1.1 reinoud 1548 1.39 nonaka if_schedule_deferred_start(ifp); 1549 1.1 reinoud } 1550 1.1 reinoud 1551 1.1 reinoud /* End of if_ie.c */ 1552