OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ide/] [pci/] [opti621.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/ide/pci/opti621.c             Version 0.7     Sept 10, 2002
3
 *
4
 *  Copyright (C) 1996-1998  Linus Torvalds & authors (see below)
5
 */
6
 
7
/*
8
 * Authors:
9
 * Jaromir Koutek <miri@punknet.cz>,
10
 * Jan Harkes <jaharkes@cwi.nl>,
11
 * Mark Lord <mlord@pobox.com>
12
 * Some parts of code are from ali14xx.c and from rz1000.c.
13
 *
14
 * OPTi is trademark of OPTi, Octek is trademark of Octek.
15
 *
16
 * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps
17
 * and disassembled/traced setupvic.exe (DOS program).
18
 * It increases kernel code about 2 kB.
19
 * I don't have this card no more, but I hope I can get some in case
20
 * of needed development.
21
 * My card is Octek PIDE 1.01 (on card) or OPTiViC (program).
22
 * It has a place for a secondary connector in circuit, but nothing
23
 * is there. Also BIOS says no address for
24
 * secondary controller (see bellow in ide_init_opti621).
25
 * I've only tested this on my system, which only has one disk.
26
 * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus
27
 * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random
28
 * lockups). I tried the OCTEK double speed CD-ROM and
29
 * it does not work! But I can't boot DOS also, so it's probably
30
 * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no
31
 * problems) and Seagate 1GB (as slave, WD as master). My experiences
32
 * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes
33
 * it slows to about 100kB/s! I don't know why and I have
34
 * not this drive now, so I can't try it again.
35
 * I write this driver because I lost the paper ("manual") with
36
 * settings of jumpers on the card and I have to boot Linux with
37
 * Loadlin except LILO, cause I have to run the setupvic.exe program
38
 * already or I get disk errors (my test: rpm -Vf
39
 * /usr/X11R6/bin/XF86_SVGA - or any big file).
40
 * Some numbers from hdparm -t /dev/hda:
41
 * Timing buffer-cache reads:   32 MB in  3.02 seconds =10.60 MB/sec
42
 * Timing buffered disk reads:  16 MB in  5.52 seconds = 2.90 MB/sec
43
 * I have 4 Megs/s before, but I don't know why (maybe changes
44
 * in hdparm test).
45
 * After release of 0.1, I got some successful reports, so it might work.
46
 *
47
 * The main problem with OPTi is that some timings for master
48
 * and slave must be the same. For example, if you have master
49
 * PIO 3 and slave PIO 0, driver have to set some timings of
50
 * master for PIO 0. Second problem is that opti621_tune_drive
51
 * got only one drive to set, but have to set both drives.
52
 * This is solved in compute_pios. If you don't set
53
 * the second drive, compute_pios use ide_get_best_pio_mode
54
 * for autoselect mode (you can change it to PIO 0, if you want).
55
 * If you then set the second drive to another PIO, the old value
56
 * (automatically selected) will be overrided by yours.
57
 * There is a 25/33MHz switch in configuration
58
 * register, but driver is written for use at any frequency which get
59
 * (use idebus=xx to select PCI bus speed).
60
 * Use ide0=autotune for automatical tune of the PIO modes.
61
 * If you get strange results, do not use this and set PIO manually
62
 * by hdparm.
63
 *
64
 * Version 0.1, Nov 8, 1996
65
 * by Jaromir Koutek, for 2.1.8.
66
 * Initial version of driver.
67
 *
68
 * Version 0.2
69
 * Number 0.2 skipped.
70
 *
71
 * Version 0.3, Nov 29, 1997
72
 * by Mark Lord (probably), for 2.1.68
73
 * Updates for use with new IDE block driver.
74
 *
75
 * Version 0.4, Dec 14, 1997
76
 * by Jan Harkes
77
 * Fixed some errors and cleaned the code.
78
 *
79
 * Version 0.5, Jan 2, 1998
80
 * by Jaromir Koutek
81
 * Updates for use with (again) new IDE block driver.
82
 * Update of documentation.
83
 *
84
 * Version 0.6, Jan 2, 1999
85
 * by Jaromir Koutek
86
 * Reversed to version 0.3 of the driver, because
87
 * 0.5 doesn't work.
88
 */
89
 
90
#undef REALLY_SLOW_IO   /* most systems can safely undef this */
91
#define OPTI621_DEBUG           /* define for debug messages */
92
 
93
#include <linux/types.h>
94
#include <linux/module.h>
95
#include <linux/kernel.h>
96
#include <linux/delay.h>
97
#include <linux/timer.h>
98
#include <linux/mm.h>
99
#include <linux/ioport.h>
100
#include <linux/blkdev.h>
101
#include <linux/pci.h>
102
#include <linux/hdreg.h>
103
#include <linux/ide.h>
104
 
105
#include <asm/io.h>
106
 
107
#include "ide_modes.h"
108
#include "opti621.h"
109
 
110
#define OPTI621_MAX_PIO 3
111
/* In fact, I do not have any PIO 4 drive
112
 * (address: 25 ns, data: 70 ns, recovery: 35 ns),
113
 * but OPTi 82C621 is programmable and it can do (minimal values):
114
 * on 40MHz PCI bus (pulse 25 ns):
115
 *  address: 25 ns, data: 25 ns, recovery: 50 ns;
116
 * on 20MHz PCI bus (pulse 50 ns):
117
 *  address: 50 ns, data: 50 ns, recovery: 100 ns.
118
 */
119
 
120
/* #define READ_PREFETCH 0 */
121
/* Uncomment for disable read prefetch.
122
 * There is some readprefetch capatibility in hdparm,
123
 * but when I type hdparm -P 1 /dev/hda, I got errors
124
 * and till reset drive is inaccessible.
125
 * This (hw) read prefetch is safe on my drive.
126
 */
127
 
128
#ifndef READ_PREFETCH
129
#define READ_PREFETCH 0x40 /* read prefetch is enabled */
130
#endif /* else read prefetch is disabled */
131
 
132
#define READ_REG 0      /* index of Read cycle timing register */
133
#define WRITE_REG 1     /* index of Write cycle timing register */
134
#define CNTRL_REG 3     /* index of Control register */
135
#define STRAP_REG 5     /* index of Strap register */
136
#define MISC_REG 6      /* index of Miscellaneous register */
137
 
138
static int reg_base;
139
 
140
#define PIO_NOT_EXIST 254
141
#define PIO_DONT_KNOW 255
142
 
143
/* there are stored pio numbers from other calls of opti621_tune_drive */
144
static void compute_pios(ide_drive_t *drive, u8 pio)
145
/* Store values into drive->drive_data
146
 *      second_contr - 0 for primary controller, 1 for secondary
147
 *      slave_drive - 0 -> pio is for master, 1 -> pio is for slave
148
 *      pio - PIO mode for selected drive (for other we don't know)
149
 */
150
{
151
        int d;
152
        ide_hwif_t *hwif = HWIF(drive);
153
 
154
        drive->drive_data = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL);
155
        for (d = 0; d < 2; ++d) {
156
                drive = &hwif->drives[d];
157
                if (drive->present) {
158
                        if (drive->drive_data == PIO_DONT_KNOW)
159
                                drive->drive_data = ide_get_best_pio_mode(drive, 255, OPTI621_MAX_PIO, NULL);
160
#ifdef OPTI621_DEBUG
161
                        printk("%s: Selected PIO mode %d\n",
162
                                drive->name, drive->drive_data);
163
#endif
164
                } else {
165
                        drive->drive_data = PIO_NOT_EXIST;
166
                }
167
        }
168
}
169
 
