📄 auide.patch
字号:
++void auide_outsl(unsigned long port, void *addr, u32 count)+{+ while (count--)+ {+ au_writel(*(u32 *)addr, port);+ /* NOTE: For IDE interfaces over PCMCIA, + * 32-bit access does not work+ */+ addr += 4;+ }+}++static void auide_tune_drive(ide_drive_t *drive, byte pio)+{+ int mem_sttime;+ int mem_stcfg;+ unsigned long flags;+ u8 speed;++ /* get the best pio mode for the drive */+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);++ printk("%s: setting Au1XXX IDE to PIO mode%d\n",+ drive->name, pio);++ spin_lock_irqsave(&ide_tune_drive_spin_lock, flags);++ mem_sttime = 0;+ mem_stcfg = au_readl(MEM_STCFG2);++ /* set pio mode! */+ switch(pio) {+ case 0:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_PIO0_TWCS+ | SBC_IDE_PIO0_TCSH+ | SBC_IDE_PIO0_TCSOFF+ | SBC_IDE_PIO0_TWP+ | SBC_IDE_PIO0_TCSW+ | SBC_IDE_PIO0_TPM+ | SBC_IDE_PIO0_TA;+ /* set configuration for RCS2# */+ mem_stcfg |= TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS;++ au_writel(mem_sttime,MEM_STTIME2);+ au_writel(mem_stcfg,MEM_STCFG2);+ break;++ case 1:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_PIO1_TWCS+ | SBC_IDE_PIO1_TCSH+ | SBC_IDE_PIO1_TCSOFF+ | SBC_IDE_PIO1_TWP+ | SBC_IDE_PIO1_TCSW+ | SBC_IDE_PIO1_TPM+ | SBC_IDE_PIO1_TA;+ /* set configuration for RCS2# */+ mem_stcfg |= TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS;+ break;++ case 2:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_PIO2_TWCS+ | SBC_IDE_PIO2_TCSH+ | SBC_IDE_PIO2_TCSOFF+ | SBC_IDE_PIO2_TWP+ | SBC_IDE_PIO2_TCSW+ | SBC_IDE_PIO2_TPM+ | SBC_IDE_PIO2_TA;+ /* set configuration for RCS2# */+ mem_stcfg &= ~TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS;+ break;++ case 3:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_PIO3_TWCS+ | SBC_IDE_PIO3_TCSH+ | SBC_IDE_PIO3_TCSOFF+ | SBC_IDE_PIO3_TWP+ | SBC_IDE_PIO3_TCSW+ | SBC_IDE_PIO3_TPM+ | SBC_IDE_PIO3_TA;+ /* set configuration for RCS2# */+ mem_stcfg |= TS_MASK;+ mem_stcfg &= ~TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS;++ break;++ case 4:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_PIO4_TWCS+ | SBC_IDE_PIO4_TCSH+ | SBC_IDE_PIO4_TCSOFF+ | SBC_IDE_PIO4_TWP+ | SBC_IDE_PIO4_TCSW+ | SBC_IDE_PIO4_TPM+ | SBC_IDE_PIO4_TA;+ /* set configuration for RCS2# */+ mem_stcfg &= ~TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS;+ break;+ }++ au_writel(mem_sttime,MEM_STTIME2);+ au_writel(mem_stcfg,MEM_STCFG2);++ spin_unlock_irqrestore(&ide_tune_drive_spin_lock, flags);++ speed = pio + XFER_PIO_0;+ ide_config_drive_speed(drive, speed);+}++static int auide_tune_chipset (ide_drive_t *drive, u8 speed)+{+ u8 mode = 0;+ int mem_sttime;+ int mem_stcfg;+ unsigned long flags;+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA+ struct hd_driveid *id = drive->id;++ /*+ * Now see what the current drive is capable of,+ * selecting UDMA only if the mate said it was ok.+ */+ if (id && (id->capability & 1) && drive->autodma &&+ !__ide_dma_bad_drive(drive)) {+ if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {+ if (id->dma_mword & 4)+ mode = XFER_MW_DMA_2;+ else if (id->dma_mword & 2)+ mode = XFER_MW_DMA_1;+ else if (id->dma_mword & 1)+ mode = XFER_MW_DMA_0;+ }+ }+#endif++ spin_lock_irqsave(&ide_tune_chipset_spin_lock, flags);++ mem_sttime = 0;+ mem_stcfg = au_readl(MEM_STCFG2);++ switch(speed) {+ case XFER_PIO_4:+ case XFER_PIO_3:+ case XFER_PIO_2:+ case XFER_PIO_1:+ case XFER_PIO_0:+ auide_tune_drive(drive, (speed - XFER_PIO_0));+ break;+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA+ case XFER_MW_DMA_2:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_MDMA2_TWCS+ | SBC_IDE_MDMA2_TCSH+ | SBC_IDE_MDMA2_TCSOFF+ | SBC_IDE_MDMA2_TWP+ | SBC_IDE_MDMA2_TCSW+ | SBC_IDE_MDMA2_TPM+ | SBC_IDE_MDMA2_TA;+ /* set configuration for RCS2# */+ mem_stcfg &= ~TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;++ mode = XFER_MW_DMA_2;+ break;+ case XFER_MW_DMA_1:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_MDMA1_TWCS+ | SBC_IDE_MDMA1_TCSH+ | SBC_IDE_MDMA1_TCSOFF+ | SBC_IDE_MDMA1_TWP+ | SBC_IDE_MDMA1_TCSW+ | SBC_IDE_MDMA1_TPM+ | SBC_IDE_MDMA1_TA;+ /* set configuration for RCS2# */+ mem_stcfg &= ~TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;++ mode = XFER_MW_DMA_1;+ break;+ case XFER_MW_DMA_0:+ /* set timing parameters for RCS2# */+ mem_sttime = SBC_IDE_MDMA0_TWCS+ | SBC_IDE_MDMA0_TCSH+ | SBC_IDE_MDMA0_TCSOFF+ | SBC_IDE_MDMA0_TWP+ | SBC_IDE_MDMA0_TCSW+ | SBC_IDE_MDMA0_TPM+ | SBC_IDE_MDMA0_TA;+ /* set configuration for RCS2# */+ mem_stcfg |= TS_MASK;+ mem_stcfg &= ~TCSOE_MASK;+ mem_stcfg &= ~TOECS_MASK;+ mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;++ mode = XFER_MW_DMA_0;+ break;+#endif+ default:+ return 1;+ }++ /*+ * Tell the drive to switch to the new mode; abort on failure.+ */+ if (!mode || ide_config_drive_speed(drive, mode))+ {+ return 1; /* failure */+ }+++ au_writel(mem_sttime,MEM_STTIME2);+ au_writel(mem_stcfg,MEM_STCFG2);++ spin_unlock_irqrestore(&ide_tune_chipset_spin_lock, flags);++ return 0;+}++/*+ * Multi-Word DMA + DbDMA functions+ */+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA++static int in_drive_list(struct hd_driveid *id, + const struct drive_list_entry *drive_table)+{+ for ( ; drive_table->id_model ; drive_table++){+ if ((!strcmp(drive_table->id_model, id->model)) &&+ ((strstr(drive_table->id_firmware, id->fw_rev)) ||+ (!strcmp(drive_table->id_firmware, "ALL")))+ )+ return 1;+ }+ return 0;+}++static int auide_build_sglist(ide_drive_t *drive, struct request *rq)+{+// printk("%s\n", __FUNCTION__);++ ide_hwif_t *hwif = drive->hwif;+ _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;+ struct scatterlist *sg = hwif->sg_table;++ ide_map_sg(drive, rq);++ if (rq_data_dir(rq) == READ)+ hwif->sg_dma_direction = DMA_FROM_DEVICE;+ else+ hwif->sg_dma_direction = DMA_TO_DEVICE;++ return dma_map_sg(ahwif->dev, sg, hwif->sg_nents,+ hwif->sg_dma_direction);+}++static int auide_build_dmatable(ide_drive_t *drive)+{+// printk("%s\n", __FUNCTION__);++ int i, iswrite, count = 0;+ ide_hwif_t *hwif = HWIF(drive);++ struct request *rq = HWGROUP(drive)->rq;++ _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;+ struct scatterlist *sg;++ iswrite = (rq_data_dir(rq) == WRITE);+ /* Save for interrupt context */+ ahwif->drive = drive;++ /* Build sglist */+ hwif->sg_nents = i = auide_build_sglist(drive, rq);++ if (!i)+ return 0;++ /* fill the descriptors */+ sg = hwif->sg_table;+ while (i && sg_dma_len(sg)) {+ u32 cur_addr;+ u32 cur_len;++ cur_addr = sg_dma_address(sg);+ cur_len = sg_dma_len(sg);++ while (cur_len) {+ u32 flags = DDMA_FLAGS_NOIE;+ unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;++ if (++count >= PRD_ENTRIES) {+ printk(KERN_WARNING "%s: DMA table too small\n",+ drive->name);+ goto use_pio_instead;+ }++ /* Lets enable intr for the last descriptor only */+ if (1==i)+ flags = DDMA_FLAGS_IE;+ else+ flags = DDMA_FLAGS_NOIE;++ if (iswrite) {+ if(!au1xxx_dbdma_put_source_flags(ahwif->tx_chan,+ (void*)phys_to_virt(cur_addr), tc, flags))+ printk(KERN_ERR "%s failed %d\n",+ __FUNCTION__, __LINE__);+ }+ else {+ if(!au1xxx_dbdma_put_dest_flags(ahwif->rx_chan,+ (void*)phys_to_virt(cur_addr), tc, flags))+ printk(KERN_ERR "%s failed %d\n",+ __FUNCTION__, __LINE__);+ }++ cur_addr += tc;+ cur_len -= tc;+ }+ sg++;+ i--;+ }++ if (count)+ return 1;++use_pio_instead:+ dma_unmap_sg(ahwif->dev,+ hwif->sg_table,+ hwif->sg_nents,+ hwif->sg_dma_direction);++ return 0; /* revert to PIO for this request */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -