Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1328928
  • 博文数量: 281
  • 博客积分: 8800
  • 博客等级: 中将
  • 技术积分: 3345
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-17 22:31
文章分类

全部博文(281)

文章存档

2013年(1)

2012年(18)

2011年(16)

2010年(44)

2009年(86)

2008年(41)

2007年(10)

2006年(65)

我的朋友

分类: LINUX

2009-06-03 11:08:46

PCMCIA相当于台式机上的PCI接口, 用来扩展的.
好处是可以热插拔.
是主板南桥支持的
计算机的所有外部设备接口和支持, 都是南桥支持的.
北桥是负责cpu, 内存, 总线之间的工作协调.
芯片市场上最多的是NEC和ALI两家厂商的, 都是不错的,NEC的属于较高档,ALI价格更实惠. 
 
PCMCIA是英文“PERSONAL COMPUTER MEMORY CARD INTERNATIONAL ASSOCIATION”的缩写,PCMCIA定义了三种不同型式的卡,它PCMCIA(PC机内存卡国际联合会的缩写)是一个有300多个成员公司的国际标准组织和贸易联合会,该组织成立于1989年,目的是建立一项集成电路国际标准,提高移动计算机的互换性。这种计算机要求强度高,能耗低,尺寸小,而且对这几条性能的要求都很高。由于可移动计算机用户的需求变了,所以PC卡的标准也相应地变了。1991年,PCMCIA定义了原本用于内存卡的68个脚的I/O连接线路标准。同时增加了插槽使用说明。生产商意识到软件需要提高兼容性,因而这项标准也就得到了相应的应用。


 Mini PCI插槽也同样是在PCI的基础上发展起来的,最初是应用于笔记本,现在不少台式机也配备了Mini PCI插槽。Mini PCI的定义与PCI基本上一致,只是在外型上进行了微缩。目前使用Mini PCI插槽的主要有内置的无线网卡、Modem+网卡、电视卡以及一些多功能扩展卡等硬件设备。 
 
 
PCMCIA是插拔的ISA Bridge, CardBus是PCI Bridge。也就是说PCMCIA卡里面就是ISA芯片,CardBus的是PCI芯片,那个PCMCIA控制器,就是识别该卡,提供电源,再把该ISA/PCI总线接入系统。
所以PCMCIA卡电压高(5V),速度慢,还吃CPU。CardBus就只需3.3V,驱动也比较简单,插进去后和内置相同的PCI芯片卡没什么区别。
 
PC-Card(16-bit)技术 

PC-Card规格是最老的笔记本电脑的规格。发展于90年代,并成为移动运算实际上的标准,这要归功于国际个人计算机记忆卡协会(PCMCIA)的努力。PC-Card规格有三种不同形式的PC-Card,都是68pin的接头。Type I、Type II和Type III,主要的不同是卡的厚度:Type I是3.3mm;Type II是5.0mm;Type III是10.5mm。薄的卡可以插在厚的插槽上,厚的卡不可以插在薄的插槽上。PC卡技术支持Zoomed Video,一种卡与VGA控制器直接连接的技术。这允许数据可以不用缓冲的在PC卡与VGA控制器间传输,因为它是用ZV bus做传输而不是系统端口。有些与ZV有相关的MPEG-2解码器使用Zoomed Video技术。

笔记本电脑用的PC-Card,不是使用Type II就是使用Type III技术。使用Type III时,你会损失上方的插槽,但是不需要使用dongle,而且连接器也内建在卡上。Type II有三种形式:一种是使用某种dongle来连接网线;一种是使用在卡外的塑料连接器;像3Com的X-Jack技术,将接头直接拉到卡外。在某些情况,使用外接式的塑料连接器会让你损失其它插槽;而其它情况,你还是可以使用其它插卡。

16-bit的PC-Card会被16-bit的总线所限制。使用16-bit的PC-Card会限制你的整个网络的数据流量,因为16-bit的数据信道不够宽。虽然16-bit的PC卡宣称有100Mb的性能,当网卡可以100Mb的速度连接的时候,我们认为它应该会有更好的表现,由于16-bit PC卡总线的原因,你的真实速度将会限制在20-25Mb。所有16-bit的PC卡都用5伏特的电压,也就是说它使用比CardBus更多的电量,但是现有的PC卡看起来都想要尽可能的使用更多的电量。在大部分的状况,较新的笔记本电脑都支持PC-Card和CardBus,但是1997年以前的系统就只支持PC卡。


CardBus(32-bit)技术

