make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / ide / pci / triflex.c
1 /*
2  * triflex.c
3  * 
4  * IDE Chipset driver for the Compaq TriFlex IDE controller.
5  * 
6  * Known to work with the Compaq Workstation 5x00 series.
7  *
8  * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
9  * Author: Torben Mathiasen <torben.mathiasen@hp.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  * 
24  * Loosely based on the piix & svwks drivers.
25  */
26
27 #include <linux/config.h>
28 #include <linux/types.h>
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/delay.h>
32 #include <linux/timer.h>
33 #include <linux/mm.h>
34 #include <linux/ioport.h>
35 #include <linux/blkdev.h>
36 #include <linux/hdreg.h>
37 #include <linux/pci.h>
38 #include <linux/ide.h>
39 #include <linux/init.h>
40
41 #include "ide_modes.h"
42 #include "triflex.h"
43
44 static struct pci_dev *triflex_dev;
45
46 static int triflex_get_info(char *buf, char **addr, off_t offset, int count)
47 {
48         char *p = buf;
49
50         struct pci_dev *dev     = triflex_dev;
51         unsigned long bibma = pci_resource_start(dev, 4);
52         u8  c0 = 0, c1 = 0;
53         u32 pri_timing, sec_timing;
54
55         p += sprintf(p, "\n                                Compaq Triflex Chipset\n");
56         
57         pci_read_config_dword(dev, 0x70, &pri_timing);
58         pci_read_config_dword(dev, 0x74, &sec_timing);
59
60         /*
61          * at that point bibma+0x2 et bibma+0xa are byte registers
62          * to investigate:
63          */
64         c0 = inb((unsigned short)bibma + 0x02);
65         c1 = inb((unsigned short)bibma + 0x0a);
66
67         p += sprintf(p, "--------------- Primary Channel "
68                         "---------------- Secondary Channel "
69                         "-------------\n");
70         p += sprintf(p, "                %sabled "
71                         "                        %sabled\n",
72                         (c0&0x80) ? "dis" : " en",
73                         (c1&0x80) ? "dis" : " en");
74         p += sprintf(p, "--------------- drive0 --------- drive1 "
75                         "-------- drive0 ---------- drive1 ------\n");
76         p += sprintf(p, "DMA enabled:    %s              %s "
77                         "            %s               %s\n",
78                         (c0&0x20) ? "yes" : "no ",
79                         (c0&0x40) ? "yes" : "no ",
80                         (c1&0x20) ? "yes" : "no ",
81                         (c1&0x40) ? "yes" : "no " );
82
83         p += sprintf(p, "DMA\n");
84         p += sprintf(p, "PIO\n");
85         
86         return p-buf;
87 }
88
89 static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed)
90 {
91         ide_hwif_t *hwif = HWIF(drive);
92         struct pci_dev *dev = hwif->pci_dev;
93         u8 channel_offset = hwif->channel ? 0x74 : 0x70;
94         u16 timing = 0;
95         u32 triflex_timings = 0;
96         u8 unit = (drive->select.b.unit & 0x01);
97         u8 speed = ide_rate_filter(0, xferspeed);
98         
99         pci_read_config_dword(dev, channel_offset, &triflex_timings);
100         
101         switch(speed) {
102                 case XFER_MW_DMA_2:
103                         timing = 0x0103; 
104                         break;
105                 case XFER_MW_DMA_1:
106                         timing = 0x0203;
107                         break;
108                 case XFER_MW_DMA_0:
109                         timing = 0x0808;
110                         break;
111                 case XFER_SW_DMA_2:
112                 case XFER_SW_DMA_1:
113                 case XFER_SW_DMA_0:
114                         timing = 0x0f0f;
115                         break;
116                 case XFER_PIO_4:
117                         timing = 0x0202;
118                         break;
119                 case XFER_PIO_3:
120                         timing = 0x0204;
121                         break;
122                 case XFER_PIO_2:
123                         timing = 0x0404;
124                         break;
125                 case XFER_PIO_1:
126                         timing = 0x0508;
127                         break;
128                 case XFER_PIO_0:
129                         timing = 0x0808;
130                         break;
131                 default:
132                         return -1;
133         }
134
135         triflex_timings &= ~(0xFFFF << (16 * unit));
136         triflex_timings |= (timing << (16 * unit));
137         
138         pci_write_config_dword(dev, channel_offset, triflex_timings);
139         
140         return (ide_config_drive_speed(drive, speed));
141 }
142
143 static void triflex_tune_drive(ide_drive_t *drive, u8 pio)
144 {
145         int use_pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
146         (void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio));
147 }
148
149 static int triflex_config_drive_for_dma(ide_drive_t *drive)
150 {
151         int speed = ide_dma_speed(drive, 0); /* No ultra speeds */
152
153         if (!speed) { 
154                 u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL);
155                 speed = XFER_PIO_0 + pspeed;
156         }
157         
158         (void) triflex_tune_chipset(drive, speed);
159          return ide_dma_enable(drive);
160 }
161
162 static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
163 {
164         ide_hwif_t *hwif        = HWIF(drive);
165         struct hd_driveid *id   = drive->id;
166         
167         if (id && (id->capability & 1) && drive->autodma) {
168                 if (hwif->ide_dma_bad_drive(drive))
169                         goto tune_pio;
170                 if (id->field_valid & 2) {
171                         if ((id->dma_mword & hwif->mwdma_mask) ||
172                                 (id->dma_1word & hwif->swdma_mask)) {
173                                 if (!triflex_config_drive_for_dma(drive))
174                                         goto tune_pio;
175                         }
176                 } else 
177                         goto tune_pio;
178         } else {
179 tune_pio:
180                 hwif->tuneproc(drive, 255);
181                 return hwif->ide_dma_off_quietly(drive);
182         }
183
184         return hwif->ide_dma_on(drive);
185 }
186
187 static void __init init_hwif_triflex(ide_hwif_t *hwif)
188 {
189         hwif->tuneproc = &triflex_tune_drive;
190         hwif->speedproc = &triflex_tune_chipset;
191
192         hwif->atapi_dma  = 1;
193         hwif->mwdma_mask = 0x07;
194         hwif->swdma_mask = 0x07;
195         hwif->ide_dma_check = &triflex_config_drive_xfer_rate;
196         
197         if (!noautodma)
198                 hwif->autodma = 1;
199         hwif->drives[0].autodma = hwif->autodma;
200         hwif->drives[1].autodma = hwif->autodma;
201 }
202
203 static unsigned int __init init_chipset_triflex(struct pci_dev *dev, 
204                 const char *name) 
205 {
206 #ifdef CONFIG_PROC_FS
207         ide_pci_register_host_proc(&triflex_proc);
208 #endif
209         return 0;       
210 }
211
212 static int __devinit triflex_init_one(struct pci_dev *dev, 
213                 const struct pci_device_id *id)
214 {
215         ide_pci_device_t *d = &triflex_devices[id->driver_data];
216         if (dev->device != d->device)
217                 BUG();
218         
219         ide_setup_pci_device(dev, d);
220         triflex_dev = dev;
221         MOD_INC_USE_COUNT;
222         
223         return 0;
224 }
225
226 static struct pci_driver driver = {
227         .name           = "TRIFLEX IDE",
228         .id_table       = triflex_pci_tbl,
229         .probe          = triflex_init_one,
230 };
231
232 static int triflex_ide_init(void)
233 {
234         return ide_pci_register_driver(&driver);
235 }
236
237 static void triflex_ide_exit(void)
238 {
239         ide_pci_unregister_driver(&driver);
240 }
241
242 module_init(triflex_ide_init);
243 module_exit(triflex_ide_exit);
244
245 MODULE_AUTHOR("Torben Mathiasen");
246 MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
247 MODULE_LICENSE("GPL");
248
249