Chinaunix首页 | 论坛 | 博客
  • 博客访问: 146324
  • 博文数量: 54
  • 博客积分: 2517
  • 博客等级: 少校
  • 技术积分: 540
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-13 18:52
文章分类
文章存档

2011年(2)

2010年(11)

2009年(41)

我的朋友

分类:

2009-09-18 12:56:41

分享下硬盘的驱动调试经验。首先,打开先找到DAVINCI IDE的接口驱动文件/drivers/ide/davinci/palm_bk3710.c

第一步还是还是模块初的始化函数,linux还是Linux,模块还是那个模块

module_init(palm_bk3710_init);//万年不变的

下一步是看palm_bk3710_init,从代码里来,还是从代码开始吧。

int palm_bk3710_init(void)//DAVINCI ide驱动初始化

{

      int ret = 0;

      hw_regs_t ide_ctlr_info;

      int index = 0;

      int pribase = IO_ADDRESS(IDE_PALM_REG_MMAP_BASE) +

                     IDE_PALM_ATA_PRI_REG_OFFSET; //映射IDE寄存器

      struct clk *clkp;

 

      volatile unsigned int regAddr0 = IO_ADDRESS(0x01c40000); //PINMUX0davinci存在GPIO和转用管脚复用的情况

      volatile unsigned int tmpData0 = *(unsigned int *)regAddr0;     

printk("\nthe pinMux1 is:0x%x!\n\n\n", tmpData);

      volatile unsigned int regAddr1 = IO_ADDRESS(0x01c40004); // 同理PINMUX1

 

      volatile unsigned int tmpData1 = *(unsigned int *)regAddr1;

      printk("\nthe pinMux0 is:0x%x!\n\n\n", tmpData0);

      printk("\nthe pinMux1 is:0x%x!\n\n\n", tmpData1);

      tmpData0 |= 0x30000;

      *(unsigned int *)regAddr0 = tmpData0;

       tmpData0 = *(unsigned int *)regAddr0;

      printk("\nthe pinMux0 set is:0x%x!\n\n\n", tmpData0);

      clkp = clk_get (NULL, "IDECLK"); //取到IDE时钟

      if (!IS_ERR(clkp)) //判断始终存在与否

      {

           ideclkp = clkp;

           clk_use (ideclkp);

           clk_enable (ideclkp);  //使能时钟

           ide_palm_clk = clk_get_rate(ideclkp)/100000;

           ide_palm_clk = (10000/ide_palm_clk) + 1;

 

           /* ATA_SEL is 1 -> Disable 0 -> Enable

            * CF_SEL  is 1 -> Disable 0 -> Enable

            *

            * Ensure both are not Enabled.

            */

           {

#ifdef CONFIG_DAVINCI_BLK_DEV_CF //片选

                 //davinci_i2c_expander_op (0x3A, ATA_SEL, 1);

                 //davinci_i2c_expander_op (0x3A, CF_RESET, 1);

                 //davinci_i2c_expander_op (0x3A, CF_SEL, 0);

#else

                 //davinci_i2c_expander_op (0x3A, CF_SEL, 1);

                 //davinci_i2c_expander_op (0x3A, ATA_SEL, 0);

#endif

           }

           /* Register the IDE interface with Linux ATA Interface */

           memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));

 

           palm_bk3710_base =

               (palm_bk3710_ideregs *) IO_ADDRESS(IDE_PALM_REG_MMAP_BASE);

           /* Configure the Palm Chip controller */ //映射IDE的寄存器

           palm_bk3710_chipinit();

 

           for (index = 0; index < IDE_NR_PORTS - 2; index++) {

                 ide_ctlr_info.io_ports[index] = pribase + index;

           }

           ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] =

               IO_ADDRESS(IDE_PALM_REG_MMAP_BASE)

               + IDE_PALM_ATA_PRI_CTL_OFFSET;

           ide_ctlr_info.irq = IRQ_IDE; //中断号22

           ide_ctlr_info.chipset = ide_palm3710;

           ide_ctlr_info.ack_intr = NULL;

           if (ide_register_hw(&ide_ctlr_info, &palm_bk3710_hwif) < 0) {//硬件注册IDE

                 printk("Palm Chip BK3710 IDE Register Fail\n");

                 return -1;

           }

 

           palm_bk3710_hwif->tuneproc = &palm_bk3710_tune_drive;

 

           palm_bk3710_hwif->noprobe = 0;

