| 311 | } |
| 312 | |
| 313 | static void |
| 314 | emac_rxeof(struct emac_softc *sc, int count) |
| 315 | { |
| 316 | struct ifnet *ifp; |
| 317 | struct mbuf *m, *m0; |
| 318 | uint32_t reg_val, rxcount; |
| 319 | int16_t len; |
| 320 | uint16_t status; |
| 321 | int i; |
| 322 | |
| 323 | ifp = sc->emac_ifp; |
| 324 | for (; count > 0 && |
| 325 | (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; count--) { |
| 326 | /* |
| 327 | * Race warning: The first packet might arrive with |
| 328 | * the interrupts disabled, but the second will fix |
| 329 | */ |
| 330 | rxcount = EMAC_READ_REG(sc, EMAC_RX_FBC); |
| 331 | if (!rxcount) { |
| 332 | /* Had one stuck? */ |
| 333 | rxcount = EMAC_READ_REG(sc, EMAC_RX_FBC); |
| 334 | if (!rxcount) |
| 335 | return; |
| 336 | } |
| 337 | /* Check packet header */ |
| 338 | reg_val = EMAC_READ_REG(sc, EMAC_RX_IO_DATA); |
| 339 | if (reg_val != EMAC_PACKET_HEADER) { |
| 340 | /* Packet header is wrong */ |
| 341 | if (bootverbose) |
| 342 | if_printf(ifp, "wrong packet header\n"); |
| 343 | /* Disable RX */ |
| 344 | reg_val = EMAC_READ_REG(sc, EMAC_CTL); |
| 345 | reg_val &= ~EMAC_CTL_RX_EN; |
| 346 | EMAC_WRITE_REG(sc, EMAC_CTL, reg_val); |
| 347 | |
| 348 | /* Flush RX FIFO */ |
| 349 | reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL); |
| 350 | reg_val |= EMAC_RX_FLUSH_FIFO; |
| 351 | EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val); |
| 352 | for (i = 100; i > 0; i--) { |
| 353 | DELAY(100); |
| 354 | if ((EMAC_READ_REG(sc, EMAC_RX_CTL) & |
| 355 | EMAC_RX_FLUSH_FIFO) == 0) |
| 356 | break; |
| 357 | } |
| 358 | if (i == 0) { |
| 359 | device_printf(sc->emac_dev, |
| 360 | "flush FIFO timeout\n"); |
| 361 | /* Reinitialize controller */ |
| 362 | emac_init_locked(sc); |
| 363 | return; |
| 364 | } |
| 365 | /* Enable RX */ |
| 366 | reg_val = EMAC_READ_REG(sc, EMAC_CTL); |
| 367 | reg_val |= EMAC_CTL_RX_EN; |
| 368 | EMAC_WRITE_REG(sc, EMAC_CTL, reg_val); |
| 369 | |
| 370 | return; |
no test coverage detected