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

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

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/drivers/ide/slc90e66.c        Version 0.10    October 4, 2000
  3  *
  4  *  Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
  5  *  May be copied or modified under the terms of the GNU General Public License
  6  *
  7  * 00:07.1 IDE interface: EFAR Microsystems:
  8  *              Unknown device 9130 (prog-if 8a [Master SecP PriP])
  9  * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV-
 10  *              VGASnoop- ParErr- Stepping- SERR- FastB2B-
 11  * Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium
 12  *              >TAbort- <TAbort- <MAbort- >SERR- <PERR-
 13  * Latency: 64
 14  * Interrupt: pin A routed to IRQ 255
 15  * Region 4: I/O ports at 1050
 16  *
 17  * 00: 55 10 30 91 05 00 00 02 00 8a 01 01 00 40 00 00
 18  * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 19  * 20: 51 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 20  * 30: 00 00 00 00 00 00 00 00 00 00 00 00 ff 01 00 00
 21  * 40: 37 e3 33 e3 b9 55 01 00 0d 00 04 22 00 00 00 00
 22  * 50: 00 00 ff a0 00 00 00 08 40 00 00 00 00 00 00 00
 23  * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 24  * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 25  * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 26  * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 27  * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 28  * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 29  * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 30  * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 31  * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 32  * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 33  *
 34  * This a look-a-like variation of the ICH0 PIIX4 Ultra-66,
 35  * but this keeps the ISA-Bridge and slots alive.
 36  *
 37  */
 38 
 39 #include <linux/config.h>
 40 #include <linux/types.h>
 41 #include <linux/kernel.h>
 42 #include <linux/ioport.h>
 43 #include <linux/pci.h>
 44 #include <linux/hdreg.h>
 45 #include <linux/ide.h>
 46 #include <linux/delay.h>
 47 #include <linux/init.h>
 48 
 49 #include <asm/io.h>
 50 
 51 #include "ide_modes.h"
 52 
 53 #define SLC90E66_DEBUG_DRIVE_INFO               0
 54 
 55 #define DISPLAY_SLC90E66_TIMINGS
 56 
 57 #if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
 58 #include <linux/stat.h>
 59 #include <linux/proc_fs.h>
 60 
 61 static int slc90e66_get_info(char *, char **, off_t, int);
 62 extern int (*slc90e66_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 63 extern char *ide_media_verbose(ide_drive_t *);
 64 static struct pci_dev *bmide_dev;
 65 
 66 static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count)
 67 {
 68         char *p = buffer;
 69         u32 bibma = pci_resource_start(bmide_dev, 4);
 70         u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
 71         u8  c0 = 0, c1 = 0;
 72         u8  reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
 73 
 74         pci_read_config_word(bmide_dev, 0x40, &reg40);
 75         pci_read_config_word(bmide_dev, 0x42, &reg42);
 76         pci_read_config_byte(bmide_dev, 0x44, &reg44);
 77         pci_read_config_byte(bmide_dev, 0x47, &reg47);
 78         pci_read_config_byte(bmide_dev, 0x48, &reg48);
 79         pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
 80         pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
 81 
 82         psitre = (reg40 & 0x4000) ? 1 : 0;
 83         ssitre = (reg42 & 0x4000) ? 1 : 0;
 84 
 85         /*
 86          * at that point bibma+0x2 et bibma+0xa are byte registers
 87          * to investigate:
 88          */
 89         c0 = inb_p((unsigned short)bibma + 0x02);
 90         c1 = inb_p((unsigned short)bibma + 0x0a);
 91 
 92         p += sprintf(p, "                                SLC90E66 Chipset.\n");
 93         p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
 94         p += sprintf(p, "                %sabled                         %sabled\n",
 95                         (c0&0x80) ? "dis" : " en",
 96                         (c1&0x80) ? "dis" : " en");
 97         p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
 98         p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
 99                         (c0&0x20) ? "yes" : "no ",
100                         (c0&0x40) ? "yes" : "no ",
101                         (c1&0x20) ? "yes" : "no ",
102                         (c1&0x40) ? "yes" : "no " );
103         p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
104                         (reg48&0x01) ? "yes" : "no ",
105                         (reg48&0x02) ? "yes" : "no ",
106                         (reg48&0x04) ? "yes" : "no ",
107                         (reg48&0x08) ? "yes" : "no " );
108         p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
109                         ((reg4a&0x04)==0x04) ? "4" :
110                         ((reg4a&0x03)==0x03) ? "3" :
111                         (reg4a&0x02) ? "2" :
112                         (reg4a&0x01) ? "1" :
113                         (reg4a&0x00) ? "" : "X",
114                         ((reg4a&0x40)==0x40) ? "4" :
115                         ((reg4a&0x30)==0x30) ? "3" :
116                         (reg4a&0x20) ? "2" :
117                         (reg4a&0x10) ? "1" :
118                         (reg4a&0x00) ? "" : "X",
119                         ((reg4b&0x04)==0x04) ? "4" :
120                         ((reg4b&0x03)==0x03) ? "3" :
121                         (reg4b&0x02) ? "2" :
122                         (reg4b&0x01) ? "1" :
123                         (reg4b&0x00) ? "" : "X",
124                         ((reg4b&0x40)==0x40) ? "4" :
125                         ((reg4b&0x30)==0x30) ? "3" :
126                         (reg4b&0x20) ? "2" :
127                         (reg4b&0x10) ? "1" :
128                         (reg4b&0x00) ? "" : "X");
129 
130         p += sprintf(p, "UDMA\n");
131         p += sprintf(p, "DMA\n");
132         p += sprintf(p, "PIO\n");
133 
134 /*
135  *      FIXME.... Add configuration junk data....blah blah......
136  */
137 
138         return p-buffer;         /* => must be less than 4k! */
139 }
140 #endif  /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */
141 
142 /*
143  *  Used to set Fifo configuration via kernel command line:
144  */
145 
146 byte slc90e66_proc = 0;
147 
148 extern char *ide_xfer_verbose (byte xfer_rate);
149 
150 #ifdef CONFIG_BLK_DEV_IDEDMA
151 /*
152  *
153  */
154 static byte slc90e66_dma_2_pio (byte xfer_rate) {
155         switch(xfer_rate) {
156                 case XFER_UDMA_4:
157                 case XFER_UDMA_3:
158                 case XFER_UDMA_2:
159                 case XFER_UDMA_1:
160                 case XFER_UDMA_0:
161                 case XFER_MW_DMA_2:
162                 case XFER_PIO_4:
163                         return 4;
164                 case XFER_MW_DMA_1:
165                 case XFER_PIO_3:
166                         return 3;
167                 case XFER_SW_DMA_2:
168                 case XFER_PIO_2:
169                         return 2;
170                 case XFER_MW_DMA_0:
171                 case XFER_SW_DMA_1:
172                 case XFER_SW_DMA_0:
173                 case XFER_PIO_1:
174                 case XFER_PIO_0:
175                 case XFER_PIO_SLOW:
176                 default:
177                         return 0;
178         }
179 }
180 #endif /* CONFIG_BLK_DEV_IDEDMA */
181 
182 /*
183  *  Based on settings done by AMI BIOS
184  *  (might be usefull if drive is not registered in CMOS for any reason).
185  */
186 static void slc90e66_tune_drive (ide_drive_t *drive, byte pio)
187 {
188         unsigned long flags;
189         u16 master_data;
190         byte slave_data;
191         int is_slave            = (&HWIF(drive)->drives[1] == drive);
192         int master_port         = HWIF(drive)->index ? 0x42 : 0x40;
193         int slave_port          = 0x44;
194                                  /* ISP  RTC */
195         byte timings[][2]       = { { 0, 0 },
196                                     { 0, 0 },
197                                     { 1, 0 },
198                                     { 2, 1 },
199                                     { 2, 3 }, };
200 
201         pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
202         pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
203         if (is_slave) {
204                 master_data = master_data | 0x4000;
205                 if (pio > 1)
206                         /* enable PPE, IE and TIME */
207                         master_data = master_data | 0x0070;
208                 pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
209                 slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
210                 slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1]
211                                            << (HWIF(drive)->index ? 4 : 0)));
212         } else {
213                 master_data = master_data & 0xccf8;
214                 if (pio > 1)
215                         /* enable PPE, IE and TIME */
216                         master_data = master_data | 0x0007;
217                 master_data = master_data | (timings[pio][0] << 12) |
218                               (timings[pio][1] << 8);
219         }
220         save_flags(flags);
221         cli();
222         pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
223         if (is_slave)
224                 pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
225         restore_flags(flags);
226 }
227 
228 #ifdef CONFIG_BLK_DEV_IDEDMA
229 static int slc90e66_tune_chipset (ide_drive_t *drive, byte speed)
230 {
231         ide_hwif_t *hwif        = HWIF(drive);
232         struct pci_dev *dev     = hwif->pci_dev;
233         byte maslave            = hwif->channel ? 0x42 : 0x40;
234         int a_speed             = 7 << (drive->dn * 4);
235         int u_flag              = 1 << drive->dn;
236         int u_speed             = 0;
237         int err                 = 0;
238         int                     sitre;
239         short                   reg4042, reg44, reg48, reg4a;
240 
241         pci_read_config_word(dev, maslave, &reg4042);
242         sitre = (reg4042 & 0x4000) ? 1 : 0;
243         pci_read_config_word(dev, 0x44, &reg44);
244         pci_read_config_word(dev, 0x48, &reg48);
245         pci_read_config_word(dev, 0x4a, &reg4a);
246 
247         switch(speed) {
248                 case XFER_UDMA_4:       u_speed = 4 << (drive->dn * 4); break;
249                 case XFER_UDMA_3:       u_speed = 3 << (drive->dn * 4); break;
250                 case XFER_UDMA_2:       u_speed = 2 << (drive->dn * 4); break;
251                 case XFER_UDMA_1:       u_speed = 1 << (drive->dn * 4); break;
252                 case XFER_UDMA_0:       u_speed = 0 << (drive->dn * 4); break;
253                 case XFER_MW_DMA_2:
254                 case XFER_MW_DMA_1:
255                 case XFER_SW_DMA_2:     break;
256                 default:                return -1;
257         }
258 
259         if (speed >= XFER_UDMA_0) {
260                 if (!(reg48 & u_flag))
261                         pci_write_config_word(dev, 0x48, reg48|u_flag);
262                 if ((reg4a & u_speed) != u_speed) {
263                         pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
264                         pci_read_config_word(dev, 0x4a, &reg4a);
265                         pci_write_config_word(dev, 0x4a, reg4a|u_speed);
266                 }
267         }
268         if (speed < XFER_UDMA_0) {
269                 if (reg48 & u_flag)
270                         pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
271                 if (reg4a & a_speed)
272                         pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
273         }
274 
275         slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed));
276 
277 #if SLC90E66_DEBUG_DRIVE_INFO
278         printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
279 #endif /* SLC90E66_DEBUG_DRIVE_INFO */
280         if (!drive->init_speed)
281                 drive->init_speed = speed;
282         err = ide_config_drive_speed(drive, speed);
283         drive->current_speed = speed;
284         return err;
285 }
286 
287 static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
288 {
289         struct hd_driveid *id   = drive->id;
290         int ultra               = 1;
291         byte speed              = 0;
292         byte udma_66            = eighty_ninty_three(drive);
293 
294         if ((id->dma_ultra & 0x0010) && (ultra)) {
295                 speed = (udma_66) ? XFER_UDMA_4 : XFER_UDMA_2;
296         } else if ((id->dma_ultra & 0x0008) && (ultra)) {
297                 speed = (udma_66) ? XFER_UDMA_3 : XFER_UDMA_1;
298         } else if ((id->dma_ultra & 0x0004) && (ultra)) {
299                 speed = XFER_UDMA_2;
300         } else if ((id->dma_ultra & 0x0002) && (ultra)) {
301                 speed = XFER_UDMA_1;
302         } else if ((id->dma_ultra & 0x0001) && (ultra)) {
303                 speed = XFER_UDMA_0;
304         } else if (id->dma_mword & 0x0004) {
305                 speed = XFER_MW_DMA_2;
306         } else if (id->dma_mword & 0x0002) {
307                 speed = XFER_MW_DMA_1;
308         } else if (id->dma_1word & 0x0004) {
309                 speed = XFER_SW_DMA_2;
310         } else {
311                 speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
312         }
313 
314         (void) slc90e66_tune_chipset(drive, speed);
315 
316         return ((int)   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
317                         ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
318                         ((id->dma_mword >> 8) & 7) ? ide_dma_on :
319                         ((id->dma_1word >> 8) & 7) ? ide_dma_on :
320                                                      ide_dma_off_quietly);
321 }
322 
323 static int slc90e66_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
324 {
325         switch (func) {
326                 case ide_dma_check:
327                          return ide_dmaproc((ide_dma_action_t) slc90e66_config_drive_for_dma(drive), drive);
328                 default :
329                         break;
330         }
331         /* Other cases are done by generic IDE-DMA code. */
332         return ide_dmaproc(func, drive);
333 }
334 #endif /* CONFIG_BLK_DEV_IDEDMA */
335 
336 unsigned int __init pci_init_slc90e66 (struct pci_dev *dev, const char *name)
337 {
338 #if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
339         if (!slc90e66_proc) {
340                 slc90e66_proc = 1;
341                 bmide_dev = dev;
342                 slc90e66_display_info = &slc90e66_get_info;
343         }
344 #endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */
345         return 0;
346 }
347 
348 unsigned int __init ata66_slc90e66 (ide_hwif_t *hwif)
349 {
350 #if 1
351         byte reg47 = 0, ata66 = 0;
352         byte mask = hwif->channel ? 0x02 : 0x01;
353 
354         pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
355 
356         ata66 = (reg47 & mask) ? 1 : 0;
357 #else
358         byte ata66 = 0;
359 #endif
360         return ata66;
361 }
362 
363 void __init ide_init_slc90e66 (ide_hwif_t *hwif)
364 {
365         if (!hwif->irq)
366                 hwif->irq = hwif->channel ? 15 : 14;
367 
368         hwif->tuneproc = &slc90e66_tune_drive;
369         hwif->drives[0].autotune = 1;
370         hwif->drives[1].autotune = 1;
371 
372         if (!hwif->dma_base)
373                 return;
374 
375 #ifndef CONFIG_BLK_DEV_IDEDMA
376         hwif->autodma = 0;
377 #else /* CONFIG_BLK_DEV_IDEDMA */
378         hwif->autodma = 1;
379         hwif->dmaproc = &slc90e66_dmaproc;
380         hwif->speedproc = &slc90e66_tune_chipset;
381 #endif /* !CONFIG_BLK_DEV_IDEDMA */
382 }
383 

~ [ 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.