#ifndef CONFIG_DAVINCI_BLK_DEV_CF

#ifdef  CONFIG_BLK_DEV_IDEDMA

                palm_bk3710_hwif->speedproc = &palm_bk3710_hostdma;

           /* Just put this for using the ide-dma.c init code */

           palm_bk3710_dummydata.extra = 0;

           palm_bk3710_hwif->cds = &palm_bk3710_dummydata;

           palm_bk3710_hwif->atapi_dma = 1;

 

           /* Setup up the memory map base for this instance of hwif */

           palm_bk3710_hwif->mmio = 0;

           palm_bk3710_hwif->ide_dma_check = palm_bk3710_checkdma;

 

           palm_bk3710_hwif->ultra_mask = 0x1f;  /* UDMA Mode 4 */

                                      /* Max (input clk 99MHz) */

           palm_bk3710_hwif->mwdma_mask = 0x7;

           palm_bk3710_hwif->swdma_mask = 0;

           palm_bk3710_hwif->dma_command =

               IO_ADDRESS(IDE_PALM_REG_MMAP_BASE);

           palm_bk3710_hwif->dma_status =

               IO_ADDRESS(IDE_PALM_REG_MMAP_BASE) + 2;

           palm_bk3710_hwif->dma_prdtable =

               IO_ADDRESS(IDE_PALM_REG_MMAP_BASE) + 4;

           palm_bk3710_hwif->drives[0].autodma = 1;

           palm_bk3710_hwif->drives[1].autodma = 1;

           palm_bk3710_hwif->udma_four = 1;

           ide_setup_dma(palm_bk3710_hwif,

                       IO_ADDRESS(IDE_PALM_REG_MMAP_BASE), 8); //建立DMA,挂上硬盘DMA的处理函数

           palm_bk3710_checkdma (&palm_bk3710_hwif->drives[0]);//配置硬盘DMA模式

           palm_bk3710_checkdma (&palm_bk3710_hwif->drives[1]);

#endif

#endif

           ret = 0;

      } else {

           ret = -ENODEV;

      }

      return ret;

}

先说下ide_register_hw这个函数看代码:

int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp)

{

      return ide_register_hw_with_fixup(hw, hwifp, NULL);

}

转手

int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif))

{

      int index, retry = 1;

      ide_hwif_t *hwif;

 

      do {

           for (index = 0; index < MAX_HWIFS; ++index) { //默认IDE有四个接口

                 hwif = &ide_hwifs[index];

                 if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])

                      goto found;

           }

           for (index = 0; index < MAX_HWIFS; ++index) {

                 hwif = &ide_hwifs[index];

                 if (hwif->hold)

                      continue;

                 if ((!hwif->present && !hwif->mate && !initializing) ||

                     (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))

                      goto found;

           }

           for (index = 0; index < MAX_HWIFS; index++)

                 ide_unregister(index);

      } while (retry--);

      return -1;

found:

      if (hwif->present)

           ide_unregister(index);

      else if (!hwif->hold) {

           init_hwif_data(hwif, index);

           init_hwif_default(hwif, index);

      }

      if (hwif->present)

           return -1;

      memcpy(&hwif->hw, hw, sizeof(*hw));

      memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));

      hwif->irq = hw->irq;

      hwif->noprobe = 0;

      hwif->chipset = hw->chipset;

 

      if (!initializing) { // initializing?哪来的我们后面再说

           probe_hwif_init_with_fixup(hwif, fixup);//主要接这步初始化

           create_proc_ide_interfaces();

      }

 

      if (hwifp)

           *hwifp = hwif;

 

      return (initializing || hwif->present) ? index : -1;

来看看probe_hwif_init_with_fixup

 

}

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