CardBus标准在1997年5月由PCMCIA所建立,并提出PC-Card的限制。大致上CardBus的速度是PC-Card总线的4到6倍,有32-bit 33MHz架构,以及3.3伏特的节能设计。CardBus有着类似PCI接口的性能与DMA和bus-mastering能力,而这正是PC-Card总线所缺乏的。CardBus设计有33MHz多重地址/数据,可产生132MHz的峰值带宽。CardBus靠着改造PCI的同步爆发式trnasfer orientation来达到这样的性能,以及与PCI非常相似的总线协议。CardBus的设计是以高带宽的产品如USB、1394(火线)、当然还有100Mb网卡等的性能所设计的。使用3.3伏特的低电压设计,CardBus应该不会像PC卡一样热。它以PC-Card的设计方式为特征,使用Type I、Type II、Type III格式。它可以用一般方式插入,但是你不能将CardBus的卡插到一台没有兼容CardBus插槽的笔记本电脑中。使用32-bit 33MHz总线CardBus的设计,它可以让CardBus网卡达到真正的100Mb网络连接。就像以前的PC-Card,CardBus的设计兼容热交换与随插即用,就像用户已经习惯的PC-Card。

笔记本电脑用的CardBus卡不是使用Type II就是Type III技术。当使用Type III的卡,你会损失上方的插槽,但是不需要使用dongle,而且连接器也内建在卡上。Type II有三种形式:一种是使用某种dongle来连接网线;一种是使用在卡外的塑料连接器;以及3Com的X-Jack技术,将接头直接拉到卡外。(这不会真的改变之前我们所看到过的PC-Card的技术格式。)CardBus卡3.3伏特的节能真正体现出节能是怎么一回事,这些卡能够大大的减少电池的耗损。如果你有新一点的笔记本电脑,CardBus卡提供的性能非常的物超所值
 
 
PCMCIA为Personal Computer Memory Card International Association(个人电脑记忆卡国际协会)的缩写,此协会旨在建立电脑记忆卡标准规格,其与日本JEIDA(日本电子工业开发协会)共同制定了以可携式电脑为主的扩充卡标准,符合其标准的IC CARD称为PCMCIA CARD(又称PC CARD),其大小就像信用卡般轻巧,提供笔记型电脑轻便且多种的扩充功能。 PCMCIA标准最初只用于记忆卡,目前已扩展到各式电脑周边I/O卡,如数据机、网路卡、音效卡、硬碟卡等。 
PC CARD的特色除了轻、小外,和USB装置一样具有随插即用(plug and play)及热插拔(hot-plug)功能,可于开机状态下轻易安装或抽换自动通知系统装置更新;其界面皆为68pin接头,面积为85.6×54mm,依厚度可分为三种规格,而其中TYPE Ⅱ是最为常见的。

随着笔记型电脑日渐普及,PC CARD运用范围也越显广泛,为因应多媒体和网路等高速周边需求,原先只提供16bit传输的PC CARD能供应的频宽已无法应付,故PCMCIA于1995年的PC Card Standard中提出高性能的PC CARD规格-CardBus。 
CardBus是为高效能的产品所设计的介面,让笔记型电脑能使用PCI 32位元汇流排宽度,执行速率为33MHz,使传输速率最高可提升至132MBps,电压设计也改为3.3V,较原先的PC CARD具有更高的效能也更为省电。接头同样为68pin,大小同TYPE Ⅱ,而在PCMCIA及Intel的推动下几乎已取代旧有的PC CARD。 
虽然CardBus采用32bit传输,但其插槽与16bit的PC CARD仍是相容的,故目前笔记型电脑的PC卡插槽大多能同时支援16bit的PC CARD及32bit的CardBus PC CARD,但早期的PC CARD插槽可能只能支援16bit的PC CARD,使用者可根据电脑手册上标示的支援规格选购相对应的PC CARD。
但因PCMCIA与CARDBUS传输频宽一直局限在132 Mbps,所以已不符合外接周边设备的需求。 

Express Card就是对应这样的需求,所产生的新一代资讯装置扩充介面,Express Card一样也是PCMCIA协会所制定,Express Card介面的传输单元部分可用USB 2.0或PCI Express等介面与笔记型电脑相连,同时Express Card也与PCMCIA Card一样具备热插拔(Hot-swap)的功能。
 
 
折腾了一个多星期,终于完成了2.6.13下的无线网卡移植..

