Import 2.3.10pre1
[davej-history.git] / drivers / block / alim15x3.c
blob4ea590fa294726cab98aec0fe21d8b0c185b34b0
1 /*
2 * linux/drivers/block/alim15x3.c Version 0.05 Jun. 29, 1999
4 * Copyright (C) 1998-99 Michel Aubry, Maintainer
5 * Copyright (C) 1998-99 Andrzej Krzysztofowicz, Maintainer
6 * Copyright (C) 1998-99 Andre Hedrick, Integrater and Maintainer
8 * (U)DMA capable version of ali 1533/1543(C)
10 * Default disable (U)DMA on all devices execpt hard disks.
11 * This measure of overkill is needed to stablize the chipset code.
15 #include <linux/config.h>
16 #include <linux/types.h>
17 #include <linux/kernel.h>
18 #include <linux/pci.h>
19 #include <linux/ide.h>
21 #include <asm/io.h>
23 #include "ide_modes.h"
25 #define DISPLAY_ALI_TIMINGS
27 #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
28 #include <linux/stat.h>
29 #include <linux/proc_fs.h>
31 static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy);
32 extern int (*ali_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
33 struct pci_dev *bmide_dev;
35 char *fifo[4] = {
36 "FIFO Off",
37 "FIFO On ",
38 "DMA mode",
39 "PIO mode" };
41 char *udmaT[8] = {
42 "1.5T",
43 " 2T",
44 "2.5T",
45 " 3T",
46 "3.5T",
47 " 4T",
48 " 6T",
49 " 8T"
52 char *channel_status[8] = {
53 "OK ",
54 "busy ",
55 "DRQ ",
56 "DRQ busy ",
57 "error ",
58 "error busy ",
59 "error DRQ ",
60 "error DRQ busy"
62 #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
64 static void ali15x3_tune_drive (ide_drive_t *drive, byte pio)
66 ide_pio_data_t d;
67 ide_hwif_t *hwif = HWIF(drive);
68 struct pci_dev *dev = hwif->pci_dev;
69 int s_time, a_time, c_time;
70 byte s_clc, a_clc, r_clc;
71 unsigned long flags;
72 int bus_speed = ide_system_bus_speed();
73 int port = hwif->index ? 0x5c : 0x58;
75 pio = ide_get_best_pio_mode(drive, pio, 5, &d);
76 s_time = ide_pio_timings[pio].setup_time;
77 a_time = ide_pio_timings[pio].active_time;
78 if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
79 s_clc = 0;
80 if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
81 a_clc = 0;
82 c_time = ide_pio_timings[pio].cycle_time;
84 #if 0
85 if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16)
86 r_clc = 0;
87 #endif
89 if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
90 r_clc = 1;
91 } else {
92 if (r_clc >= 16)
93 r_clc = 0;
95 save_flags(flags);
96 cli();
97 pci_write_config_byte(dev, port, s_clc);
98 pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
99 restore_flags(flags);
102 * setup active rec
103 * { 70, 165, 365 }, PIO Mode 0
104 * { 50, 125, 208 }, PIO Mode 1
105 * { 30, 100, 110 }, PIO Mode 2
106 * { 30, 80, 70 }, PIO Mode 3 with IORDY
107 * { 25, 70, 25 }, PIO Mode 4 with IORDY ns
108 * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard)
113 __initfunc(unsigned int pci_init_ali15x3 (struct pci_dev *dev, const char *name))
115 byte confreg0 = 0, confreg1 =0, progif = 0;
116 int errors = 0;
118 if (pci_read_config_byte(dev, 0x50, &confreg1))
119 goto veryspecialsettingserror;
120 if (!(confreg1 & 0x02))
121 if (pci_write_config_byte(dev, 0x50, confreg1 | 0x02))
122 goto veryspecialsettingserror;
124 if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif))
125 goto veryspecialsettingserror;
126 if (!(progif & 0x40)) {
128 * The way to enable them is to set progif
129 * writable at 0x4Dh register, and set bit 6
130 * of progif to 1:
132 if (pci_read_config_byte(dev, 0x4d, &confreg0))
133 goto veryspecialsettingserror;
134 if (confreg0 & 0x80)
135 if (pci_write_config_byte(dev, 0x4d, confreg0 & ~0x80))
136 goto veryspecialsettingserror;
137 if (pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x40))
138 goto veryspecialsettingserror;
139 if (confreg0 & 0x80)
140 if (pci_write_config_byte(dev, 0x4d, confreg0))
141 errors++;
144 if ((pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) || (!(progif & 0x40)))
145 goto veryspecialsettingserror;
147 printk("%s: enabled read of IDE channels state (en/dis-abled) %s.\n",
148 name, errors ? "with Error(s)" : "Succeeded" );
149 return 0;
151 veryspecialsettingserror:
152 printk("%s: impossible to enable read of IDE channels state (en/dis-abled)!\n", name);
153 return 0;
156 int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
158 switch (func) {
159 case ide_dma_check:
160 if (drive->media == ide_cdrom) {
161 ide_hwif_t *hwif = HWIF(drive);
162 struct pci_dev *dev = hwif->pci_dev;
163 struct hd_driveid *id = drive->id;
164 byte cd_dma_fifo = 0;
166 pci_read_config_byte(dev, 0x53, &cd_dma_fifo);
168 if (((id->field_valid & 4) || (id->field_valid & 2)) &&
169 (id->capability & 1) && hwif->autodma) {
170 unsigned long dma_set_bit = hwif->dma_base + 2;
171 #if 0
172 if (cd_dma_fifo & 0x02)
173 pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x02);
174 pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01);
175 #else
176 pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01|0x02);
177 #endif
178 if (drive->select.b.unit & 0x01) {
179 outb(inb(dma_set_bit)|0x40, dma_set_bit);
180 } else {
181 outb(inb(dma_set_bit)|0x20, dma_set_bit);
183 } else {
184 if (cd_dma_fifo & 0x01)
185 pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x01);
186 pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x02);
188 } else if (drive->media != ide_disk) {
189 return ide_dmaproc(ide_dma_off_quietly, drive);
191 default:
192 break;
194 return ide_dmaproc(func, drive); /* use standard DMA stuff */
197 __initfunc(void ide_init_ali15x3 (ide_hwif_t *hwif))
199 struct pci_dev *dev;
200 byte ideic, inmir, iderev;
201 byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6,
202 1, 11, 0, 12, 0, 14, 0, 15 };
204 pci_read_config_byte(hwif->pci_dev, PCI_REVISION_ID, &iderev);
206 hwif->irq = hwif->channel ? 15 : 14;
207 for (dev = pci_devices; dev; dev=dev->next) /* look for ISA bridge */
208 if (dev->vendor==PCI_VENDOR_ID_AL &&
209 dev->device==PCI_DEVICE_ID_AL_M1533)
210 break;
211 if (dev) {
212 pci_read_config_byte(dev, 0x58, &ideic);
213 ideic = ideic & 0x03;
214 if ((hwif->channel && ideic == 0x03) ||
215 (!hwif->channel && !ideic)) {
216 pci_read_config_byte(dev, 0x44, &inmir);
217 inmir = inmir & 0x0f;
218 hwif->irq = irq_routing_table[inmir];
219 } else
220 if (hwif->channel && !(ideic & 0x01)) {
221 pci_read_config_byte(dev, 0x75, &inmir);
222 inmir = inmir & 0x0f;
223 hwif->irq = irq_routing_table[inmir];
226 #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
227 bmide_dev = hwif->pci_dev;
228 ali_display_info = &ali_get_info;
229 #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
231 hwif->tuneproc = &ali15x3_tune_drive;
232 if ((hwif->dma_base) && (iderev >= 0xC1)) {
233 /* M1543C or newer for DMAing */
234 hwif->dmaproc = &ali15x3_dmaproc;
235 } else {
236 hwif->autodma = 0;
237 hwif->drives[0].autotune = 1;
238 hwif->drives[1].autotune = 1;
240 return;
243 #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
244 static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy)
246 byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1;
247 unsigned int bibma;
248 byte c0, c1;
249 byte rev, tmp;
250 char *p = buffer;
251 char *q;
253 /* fetch rev. */
254 pci_read_config_byte(bmide_dev, 0x08, &rev);
255 if (rev >= 0xc1) /* M1543C or newer */
256 udmaT[7] = " ???";
257 else
258 fifo[3] = " ??? ";
260 /* first fetch bibma: */
261 pci_read_config_dword(bmide_dev, 0x20, &bibma);
262 bibma = (bibma & 0xfff0) ;
264 * at that point bibma+0x2 et bibma+0xa are byte
265 * registers to investigate:
267 c0 = inb((unsigned short)bibma + 0x02);
268 c1 = inb((unsigned short)bibma + 0x0a);
270 p += sprintf(p,
271 "\n Ali M15x3 Chipset.\n");
272 p += sprintf(p,
273 " ------------------\n");
274 pci_read_config_byte(bmide_dev, 0x78, &reg53h);
275 p += sprintf(p, "PCI Clock: %d.\n", reg53h);
277 pci_read_config_byte(bmide_dev, 0x53, &reg53h);
278 p += sprintf(p,
279 "CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
280 (reg53h & 0x02) ? "Yes" : "No ",
281 (reg53h & 0x01) ? "Yes" : "No " );
282 pci_read_config_byte(bmide_dev, 0x74, &reg53h);
283 p += sprintf(p,
284 "FIFO Status: contains %d Words, runs%s%s\n\n",
285 (reg53h & 0x3f),
286 (reg53h & 0x40) ? " OVERWR" : "",
287 (reg53h & 0x80) ? " OVERRD." : "." );
289 p += sprintf(p,
290 "-------------------primary channel-------------------secondary channel---------\n\n");
292 pci_read_config_byte(bmide_dev, 0x09, &reg53h);
293 p += sprintf(p,
294 "channel status: %s %s\n",
295 (reg53h & 0x20) ? "On " : "Off",
296 (reg53h & 0x10) ? "On " : "Off" );
298 p += sprintf(p,
299 "both channels togth: %s %s\n",
300 (c0&0x80) ? "No " : "Yes",
301 (c1&0x80) ? "No " : "Yes" );
303 pci_read_config_byte(bmide_dev, 0x76, &reg53h);
304 p += sprintf(p,
305 "Channel state: %s %s\n",
306 channel_status[reg53h & 0x07],
307 channel_status[(reg53h & 0x70) >> 4] );
309 pci_read_config_byte(bmide_dev, 0x58, &reg5xh);
310 pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);
311 p += sprintf(p,
312 "Add. Setup Timing: %dT %dT\n",
313 (reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
314 (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
316 pci_read_config_byte(bmide_dev, 0x59, &reg5xh);
317 pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);
318 p += sprintf(p,
319 "Command Act. Count: %dT %dT\n"
320 "Command Rec. Count: %dT %dT\n\n",
321 (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
322 (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
323 (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
324 (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
326 p += sprintf(p,
327 "----------------drive0-----------drive1------------drive0-----------drive1------\n\n");
328 p += sprintf(p,
329 "DMA enabled: %s %s %s %s\n",
330 (c0&0x20) ? "Yes" : "No ",
331 (c0&0x40) ? "Yes" : "No ",
332 (c1&0x20) ? "Yes" : "No ",
333 (c1&0x40) ? "Yes" : "No " );
335 pci_read_config_byte(bmide_dev, 0x54, &reg5xh);
336 pci_read_config_byte(bmide_dev, 0x55, &reg5yh);
337 q = "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n";
338 if (rev < 0xc1) {
339 if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {
340 p += sprintf(p, q, 8, 8, 8, 8);
341 } else {
342 p += sprintf(p, q,
343 (reg5xh & 0x03) + 12,
344 ((reg5xh & 0x30)>>4) + 12,
345 (reg5yh & 0x03) + 12,
346 ((reg5yh & 0x30)>>4) + 12 );
348 } else {
349 p += sprintf(p, q,
350 (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4,
351 (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4,
352 (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4,
353 (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4 );
356 #if 0
357 p += sprintf(p,
358 "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n",
359 (reg5xh & 0x03) + 12,
360 ((reg5xh & 0x30)>>4) + 12,
361 (reg5yh & 0x03) + 12,
362 ((reg5yh & 0x30)>>4) + 12 );
363 #endif
365 p += sprintf(p,
366 "FIFO mode: %s %s %s %s\n",
367 fifo[((reg5xh & 0x0c) >> 2)],
368 fifo[((reg5xh & 0xc0) >> 6)],
369 fifo[((reg5yh & 0x0c) >> 2)],
370 fifo[((reg5yh & 0xc0) >> 6)] );
372 pci_read_config_byte(bmide_dev, 0x5a, &reg5xh);
373 pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);
374 pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);
375 pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);
377 p += sprintf(p,/*
378 "------------------drive0-----------drive1------------drive0-----------drive1------\n")*/
379 "Dt RW act. Cnt %2dT %2dT %2dT %2dT\n"
380 "Dt RW rec. Cnt %2dT %2dT %2dT %2dT\n\n",
381 (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
382 (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
383 (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
384 (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
385 (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
386 (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
387 (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
388 (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
390 p += sprintf(p,
391 "-----------------------------------UDMA Timings--------------------------------\n\n");
393 pci_read_config_byte(bmide_dev, 0x56, &reg5xh);
394 pci_read_config_byte(bmide_dev, 0x57, &reg5yh);
395 p += sprintf(p,
396 "UDMA: %s %s %s %s\n"
397 "UDMA timings: %s %s %s %s\n\n",
398 (reg5xh & 0x08) ? "OK" : "No",
399 (reg5xh & 0x80) ? "OK" : "No",
400 (reg5yh & 0x08) ? "OK" : "No",
401 (reg5yh & 0x80) ? "OK" : "No",
402 udmaT[(reg5xh & 0x07)],
403 udmaT[(reg5xh & 0x70) >> 4],
404 udmaT[reg5yh & 0x07],
405 udmaT[(reg5yh & 0x70) >> 4] );
407 return p-buffer; /* => must be less than 4k! */
409 #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */