update dm9000a driver to fix 16bit transmit bug.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@238 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
bernard.xiong 2009-12-27 06:45:49 +00:00
parent 81c1b21e5d
commit 6abb53c3d4
1 changed files with 38 additions and 65 deletions

View File

@ -160,7 +160,7 @@ void rt_dm9000_isr()
dm9000_io_write(DM9000_ISR, int_status); /* Clear ISR status */ dm9000_io_write(DM9000_ISR, int_status); /* Clear ISR status */
DM9000_TRACE("dm9000 isr: int status %04x\n", int_status); DM9000_TRACE("dm9000 isr: int status %04x\n", int_status);
/* receive overflow */ /* receive overflow */
if (int_status & ISR_ROS) if (int_status & ISR_ROS)
{ {
@ -194,7 +194,7 @@ void rt_dm9000_isr()
if (dm9000_device.packet_cnt > 0) if (dm9000_device.packet_cnt > 0)
{ {
DM9000_TRACE("dm9000 isr: tx second packet\n"); DM9000_TRACE("dm9000 isr: tx second packet\n");
/* transmit packet II */ /* transmit packet II */
/* Set TX length to DM9000 */ /* Set TX length to DM9000 */
dm9000_io_write(DM9000_TXPLL, dm9000_device.queue_packet_len & 0xff); dm9000_io_write(DM9000_TXPLL, dm9000_device.queue_packet_len & 0xff);
@ -362,15 +362,6 @@ static rt_err_t rt_dm9000_control(rt_device_t dev, rt_uint8_t cmd, void *args)
/* transmit packet. */ /* transmit packet. */
rt_err_t rt_dm9000_tx( rt_device_t dev, struct pbuf* p) rt_err_t rt_dm9000_tx( rt_device_t dev, struct pbuf* p)
{ {
struct pbuf* q;
rt_int32_t len;
rt_uint16_t* ptr;
#if DM9000_DEBUG
rt_uint8_t* dump_ptr;
rt_uint32_t cnt = 0;
#endif
DM9000_TRACE("dm9000 tx: %d\n", p->tot_len); DM9000_TRACE("dm9000 tx: %d\n", p->tot_len);
/* lock DM9000 device */ /* lock DM9000 device */
@ -382,34 +373,45 @@ rt_err_t rt_dm9000_tx( rt_device_t dev, struct pbuf* p)
/* Move data to DM9000 TX RAM */ /* Move data to DM9000 TX RAM */
DM9000_outb(DM9000_IO_BASE, DM9000_MWCMD); DM9000_outb(DM9000_IO_BASE, DM9000_MWCMD);
for (q = p; q != NULL; q = q->next)
{ {
len = q->len; /* q traverses through linked list of pbuf's
ptr = q->payload; * This list MUST consist of a single packet ONLY */
struct pbuf *q;
rt_uint16_t pbuf_index = 0;
rt_uint8_t word[2], word_index = 0;
#if DM9000_DEBUG q = p;
dump_ptr = q->payload; /* Write data into dm9000a, two bytes at a time
#endif * Handling pbuf's with odd number of bytes correctly
* No attempt to optimize for speed has been made */
/* use 16bit mode to write data to DM9000 RAM */ while (q)
while (len > 0) {
{ if (pbuf_index < q->len)
DM9000_outw(DM9000_DATA_BASE, *ptr); {
ptr ++; word[word_index++] = ((u8_t*)q->payload)[pbuf_index++];
len -= 2; if (word_index == 2)
{
#ifdef DM9000_DEBUG DM9000_outw(DM9000_DATA_BASE, (word[1] << 8) | word[0]);
DM9000_TRACE("%02x ", *dump_ptr++); word_index = 0;
if (++cnt % 16 == 0) DM9000_TRACE("\n"); }
#endif }
} else
{
q = q->next;
pbuf_index = 0;
}
}
/* One byte could still be unsent */
if (word_index == 1)
{
DM9000_outw(DM9000_DATA_BASE, word[0]);
}
} }
DM9000_TRACE("\n");
if (dm9000_device.packet_cnt == 0) if (dm9000_device.packet_cnt == 0)
{ {
DM9000_TRACE("dm9000 tx: first packet\n"); DM9000_TRACE("dm9000 tx: first packet\n");
dm9000_device.packet_cnt ++; dm9000_device.packet_cnt ++;
/* Set TX length to DM9000 */ /* Set TX length to DM9000 */
dm9000_io_write(DM9000_TXPLL, p->tot_len & 0xff); dm9000_io_write(DM9000_TXPLL, p->tot_len & 0xff);
@ -446,11 +448,6 @@ struct pbuf *rt_dm9000_rx(rt_device_t dev)
struct pbuf* p; struct pbuf* p;
rt_uint32_t rxbyte; rt_uint32_t rxbyte;
#if DM9000_DEBUG
rt_uint8_t* dump_ptr;
rt_uint32_t cnt = 0;
#endif
/* init p pointer */ /* init p pointer */
p = RT_NULL; p = RT_NULL;
@ -468,7 +465,7 @@ struct pbuf *rt_dm9000_rx(rt_device_t dev)
if (rxbyte > 1) if (rxbyte > 1)
{ {
DM9000_TRACE("dm9000 rx: rx error, stop device\n"); DM9000_TRACE("dm9000 rx: rx error, stop device\n");
dm9000_io_write(DM9000_RCR, 0x00); /* Stop Device */ dm9000_io_write(DM9000_RCR, 0x00); /* Stop Device */
dm9000_io_write(DM9000_ISR, 0x80); /* Stop INT request */ dm9000_io_write(DM9000_ISR, 0x80); /* Stop INT request */
} }
@ -493,20 +490,11 @@ struct pbuf *rt_dm9000_rx(rt_device_t dev)
data = (rt_uint16_t*)q->payload; data = (rt_uint16_t*)q->payload;
len = q->len; len = q->len;
#if DM9000_DEBUG
dump_ptr = q->payload;
#endif
while (len > 0) while (len > 0)
{ {
*data = DM9000_inw(DM9000_DATA_BASE); *data = DM9000_inw(DM9000_DATA_BASE);
data ++; data ++;
len -= 2; len -= 2;
#if DM9000_DEBUG
DM9000_TRACE("%02x ", *dump_ptr++);
if (++cnt % 16 == 0) DM9000_TRACE("\n");
#endif
} }
} }
DM9000_TRACE("\n"); DM9000_TRACE("\n");
@ -570,7 +558,6 @@ struct pbuf *rt_dm9000_rx(rt_device_t dev)
return p; return p;
} }
static void RCC_Configuration(void) static void RCC_Configuration(void)
{ {
/* enable gpiob port clock */ /* enable gpiob port clock */
@ -666,8 +653,6 @@ void rt_hw_dm9000_init()
eth_device_init(&(dm9000_device.parent), "e0"); eth_device_init(&(dm9000_device.parent), "e0");
} }
#ifdef RT_USING_FINSH
#include <finsh.h>
void dm9000(void) void dm9000(void)
{ {
rt_kprintf("\n"); rt_kprintf("\n");
@ -686,20 +671,8 @@ void dm9000(void)
rt_kprintf("IMR (0xFF): %02x\n", dm9000_io_read(DM9000_IMR)); rt_kprintf("IMR (0xFF): %02x\n", dm9000_io_read(DM9000_IMR));
rt_kprintf("\n"); rt_kprintf("\n");
} }
#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT(dm9000, dm9000 register dump); FINSH_FUNCTION_EXPORT(dm9000, dm9000 register dump);
void rx(void)
{
rt_err_t result;
dm9000_io_write(DM9000_ISR, ISR_PRS); /* Clear rx status */
/* a frame has been received */
result = eth_device_ready(&(dm9000_device.parent));
if (result != RT_EOK) rt_kprintf("eth notification failed\n");
RT_ASSERT(result == RT_EOK);
}
FINSH_FUNCTION_EXPORT(rx, notify packet rx);
#endif #endif