/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Tohru Nishimura.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* speed and duplexity are found at 82451 internal GPHY reg 17 */
val = mii_read(l, l->phy, 0x11);
fdx = !!(val & 0x0200);
switch (val & 0xc000) {
case 0x4000: printf("10Mbps"); break;
case 0x8000: printf("100Mbps"); break;
case 0xc000: printf("1000Mbps"); break;
}
if (fdx)
printf("-FDX");
printf("\n");
bound = 1000 * timo;
printf("recving with %u sec. timeout\n", timo);
again:
rxd = &l->rxd[l->rx];
do {
inv(rxd, sizeof(struct rdesc));
rxstat = le32toh(rxd->r3);
if ((rxstat & R3_DD) != 0)
goto gotone;
DELAY(1000); /* 1 milli second */
} while (--bound > 0);
errno = 0;
return -1;
gotone:
/* expect this has R3_EOP mark */
if (rxstat & (R3_CE|R3_SE|R3_SEQ|R3_CXE|R3_RXE)) {
rxd->r2 = 0;
rxd->r3 = 0;
wbinv(rxd, sizeof(struct rdesc));
CSR_WRITE(l, WMREG_RDT, l->rx);
l->rx ^= 1;
goto again;
}
len = (rxstat & R2_FLMASK) - 4 /* HASFCS */;
if (len > maxlen)
len = maxlen;
ptr = l->rxstore[l->rx];
inv(ptr, len);
memcpy(buf, ptr, len);
rxd->r2 = 0;
rxd->r3 = 0;
wbinv(rxd, sizeof(struct rdesc));
CSR_WRITE(l, WMREG_RDT, l->rx);
l->rx ^= 1;
return len;
}
/*
* bare SEEPROM access with bitbang'ing
*/
#define R110 6 /* SEEPROM read op */
#define CS (1U << 0) /* hold chip select */
#define CLK (1U << 1) /* clk bit */
#define D1 (1U << 2) /* bit existence */
#define VV (1U << 3) /* taken 0/1 from SEEPROM */
static int
read_srom(struct local *l, int off)
{
unsigned data, v, i;
data = off & 0xff; /* A5/A7-A0 */
data |= R110 << l->sromsft; /* 110 for READ */
v = CSR_READ(l, WMREG_EECD) & ~(EECD_SK | EECD_DI);
CSR_WRITE(l, WMREG_EECD, v);
v |= EECD_CS; /* hold CS */
CSR_WRITE(l, WMREG_EECD, v);
DELAY(2);
/* instruct R110 op. at off in MSB first order */
for (i = (1 << (l->sromsft + 2)); i != 0; i >>= 1) {
if (data & i)
v |= EECD_DI;
else
v &= ~EECD_DI;
CSR_WRITE(l, WMREG_EECD, v);
DELAY(2);
CSR_WRITE(l, WMREG_EECD, v | EECD_SK);
DELAY(2);
CSR_WRITE(l, WMREG_EECD, v);
DELAY(2);
}
v &= ~EECD_DI;
/* read 16bit quantity in MSB first order */
data = 0;
for (i = 0; i < 16; i++) {
CSR_WRITE(l, WMREG_EECD, v | EECD_SK);
DELAY(2);
data = (data << 1) | !!(CSR_READ(l, WMREG_EECD) & EECD_DO);
CSR_WRITE(l, WMREG_EECD, v);
DELAY(2);
}
/* turn off chip select */
v = CSR_READ(l, WMREG_EECD) & ~EECD_CS;
CSR_WRITE(l, WMREG_EECD, v);
DELAY(2);