Misc fixes to support 21041 on Qube2700:

- prepare two TX descriptors to avoid race and also use chaind mode
- use a recently added pcicfgread() function to get tulip I/O address
- use cobalt model id to see if we have 21041 or 21143
  (XXX maybe it's better to see PCI product ID)
- add code to reset SIA on 21041
- prepare and send filter setup packet on init
- reduce delay in RX polling
- bump version again

Now netboot works fine on Qube 2700 (even without console). Yay.
This commit is contained in:
tsutsui 2008-03-01 20:39:25 +00:00
parent 55edbc2411
commit 069af26195
2 changed files with 101 additions and 55 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: tlp.c,v 1.4 2008/03/01 20:24:25 tsutsui Exp $ */
/* $NetBSD: tlp.c,v 1.5 2008/03/01 20:39:25 tsutsui Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@ -72,6 +72,7 @@ do { \
#define T1_FS (1U<<29) /* first segment */
#define T1_SET (1U<<27) /* "setup packet" */
#define T1_TER (1U<<25) /* end of ring mark */
#define T1_TCH (1U<<24) /* Second address chained */
#define T1_TBS_MASK 0x7ff /* segment size 10:0 */
#define R0_OWN (1U<<31) /* desc is empty */
#define R0_FS (1U<<30) /* first desc of frame */
@ -90,18 +91,21 @@ struct desc {
#endif
};
#define TLP_BMR 0x000 /* 0: bus mode */
#define TLP_BMR 0x00 /* 0: bus mode */
#define BMR_RST (1U<< 0) /* software reset */
#define TLP_TPD 0x008 /* 1: instruct Tx to start */
#define BMR_BAR (1U<< 1) /* bus arbitration */
#define BMR_PBL8 (1U<<11) /* burst length 8 longword */
#define BMR_CAL8 (1U<<13) /* cache alignment 8 longword */
#define TLP_TPD 0x08 /* 1: instruct Tx to start */
#define TPD_POLL (1U<< 0) /* transmit poll demand */
#define TLP_RPD 0x010 /* 2: instruct Rx to start */
#define TLP_RPD 0x10 /* 2: instruct Rx to start */
#define RPD_POLL (1U<< 0) /* receive poll demand */
#define TLP_RRBA 0x018 /* 3: Rx descriptor base */
#define TLP_TRBA 0x020 /* 4: Tx descriptor base */
#define TLP_STS 0x028 /* 5: status */
#define TLP_RRBA 0x18 /* 3: Rx descriptor base */
#define TLP_TRBA 0x20 /* 4: Tx descriptor base */
#define TLP_STS 0x28 /* 5: status */
#define STS_TS 0x00700000 /* Tx status */
#define STS_RS 0x000e0000 /* Rx status */
#define TLP_OMR 0x030 /* 6: operation mode */
#define TLP_OMR 0x30 /* 6: operation mode */
#define OMR_SDP (1U<<25) /* always ON */
#define OMR_PS (1U<<18) /* port select */
#define OMR_PM (1U<< 6) /* promicuous */
@ -109,27 +113,40 @@ struct desc {
#define OMR_REN (1U<< 1) /* instruct start/stop Rx */
#define OMR_FD (1U<< 9) /* FDX */
#define TLP_IEN 0x38 /* 7: interrupt enable mask */
#define TLP_APROM 0x048 /* 9: SEEPROM and MII management */
#define TLP_APROM 0x48 /* 9: SEEPROM and MII management */
#define SROM_RD (1U <<14) /* read operation */
#define SROM_WR (1U <<13) /* write openration */
#define SROM_SR (1U <<11) /* SEEPROM select */
#define TLP_CSR12 0x60 /* SIA status */
#define TLP_CSR13 0x68 /* SIA connectivity register */
#define SIACONN_10BT 0x0000ef01 /* 10BASE-T for 21041 */
#define TLP_CSR14 0x70 /* SIA TX RX register */
#define SIATXRX_10BT 0x0000ffff /* 10BASE-T for 21041 pass 2 */
#define TLP_CSR15 0x78 /* SIA general register */
#define SIAGEN_MD0 (1U<<16)
#define SIAGEN_CWE (1U<<28)
#define SIAGEN_10BT 0x00000000 /* 10BASE-T for 21041 */
#define TLP_SETUP_NADDR 16
#define TLP_SETUPLEN 192 /* 16 * 3 * sizeof(uint32_t) */
#define FRAMESIZE 1536
#define BUFSIZE 2048
#define NTXBUF 2
#define NEXT_TXBUF(x) (((x) + 1) & (NTXBUF - 1))
#define NRXBUF 2
#define NEXT_RXBUF(x) (((x) + 1) & (NRXBUF - 1))
struct local {
struct desc txd;
struct desc txd[NTXBUF];
struct desc rxd[NRXBUF];
uint8_t txstore[BUFSIZE];
uint8_t txstore[TLP_SETUPLEN];
uint8_t rxstore[NRXBUF][BUFSIZE];
uint32_t csr, omr;
u_int tx;
u_int rx;
u_int sromsft;
u_int phy;
@ -150,25 +167,33 @@ static void mii_initphy(struct local *);
void *
tlp_init(void *cookie)
{
uint32_t val;
uint32_t val, tag;
struct local *l;
struct desc *txd, *rxd;
uint8_t *en;
uint8_t *en, *p;
int i;
int is21041;
if (cobalt_id == COBALT_ID_QUBE2700)
is21041 = 1;
else
is21041 = 0;
l = ALLOC(struct local, CACHELINESIZE);
memset(l, 0, sizeof(struct local));
DPRINTF(("tlp: l = %p, txd = %p, rxd[0] = %p, rxd[1] = %p\n",
l, &l->txd, &l->rxd[0], &l->rxd[1]));
DPRINTF(("tlp: l = %p, txd[0] = %p, txd[1] = %p\n",
l, &l->txd[0], &l->txd[1]));
DPRINTF(("tlp: rxd[0] = %p, rxd[1] = %p\n",
&l->rxd[0], &l->rxd[1]));
DPRINTF(("tlp: txstore = %p, rxstore[0] = %p, rxstore[1] = %p\n",
l->txstore, l->rxstore[0], l->rxstore[1]));
#if 0
#if 1
/* XXX assume tlp0 at pci0 dev 7 function 0 */
tag = (0 << 16) | ( 7 << 11) | (0 << 8);
/* memory map is not initialized by the firmware on cobalt */
l->csr = MIPS_PHYS_TO_KSEG1(pcicfgread(tag, 0x10) & 0xfffffffc);
l->csr = MIPS_PHYS_TO_KSEG1(pcicfgread(tag, 0x10) & ~3U);
DPRINTF(("%s: CSR = 0x%x\n", __func__, l->csr));
#else
l->csr = MIPS_PHYS_TO_KSEG1(COBALT_TLP0_BASE);
@ -181,10 +206,25 @@ tlp_init(void *cookie)
DELAY(1000);
(void)CSR_READ(l, TLP_BMR);
if (is21041) {
/* reset SIA for 10BASE-T */
CSR_WRITE(l, TLP_CSR13, 0);
DELAY(1000);
CSR_WRITE(l, TLP_CSR15, SIAGEN_10BT);
CSR_WRITE(l, TLP_CSR14, SIATXRX_10BT);
CSR_WRITE(l, TLP_CSR13, SIACONN_10BT);
} else {
/* reset PHY (cobalt quirk from if_tlp_pci.c) */
CSR_WRITE(l, TLP_CSR15, SIAGEN_CWE | SIAGEN_MD0);
DELAY(10);
CSR_WRITE(l, TLP_CSR15, SIAGEN_CWE);
DELAY(10);
}
l->omr = OMR_PS | OMR_SDP;
CSR_WRITE(l, TLP_OMR, l->omr);
CSR_WRITE(l, TLP_STS, ~0);
CSR_WRITE(l, TLP_IEN, 0);
CSR_WRITE(l, TLP_STS, ~0);
#if 0
mii_initphy(l);
@ -213,37 +253,51 @@ tlp_init(void *cookie)
rxd[i].xd1 = htole32(R1_RCH|FRAMESIZE);
rxd[i].xd0 = htole32(R0_OWN);
}
CSR_WRITE(l, TLP_RRBA, VTOPHYS(rxd));
/* "setup packet" to have own station address */
txd = &l->txd;
txd->xd3 = htole32(VTOPHYS(txd));
txd = &l->txd[0];
for (i = 0; i < NTXBUF; i++) {
txd[i].xd3 = htole32(VTOPHYS(&txd[NEXT_TXBUF(i)]));
txd[i].xd0 = htole32(0);
}
/* prepare setup packet */
p = l->txstore;
memset(p, 0, TLP_SETUPLEN);
/* put broadcast first */
p[0] = p[1] = p[4] = p[5] = p[8] = p[9] = 0xff;
for (i = 1; i < TLP_SETUP_NADDR; i++) {
/* put own station address to the rest */
p[i * 12 + 0] = en[0];
p[i * 12 + 1] = en[1];
p[i * 12 + 4] = en[2];
p[i * 12 + 5] = en[3];
p[i * 12 + 8] = en[4];
p[i * 12 + 9] = en[5];
}
txd = &l->txd[0];
txd->xd2 = htole32(VTOPHYS(l->txstore));
txd->xd1 = htole32(T1_SET | T1_TER);
txd->xd0 = htole32(0);
CSR_WRITE(l, TLP_TRBA, VTOPHYS(txd));
memset(l->txstore, 0, FRAMESIZE);
txd->xd1 = htole32(T1_SET | T1_TCH | TLP_SETUPLEN);
txd->xd0 = htole32(T0_OWN);
/* make sure the entire descriptors transfered to memory */
wbinv(l, sizeof(struct local));
l->rx = 0;
l->omr |= OMR_FD | OMR_TEN | OMR_REN;
CSR_WRITE(l, TLP_RRBA, VTOPHYS(rxd));
CSR_WRITE(l, TLP_TRBA, VTOPHYS(txd));
#if 1
/* reset PHY (cobalt quirk from if_tlp_pci.c) */
CSR_WRITE(l, TLP_CSR15, SIAGEN_CWE | SIAGEN_MD0);
DELAY(10);
CSR_WRITE(l, TLP_CSR15, SIAGEN_CWE);
DELAY(10);
#endif
/* start Tx/Rx */
l->tx = NEXT_TXBUF(0);
l->rx = 0;
l->omr |= OMR_TEN | OMR_REN;
if (!is21041)
l->omr |= OMR_FD;
/* enable Tx/Rx */
CSR_WRITE(l, TLP_OMR, l->omr);
#if 0
/* start TX and send setup packet */
CSR_WRITE(l, TLP_TPD, TPD_POLL);
#endif
DELAY(1000);
/* start RX */
CSR_WRITE(l, TLP_RPD, RPD_POLL);
return l;
@ -256,23 +310,14 @@ tlp_send(void *dev, char *buf, u_int len)
struct desc *txd;
u_int loop;
#if 1
wb(buf, len);
txd = &l->txd;
txd->xd3 = htole32(VTOPHYS(txd));
txd = &l->txd[l->tx];
txd->xd2 = htole32(VTOPHYS(buf));
txd->xd1 = htole32(T1_FS | T1_LS | T1_TER | (len & T1_TBS_MASK));
#else
memcpy(l->txstore, buf, len);
wb(l->txstore, len);
txd = &l->txd;
txd->xd3 = htole32(VTOPHYS(txd));
txd->xd2 = htole32(VTOPHYS(l->txstore));
txd->xd1 = htole32(T1_FS | T1_LS | T1_TER | (len & T1_TBS_MASK));
#endif
txd->xd1 = htole32(T1_FS | T1_LS | T1_TCH | (len & T1_TBS_MASK));
txd->xd0 = htole32(T0_OWN);
wbinv(txd, sizeof(struct desc));
CSR_WRITE(l, TLP_TPD, TPD_POLL);
l->tx = NEXT_TXBUF(l->tx);
loop = 100;
do {
if ((le32toh(txd->xd0) & T0_OWN) == 0)
@ -295,7 +340,7 @@ tlp_recv(void *dev, char *buf, u_int maxlen, u_int timo)
uint32_t rxstat;
uint8_t *ptr;
bound = 1000 * timo;
bound = timo * 1000000;
again:
rxd = &l->rxd[l->rx];
@ -304,7 +349,7 @@ tlp_recv(void *dev, char *buf, u_int maxlen, u_int timo)
inv(rxd, sizeof(struct desc));
if ((rxstat & R0_OWN) == 0)
goto gotone;
DELAY(1000); /* 1 milli second */
DELAY(1);
} while (--bound > 0);
errno = 0;
CSR_WRITE(l, TLP_RPD, RPD_POLL);

View File

@ -1,4 +1,4 @@
$NetBSD: version,v 1.7 2008/03/01 17:45:11 tsutsui Exp $
$NetBSD: version,v 1.8 2008/03/01 20:39:25 tsutsui Exp $
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
file is important - make sure the entries are appended on end, last item
@ -11,3 +11,4 @@ is taken as the current.
set default boot device accordingly
0.5: Add support for netboot via tlp0
0.6: Print a cobalt model name in banner
0.7: Add support for netboot via 21041 on Qube2700