170
static int cmpt_clk(int time, int bus_speed)
171
/* Returns (rounded up) time in clocks for time in ns,
172
 * with bus_speed in MHz.
173
 * Example: bus_speed = 40 MHz, time = 80 ns
174
 * 1000/40 = 25 ns (clk value),
175
 * 80/25 = 3.2, rounded up to 4 (I hope ;-)).
176
 * Use idebus=xx to select right frequency.
177
 */
178
{
179
        return ((time*bus_speed+999)/1000);
180
}
181
 
182
static void write_reg(ide_hwif_t *hwif, u8 value, int reg)
183
/* Write value to register reg, base of register
184
 * is at reg_base (0x1f0 primary, 0x170 secondary,
185
 * if not changed by PCI configuration).
186
 * This is from setupvic.exe program.
187
 */
188
{
189
        hwif->INW(reg_base+1);
190
        hwif->INW(reg_base+1);
191
        hwif->OUTB(3, reg_base+2);
192
        hwif->OUTB(value, reg_base+reg);
193
        hwif->OUTB(0x83, reg_base+2);
194
}
195
 
196
static u8 read_reg(ide_hwif_t *hwif, int reg)
197
/* Read value from register reg, base of register
198
 * is at reg_base (0x1f0 primary, 0x170 secondary,
199
 * if not changed by PCI configuration).
200
 * This is from setupvic.exe program.
201
 */
