Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sandpoint/stand/altboot Driver seems to work now. S...



details:   https://anonhg.NetBSD.org/src/rev/edc6d6909a17
branches:  trunk
changeset: 763032:edc6d6909a17
user:      phx <phx%NetBSD.org@localhost>
date:      Tue Mar 08 19:00:38 2011 +0000

description:
Driver seems to work now. Successfully booted a kernel via BOOTP and NFS on
an ST1023-compatible IC+ IP1000A chip.

diffstat:

 sys/arch/sandpoint/stand/altboot/stg.c |  178 ++++++++++++++++----------------
 1 files changed, 88 insertions(+), 90 deletions(-)

diffs (truncated from 309 to 300 lines):

diff -r c23bd4eb1b1b -r edc6d6909a17 sys/arch/sandpoint/stand/altboot/stg.c
--- a/sys/arch/sandpoint/stand/altboot/stg.c    Tue Mar 08 18:35:10 2011 +0000
+++ b/sys/arch/sandpoint/stand/altboot/stg.c    Tue Mar 08 19:00:38 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: stg.c,v 1.1 2011/03/06 13:55:12 phx Exp $ */
+/* $NetBSD: stg.c,v 1.2 2011/03/08 19:00:38 phx Exp $ */
 
 /*-
  * Copyright (c) 2011 Frank Wille.
@@ -52,17 +52,15 @@
 #define ALLOC(T,A)             (T *)allocaligned(sizeof(T),(A))
 
 struct desc {
-       uint64_t xd0, xd1, xd2;
+       uint64_t xd0, xd1, xd2, dummy;
 };
-/* xd1 */
-#define RXLEN(x)               ((x) & 0xffff)
-#define RXERRORMASK            0x3f0000LL
-#define TXNOALIGN              (1ULL << 16)
-#define TXFRAGCOUNT(x)         (((uint64_t)((x) & 0xf)) << 48)
-#define DONE                   (1ULL << 31)
-/* xd2 */
-#define FRAGADDR(x)            ((uint64_t)(x))
-#define FRAGLEN(x)             (((uint64_t)((x) & 0xffff)) << 48)
+#define T1_EMPTY               (1U << 31)      /* no Tx frame available */
+#define T1_NOALIGN             (03 << 16)      /* allow any Tx alignment */
+#define T1_CNTSHIFT            24              /* Tx fragment count */
+#define T2_LENSHIFT            48              /* Tx frame length */
+#define R1_DONE                        (1U << 31)      /* desc has a Rx frame */
+#define R1_FL_MASK             0xffff          /* Rx frame length */
+#define R1_ER_MASK             0x3f0000        /* Rx error indication */
 
 #define STGE_DMACtrl           0x00
 #define  DMAC_RxDMAComplete    (1U << 3)
@@ -73,6 +71,7 @@
 #define STGE_TFDListPtrHi      0x14
 #define STGE_RFDListPtrLo      0x1c
 #define STGE_RFDListPtrHi      0x20
+#define STGE_DebugCtrl         0x2c
 #define STGE_AsicCtrl          0x30
 #define  AC_PhyMedia           (1U << 7)
 #define  AC_GlobalReset                (1U << 16)
@@ -93,6 +92,8 @@
 #define  EC_EepromBusy         (1U << 15)
 #define STGE_IntEnable         0x5c
 #define STGE_MACCtrl           0x6c
+#define  MC_DuplexSelect       (1U << 5)
+#define  MC_StatisticsDisable  (1U << 22)
 #define  MC_TxEnable           (1U << 24)
 #define  MC_RxEnable           (1U << 27)
 #define STGE_PhyCtrl           0x76
@@ -110,18 +111,17 @@
 #define STGE_StationAddress0   0x78
 #define STGE_StationAddress1   0x7a
 #define STGE_StationAddress2   0x7c
+#define STGE_MaxFrameSize      0x84
+#define STGE_ReceiveMode       0x88
+#define  RM_ReceiveUnicast     (1U << 0)
+#define  RM_ReceiveMulticast   (1U << 1)
+#define  RM_ReceiveBroadcast   (1U << 2)
+#define  RM_ReceiveAllFrames   (1U << 3)
+#define  RM_ReceiveMulticastHash (1U << 4)
+#define  RM_ReceiveIPMulticast (1U << 5)
 
 #define STGE_EEPROM_SA0                0x10
 
