From: Russ D. <ru...@us...> - 2003-11-27 03:30:53
|
Update of /cvsroot/blob/blob/src/lib In directory sc8-pr-cvs1:/tmp/cvs-serv1524 Modified Files: ether-s3c2500.c Log Message: fix halts in s3c2500 ether driver Index: ether-s3c2500.c =================================================================== RCS file: /cvsroot/blob/blob/src/lib/ether-s3c2500.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- ether-s3c2500.c 5 Sep 2003 01:09:45 -0000 1.2 +++ ether-s3c2500.c 27 Nov 2003 03:30:50 -0000 1.3 @@ -1,3 +1,4 @@ + /* * ether-s3c2500.c: Low-level ethernet polling functions * @@ -55,10 +56,9 @@ #define NFRAMESB 4 #define NFRAMES (1 << NFRAMESB) -struct buffer_t tx_buffer, rx_buffer[NFRAMES]; +#define __uncached __attribute__ ((__section__(".uncached"))) -/* rx buffers */ -u8 pkts[NFRAMES][PKT_SIZE]; +struct buffer_t *tx_buffer, *rx_buffer; static int dbg = 0; static u32 s3c2500_ether_chip_base = 0; @@ -125,31 +125,41 @@ u32 stat, len, base, pos, desc, copy_len; int ret = 0, i; u8 *copy_base; + int error = 0; if (!(base = s3c2500_ether_chip_base)) return -EINVAL; i = curr_desc; - /* do we own it yet? */ - if (rx_buffer[i].desc & BDMA_owner) return 0; - /* Read/clear stat */ stat = se_inw(base + BMRXSTAT); se_outw(base + BMRXSTAT, 0); + /* do we own it yet? */ + if (rx_buffer[i].desc & BDMA_owner) goto done; + /* do we have a packet? */ - if (!(rx_buffer[i].desc & BRxDone)) return 0; + if (!(rx_buffer[i].desc & BRxDone)) { + /* We have one, either there is a problem with it, + * or the engine isn't truly done yet */ + if (rx_buffer[i].desc & (DescMSO | DescHalted | DescRxParErr | + DescMUFS | DescOverflow | DescCRCErr | + DescAlignErr)) + error = 1; + else goto done; /* not quite ready yet */ + } pos = 0; len = rx_buffer[i].desc & 0xffff; len -= 4; /* Strip the FCS */ + if (len > length) error = 1; do { desc = rx_buffer[i].desc; - /* only do the copying if it will fit */ - if (len <= length) { + /* only do the copying if its ok */ + if (!error) { copy_base = rx_buffer[i].ptr; if (desc & DescEOF) copy_len = len - pos; else copy_len = PKT_SIZE; @@ -163,17 +173,21 @@ i = (i + 1) % NFRAMES; } while (!(desc & DescEOF)); - /* Reenable used (or discarded) for reception */ + /* Reenable used (or discarded) buffers for reception */ do { rx_buffer[curr_desc++].desc = BDMA_owner; if (curr_desc >= NFRAMES) curr_desc = 0; } while (i != curr_desc); + if (!error) ret = len; + +done: /* Make sure transmission is still enabled */ - se_bset(base + BDMARXCON, BRxEn); - se_bset(base + MACRXCON, MRxEn); + se_outw(base + BDMARXCON, BRxEn | (0x2 << BRxMSL) | + (NFRAMESB << BRxNBD)); + se_outw(base + MACRXCON, MRxEn); - return (len <= length) ? len : 0; + return ret; } @@ -193,11 +207,11 @@ } /* wait for the descriptor to free up */ - while (tx_buffer.desc & BDMA_owner); + while (tx_buffer->desc & BDMA_owner); /* Setup the descriptor */ - tx_buffer.ptr = (u8 *) data; - tx_buffer.desc = length | ((((u32) data) % 4) << 16) | BDMA_owner; + tx_buffer->ptr = (u8 *) data; + tx_buffer->desc = length | ((((u32) data) % 4) << 16) | BDMA_owner; /* Make sure everything is ready to go */ se_bset(base + BDMATXCON, BTxEn); @@ -210,7 +224,7 @@ se_outw(base + BMTXSTAT, 0x0); /* give it back */ - tx_buffer.desc = 0; + tx_buffer->desc = 0; return 0; } @@ -243,10 +257,20 @@ } +void *malloc_uncached(u32 size) +{ + static char *uncached_area = (char *) 0x1F00000L; + char *ret = uncached_area; + uncached_area += size; + return ret; +} + + /* Enable everything */ static void s3c2500_ether_enable(u32 base) { int i; + /* Set the MAC to full duplex */ se_outw(base + MACCON, MACFD); @@ -254,14 +278,14 @@ se_outw(base + BDMARXLEN, PKT_SIZE | MAX_FRAME << 16); /* point the chip to our buffers */ - se_outw(base + BDMATXDPTR, (u32) &tx_buffer); - se_outw(base + BDMARXDPTR, (u32) &rx_buffer); + se_outw(base + BDMATXDPTR, (u32) tx_buffer); + se_outw(base + BDMARXDPTR, (u32) rx_buffer); /* setup our buffer descriptors */ - tx_buffer.ptr = 0; - tx_buffer.desc = 0; + tx_buffer->ptr = 0; + tx_buffer->desc = 0; for (i = 0; i < NFRAMES; i++) { - rx_buffer[i].ptr = (u8 *) pkts[i]; + rx_buffer[i].ptr = malloc_uncached(PKT_SIZE); rx_buffer[i].desc = BDMA_owner; } curr_desc = 0; @@ -289,8 +313,10 @@ static int s3c2500_ether_init(u32 base) { - DBG(1, "%s(%08x)\n", __FUNCTION__, base); + + tx_buffer = malloc_uncached(sizeof(struct buffer_t)); + rx_buffer = malloc_uncached(sizeof(struct buffer_t) * NFRAMES); s3c2500_ether_chip_base = base; |