202
{
203
        u8 ret = 0;
204
 
205
        hwif->INW(reg_base+1);
206
        hwif->INW(reg_base+1);
207
        hwif->OUTB(3, reg_base+2);
208
        ret = hwif->INB(reg_base+reg);
209
        hwif->OUTB(0x83, reg_base+2);
210
        return ret;
211
}
212
 
213
typedef struct pio_clocks_s {
214
        int     address_time;   /* Address setup (clocks) */
215
        int     data_time;      /* Active/data pulse (clocks) */
216
        int     recovery_time;  /* Recovery time (clocks) */
217
} pio_clocks_t;
218
 
219
static void compute_clocks(int pio, pio_clocks_t *clks)
220
{
221
        if (pio != PIO_NOT_EXIST) {
222
                int adr_setup, data_pls;
223
                int bus_speed = system_bus_clock();
224
 
225
                adr_setup = ide_pio_timings[pio].setup_time;
226
                data_pls = ide_pio_timings[pio].active_time;
227
                clks->address_time = cmpt_clk(adr_setup, bus_speed);
228
                clks->data_time = cmpt_clk(data_pls, bus_speed);
229
                clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
230
                        - adr_setup-data_pls, bus_speed);
231
                if (clks->address_time<1) clks->address_time = 1;
232
                if (clks->address_time>4) clks->address_time = 4;
233
                if (clks->data_time<1) clks->data_time = 1;
234
                if (clks->data_time>16) clks->data_time = 16;
235
                if (clks->recovery_time<2) clks->recovery_time = 2;
236
                if (clks->recovery_time>17) clks->recovery_time = 17;
237
        } else {
238
                clks->address_time = 1;
239
                clks->data_time = 1;
240
                clks->recovery_time = 2;
241
                /* minimal values */
242
        }
243
 
244
}
245
 
246
/* Main tune procedure, called from tuneproc. */
247
static void opti621_tune_drive (ide_drive_t *drive, u8 pio)
248
{
249
        /* primary and secondary drives share some registers,
250
         * so we have to program both drives
251
         */
252
        unsigned long flags;
253
        u8 pio1 = 0, pio2 = 0;
254
        pio_clocks_t first, second;
255
        int ax, drdy;
256
        u8 cycle1, cycle2, misc;
257
        ide_hwif_t *hwif = HWIF(drive);
258
 
259
        /* sets drive->drive_data for both drives */
260
        compute_pios(drive, pio);
261
        pio1 = hwif->drives[0].drive_data;
262
        pio2 = hwif->drives[1].drive_data;
263
 
264
        compute_clocks(pio1, &first);
265
        compute_clocks(pio2, &second);
266
 
267
        /* ax = max(a1,a2) */
268
        ax = (first.address_time < second.address_time) ? second.address_time : first.address_time;
269
 
270
        drdy = 2; /* DRDY is default 2 (by OPTi Databook) */
271
 
272
        cycle1 = ((first.data_time-1)<<4)  | (first.recovery_time-2);
273
        cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2);
274
        misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1);
275
 
276
#ifdef OPTI621_DEBUG
277
        printk("%s: master: address: %d, data: %d, "
278
                "recovery: %d, drdy: %d [clk]\n",
279
                hwif->name, ax, first.data_time,
280
                first.recovery_time, drdy);
281
        printk("%s: slave:  address: %d, data: %d, "
282
                "recovery: %d, drdy: %d [clk]\n",
283
                hwif->name, ax, second.data_time,
284
                second.recovery_time, drdy);
285
#endif
286
 
287
        spin_lock_irqsave(&ide_lock, flags);