我们所使用了复旦大学CAT实验室自制的系统板,其采用S3C2410为核心,通过PD6710进行PCMCIA总线扩展,无线网卡采用的是清华同方的TFW1000.
硬件介绍:
PD6710接在nGCS1空间,使用A20进行IO与MEM空间的分隔.因此地址分配如下:
    A20=1, I/O area (A26 should have been used.)
    A20=0, mem area
    AEN=nGCS1,

    absolute address       
    0x08000000~0x080FFFFF: memory area
    0x08100000~0x081FFFFF: I/O area

中断:
card IRQ使用IRQ3,并连接到s3c2410的EINT4管脚.
manager IRQ没有使用.

主要的移植工作包括:
1.在./arch/arm/mach-s3c2410/mach-smdk2410.c中添加以上虚拟地址映射,代码如下:
//>>>>----------Modified by Zengyi 2007-5-23
  { (u32)S3C24XX_VA_ISA_WORD, pCF_IO_BASE, SZ_1M, MT_DEVICE },
  { (u32)S3C24XX_VA_ISA_BYTE, pCF_IO_BASE, SZ_1M, MT_DEVICE },

  { (u32)vCF_MEM_BASE,                    pCF_MEM_BASE,  SZ_1M, MT_DEVICE },
  { (u32)vCF_IO_BASE,                     pCF_IO_BASE,   SZ_1M, MT_DEVICE },
