diff options
author | Sergei Shtylyov <sshtylyov@ru.mvista.com> | 2007-05-15 18:51:44 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-15 18:51:44 -0400 |
commit | 46cedc9b773795b6190c31e5d32de5207b55a356 (patch) | |
tree | ede4fb5593e092fc989286e9f14a2c9efdf23fed /drivers/ide/pci/sl82c105.c | |
parent | 3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f (diff) |
sl82c105: add speedproc() method and MWDMA0/1 support
Add the speedproc() method for setting transfer modes, modify config_for_dma()
to call it and use ide_max_dma_mode() to select the best DMA mode.
Add support for the multiword DMA modes 0 and 1, using the upper half of the
'drive_data' field to store the DMA timings to program into the drive control
register when DMA is turned on for real.
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/sl82c105.c')
-rw-r--r-- | drivers/ide/pci/sl82c105.c | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index fe3b4b91f854..3d7759c361ff 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c | |||
@@ -82,7 +82,14 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio) | |||
82 | 82 | ||
83 | pio = ide_get_best_pio_mode(drive, pio, 5, &p); | 83 | pio = ide_get_best_pio_mode(drive, pio, 5, &p); |
84 | 84 | ||
85 | drive->drive_data = drv_ctrl = get_pio_timings(&p); | 85 | drv_ctrl = get_pio_timings(&p); |
86 | |||
87 | /* | ||
88 | * Store the PIO timings so that we can restore them | ||
89 | * in case DMA will be turned off... | ||
90 | */ | ||
91 | drive->drive_data &= 0xffff0000; | ||
92 | drive->drive_data |= drv_ctrl; | ||
86 | 93 | ||
87 | if (!drive->using_dma) { | 94 | if (!drive->using_dma) { |
88 | /* | 95 | /* |
@@ -100,14 +107,67 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio) | |||
100 | } | 107 | } |
101 | 108 | ||
102 | /* | 109 | /* |
110 | * Configure the drive and chipset for a new transfer speed. | ||
111 | */ | ||
112 | static int sl82c105_tune_chipset(ide_drive_t *drive, u8 speed) | ||
113 | { | ||
114 | static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200}; | ||
115 | u16 drv_ctrl; | ||
116 | |||
117 | DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n", | ||
118 | drive->name, ide_xfer_verbose(speed))); | ||
119 | |||
120 | speed = ide_rate_filter(drive, speed); | ||
121 | |||
122 | switch (speed) { | ||
123 | case XFER_MW_DMA_2: | ||
124 | case XFER_MW_DMA_1: | ||
125 | case XFER_MW_DMA_0: | ||
126 | drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; | ||
127 | |||
128 | /* | ||
129 | * Store the DMA timings so that we can actually program | ||
130 | * them when DMA will be turned on... | ||
131 | */ | ||
132 | drive->drive_data &= 0x0000ffff; | ||
133 | drive->drive_data |= (unsigned long)drv_ctrl << 16; | ||
134 | |||
135 | /* | ||
136 | * If we are already using DMA, we just reprogram | ||
137 | * the drive control register. | ||
138 | */ | ||
139 | if (drive->using_dma) { | ||
140 | struct pci_dev *dev = HWIF(drive)->pci_dev; | ||
141 | int reg = 0x44 + drive->dn * 4; | ||
142 | |||
143 | pci_write_config_word(dev, reg, drv_ctrl); | ||
144 | } | ||
145 | break; | ||
146 | case XFER_PIO_5: | ||
147 | case XFER_PIO_4: | ||
148 | case XFER_PIO_3: | ||
149 | case XFER_PIO_2: | ||
150 | case XFER_PIO_1: | ||
151 | case XFER_PIO_0: | ||
152 | (void) sl82c105_tune_pio(drive, speed - XFER_PIO_0); | ||
153 | break; | ||
154 | default: | ||
155 | return -1; | ||
156 | } | ||
157 | |||
158 | return ide_config_drive_speed(drive, speed); | ||
159 | } | ||
160 | |||
161 | /* | ||
103 | * Configure the drive for DMA. | 162 | * Configure the drive for DMA. |
104 | * We'll program the chipset only when DMA is actually turned on. | ||
105 | */ | 163 | */ |
106 | static int config_for_dma(ide_drive_t *drive) | 164 | static int config_for_dma(ide_drive_t *drive) |
107 | { | 165 | { |
166 | u8 speed = ide_max_dma_mode(drive); | ||
167 | |||
108 | DBG(("config_for_dma(drive:%s)\n", drive->name)); | 168 | DBG(("config_for_dma(drive:%s)\n", drive->name)); |
109 | 169 | ||
110 | if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) | 170 | if (!speed || sl82c105_tune_chipset(drive, speed)) |
111 | return 0; | 171 | return 0; |
112 | 172 | ||
113 | return ide_dma_enable(drive); | 173 | return ide_dma_enable(drive); |
@@ -219,7 +279,7 @@ static int sl82c105_ide_dma_on(ide_drive_t *drive) | |||
219 | 279 | ||
220 | rc = __ide_dma_on(drive); | 280 | rc = __ide_dma_on(drive); |
221 | if (rc == 0) { | 281 | if (rc == 0) { |
222 | pci_write_config_word(dev, reg, 0x0200); | 282 | pci_write_config_word(dev, reg, drive->drive_data >> 16); |
223 | 283 | ||
224 | printk(KERN_INFO "%s: DMA enabled\n", drive->name); | 284 | printk(KERN_INFO "%s: DMA enabled\n", drive->name); |
225 | } | 285 | } |
@@ -357,6 +417,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | |||
357 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); | 417 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); |
358 | 418 | ||
359 | hwif->tuneproc = &sl82c105_tune_drive; | 419 | hwif->tuneproc = &sl82c105_tune_drive; |
420 | hwif->speedproc = &sl82c105_tune_chipset; | ||
360 | hwif->selectproc = &sl82c105_selectproc; | 421 | hwif->selectproc = &sl82c105_selectproc; |
361 | hwif->resetproc = &sl82c105_resetproc; | 422 | hwif->resetproc = &sl82c105_resetproc; |
362 | 423 | ||
@@ -388,7 +449,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | |||
388 | } | 449 | } |
389 | 450 | ||
390 | hwif->atapi_dma = 1; | 451 | hwif->atapi_dma = 1; |
391 | hwif->mwdma_mask = 0x04; | 452 | hwif->mwdma_mask = 0x07; |
392 | 453 | ||
393 | hwif->ide_dma_check = &sl82c105_ide_dma_check; | 454 | hwif->ide_dma_check = &sl82c105_ide_dma_check; |
394 | hwif->ide_dma_on = &sl82c105_ide_dma_on; | 455 | hwif->ide_dma_on = &sl82c105_ide_dma_on; |