X-Git-Url: http://git.joshuawise.com/netwatch.git/blobdiff_plain/037ce545946a8bc2d482d24e3bbdb6174a93ca46..2a44d50497d0bf670265bd8a2eb5d75cc92ebb08:/net/3c90x.c?ds=inline diff --git a/net/3c90x.c b/net/3c90x.c index 0e695ac..e3236d9 100644 --- a/net/3c90x.c +++ b/net/3c90x.c @@ -224,8 +224,10 @@ typedef struct { unsigned int DnNextPtr; unsigned int FrameStartHeader; - unsigned int DataAddr; - unsigned int DataLength; + struct { + unsigned int addr; + unsigned int len; + } __attribute ((aligned(8))) segments[64]; } TXD __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */ @@ -473,34 +475,30 @@ static void a3c90x_reset(void) *** pkt - the pointer to the packet data itself. ***/ static void -a3c90x_transmit(unsigned int size, const char *pkt) +a3c90x_transmit(struct pbuf *p) { unsigned char status; static unsigned int stillwaiting = 0; - - if (stillwaiting) - { - while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_TXCOMPLETE) && oneshot_running()) - ; - if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_TXCOMPLETE)) - { - outputf("3c90x: tx timeout? txstat %02x", inb(INF_3C90X.IOAddr + regTxStatus_b)); - outputf("3c90x: Gen sts %04x", inw(INF_3C90X.IOAddr + regCommandIntStatus_w)); - } - status = inb(INF_3C90X.IOAddr + regTxStatus_b); - outb(INF_3C90X.IOAddr + regTxStatus_b, 0x00); - stillwaiting = 0; - } + unsigned int n, len; _issue_command(INF_3C90X.IOAddr, cmdStallCtl, 2 /* Stall download */); /** Setup the DPD (download descriptor) **/ INF_3C90X.TransmitDPD.DnNextPtr = 0; + len = 0; + n = 0; + for (; p; p = p->next) + { + INF_3C90X.TransmitDPD.segments[n].addr = (unsigned int)p->payload; + INF_3C90X.TransmitDPD.segments[n].len = p->len | (p->next ? 0 : (1 << 31)); + len += p->len; + n++; + } /** set notification for transmission completion (bit 15) **/ - INF_3C90X.TransmitDPD.FrameStartHeader = (size) | 0x8000; - INF_3C90X.TransmitDPD.DataAddr = v2p((void*)pkt); - INF_3C90X.TransmitDPD.DataLength = size + (1<<31); + INF_3C90X.TransmitDPD.FrameStartHeader = (len) | 0x8000; + outputf("3c90x: Sending %d byte %d seg packet", len, n); + /** Send the packet **/ outl(INF_3C90X.IOAddr + regDnListPtr_l, v2p(&(INF_3C90X.TransmitDPD))); _issue_command(INF_3C90X.IOAddr, cmdStallCtl, 3 /* Unstall download */); @@ -516,6 +514,19 @@ a3c90x_transmit(unsigned int size, const char *pkt) oneshot_start_ms(10); stillwaiting = 1; + if (stillwaiting) + { + while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_TXCOMPLETE) && oneshot_running()) + ; + if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_TXCOMPLETE)) + { + outputf("3c90x: tx timeout? txstat %02x", inb(INF_3C90X.IOAddr + regTxStatus_b)); + outputf("3c90x: Gen sts %04x", inw(INF_3C90X.IOAddr + regCommandIntStatus_w)); + } + status = inb(INF_3C90X.IOAddr + regTxStatus_b); + outb(INF_3C90X.IOAddr + regTxStatus_b, 0x00); + stillwaiting = 0; + } #if 0 /** successful completion (sans "interrupt Requested" bit) **/