Date: Tue, 17 Sep 2002 15:48:47 +0200 (CEST) From: Harti Brandt <brandt@fokus.gmd.de> To: Bruce Evans <bde@zeta.org.au> Cc: Don Lewis <dl-freebsd@catspoiler.org>, <brandt@fokus.gmd.de>, <phk@critter.freebsd.dk>, <archie@dellroad.org>, <joe@FreeBSD.org>, <obrien@FreeBSD.org>, <cvs-committers@FreeBSD.org>, <cvs-all@FreeBSD.org> Subject: Re: cvs commit: src/sys/kern kern_timeout.c Message-ID: <20020917153943.X812-200000@beagle.fokus.gmd.de> In-Reply-To: <20020917233828.H11067-100000@gamplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] On Tue, 17 Sep 2002, Bruce Evans wrote: BE>On Tue, 17 Sep 2002, Don Lewis wrote: BE> BE>> On 17 Sep, Harti Brandt wrote: BE>> .... BE>> > (1) replaced all calls to DELAY(1) with a bus_space_read_4() on a card BE>> > address. Because there are 184 DELAY(1) calls in each xl_mii_readreg each BE>> > of which takes a mean of 8.5usecs this cuts down the overall time from BE>> > 1.8msec to around 320usecs. BE>> BE>> I think we're probably ok here. The standard says the minimum high and BE>> low times for the clock signal are 160ns, with a minimum clock period of BE>> 400ns. If I do the math correctly, your scheme wiggles something about BE>> every 1.7us. BE> BE>Maybe the total time can be reduced a lot more by using the minimum delays BE>specified by the standard (using nanodelay(9unimplemented)). You would BE>find out if there is hardware that doesn't comply with the standard :-). I have reduced the time to around 240usec per readreg and 950usec per xl_status_update by removing the delays altogether. This is possible, because the macros used to toggle the bits first do a read to the address and then only a write. The delay introduced by this read is enough it seems. The time could be reduced further (if we had nanodelay()) by not reading the registers, but by using nanodelay() and writes. This is possible because we always know what we have in the register so there is no point in reading it. I can reduce the time to 100usec per readreg by not writing the 32bit sync preamble. The PHY normally should signal this ability in a bit in the BMSR. Mine doesn't, but works without preamble (a comment in the linux driver suggests that all except some very old cards work without preamble). See attached diffs. harti -- harti brandt, http://www.fokus.gmd.de/research/cc/cats/employees/hartmut.brandt/private brandt@fokus.gmd.de, brandt@fokus.fhg.de [-- Attachment #2 --] Index: if_xl.c =================================================================== RCS file: /usr/ncvs/src/sys/pci/if_xl.c,v retrieving revision 1.105 diff -u -r1.105 if_xl.c --- if_xl.c 24 Aug 2002 00:02:03 -0000 1.105 +++ if_xl.c 16 Sep 2002 14:00:55 -0000 @@ -356,6 +356,16 @@ CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~x) +#define MII_SETCLR(x,y) \ + CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ + (CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~y) | x) + +static __inline void +xl_mii_delay(struct xl_softc *sc, u_int addr) +{ + CSR_READ_4(sc, addr); +} + /* * Sync the PHYs by setting data bit and strobing the clock 32 times. */ @@ -370,9 +380,9 @@ for (i = 0; i < 32; i++) { MII_SET(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); MII_CLR(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); } return; @@ -390,18 +400,18 @@ int i; XL_SEL_WIN(4); - MII_CLR(XL_MII_CLK); + /* XXX MII_CLR(XL_MII_CLK); */ + /* XXX could join the MII_SET/CLR of data with the CLR of the clock */ for (i = (0x1 << (cnt - 1)); i; i >>= 1) { if (bits & i) { - MII_SET(XL_MII_DATA); + MII_SETCLR(XL_MII_DATA, XL_MII_CLK); } else { - MII_CLR(XL_MII_DATA); + MII_CLR((XL_MII_DATA | XL_MII_CLK)); } - DELAY(1); - MII_CLR(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); MII_SET(XL_MII_CLK); + xl_mii_delay(sc, XL_W4_PHY_MGMT); } } @@ -433,11 +443,6 @@ XL_SEL_WIN(4); CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0); - /* - * Turn on data xmit. - */ - MII_SET(XL_MII_DIR); - xl_mii_sync(sc); /* @@ -448,20 +453,20 @@ xl_mii_send(sc, frame->mii_phyaddr, 5); xl_mii_send(sc, frame->mii_regaddr, 5); - /* Idle bit */ - MII_CLR((XL_MII_CLK|XL_MII_DATA)); - DELAY(1); - MII_SET(XL_MII_CLK); - DELAY(1); - /* Turn off xmit. */ MII_CLR(XL_MII_DIR); + /* turnaround */ + MII_CLR((XL_MII_CLK|XL_MII_DATA)); + xl_mii_delay(sc, XL_W4_PHY_MGMT); + MII_SET(XL_MII_CLK); + xl_mii_delay(sc, XL_W4_PHY_MGMT); + /* Check for ack */ MII_CLR(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); MII_SET(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA; /* @@ -471,31 +476,29 @@ if (ack) { for(i = 0; i < 16; i++) { MII_CLR(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); MII_SET(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); } goto fail; } for (i = 0x8000; i; i >>= 1) { MII_CLR(XL_MII_CLK); - DELAY(1); - if (!ack) { - if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA) - frame->mii_data |= i; - DELAY(1); - } + xl_mii_delay(sc, XL_W4_PHY_MGMT); + if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA) + frame->mii_data |= i; MII_SET(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); } fail: + /* Idle bit */ MII_CLR(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); MII_SET(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); XL_UNLOCK(sc); @@ -544,9 +547,9 @@ /* Idle bit. */ MII_SET(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); MII_CLR(XL_MII_CLK); - DELAY(1); + xl_mii_delay(sc, XL_W4_PHY_MGMT); /* * Turn off xmit.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020917153943.X812-200000>
