if_hpp.c
来自「GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目」· C语言 代码 · 共 691 行 · 第 1/2 页
C
691 行
{ int s, unit = minor(dev); struct bus_device *bd; struct hppsoftc *hpp; struct nssoftc *ns = &hppnssoftc[unit]; int ioaddr = ns->sc_port - HPP_NIC_OFFSET; int option_reg; if (unit < 0 || unit >= NHPP || (bd = hpp_info[unit]) == 0 || !(bd->alive)) return ENXIO; /* * Start watchdog. */ if (!hppwstart) { hppwstart++; timeout(hppwatch, 0, hz); } hpp = &hppsoftc[unit]; ns->sc_if.if_flags |= IFF_UP; s = splimp(); /* Reset the 8390 and HP chip. */ option_reg = inw(ioaddr + HPP_OPTION); outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) ); IO_DELAY; IO_DELAY; /* Unreset the board and enable interrupts. */ outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset)); /* Set the wrap registers for programmed-I/O operation. */ outw( ioaddr + HP_PAGING, HW_Page ); outw( ioaddr + 14, (HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8) ); /* Select the operational page. */ outw( ioaddr + HP_PAGING, Perf_Page ); nsinit(ns); splx(s); return (0);}/* * needs to be called at splimp()? * */voidhpp_reset_8390(ns) struct nssoftc *ns;{ int ioaddr = ns->sc_port - HPP_NIC_OFFSET; int option_reg = inw(ioaddr + HPP_OPTION); outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) ); /* Pause a few cycles for the hardware reset to take place. */ IO_DELAY; IO_DELAY; ns->sc_txing = 0; outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset) ); /* * XXX - I'm not sure there needs to be this many IO_DELAY's... */ IO_DELAY; IO_DELAY; IO_DELAY; IO_DELAY; if ((inb_p(ioaddr + HPP_NIC_OFFSET + EN0_ISR) & ENISR_RESET) == 0) printf("%s: hp_reset_8390() did not complete.\n", ns->sc_name); return;}/* * Block input and output, similar to the Crynwr packet driver. * Note that transfer with the EtherTwist+ must be on word boundaries. */voidhpp_io_block_input(ns, count, buf, ring_offset) struct nssoftc *ns; int count; char *buf; int ring_offset;{ int ioaddr = ns->sc_port - HPP_NIC_OFFSET; outw(ioaddr + HPP_IN_ADDR, ring_offset); insw(ioaddr + HP_DATAPORT, buf, count >> 1 ); if (count & 0x01) buf[count-1] = (char) inw(ioaddr + HP_DATAPORT);}voidhpp_mem_block_input(ns, count, buf, ring_offset) struct nssoftc *ns; int count; char *buf; int ring_offset;{ int ioaddr = ns->sc_port - HPP_NIC_OFFSET; int option_reg = inw(ioaddr + HPP_OPTION); char *mem_start = (char *)phystokv(hppsoftc[ns->sc_unit].mem_start); outw(ioaddr + HPP_IN_ADDR, ring_offset); outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb)); /* copy as much as we can straight through */ bcopy16(mem_start, buf, count & ~1); /* Now we copy that last byte. */ if (count & 0x01) { u_short savebyte[2]; bcopy16(mem_start + (count & ~1), savebyte, 2); buf[count-1] = savebyte[0]; } outw(ioaddr + HPP_OPTION, option_reg);}/* * output data into NIC buffers. * * NOTE: All transfers must be on word boundaries. */inthpp_io_block_output(ns, count, buf, start_page) struct nssoftc *ns; int count; char *buf; int start_page;{ int ioaddr = ns->sc_port - HPP_NIC_OFFSET; outw(ioaddr + HPP_OUT_ADDR, start_page << 8) ; if (count > 1) { outsw(ioaddr + HP_DATAPORT, buf, count >> 1); } if ( (count & 1) == 1 ) { u_char savebyte[2]; savebyte[1] = 0; savebyte[0] = buf[count - 1]; outw(ioaddr + HP_DATAPORT, *(u_short *)savebyte); } if (count < (ETHERMIN + sizeof( struct ether_header ))) count = ETHERMIN + sizeof( struct ether_header ); return (count) ;}/* XXX * * I take great pains to not try and bcopy past the end of the buffer, * does this matter? Are the io request buffers the exact byte size? */inthpp_mem_block_output(ns, count, buf, start_page ) struct nssoftc *ns; int count; char *buf; int start_page;{ int ioaddr = ns->sc_port - HPP_NIC_OFFSET; int option_reg = inw(ioaddr + HPP_OPTION); struct hppsoftc *hpp = &hppsoftc[ns->sc_unit]; char *shmem; outw(ioaddr + HPP_OUT_ADDR, start_page << 8); outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb)); shmem = (char *)phystokv(hpp->mem_start); bcopy16(buf, shmem, count & ~1); if ( (count & 1) == 1 ) { u_char savebyte[2]; savebyte[1] = 0; savebyte[0] = buf[count - 1]; bcopy16(savebyte, shmem + (count & ~1), 2); } while (count < ETHERMIN + sizeof(struct ether_header)) { *(shmem + count) = 0; count++; } outw(ioaddr + HPP_OPTION, option_reg); return count;}inthppintr(unit) int unit;{ nsintr(&hppnssoftc[unit]); return(0);}voidhppstart(unit) int unit;{ nsstart(&hppnssoftc[unit]);}int hppoutput();inthppoutput(dev, ior) dev_t dev; io_req_t ior;{ int unit = minor(dev); struct bus_device *ui; if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) return (ENXIO); return (net_write(&hppnssoftc[unit].sc_if, hppstart, ior));}inthppsetinput(dev, receive_port, priority, filter, filter_count) dev_t dev; mach_port_t receive_port; int priority; filter_t *filter; unsigned filter_count;{ int unit = minor(dev); struct bus_device *ui; if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) return (ENXIO); return (net_set_filter(&hppnssoftc[unit].sc_if, receive_port, priority, filter, filter_count));}inthppgetstat(dev, flavor, status, count) dev_t dev; int flavor; dev_status_t status; unsigned *count;{ int unit = minor(dev); struct bus_device *ui; if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) return (ENXIO); return (net_getstat(&hppnssoftc[unit].sc_if, flavor, status, count));}inthppsetstat(dev, flavor, status, count) dev_t dev; int flavor; dev_status_t status; unsigned count;{ int unit = minor(dev), oflags, s; struct bus_device *ui; struct ifnet *ifp; struct net_status *ns; if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) return (ENXIO); ifp = &hppnssoftc[unit].sc_if; switch (flavor) { case NET_STATUS: if (count < NET_STATUS_COUNT) return (D_INVALID_SIZE); ns = (struct net_status *)status; oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC); ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC); ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC); if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) { s = splimp(); nsinit(&hppnssoftc[unit]); splx(s); } break; default: return (D_INVALID_OPERATION); } return (D_SUCCESS);}/* * Watchdog. * Check for hung transmissions. */voidhppwatch(){ int unit, s; struct nssoftc *ns; timeout(hppwatch, 0, hz); s = splimp(); for (unit = 0; unit < NHPP; unit++) { if (hpp_info[unit] == 0 || hpp_info[unit]->alive == 0) continue; ns = &hppnssoftc[unit]; if (ns->sc_timer && --ns->sc_timer == 0) { printf("hpp%d: transmission timeout\n", unit); (*ns->sc_reset)(ns); nsinit(ns); } } splx(s);}#endif /* NHPP > 0 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?