On Fri, 14 Sep 2007 23:21:05 +0200 Francois Romieu <[EMAIL PROTECTED]> wrote:
> ... > > + > +static void ipg_dump_tfdlist(struct net_device *dev) > +{ > + struct ipg_nic_private *sp = netdev_priv(dev); > + void __iomem *ioaddr = sp->ioaddr; > + unsigned int i; > + u32 offset; > + > + IPG_DEBUG_MSG("_dump_tfdlist\n"); > + > + printk(KERN_INFO "tx_current = %2.2x\n", sp->tx_current); > + printk(KERN_INFO "tx_dirty = %2.2x\n", sp->tx_dirty); > + printk(KERN_INFO "TFDList start address = %16.16lx\n", > + (unsigned long) sp->txd_map); > + printk(KERN_INFO "TFDListPtr register = %8.8x%8.8x\n", > + ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0)); > + > + for (i = 0; i < IPG_TFDLIST_LENGTH; i++) { > + offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd; > + printk(KERN_INFO "%2.2x %4.4x TFDNextPtr = %16.16lx\n", i, > + offset, (unsigned long) sp->txd[i].next_desc); > + > + offset = (u32) &sp->txd[i].tfc - (u32) sp->txd; Is the u32 cast safe here on all architectures? > + printk(KERN_INFO "%2.2x %4.4x TFC = %16.16lx\n", i, > + offset, (unsigned long) sp->txd[i].tfc); > + offset = (u32) &sp->txd[i].frag_info - (u32) sp->txd; > + printk(KERN_INFO "%2.2x %4.4x frag_info = %16.16lx\n", i, > + offset, (unsigned long) sp->txd[i].frag_info); > + } > +} > > ... > > +static int mdio_read(struct net_device * dev, int phy_id, int phy_reg) > +{ > + void __iomem *ioaddr = ipg_ioaddr(dev); > + /* > + * The GMII mangement frame structure for a read is as follows: > + * > + * |Preamble|st|op|phyad|regad|ta| data |idle| > + * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z | > + * > + * <32 1s> = 32 consecutive logic 1 values > + * A = bit of Physical Layer device address (MSB first) > + * R = bit of register address (MSB first) > + * z = High impedance state > + * D = bit of read data (MSB first) > + * > + * Transmission order is 'Preamble' field first, bits transmitted > + * left to right (first to last). > + */ > + struct { > + u32 field; > + unsigned int len; > + } p[] = { > + { GMII_PREAMBLE, 32 }, /* Preamble */ > + { GMII_ST, 2 }, /* ST */ > + { GMII_READ, 2 }, /* OP */ > + { phy_id, 5 }, /* PHYAD */ > + { phy_reg, 5 }, /* REGAD */ > + { 0x0000, 2 }, /* TA */ > + { 0x0000, 16 }, /* DATA */ > + { 0x0000, 1 } /* IDLE */ > + }; This will be built on the stack at runtime. > + unsigned int i, j; > + u8 polarity, data; > + > + polarity = ipg_r8(PHY_CTRL); > + polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY); > + > + /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */ > + for (j = 0; j < 5; j++) { > + for (i = 0; i < p[j].len; i++) { > + /* For each variable length field, the MSB must be > + * transmitted first. Rotate through the field bits, > + * starting with the MSB, and move each bit into the > + * the 1st (2^1) bit position (this is the bit position > + * corresponding to the MgmtData bit of the PhyCtrl > + * register for the IPG). > + * > + * Example: ST = 01; > + * > + * First write a '0' to bit 1 of the PhyCtrl > + * register, then write a '1' to bit 1 of the > + * PhyCtrl register. > + * > + * To do this, right shift the MSB of ST by the value: > + * [field length - 1 - #ST bits already written] > + * then left shift this result by 1. > + */ > + data = (p[j].field >> (p[j].len - 1 - i)) << 1; > + data &= IPG_PC_MGMTDATA; > + data |= polarity | IPG_PC_MGMTDIR; > + > + ipg_drive_phy_ctl_low_high(ioaddr, data); > + } > + } > + > + send_three_state(ioaddr, polarity); > + > + read_phy_bit(ioaddr, polarity); > + > + /* > + * For a read cycle, the bits for the next two fields (TA and > + * DATA) are driven by the PHY (the IPG reads these bits). > + */ > + for (i = 0; i < p[6].len; i++) { > + p[6].field |= > + (read_phy_bit(ioaddr, polarity) << (p[6].len - 1 - i)); > + } Simply because we're using p[6] as a temporary variable. This can be tightened up. > + send_three_state(ioaddr, polarity); > + send_three_state(ioaddr, polarity); > + send_three_state(ioaddr, polarity); > + send_end(ioaddr, polarity); > + > + /* Return the value of the DATA field. */ > + return p[6].field; > +} > + > +/* > + * Write to a register from the Physical Layer device located > + * on the IPG NIC, using the IPG PHYCTRL register. > + */ > +static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int > val) > +{ > + void __iomem *ioaddr = ipg_ioaddr(dev); > + /* > + * The GMII mangement frame structure for a read is as follows: > + * > + * |Preamble|st|op|phyad|regad|ta| data |idle| > + * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z | > + * > + * <32 1s> = 32 consecutive logic 1 values > + * A = bit of Physical Layer device address (MSB first) > + * R = bit of register address (MSB first) > + * z = High impedance state > + * D = bit of write data (MSB first) > + * > + * Transmission order is 'Preamble' field first, bits transmitted > + * left to right (first to last). > + */ > + struct { > + u32 field; > + unsigned int len; > + } p[] = { > + { GMII_PREAMBLE, 32 }, /* Preamble */ > + { GMII_ST, 2 }, /* ST */ > + { GMII_WRITE, 2 }, /* OP */ > + { phy_id, 5 }, /* PHYAD */ > + { phy_reg, 5 }, /* REGAD */ > + { 0x0002, 2 }, /* TA */ > + { val & 0xffff, 16 }, /* DATA */ > + { 0x0000, 1 } /* IDLE */ > + }; similar here > + unsigned int i, j; > + u8 polarity, data; > + > + polarity = ipg_r8(PHY_CTRL); > + polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY); > + > + /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */ > + for (j = 0; j < 7; j++) { > + for (i = 0; i < p[j].len; i++) { > + /* For each variable length field, the MSB must be > + * transmitted first. Rotate through the field bits, > + * starting with the MSB, and move each bit into the > + * the 1st (2^1) bit position (this is the bit position > + * corresponding to the MgmtData bit of the PhyCtrl > + * register for the IPG). > + * > + * Example: ST = 01; > + * > + * First write a '0' to bit 1 of the PhyCtrl > + * register, then write a '1' to bit 1 of the > + * PhyCtrl register. > + * > + * To do this, right shift the MSB of ST by the value: > + * [field length - 1 - #ST bits already written] > + * then left shift this result by 1. > + */ > + data = (p[j].field >> (p[j].len - 1 - i)) << 1; > + data &= IPG_PC_MGMTDATA; > + data |= polarity | IPG_PC_MGMTDIR; > + > + ipg_drive_phy_ctl_low_high(ioaddr, data); > + } > + } > + > + /* The last cycle is a tri-state, so read from the PHY. */ > + for (j = 7; j < 8; j++) { > + for (i = 0; i < p[j].len; i++) { > + ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity); > + > + p[j].field |= ((ipg_r8(PHY_CTRL) & > + IPG_PC_MGMTDATA) >> 1) << (p[j].len - 1 - i); > + > + ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity); > + } > + } although it might be tricky to avoid > +} > + > > ... > > +static int ipg_reset(struct net_device *dev, u32 resetflags) > +{ > + /* Assert functional resets via the IPG AsicCtrl > + * register as specified by the 'resetflags' input > + * parameter. > + */ > + void __iomem *ioaddr = ipg_ioaddr(dev); //JES20040127EEPROM: > + unsigned int timeout_count = 0; > + > + IPG_DEBUG_MSG("_reset\n"); > + > + ipg_w32(ipg_r32(ASIC_CTRL) | resetflags, ASIC_CTRL); > + > + /* Delay added to account for problem with 10Mbps reset. */ > + mdelay(IPG_AC_RESETWAIT); > + > + while (IPG_AC_RESET_BUSY & ipg_r32(ASIC_CTRL)) { > + mdelay(IPG_AC_RESETWAIT); > + if (++timeout_count > IPG_AC_RESET_TIMEOUT) > + return -ETIME; Is ETIME an appropriate errno here? Zillions of drivers use it, but I think it's for posix timers or something like that? > + } > + /* Set LED Mode in Asic Control JES20040127EEPROM */ > + ipg_set_led_mode(dev); > + > + /* Set PHYSet Register Value JES20040127EEPROM */ > + ipg_set_phy_set(dev); > + return 0; > +} > + > > [vast amounts trimmed] > Attention span expired, sorry. ETIME. - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html