基于S3C2440A的DM9000A的调试笔记

刘启明2010-5-3
  FL2440的开发板提供了DM9000A的驱动源码,在开发板上测试通过,能正常上网。将驱动移到公司的机器上,由于公司的硬件电路和FL2440上连接有一些差别,所以移起来并不是那么一帆风顺。
  对比飞凌开发板和公司产品的硬件电路,区别如下:
  一:飞凌开发板的DM9000A,中断脚即34脚连到了2440的GPF7,而公司产品连到了GPF3.
  二:FL2440的DM9000A选择脚CS脚,即37脚连到了2440的NGCS4,而公司产品连到了NGCS1.
  三:FL2440的DM9000A的CMD脚,即第32脚连到了2440地址总线的ADDR2,而公司产品却连到了ADDR11.
  四:网口,FL2440用的HR911105A,而公司产品为了省钱,这么昂贵的东西舍不得啊,不过对编程这个没有影响。
  这里我们只关心前面三点,第一点,中断脚。在整个DM9000A的源码中,找不到中断脚的任何配置,首先这个就难住了一片人。我们仔细分析,发现在Dm9isa.cpp的开头处,有这么一个结构数组:
  CONFIG_PARAMETER g_szDm9ConfigParams[] =
  {
  { CID_CONNECTION_TYPE, -1, NDIS_STRING_CONST("ConnectionType") },
  { CID_SLOT_NUMBER, -1, NDIS_STRING_CONST("SlotNumber")},
  { CID_BUFFER_PHYSICAL_ADDRESS, 0, NDIS_STRING_CONST("BufferPhysicalAddress")},
  { CID_TXBUFFER_NUMBER, 0x20, NDIS_STRING_CONST("XmitBuffer")},
  { CID_RXBUFFER_NUMBER, 0x10, NDIS_STRING_CONST("RecvBuffer")},
  { CID_ADAPTER_NUMBER, 0, NDIS_STRING_CONST("AdapterNumber")},
  { CID_IO_BASE_ADDRESS, 0x08300000/*0x08000300*/, NDIS_STRING_CONST("IoAddress")},// 这样应该就改成nGCS1了吧!!!
  //{ CID_IO_BASE_ADDRESS, 0x20300000, NDIS_STRING_CONST("IoAddress")},
  { CID_IO_RANGE, 0x10, NDIS_STRING_CONST("IoRange")},
  //{ CID_IRQ_NUMBER, 0X23, NDIS_STRING_CONST("IrqNumber")},
  { CID_IRQ_NUMBER, 0x3, NDIS_STRING_CONST("IrqNumber")},// 这里是物理中断号.K390硬件接GPF3.lqm:10-04-30
  { -1,-1,NULL}
  };
  这里CID_IRQ_NUMBER表示DM9000A所连接的物理中断号,FL2440默认为0x23,转化为十进制为35,在s3c2440a_intr.h里面,不然发现,原来35表示IRQ_EINT7,其定义如下:
  #define IRQ_EINT7 35
  这就是定义DM9000A的中断所在!由于公司产品使用的是GPF3,同样看s3c2440a_intr.h里面的定义,发现IRQ_EINT3=3,于是我们顺理成章的将0x23改成了0x3。
  上面数组中还有一个数字很重要,0x20300000。打开三星的内存映射表,具体如下:
  可以看到,上面的地址在bank4的范围内,而bank4是通过nGCS4选择的!这一点与FL2440的硬件连接不谋而合,这也正是为什么飞凌DM9000A驱动使用这个地址的原因所在!由于公司产品使用的nGCS1,于是我将地址改成了0x80000300。
  也许你认为两处差异,一下子就在这里解决了,其实事情远没有这么简单!难道中断,就只用在一个数组里面定义就OK了吗?仔细看驱动源代码,不然发现程序是通过读取注册表的键值来决定中断,IP地址等的。打开注册表,platform.reg,相关代码如下:
  IF BSP_DM9000 !
  [HKEY_LOCAL_MACHINE/Comm/DM9CE]
  "DisplayName"="DM9000A/9010 ISA Fast Ethernet Adapter"
  "Group"="NDIS"
  "ImagePath"="dm9isa.dll"
  [HKEY_LOCAL_MACHINE/Comm/DM9CE/Linkage]
  "Route"=multi_sz:"dm9ce1"
  [HKEY_LOCAL_MACHINE/Comm/DM9CE1]
  "DisplayName"="DM9000A/9010 ISA Fast Ethernet Adapter"
  "Group"="NDIS"
  "ImagePath"="dm9isa.dll"
  [HKEY_LOCAL_MACHINE/Comm/Tcpip/Linkage]
  "Bind"="dm9ce1"
  [HKEY_LOCAL_MACHINE/Comm/DM9CE1/Parms]
  "BusNumber"=dword:0
  "BusType"=dword:0
  "XmitBuffer"=dword:20
  "RecvBuffer"=dword:20
  ;"IrqNumber"=dword:23
  "IrqNumber"=dword:3 ;lqm changed for K390.
  "MACAddress" =hex:00,0A,EB,FD,7A,00

  [HKEY_LOCAL_MACHINE/Comm/DM9CE1/Parms/TcpIp]
  "EnableDHCP"=dword:0
  "UseZeroBroadcast"=dword:0
  "DefaultGateway"="192.168.1.1"
  "IpAddress"="192.168.1.227" "Subnetmask"="255.255.255.0" "DNS"="202.96.134.133" ENDIF BSP_DM9000 ! 将上面的IrqNumber值改成0x3,将IP地址,子网掩码,DNS等全照你电脑上的设置(通过ipconfig /all命令查看)。
  再看第三点,CMD。该管脚为高电平时,表示访问数据端口,为低电平时,表示访问INDEX端口。在Dm9isa.h的最前面,有如下定义:
  #define DM9000_ADDR_OFFSET 0x00//(SMSC_ETHERNET_BASE_U_VIRTUAL+0x300)
  //#define DM9000_DATA_OFFSET 0x04
  #define DM9000_DATA_OFFSET 0x800 //lqm changed for K390

  飞凌的板CMD接到了ADDR2上,拿起指甲数数,是不是0x04?再看公司接的是ADDR11上,再数下,是不是0x800了?如果这里设置错误,读取到的DM9000A的ID号会读成地址值,即0x28292a2b。
  理论上,到此,程序已经改完了。但是还有一点我们绝对不能忽视,那就是中断的实现机制。在E:/WINCE500/PLATFORM/SMDK2440A/Src/Kernel/Oal中目录下,打开intr.c文件,将默认的GPF7中断全改为GPF3,包括EXTINT0寄存器。具体更改后的代码如下:
  BOOL BSPIntrInit()
  {
  S3C2440A_IOPORT_REG *pOalPortRegs;
  ULONG value;
  OALMSG(OAL_INTR&&OAL_FUNC, (L"+BSPIntrInit/r/n"));
  // Then get virtual address for IO port
  pOalPortRegs = OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
  // Set GPF7 as EINT7
  value = INREG32(&pOalPortRegs->GPFCON);
  //OUTREG32(&pOalPortRegs->GPFCON, (value & ~(3 << 14))|(2 << 14));
  OUTREG32(&pOalPortRegs->GPFCON, (value & ~(3 << 6))|(2 << 6));// lqm changed to GPF3 for K390.
  // Disable pullup
  value = INREG32(&pOalPortRegs->GPFUP);
  //OUTREG32(&pOalPortRegs->GPFUP, value | (1 << 7));
  OUTREG32(&pOalPortRegs->GPFUP, value | (1 << 3));// lqm changed to GPF3 for K390.
  // High level interrupt
  value = INREG32(&pOalPortRegs->EXTINT0);
  //OUTREG32(&pOalPortRegs->EXTINT0, (value & ~(0xf << 28))|(0x1 << 28));
  OUTREG32(&pOalPortRegs->EXTINT0, (value & ~(0xf << 12))|(0x1 << 12));// lqm changed to GPF3 for K390.
  // Set GPG1 as EINT9
  value = INREG32(&pOalPortRegs->GPGCON);
  OUTREG32(&pOalPortRegs->GPGCON, (value & ~(3 << 2))|(2 << 2));
  // Disable pullup
  value = INREG32(&pOalPortRegs->GPGUP);
  OUTREG32(&pOalPortRegs->GPGUP, value | (1 << 1));
  // High level interrupt
  value = INREG32(&pOalPortRegs->EXTINT1);
  OUTREG32(&pOalPortRegs->EXTINT1, (value & ~(0xf << 4))|(0x4 << 4));
  // Add static mapping for Built-In OHCI
  OALIntrStaticTranslate(SYSINTR_OHCI, IRQ_USBH);
  // OALIntrStaticTranslate(SYSINTR_USBFN, IRQ_USBFN);
  OALMSG(OAL_INTR&&OAL_FUNC, (L"-BSPIntrInit(rc = 1)/r/n"));
  return TRUE;
  }
  注意,如果DM9000A的EECK脚悬空或是下拉,那么中断脚一定要设置为高电平触发中断,如果EECK脚上拉,那么中断脚一定要设置为低电平触发!
  再打开E:/WINCE500/PLATFORM/SMDK2440A/Src/Common/Intr的intr.c文件,仔细查看里面的每一个函数的实现,如果没有对GPF3设置,需要修改!这里我对OALIntrEnableIrqs函数做了如下修改:
  BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
 {

 BOOL rc = TRUE;
 UINT32 i, mask, irq;

 OALMSG(OAL_INTR&&OAL_FUNC, (
  L"+OALIntrEnableIrqs(%d, 0x%08x)/r/n", count, pIrqs
 ));

 for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
  irq = pIrqs[i];
#else
  // Give BSP chance to enable irq on subordinate interrupt controller
  irq = BSPIntrEnableIrq(pIrqs[i]);
#endif
  if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
  // Depending on IRQ number use internal or external mask register
  if (irq <= IRQ_ADC) {
   // Use interrupt mask register
   CLRREG32(&g_pIntrRegs->INTMSK, 1 << irq);
  } else if (irq <= IRQ_EINT7) {
   // Use external mask register
   CLRREG32(&g_pIntrRegs->INTMSK, 1 << IRQ_EINT4_7);
   CLRREG32(&g_pPortRegs->EINTMASK, 1 << (irq - IRQ_EINT4 + 4));
  } else if (irq <= IRQ_EINT23) {
   // Use external mask register
   mask = 1 << (irq - IRQ_EINT4 + 4);
   OUTREG32(&g_pPortRegs->EINTPEND, mask);
   CLRREG32(&g_pPortRegs->EINTMASK, mask);
   mask = 1 << IRQ_EINT8_23;
   if ((INREG32(&g_pIntrRegs->INTPND) & mask) != 0) {
    OUTREG32(&g_pIntrRegs->INTPND, mask);
   }
   CLRREG32( &g_pIntrRegs->INTMSK, 1 << IRQ_EINT8_23);
  } else {
   rc = FALSE;
  }
 }  

 OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrEnableIrqs(rc = %d)/r/n", rc));
 return rc; 

}

 

查看S3C2440的EINTMASK寄存器,发现EINT0到EINT3是保留的,不知三星出于什么目的。如果三星规格书没有错,使用GPF3做中断脚时,EINTMASK应该可以不设置,即这个函数可以不作修改。
  最后一步,在整个BSP包中搜索关于GPF3,GPA12(即nGCS1)的设置情况,如果发现有错误设置的,一定要屏掉,否则无法正常上网!在FL2440的包中,流水灯使用了GPF3,OAL的init.c中误设置了GPF3,更正过来后,编译common下的intr文件夹,编译kernel,make。到此为止,DM9000A驱动移植告一段落。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值