-#define MII_PSSR               0x11    /* MAKPHY status register */
-#define  PSSR_DUPLEX           0x2000  /* FDX */
-#define  PSSR_RESOLVED         0x0800  /* speed and duplex resolved */
-#define  PSSR_LINK             0x0400  /* link indication */
-#define  PSSR_SPEED(x)         (((x) >> 14) & 0x3)
-#define  SPEED10               0
-#define  SPEED100              1
-#define  SPEED1000             2
-
 #define FRAMESIZE      1536
 
 struct local {
@@ -162,7 +162,7 @@
        struct desc *txd, *rxd;
        uint8_t *en;
        unsigned i;
-       uint32_t reg;
+       uint32_t macctl, reg;
 
        l = ALLOC(struct local, 32);            /* desc alignment */
        memset(l, 0, sizeof(struct local));
@@ -231,6 +231,43 @@
        DPRINTF(("PHY %d (%04x.%04x)\n", l->phy,
            mii_read(l, l->phy, 2), mii_read(l, l->phy, 3)));
 
+       /* setup descriptors */
+       txd = &l->txd[0];
+       txd[0].xd0 = htole64(VTOPHYS(&txd[1]));
+       txd[0].xd1 = htole64(T1_EMPTY);
+       txd[1].xd0 = htole64(VTOPHYS(&txd[0]));
+       txd[1].xd1 = htole64(T1_EMPTY);
+       rxd = &l->rxd[0];
+       rxd[0].xd0 = htole64(VTOPHYS(&rxd[1]));
+       rxd[0].xd2 = htole64((uint64_t)VTOPHYS(l->rxstore[0]) |
+           ((uint64_t)FRAMESIZE << 48));
+       rxd[1].xd0 = htole64(VTOPHYS(&rxd[0]));
+       rxd[1].xd2 = htole64((uint64_t)VTOPHYS(l->rxstore[1]) |
+           ((uint64_t)FRAMESIZE << 48));
+       wbinv(l, sizeof(struct local));
+
+       CSR_WRITE_2(l, STGE_IntEnable, 0);
+       CSR_WRITE_2(l, STGE_ReceiveMode, RM_ReceiveUnicast |
+           RM_ReceiveBroadcast | RM_ReceiveAllFrames | RM_ReceiveMulticast);
+       CSR_WRITE_4(l, STGE_TFDListPtrHi, 0);
+       CSR_WRITE_4(l, STGE_TFDListPtrLo, VTOPHYS(txd));
+       CSR_WRITE_4(l, STGE_RFDListPtrHi, 0);
+       CSR_WRITE_4(l, STGE_RFDListPtrLo, VTOPHYS(rxd));
+       CSR_WRITE_2(l, STGE_MaxFrameSize, FRAMESIZE);
+       CSR_WRITE_4(l, STGE_MACCtrl, 0);        /* do IFSSelect(0) first */
+       macctl = MC_StatisticsDisable | MC_TxEnable | MC_RxEnable;
+
+       if ((pcicfgread(tag, PCI_CLASS_REG) & 0xff) >= 6) {
+               /* some workarounds for revisions >= 6 */
+               CSR_WRITE_2(l, STGE_DebugCtrl,
+                   CSR_READ_2(l, STGE_DebugCtrl) | 0x0200);
+               CSR_WRITE_2(l, STGE_DebugCtrl,
+                   CSR_READ_2(l, STGE_DebugCtrl) | 0x0010);
+               CSR_WRITE_2(l, STGE_DebugCtrl,
+                   CSR_READ_2(l, STGE_DebugCtrl) | 0x0020);
+       }
+
+       /* auto negotiation, set the current media */
        mii_dealan(l, 5);
 
        reg = CSR_READ_1(l, STGE_PhyCtrl);
@@ -245,34 +282,13 @@
                printf("10Mbps");
                break;
        }
-       if (reg & PC_PhyDuplexStatus)
+       if (reg & PC_PhyDuplexStatus) {
+               macctl |= MC_DuplexSelect;
                printf("-FDX");
+       }
        printf("\n");
+       CSR_WRITE_4(l, STGE_MACCtrl, macctl);
 
-       /* setup descriptors */
-       txd = &l->txd[0];
-       txd[0].xd0 = htole64(VTOPHYS(&txd[1]));
-       txd[0].xd1 = htole64(DONE);
-       txd[1].xd0 = htole64(VTOPHYS(&txd[0]));
-       txd[1].xd1 = htole64(DONE);
-       rxd = &l->rxd[0];
-       rxd[0].xd0 = htole64(VTOPHYS(&rxd[1]));
-       rxd[0].xd2 = htole64(FRAGADDR(VTOPHYS(l->rxstore[0])) |
-           FRAGLEN(FRAMESIZE));
-       rxd[1].xd0 = htole64(VTOPHYS(&rxd[0]));
-       rxd[1].xd2 = htole64(FRAGADDR(VTOPHYS(l->rxstore[1])) |
-           FRAGLEN(FRAMESIZE));
-       wbinv(l, sizeof(struct local));
-
-       CSR_WRITE_2(l, STGE_IntEnable, 0);
-       CSR_WRITE_4(l, STGE_TFDListPtrHi, 0);
-       CSR_WRITE_4(l, STGE_TFDListPtrLo, VTOPHYS(txd));
-       CSR_WRITE_4(l, STGE_RFDListPtrHi, 0);
-       CSR_WRITE_4(l, STGE_RFDListPtrLo, VTOPHYS(rxd));
-       CSR_WRITE_4(l, STGE_MACCtrl, MC_TxEnable | MC_RxEnable);
-#if 0
-       CSR_WRITE_4(l, STGE_DMACtrl, DMAC_RxDMAPollNow | DMAC_TxDMAPollNow);
-#endif
        return l;
 }
 
@@ -285,16 +301,13 @@
 
        wbinv(buf, len);
        txd = &l->txd[l->tx];