288
 
289
        reg_base = hwif->io_ports[IDE_DATA_OFFSET];
290
 
291
        /* allow Register-B */
292
        hwif->OUTB(0xc0, reg_base+CNTRL_REG);
293
        /* hmm, setupvic.exe does this ;-) */
294
        hwif->OUTB(0xff, reg_base+5);
295
        /* if reads 0xff, adapter not exist? */
296
        (void) hwif->INB(reg_base+CNTRL_REG);
297
        /* if reads 0xc0, no interface exist? */
298
        read_reg(hwif, CNTRL_REG);
299
        /* read version, probably 0 */
300
        read_reg(hwif, STRAP_REG);
301
 
302
        /* program primary drive */
303
                /* select Index-0 for Register-A */
304
        write_reg(hwif, 0,      MISC_REG);
305
                /* set read cycle timings */
306
        write_reg(hwif, cycle1, READ_REG);
307
                /* set write cycle timings */
308
        write_reg(hwif, cycle1, WRITE_REG);
309
 
310
        /* program secondary drive */
311
                /* select Index-1 for Register-B */
312
        write_reg(hwif, 1,      MISC_REG);
313
                /* set read cycle timings */
314
        write_reg(hwif, cycle2, READ_REG);
315
                /* set write cycle timings */
316
        write_reg(hwif, cycle2, WRITE_REG);
317
 
318
        /* use Register-A for drive 0 */
319
        /* use Register-B for drive 1 */
320
        write_reg(hwif, 0x85, CNTRL_REG);
321
 
322
        /* set address setup, DRDY timings,   */
323
        /*  and read prefetch for both drives */
324
        write_reg(hwif, misc, MISC_REG);
325
 
326
        spin_unlock_irqrestore(&ide_lock, flags);
327
}
328
 
329
/*
330
 * init_hwif_opti621() is called once for each hwif found at boot.
331
 */
332
static void __init init_hwif_opti621 (ide_hwif_t *hwif)
333
{
334
        hwif->autodma = 0;
335
        hwif->drives[0].drive_data = PIO_DONT_KNOW;
336
        hwif->drives[1].drive_data = PIO_DONT_KNOW;
337
        hwif->tuneproc = &opti621_tune_drive;
338
 
339
        if (!(hwif->dma_base))
340
                return;
341
 
342
        hwif->atapi_dma = 1;
343
        hwif->mwdma_mask = 0x07;
344
        hwif->swdma_mask = 0x07;
345
 
346
        if (!noautodma)
347
                hwif->autodma = 1;
348
        hwif->drives[0].autodma = hwif->autodma;
349
        hwif->drives[1].autodma = hwif->autodma;
350
}
351
 
352
static void __init init_dma_opti621 (ide_hwif_t *hwif, unsigned long dmabase)
353
{
354
        ide_setup_dma(hwif, dmabase, 8);
355
}
356
 
357
extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
358
 
359
static void __init init_setup_opti621 (struct pci_dev *dev, ide_pci_device_t *d)
360
{
361
        ide_setup_pci_device(dev, d);
362
}
363
 
364
static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
365
{
366
        ide_pci_device_t *d = &opti621_chipsets[id->driver_data];
367
        if (dev->device != d->device)
368
                BUG();
369
        ide_setup_pci_device(dev, d);
370
        MOD_INC_USE_COUNT;
371
        return 0;
372
}
373
 
374
static struct pci_device_id opti621_pci_tbl[] __devinitdata = {
375
        { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
376
        { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
377
        { 0, },
378
};
379
 
380
static struct pci_driver driver = {
381
        .name           = "Opti621 IDE",
382
        .id_table       = opti621_pci_tbl,
383
        .probe          = opti621_init_one,
384
};
385
 
386
static int opti621_ide_init(void)
387
{
388
        return ide_pci_register_driver(&driver);
389
}
390
 
391
static void opti621_ide_exit(void)
392
{
393
        ide_pci_unregister_driver(&driver);
394
}
395
 
396
module_init(opti621_ide_init);
397
module_exit(opti621_ide_exit);
398
 
399
MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
400
MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
401
MODULE_LICENSE("GPL");
402
 
403
EXPORT_NO_SYMBOLS;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.