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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [ata/] [pata_triflex.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * pata_triflex.c       - Compaq PATA for new ATA layer
3
 *                        (C) 2005 Red Hat Inc
4
 *                        Alan Cox <alan@redhat.com>
5
 *
6
 * based upon
7
 *
8
 * triflex.c
9
 *
10
 * IDE Chipset driver for the Compaq TriFlex IDE controller.
11
 *
12
 * Known to work with the Compaq Workstation 5x00 series.
13
 *
14
 * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
15
 * Author: Torben Mathiasen <torben.mathiasen@hp.com>
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License version 2 as
19
 * published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
 *
30
 * Loosely based on the piix & svwks drivers.
31
 *
32
 * Documentation:
33
 *      Not publically available.
34
 */
35
 
36
#include <linux/kernel.h>
37
#include <linux/module.h>
38
#include <linux/pci.h>
39
#include <linux/init.h>
40
#include <linux/blkdev.h>
41
#include <linux/delay.h>
42
#include <scsi/scsi_host.h>
43
#include <linux/libata.h>
44
 
45
#define DRV_NAME "pata_triflex"
46
#define DRV_VERSION "0.2.8"
47
 
48
/**
49
 *      triflex_prereset                -       probe begin
50
 *      @link: ATA link
51
 *      @deadline: deadline jiffies for the operation
52
 *
53
 *      Set up cable type and use generic probe init
54
 */
55
 
56
static int triflex_prereset(struct ata_link *link, unsigned long deadline)
57
{
58
        static const struct pci_bits triflex_enable_bits[] = {
59
                { 0x80, 1, 0x01, 0x01 },
60
                { 0x80, 1, 0x02, 0x02 }
61
        };
62
 
63
        struct ata_port *ap = link->ap;
64
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
65
 
66
        if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
67
                return -ENOENT;
68
 
69
        return ata_std_prereset(link, deadline);
70
}
71
 
72
 
73
 
74
static void triflex_error_handler(struct ata_port *ap)
75
{
76
        ata_bmdma_drive_eh(ap, triflex_prereset, ata_std_softreset, NULL, ata_std_postreset);
77
}
78
 
79
/**
80
 *      triflex_load_timing             -       timing configuration
81
 *      @ap: ATA interface
82
 *      @adev: Device on the bus
83
 *      @speed: speed to configure
84
 *
85
 *      The Triflex has one set of timings per device per channel. This
86
 *      means we must do some switching. As the PIO and DMA timings don't
87
 *      match we have to do some reloading unlike PIIX devices where tuning
88
 *      tricks can avoid it.
89
 */
90
 
91
static void triflex_load_timing(struct ata_port *ap, struct ata_device *adev, int speed)
92
{
93
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
94
        u32 timing = 0;
95
        u32 triflex_timing, old_triflex_timing;
96
        int channel_offset = ap->port_no ? 0x74: 0x70;
97
        unsigned int is_slave   = (adev->devno != 0);
98
 
99
 
100
        pci_read_config_dword(pdev, channel_offset, &old_triflex_timing);
101
        triflex_timing = old_triflex_timing;
102
 
103
        switch(speed)
104
        {
105
                case XFER_MW_DMA_2:
106
                        timing = 0x0103;break;
107
                case XFER_MW_DMA_1:
108
                        timing = 0x0203;break;
109
                case XFER_MW_DMA_0:
110
                        timing = 0x0808;break;
111
                case XFER_SW_DMA_2:
112
                case XFER_SW_DMA_1:
113
                case XFER_SW_DMA_0:
114
                        timing = 0x0F0F;break;
115
                case XFER_PIO_4:
116
                        timing = 0x0202;break;
117
                case XFER_PIO_3:
118
                        timing = 0x0204;break;
119
                case XFER_PIO_2:
120
                        timing = 0x0404;break;
121
                case XFER_PIO_1:
122
                        timing = 0x0508;break;
123
                case XFER_PIO_0:
124
                        timing = 0x0808;break;
125
                default:
126
                        BUG();
127
        }
128
        triflex_timing &= ~ (0xFFFF << (16 * is_slave));
129
        triflex_timing |= (timing << (16 * is_slave));
130
 
131
        if (triflex_timing != old_triflex_timing)
132
                pci_write_config_dword(pdev, channel_offset, triflex_timing);
133
}
134
 
135
/**
136
 *      triflex_set_piomode     -       set initial PIO mode data
137
 *      @ap: ATA interface
138
 *      @adev: ATA device
139
 *
140
 *      Use the timing loader to set up the PIO mode. We have to do this
141
 *      because DMA start/stop will only be called once DMA occurs. If there
142
 *      has been no DMA then the PIO timings are still needed.
143
 */
144
static void triflex_set_piomode(struct ata_port *ap, struct ata_device *adev)
145
{
146
        triflex_load_timing(ap, adev, adev->pio_mode);
147
}
148
 
149
/**
150
 *      triflex_dma_start       -       DMA start callback
151
 *      @qc: Command in progress
152
 *
153
 *      Usually drivers set the DMA timing at the point the set_dmamode call
154
 *      is made. Triflex however requires we load new timings on the
155
 *      transition or keep matching PIO/DMA pairs (ie MWDMA2/PIO4 etc).
156
 *      We load the DMA timings just before starting DMA and then restore
157
 *      the PIO timing when the DMA is finished.
158
 */
159
 
160
static void triflex_bmdma_start(struct ata_queued_cmd *qc)
161
{
162
        triflex_load_timing(qc->ap, qc->dev, qc->dev->dma_mode);
163
        ata_bmdma_start(qc);
164
}
165
 
166
/**
167
 *      triflex_dma_stop        -       DMA stop callback
168
 *      @ap: ATA interface
169
 *      @adev: ATA device
170
 *
171
 *      We loaded new timings in dma_start, as a result we need to restore
172
 *      the PIO timings in dma_stop so that the next command issue gets the
173
 *      right clock values.
174
 */
175
 
176
static void triflex_bmdma_stop(struct ata_queued_cmd *qc)
177
{
178
        ata_bmdma_stop(qc);
179
        triflex_load_timing(qc->ap, qc->dev, qc->dev->pio_mode);
180
}
181
 
182
static struct scsi_host_template triflex_sht = {
183
        .module                 = THIS_MODULE,
184
        .name                   = DRV_NAME,
185
        .ioctl                  = ata_scsi_ioctl,
186
        .queuecommand           = ata_scsi_queuecmd,
187
        .can_queue              = ATA_DEF_QUEUE,
188
        .this_id                = ATA_SHT_THIS_ID,
189
        .sg_tablesize           = LIBATA_MAX_PRD,
190
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
191
        .emulated               = ATA_SHT_EMULATED,
192
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
193
        .proc_name              = DRV_NAME,
194
        .dma_boundary           = ATA_DMA_BOUNDARY,
195
        .slave_configure        = ata_scsi_slave_config,
196
        .slave_destroy          = ata_scsi_slave_destroy,
197
        .bios_param             = ata_std_bios_param,
198
};
199
 
200
static struct ata_port_operations triflex_port_ops = {
201
        .set_piomode    = triflex_set_piomode,
202
        .mode_filter    = ata_pci_default_filter,
203
 
204
        .tf_load        = ata_tf_load,
205
        .tf_read        = ata_tf_read,
206
        .check_status   = ata_check_status,
207
        .exec_command   = ata_exec_command,
208
        .dev_select     = ata_std_dev_select,
209
 
210
        .freeze         = ata_bmdma_freeze,
211
        .thaw           = ata_bmdma_thaw,
212
        .error_handler  = triflex_error_handler,
213
        .post_internal_cmd = ata_bmdma_post_internal_cmd,
214
        .cable_detect   = ata_cable_40wire,
215
 
216
        .bmdma_setup    = ata_bmdma_setup,
217
        .bmdma_start    = triflex_bmdma_start,
218
        .bmdma_stop     = triflex_bmdma_stop,
219
        .bmdma_status   = ata_bmdma_status,
220
 
221
        .qc_prep        = ata_qc_prep,
222
        .qc_issue       = ata_qc_issue_prot,
223
 
224
        .data_xfer      = ata_data_xfer,
225
 
226
        .irq_handler    = ata_interrupt,
227
        .irq_clear      = ata_bmdma_irq_clear,
228
        .irq_on         = ata_irq_on,
229
 
230
        .port_start     = ata_sff_port_start,
231
};
232
 
233
static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
234
{
235
        static const struct ata_port_info info = {
236
                .sht = &triflex_sht,
237
                .flags = ATA_FLAG_SLAVE_POSS,
238
                .pio_mask = 0x1f,
239
                .mwdma_mask = 0x07,
240
                .port_ops = &triflex_port_ops
241
        };
242
        const struct ata_port_info *ppi[] = { &info, NULL };
243
        static int printed_version;
244
 
245
        if (!printed_version++)
246
                dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
247
 
248
        return ata_pci_init_one(dev, ppi);
249
}
250
 
251
static const struct pci_device_id triflex[] = {
252
        { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), },
253
 
254
        { },
255
};
256
 
257
static struct pci_driver triflex_pci_driver = {
258
        .name           = DRV_NAME,
259
        .id_table       = triflex,
260
        .probe          = triflex_init_one,
261
        .remove         = ata_pci_remove_one,
262
#ifdef CONFIG_PM
263
        .suspend        = ata_pci_device_suspend,
264
        .resume         = ata_pci_device_resume,
265
#endif
266
};
267
 
268
static int __init triflex_init(void)
269
{
270
        return pci_register_driver(&triflex_pci_driver);
271
}
272
 
273
static void __exit triflex_exit(void)
274
{
275
        pci_unregister_driver(&triflex_pci_driver);
276
}
277
 
278
MODULE_AUTHOR("Alan Cox");
279
MODULE_DESCRIPTION("low-level driver for Compaq Triflex");
280
MODULE_LICENSE("GPL");
281
MODULE_DEVICE_TABLE(pci, triflex);
282
MODULE_VERSION(DRV_VERSION);
283
 
284
module_init(triflex_init);
285
module_exit(triflex_exit);

powered by: WebSVN 2.1.0

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