-       txd->xd1 = htole64(DONE);
+       txd->xd2 = htole64(VTOPHYS(buf) | ((uint64_t)len << 48));
+       txd->xd1 = htole64(T1_NOALIGN | (1 << 24));
        wbinv(txd, sizeof(struct desc));
-       txd->xd2 = htole64(FRAGADDR(VTOPHYS(buf)) | FRAGLEN(len));
-       txd->xd1 = htole64(DONE | TXNOALIGN | 0x400000 | TXFRAGCOUNT(1));
-       txd->xd1 = htole64(TXNOALIGN | 0x400000 | TXFRAGCOUNT(1));
-       wbinv(txd, sizeof(struct desc));
-       CSR_WRITE_4(l, STGE_DMACtrl, DMAC_TxDMAPollNow);        /* XXX ? */
+       CSR_WRITE_4(l, STGE_DMACtrl, DMAC_TxDMAPollNow);
        loop = 100;
        do {
-               if ((le64toh(txd->xd1) & DONE) != 0)
+               if ((le64toh(txd->xd1) & T1_EMPTY) != 0)
                        goto done;
                DELAY(10);
                inv(txd, sizeof(struct desc));
@@ -311,7 +324,7 @@
 {
        struct local *l = dev;
        volatile struct desc *rxd;
-       uint64_t sts;
+       uint32_t sts;
        unsigned bound, len;
        uint8_t *ptr;
 
@@ -320,21 +333,21 @@
        rxd = &l->rxd[l->rx];
        do {
                inv(rxd, sizeof(struct desc));
-               sts = le64toh(rxd->xd1);
-               if ((sts & DONE) != 0)
+               sts = (uint32_t)le64toh(rxd->xd1);
+               if ((sts & R1_DONE) != 0)
                        goto gotone;
                DELAY(1000);    /* 1 milli second */
        } while (--bound > 0);
        errno = 0;
        return -1;
   gotone:
-       if ((sts & RXERRORMASK) != 0) {
+       if ((sts & R1_ER_MASK) != 0) {
                rxd->xd1 = 0;
                wbinv(rxd, sizeof(struct desc));
                l->rx ^= 1;
                goto again;
        }
-       len = RXLEN(sts);
+       len = sts & R1_FL_MASK;
        if (len > maxlen)
                len = maxlen;
        ptr = l->rxstore[l->rx];
@@ -346,64 +359,49 @@
        return len;
 }
 
-#define MIICMD_START   1
-#define MIICMD_READ    2
-#define MIICMD_WRITE   1
-#define MIICMD_ACK     2
+#define R0110  6               /* 0110b read op */
+#define W0101  5               /* 0101b write op */
+#define A10    2               /* 10b ack turn around */
 
 /* read the MII by bitbanging STGE_PhyCtrl */
 static int
 mii_read(struct local *l, int phy, int reg)
 {
-       int data, i;
+       unsigned data;
+       int i;
        uint8_t v;
 
        /* initiate read access */
-       data = 0;
+       data = (R0110 << 10) | (phy << 5) | reg;
        mii_bitbang_sync(l);
-       mii_bitbang_send(l, MIICMD_START, 2);
-       mii_bitbang_send(l, MIICMD_READ, 2);
-       mii_bitbang_send(l, phy, 5);
-       mii_bitbang_send(l, reg, 5);
+       mii_bitbang_send(l, data, 14); /* 4OP + 5PHY + 5REG */
 
        /* switch direction to PHY->host */
        v = l->phyctrl_saved;
        CSR_WRITE_1(l, STGE_PhyCtrl, v);
-       DELAY(1);
-       mii_bitbang_clk(l, v);
-       if (CSR_READ_1(l, STGE_PhyCtrl) & PC_MgmtData)
-               printf("MII: read error\n");
-       mii_bitbang_clk(l, v);
 
        /* read data */
-       for (i = 0; i < 16; i++) {
+       data = 0;
+       for (i = 0; i < 18; i++) { /* 2TA + 16DATA */
                data <<= 1;
-               if ((CSR_READ_1(l, STGE_PhyCtrl) & PC_MgmtData) != 0)
-                       data |= 1;
+               data |= !!(CSR_READ_1(l, STGE_PhyCtrl) & PC_MgmtData);
                mii_bitbang_clk(l, v);
        }
-       /* reset direction to host->PHY */
-       CSR_WRITE_1(l, STGE_PhyCtrl, v | PC_MgmtDir);
-       return data;
+
+       return data & 0xffff;
 }
 
 /* write the MII by bitbanging STGE_PhyCtrl */
 static void
 mii_write(struct local *l, int phy, int reg, int val)
 {
+       unsigned data;
 
-       /* initiate write access */
+       data = (W0101 << 28) | (phy << 23) | (reg << 18) | (A10 << 16);
+       data |= val;
+
        mii_bitbang_sync(l);
-       mii_bitbang_send(l, MIICMD_START, 2);
-       mii_bitbang_send(l, MIICMD_WRITE, 2);
-       mii_bitbang_send(l, phy, 5);
-       mii_bitbang_send(l, reg, 5);
-



Home | Main Index | Thread Index | Old Index