~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/ide/amd7409.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/drivers/ide/amd7409.c          Version 0.05    June 9, 2000
  3  *
  4  * Copyright (C) 1999-2000              Andre Hedrick <andre@linux-ide.org>
  5  * May be copied or modified under the terms of the GNU General Public License
  6  *
  7  */
  8 
  9 #include <linux/config.h>
 10 #include <linux/types.h>
 11 #include <linux/kernel.h>
 12 #include <linux/delay.h>
 13 #include <linux/timer.h>
 14 #include <linux/mm.h>
 15 #include <linux/ioport.h>
 16 #include <linux/blkdev.h>
 17 #include <linux/hdreg.h>
 18 
 19 #include <linux/interrupt.h>
 20 #include <linux/init.h>
 21 #include <linux/pci.h>
 22 #include <linux/ide.h>
 23 
 24 #include <asm/io.h>
 25 #include <asm/irq.h>
 26 
 27 #include "ide_modes.h"
 28 
 29 #define DISPLAY_VIPER_TIMINGS
 30 
 31 #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
 32 #include <linux/stat.h>
 33 #include <linux/proc_fs.h>
 34 
 35 static int amd7409_get_info(char *, char **, off_t, int);
 36 extern int (*amd7409_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 37 extern char *ide_media_verbose(ide_drive_t *);
 38 static struct pci_dev *bmide_dev;
 39 
 40 static int amd7409_get_info (char *buffer, char **addr, off_t offset, int count)
 41 {
 42         char *p = buffer;
 43         u32 bibma = pci_resource_start(bmide_dev, 4);
 44         u8 c0 = 0, c1 = 0;
 45 
 46         /*
 47          * at that point bibma+0x2 et bibma+0xa are byte registers
 48          * to investigate:
 49          */
 50         c0 = inb_p((unsigned short)bibma + 0x02);
 51         c1 = inb_p((unsigned short)bibma + 0x0a);
 52 
 53         p += sprintf(p, "\n                                AMD 7409 VIPER Chipset.\n");
 54         p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
 55         p += sprintf(p, "                %sabled                         %sabled\n",
 56                         (c0&0x80) ? "dis" : " en",
 57                         (c1&0x80) ? "dis" : " en");
 58         p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
 59         p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
 60                         (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
 61                         (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
 62         p += sprintf(p, "UDMA\n");
 63         p += sprintf(p, "DMA\n");
 64         p += sprintf(p, "PIO\n");
 65 
 66         return p-buffer;        /* => must be less than 4k! */
 67 }
 68 #endif  /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */
 69 
 70 byte amd7409_proc = 0;
 71 
 72 extern char *ide_xfer_verbose (byte xfer_rate);
 73 
 74 static unsigned int amd7409_swdma_check (struct pci_dev *dev)
 75 {
 76         unsigned int class_rev;
 77         pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
 78         class_rev &= 0xff;
 79         return ((int) (class_rev >= 7) ? 1 : 0);
 80 }
 81 
 82 static int amd7409_swdma_error(ide_drive_t *drive)
 83 {
 84         printk("%s: single-word DMA not support (revision < C4)\n", drive->name);
 85         return 0;
 86 }
 87 
 88 /*
 89  * Here is where all the hard work goes to program the chipset.
 90  *
 91  */
 92 static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
 93 {
 94         ide_hwif_t *hwif        = HWIF(drive);
 95         struct pci_dev *dev     = hwif->pci_dev;
 96         int err                 = 0;
 97         byte unit               = (drive->select.b.unit & 0x01);
 98 #ifdef CONFIG_BLK_DEV_IDEDMA
 99         unsigned long dma_base  = hwif->dma_base;
100 #endif /* CONFIG_BLK_DEV_IDEDMA */
101         byte drive_pci          = 0x00;
102         byte drive_pci2         = 0x00;
103         byte ultra_timing       = 0x00;
104         byte dma_pio_timing     = 0x00;
105         byte pio_timing         = 0x00;
106 
107         switch (drive->dn) {
108                 case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break;
109                 case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break;
110                 case 2: drive_pci = 0x51; drive_pci2 = 0x49; break;
111                 case 3: drive_pci = 0x50; drive_pci2 = 0x48; break;
112                 default:
113                         return -1;
114         }
115 
116         pci_read_config_byte(dev, drive_pci, &ultra_timing);
117         pci_read_config_byte(dev, drive_pci2, &dma_pio_timing);
118         pci_read_config_byte(dev, 0x4c, &pio_timing);
119 
120 #ifdef DEBUG
121         printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
122                 drive->name, ultra_timing, dma_pio_timing, pio_timing);
123 #endif
124 
125         ultra_timing &= ~0xC7;
126         dma_pio_timing &= ~0xFF;
127         pio_timing &= ~(0x03 << drive->dn);
128 
129 #ifdef DEBUG
130         printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
131                 ultra_timing, dma_pio_timing, pio_timing);
132 #endif
133 
134         switch(speed) {
135 #ifdef CONFIG_BLK_DEV_IDEDMA
136                 case XFER_UDMA_4:
137                         ultra_timing |= 0x45;
138                         dma_pio_timing |= 0x20;
139                         break;
140                 case XFER_UDMA_3:
141                         ultra_timing |= 0x44;
142                         dma_pio_timing |= 0x20;
143                         break;
144                 case XFER_UDMA_2:
145                         ultra_timing |= 0x40;
146                         dma_pio_timing |= 0x20;
147                         break;
148                 case XFER_UDMA_1:
149                         ultra_timing |= 0x41;
150                         dma_pio_timing |= 0x20;
151                         break;
152                 case XFER_UDMA_0:
153                         ultra_timing |= 0x42;
154                         dma_pio_timing |= 0x20;
155                         break;
156                 case XFER_MW_DMA_2:
157                         dma_pio_timing |= 0x20;
158                         break;
159                 case XFER_MW_DMA_1:
160                         dma_pio_timing |= 0x21;
161                         break;
162                 case XFER_MW_DMA_0:
163                         dma_pio_timing |= 0x77;
164                         break;
165                 case XFER_SW_DMA_2:
166                         if (!amd7409_swdma_check(dev))
167                                 return amd7409_swdma_error(drive);
168                         dma_pio_timing |= 0x42;
169                         break;
170                 case XFER_SW_DMA_1:
171                         if (!amd7409_swdma_check(dev))
172                                 return amd7409_swdma_error(drive);
173                         dma_pio_timing |= 0x65;
174                         break;
175                 case XFER_SW_DMA_0:
176                         if (!amd7409_swdma_check(dev))
177                                 return amd7409_swdma_error(drive);
178                         dma_pio_timing |= 0xA8;
179                         break;
180 #endif /* CONFIG_BLK_DEV_IDEDMA */
181                 case XFER_PIO_4:
182                         dma_pio_timing |= 0x20;
183                         break;
184                 case XFER_PIO_3:
185                         dma_pio_timing |= 0x22;
186                         break;
187                 case XFER_PIO_2:
188                         dma_pio_timing |= 0x42;
189                         break;
190                 case XFER_PIO_1:
191                         dma_pio_timing |= 0x65;
192                         break;
193                 case XFER_PIO_0:
194                 default:
195                         dma_pio_timing |= 0xA8;
196                         break;
197         }
198 
199         pio_timing |= (0x03 << drive->dn);
200 
201         if (!drive->init_speed)
202                 drive->init_speed = speed;
203 
204 #ifdef CONFIG_BLK_DEV_IDEDMA
205         pci_write_config_byte(dev, drive_pci, ultra_timing);
206 #endif /* CONFIG_BLK_DEV_IDEDMA */
207         pci_write_config_byte(dev, drive_pci2, dma_pio_timing);
208         pci_write_config_byte(dev, 0x4c, pio_timing);
209 
210 #ifdef DEBUG
211         printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
212                 ultra_timing, dma_pio_timing, pio_timing);
213 #endif
214 
215 #ifdef CONFIG_BLK_DEV_IDEDMA
216         if (speed > XFER_PIO_4) {
217                 outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
218         } else {
219                 outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
220         }
221 #endif /* CONFIG_BLK_DEV_IDEDMA */
222 
223         err = ide_config_drive_speed(drive, speed);
224         drive->current_speed = speed;
225         return (err);
226 }
227 
228 static void config_chipset_for_pio (ide_drive_t *drive)
229 {
230         unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
231         unsigned short xfer_pio = drive->id->eide_pio_modes;
232         byte                    timing, speed, pio;
233 
234         pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
235 
236         if (xfer_pio> 4)
237                 xfer_pio = 0;
238 
239         if (drive->id->eide_pio_iordy > 0) {
240                 for (xfer_pio = 5;
241                         xfer_pio>0 &&
242                         drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
243                         xfer_pio--);
244         } else {
245                 xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
246                            (drive->id->eide_pio_modes & 2) ? 0x04 :
247                            (drive->id->eide_pio_modes & 1) ? 0x03 :
248                            (drive->id->tPIO & 2) ? 0x02 :
249                            (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
250         }
251 
252         timing = (xfer_pio >= pio) ? xfer_pio : pio;
253 
254         switch(timing) {
255                 case 4: speed = XFER_PIO_4;break;
256                 case 3: speed = XFER_PIO_3;break;
257                 case 2: speed = XFER_PIO_2;break;
258                 case 1: speed = XFER_PIO_1;break;
259                 default:
260                         speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
261                         break;
262         }
263         (void) amd7409_tune_chipset(drive, speed);
264         drive->current_speed = speed;
265 }
266 
267 static void amd7409_tune_drive (ide_drive_t *drive, byte pio)
268 {
269         byte speed;
270         switch(pio) {
271                 case 4:         speed = XFER_PIO_4;break;
272                 case 3:         speed = XFER_PIO_3;break;
273                 case 2:         speed = XFER_PIO_2;break;
274                 case 1:         speed = XFER_PIO_1;break;
275                 default:        speed = XFER_PIO_0;break;
276         }
277         (void) amd7409_tune_chipset(drive, speed);
278 }
279 
280 #ifdef CONFIG_BLK_DEV_IDEDMA
281 /*
282  * This allows the configuration of ide_pci chipset registers
283  * for cards that learn about the drive's UDMA, DMA, PIO capabilities
284  * after the drive is reported by the OS.
285  */
286 static int config_chipset_for_dma (ide_drive_t *drive)
287 {
288         struct hd_driveid *id   = drive->id;
289         byte udma_66            = eighty_ninty_three(drive);
290         byte udma_100           = 0;
291         byte speed              = 0x00;
292         int  rval;
293 
294         if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) {
295                 speed = XFER_UDMA_5;
296         } else if ((id->dma_ultra & 0x0010) && (udma_66)) {
297                 speed = XFER_UDMA_4;
298         } else if ((id->dma_ultra & 0x0008) && (udma_66)) {
299                 speed = XFER_UDMA_3;
300         } else if (id->dma_ultra & 0x0004) {
301                 speed = XFER_UDMA_2;
302         } else if (id->dma_ultra & 0x0002) {
303                 speed = XFER_UDMA_1;
304         } else if (id->dma_ultra & 0x0001) {
305                 speed = XFER_UDMA_0;
306         } else if (id->dma_mword & 0x0004) {
307                 speed = XFER_MW_DMA_2;
308         } else if (id->dma_mword & 0x0002) {
309                 speed = XFER_MW_DMA_1;
310         } else if (id->dma_mword & 0x0001) {
311                 speed = XFER_MW_DMA_0;
312         } else {
313                 return ((int) ide_dma_off_quietly);
314         }
315 
316         (void) amd7409_tune_chipset(drive, speed);
317 
318         rval = (int)(   ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
319                         ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
320                         ((id->dma_mword >> 8) & 7) ? ide_dma_on :
321                                                      ide_dma_off_quietly);
322 
323         return rval;
324 }
325 
326 
327 
328 static int config_drive_xfer_rate (ide_drive_t *drive)
329 {
330         struct hd_driveid *id = drive->id;
331         ide_dma_action_t dma_func = ide_dma_on;
332 
333         if (id && (id->capability & 1) && HWIF(drive)->autodma) {
334                 /* Consult the list of known "bad" drives */
335                 if (ide_dmaproc(ide_dma_bad_drive, drive)) {
336                         dma_func = ide_dma_off;
337                         goto fast_ata_pio;
338                 }
339                 dma_func = ide_dma_off_quietly;
340                 if (id->field_valid & 4) {
341                         if (id->dma_ultra & 0x002F) {
342                                 /* Force if Capable UltraDMA */
343                                 dma_func = config_chipset_for_dma(drive);
344                                 if ((id->field_valid & 2) &&
345                                     (dma_func != ide_dma_on))
346                                         goto try_dma_modes;
347                         }
348                 } else if (id->field_valid & 2) {
349 try_dma_modes:
350                         if ((id->dma_mword & 0x0007) ||
351                             ((id->dma_1word & 0x007) &&
352                              (amd7409_swdma_check(HWIF(drive)->pci_dev)))) {
353                                 /* Force if Capable regular DMA modes */
354                                 dma_func = config_chipset_for_dma(drive);
355                                 if (dma_func != ide_dma_on)
356                                         goto no_dma_set;
357                         }
358                         
359                 } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
360                         if (id->eide_dma_time > 150) {
361                                 goto no_dma_set;
362                         }
363                         /* Consult the list of known "good" drives */
364                         dma_func = config_chipset_for_dma(drive);
365                         if (dma_func != ide_dma_on)
366                                 goto no_dma_set;
367                 } else {
368                         goto fast_ata_pio;
369                 }
370         } else if ((id->capability & 8) || (id->field_valid & 2)) {
371 fast_ata_pio:
372                 dma_func = ide_dma_off_quietly;
373 no_dma_set:
374 
375                 config_chipset_for_pio(drive);
376         }
377         return HWIF(drive)->dmaproc(dma_func, drive);
378 }
379 
380 /*
381  * amd7409_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
382  */
383 
384 int amd7409_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
385 {
386         switch (func) {
387                 case ide_dma_check:
388                         return config_drive_xfer_rate(drive);
389                 default:
390                         break;
391         }
392         return ide_dmaproc(func, drive);        /* use standard DMA stuff */
393 }
394 #endif /* CONFIG_BLK_DEV_IDEDMA */
395 
396 unsigned int __init pci_init_amd7409 (struct pci_dev *dev, const char *name)
397 {
398         unsigned long fixdma_base = pci_resource_start(dev, 4);
399 
400 #ifdef CONFIG_BLK_DEV_IDEDMA
401         if (!amd7409_swdma_check(dev))
402                 printk("%s: disabling single-word DMA support (revision < C4)\n", name);
403 #endif /* CONFIG_BLK_DEV_IDEDMA */
404 
405         if (!fixdma_base) {
406                 /*
407                  *
408                  */
409         } else {
410                 /*
411                  * enable DMA capable bit, and "not" simplex only
412                  */
413                 outb(inb(fixdma_base+2) & 0x60, fixdma_base+2);
414 
415                 if (inb(fixdma_base+2) & 0x80)
416                         printk("%s: simplex device: DMA will fail!!\n", name);
417         }
418 #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
419         if (!amd7409_proc) {
420                 amd7409_proc = 1;
421                 bmide_dev = dev;
422                 amd7409_display_info = &amd7409_get_info;
423         }
424 #endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */
425 
426         return 0;
427 }
428 
429 unsigned int __init ata66_amd7409 (ide_hwif_t *hwif)
430 {
431 #ifdef CONFIG_AMD7409_OVERRIDE
432         byte ata66 = 1;
433 #else
434         byte ata66 = 0;
435 #endif /* CONFIG_AMD7409_OVERRIDE */
436 
437 #if 0
438         pci_read_config_byte(hwif->pci_dev, 0x48, &ata66);
439         return ((ata66 & 0x02) ? 0 : 1);
440 #endif
441         return ata66;
442 }
443 
444 void __init ide_init_amd7409 (ide_hwif_t *hwif)
445 {
446         hwif->tuneproc = &amd7409_tune_drive;
447         hwif->speedproc = &amd7409_tune_chipset;
448 
449 #ifndef CONFIG_BLK_DEV_IDEDMA
450         hwif->drives[0].autotune = 1;
451         hwif->drives[1].autotune = 1;
452         hwif->autodma = 0;
453         return;
454 #else
455 
456         if (hwif->dma_base) {
457                 hwif->dmaproc = &amd7409_dmaproc;
458                 hwif->autodma = 1;
459         } else {
460                 hwif->autodma = 0;
461                 hwif->drives[0].autotune = 1;
462                 hwif->drives[1].autotune = 1;
463         }
464 #endif /* CONFIG_BLK_DEV_IDEDMA */
465 }
466 
467 void __init ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase)
468 {
469         ide_setup_dma(hwif, dmabase, 8);
470 }
471 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.