//<<<<----------Modify End
其中,S3C24XX_VA_ISA_WORD以及S3C24XX_VA_ISA_BYTE的映射主要是为了将isa的io空间读取映射到PD6710的io区域,
例如,调用inb(0x00)是,将等效于调用((uchar*)(pCF_IO_BASE).这样可以保证PD6710中部分代码不用修改,但是需要注意的
是如果还是其他驱动程序调用inb等函数时,将会产生问题,这是建立将以上两个映射取消,然后修改驱动函数中的inb函数调用.
2.(可选),修改系统时钟,由于板子电器特性问题,pd6710在memory时钟为200MHz时,会出现读写错误,因此不得不降低系统时钟,将时钟修改为180MHz, memory时钟为90MHz.主要的修改/arch/arm/mach-s3c2410/s3c2410.c:
unsigned long mpllvalue = (0x52<<12)|(0x01<<4)|(0x01); //Set Clock to 180MHz, PD6710 can't work well in 200MHz
__raw_writel(mpllvalue,S3C2410_MPLLCON);

3.因为PD6710为82365兼容芯片,因此其驱动在./driver/pcmcia/i82365.c文件中,主要需要进行如下修改:
a.  修改 
static int has_dma = -1;
static int has_led = -1;
static int has_ring = -1;
static int dynamic_mode = 1;
static int freq_bypass = 1;
static int setup_time = 1; /* default value*/
static int cmd_time = 6;  /*  default value*/
static int recov_time = 3; /*default value */
主要是修改一些默认参数,setup_time,cmd_time ,recov_time,均设为PD6710手册上所标记的默认值.(不知道为什么如果
上电后读出来的值并不是手册上的默认值,所以我们手动置为默认值).
b. 在 cirrus_set_state函数中添加:
//>>>>----------- Added by Zengyi 2007_5_29
    //flush fifo first
    i365_set(s, PD67_FIFO_CTL , 0x80);
    //>>>>----------- end of add
    for (i = 0; i < 6; i++)
        i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
   这是按照手册上的要求,修改TIME寄存器之前需要将FIFO清空.
c.  在add_pcic函数中添加如下部分(重要):
    //>>>>------------- Add by Zengyi 2007_5_23
    #ifdef CONFIG_ARCH_SMDK2410_CATLAB
    /* Use SS_CAP_STATIC_MAP which disables the memory resource
       database check and SS_CAP_PAGE_REGS which disable io port
       maximun limit 0xffff */
    t[i].socket.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_PAGE_REGS;
    /* We just pass up an offset which is applied to client-requested
       base I/O addresses in alloc_io_space() */
    t[i].socket.io_offset = vCF_IO_BASE;
    /* Map Size */
    t[i].socket.map_size = 0x1000;
    /* Do not use ISA irq */
    t[i].socket.irq_mask = 0;
    t[i].socket.pci_irq = IRQ_CF_RDY;
    /* Card Detect IRQ */
    t[i].cs_irq = 0;
    /* Enable Management Interrupt for card detect */
    t[i].intr = I365_INTR_ENA;
    /* PD6710 IRQ3 is only connected to IRQ_CF_RDY */
    t[i].intr |= 3 << 0;

#else

    t[i].socket.features |= SS_CAP_PCCARD;
    t[i].socket.map_size = 0x1000;
    t[i].socket.irq_mask = mask;
    t[i].cs_irq = isa_irq;
#endif
//>>>>------------- end of add

以上部分的作用主要是
设置socket.为STATIC MAP的, 设置io_offset 为新的虚拟地址,配置pci_irq 外部中断 EINT4, 配置使用PD6710的IRQ3作为PC CARD的card IRQ.

d. 在isa_probe函数中,直接添加一个pcic,因为我们只有一个pcic.
//<<<<----------------Add by Zengyi 2007_5_23
#ifdef CONFIG_ARCH_SMDK2410_CATLAB
    /* There is just one socket */
    add_socket(i365_base, 0, id);
    add_pcic(1, id);
#else
//>>>>----------------end of Add

e. 由于我们设置了socket为STATIC MAP,因此我们IO/MEMORY的映射需要自己手动完成:
在pcic_init函数中,可以修改
pccard_io_map io = { 0, 0, 0, 0, 0x100 }; 先设置好一段IO映射,但是我们现在还没有enable.
enable的操作本来应该在set_io_map函数中,但是有些上层的驱动并不会调用set_io_map函数(如我们的orinoco驱动),因此
我们选择在i365_set_socket函数中调用:
 /* IO card, RESET flag, IO interrupt */
    reg = t->intr;
    //reg |= state->io_irq;
    reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
    reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
    i365_set(sock, I365_INTCTL, reg);
    //<<<<----------------- Added by Zengyi 2007_5_28
    if(reg & I365_PC_IOCARD) {
        //Enable IO MAP
        i365_bset(0, I365_ADDRWIN, I365_ENA_IO(0));
    }
    //>>>>------------------ end of Add
即,如果在set_socket的参数
state->flags中设置了SS_IOCARD那么,我们就把IO MAP0使能.

f. 修改set_mem_map函数(相当重要!!!)
在函数的开头部分添加:

//<<<<------------- Added by Zengyi 2007_5_25
#ifdef CONFIG_ARCH_SMDK2410_CATLAB
  if(mem->res == NULL) {
    printk(KERN_DEBUG "Make resource ourseleves\n");
    mem->res = claim_region(NULL,pCF_MEM_BASE,SZ_1M,IORESOURCE_MEM,"PD6710 Mem");
  } else {
    //i365_get_mem_map(sock,mem);
  }
  while (mem->res->start >= pCF_MEM_BASE) mem->res->start -= pCF_MEM_BASE;
  while (mem->res->end >= pCF_MEM_BASE) mem->res->end -= pCF_MEM_BASE;
#endif
//>>>>------------- end of Add
在函数尾添加:
//<<<<----------------- Add by Zengyi 2007_5_24
#ifdef CONFIG_ARCH_SMDK2410_CATLAB
    mem->res->start += pCF_MEM_BASE;
    mem->res->end += pCF_MEM_BASE;
#endif

    mem->static_start = mem->res->start;
该步骤的作用有以下部分:
首先检测mem->res是否非空,这一点不知道是不是2.6.13内核的bug,因为当设置为STATIC_MAP时,调用 pcmcia_validate_mem后会将s->mem->res置为NULL,这样接下来如pccard_validate_cis等就可能会传递NULL指针
给set_mem_map函数,因此如果我们发现mem->res为NULL时则需要自己生成mem->res.
  while (mem->res->start >= pCF_MEM_BASE) mem->res->start -= pCF_MEM_BASE;
  while (mem->res->end >= pCF_MEM_BASE) mem->res->end -= pCF_MEM_BASE;
以及
    mem->res->start += pCF_MEM_BASE;
    mem->res->end += pCF_MEM_BASE;
的作用是对硬件地址的偏移进行调整,记住我们PD6710的mem空间为
0x08000000~0x080FFFFF.
mem->static_start = mem->res->start; 是重新设置mem->static_start .因为当设置为STATIC_MAP时,
上层函数会调用set_cis_map,而在该函数中会调用
s->cis_virt = ioremap(mem->static_start, s->map_size);
重新生成
s->cis_virt.
static void __iomem *
set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
{
    pccard_mem_map *mem = &s->cis_mem;
    int ret;

    if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
        mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
        if (mem->res == NULL) {
            printk(KERN_NOTICE "cs: unable to map card memory!\n");
            return NULL;
        }
        s->cis_virt = NULL;
    }

    if (!(s->features & SS_CAP_STATIC_MAP) && (!s->cis_virt))
        s->cis_virt = ioremap(mem->res->start, s->map_size);

    mem->card_start = card_offset;
    mem->flags = flags;

    ret = s->ops->set_mem_map(s, mem);
    if (ret) {
        iounmap(s->cis_virt);
        s->cis_virt = NULL;
        return NULL;
    }

    if (s->features & SS_CAP_STATIC_MAP) {
        if (s->cis_virt)
            iounmap(s->cis_virt);
        s->cis_virt = ioremap(mem->static_start, s->map_size);
    }


    return s->cis_virt;
}

g. 在init_i82365中添加S3C2410 bank1 以及中断配置代码:
//>>>---------Add by Zengyi 2007_5_23
#ifdef CONFIG_ARCH_SMDK2410_CATLAB
        volatile unsigned int regval;
        void __iomem *port;
//      printk(KERN_ERR "init_pd6710 start!\n");
        port=S3C2410_BWSCON;
//      printk(KERN_ALERT "Register BWSCON's address is %#x\n",port);

        //regval=inl_p(port);
        regval = __raw_readl(port);
        //printk(KERN_ALERT "BWSCON's value before change is %#x\n",regval);

        regval=(regval &(0xffffff0f))|(S3C2410_BWSCON_ST1|S3C2410_BWSCON_WS1|S3C2410_BWSCON_DW1_16);
        //outl_p(regval,port);
        __raw_writel(regval,port);
        //regval = __raw_readl(port);
        //printk(KERN_ALERT "BWSCON's value after change is %#x\n",regval);

        port=S3C2410_BANKCON1;
        //regval = __raw_readw(port);
        //printk(KERN_ALERT "BANKCON1's value before change is 0x%#x\n",regval);
//      printk(KERN_ERR "BWSCON step is OK!\n");
        regval=S3C2410_BANKCON_Tacs1|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|
               S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah1|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm;
        //regval=S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|
        //        S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm;

        //outl_p(regval,port);
        __raw_writew(regval,port);

        //regval = __raw_readw(port);
        //printk(KERN_ALERT "BANKCON1's value after change is %#x\n",regval);

//      printk(KERN_ERR "BWSCON1 step is OK!\n");
        if(IRQ_nCF_INS!=0)
        {
                set_irq_type(IRQ_nCF_INS,IRQT_FALLING);
        }
//      printk(KERN_ERR " set_irq_type(IRQ_nCF_INS) is ok\n");
        set_irq_type(IRQ_CF_RDY,IRQT_RISING);
        s3c2410_gpio_pullup(S3C2410_GPF4,0);
        printk(KERN_ALERT "init_pd6710 has successfully finished!\n");

#endif /* CONFIG_ARCH_SMDK2410_CATLAB */

4.修改rsrc_nonstatic.c文件:
//>>>>---------- Modified by Zengyi 2007_5_27
//INT_MODULE_PARM(probe_mem,    1);     /* memory probe? */
INT_MODULE_PARM(probe_mem,  0);     /* memory probe? */
//>>>>---------- end of modify
#ifdef CONFIG_PCMCIA_PROBE
//>>>>---------- Modified by Zengyi 2007_5_27
//INT_MODULE_PARM(probe_io, 1);     /* IO port probe? */
INT_MODULE_PARM(probe_io,   0);     /* IO port probe? */
//>>>>---------- end of modify
INT_MODULE_PARM(mem_limit,  0x10000);
#endif

主要是将probe_io以及probe_mem均设为0,因为我们使用的是static的地址,因此没有必要进行probe.

在修改好以上文件后,在make menuconfig 中将PCMCIA,以及i386支持编入内核,重新编译后的内核就可以
认出我们PD6710.

5.交叉编译cardmgr程序.可以在pcmcia-cs网站中找到.
6.编译orinoco驱动. 选项为Network device support下的Wireless LAN (non-hamradio),<*> Hermes chipset 802.11b support (Orinoco/Prism2/Symbol) 以及<*> Hermes PCMCIA card support.
使用linux 2.6.13中的orinoco驱动时会出现如下错误:
hermes @ e1000000: BAP1 offset error: reg=0x3c id=0xbc offset=0x0
eth1: error -5 reading Rx descriptor. Frame dropped.
但是换成2.4内核中的orinoco驱动后就没有这个错误了.具体原因还没有发现.
7.重新启动以后,无线网卡便可成功启动.

 

阅读(2852) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-07-24 17:09:20

非常好的帖子!很有帮助谢谢

chinaunix网友2009-06-08 11:12:52

好服月租型IT服务台,与你共成长! 月租型ITSM软件,注册即可免费体验! 详情请登录官方网站:http://www.servicezon.com