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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [ata/] [pata_ns87410.c] - Blame information for rev 79

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

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * pata_ns87410.c       - National Semiconductor 87410 PATA for new ATA layer
3
 *                        (C) 2006 Red Hat Inc
4
 *                        Alan Cox <alan@redhat.com>
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2, or (at your option)
9
 *  any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; see the file COPYING.  If not, write to
18
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
 
21
#include <linux/kernel.h>
22
#include <linux/module.h>
23
#include <linux/pci.h>
24
#include <linux/init.h>
25
#include <linux/blkdev.h>
26
#include <linux/delay.h>
27
#include <scsi/scsi_host.h>
28
#include <linux/libata.h>
29
 
30
#define DRV_NAME "pata_ns87410"
31
#define DRV_VERSION "0.4.6"
32
 
33
/**
34
 *      ns87410_pre_reset               -       probe begin
35
 *      @link: ATA link
36
 *      @deadline: deadline jiffies for the operation
37
 *
38
 *      Check enabled ports
39
 */
40
 
41
static int ns87410_pre_reset(struct ata_link *link, unsigned long deadline)
42
{
43
        struct ata_port *ap = link->ap;
44
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
45
        static const struct pci_bits ns87410_enable_bits[] = {
46
                { 0x43, 1, 0x08, 0x08 },
47
                { 0x47, 1, 0x08, 0x08 }
48
        };
49
 
50
        if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
51
                return -ENOENT;
52
 
53
        return ata_std_prereset(link, deadline);
54
}
55
 
56
/**
57
 *      ns87410_error_handler           -       probe reset
58
 *      @ap: ATA port
59
 *
60
 *      Perform the ATA probe and bus reset sequence plus specific handling
61
 *      for this hardware. The MPIIX has the enable bits in a different place
62
 *      to PIIX4 and friends. As a pure PIO device it has no cable detect
63
 */
64
 
65
static void ns87410_error_handler(struct ata_port *ap)
66
{
67
        ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
68
}
69
 
70
/**
71
 *      ns87410_set_piomode     -       set initial PIO mode data
72
 *      @ap: ATA interface
73
 *      @adev: ATA device
74
 *
75
 *      Program timing data. This is kept per channel not per device,
76
 *      and only affects the data port.
77
 */
78
 
79
static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
80
{
81
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
82
        int port = 0x40 + 4 * ap->port_no;
83
        u8 idetcr, idefr;
84
        struct ata_timing at;
85
 
86
        static const u8 activebits[15] = {
87
                0, 1, 2, 3, 4,
88
                5, 5, 6, 6, 6,
89
                6, 7, 7, 7, 7
90
        };
91
 
92
        static const u8 recoverbits[12] = {
93
                0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7
94
        };
95
 
96
        pci_read_config_byte(pdev, port + 3, &idefr);
97
 
98
        if (ata_pio_need_iordy(adev))
99
                idefr |= 0x04;  /* IORDY enable */
100
        else
101
                idefr &= ~0x04;
102
 
103
        if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) {
104
                dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode);
105
                return;
106
        }
107
 
108
        at.active = FIT(at.active, 2, 16) - 2;
109
        at.setup = FIT(at.setup, 1, 4) - 1;
110
        at.recover = FIT(at.recover, 1, 12) - 1;
111
 
112
        idetcr = (at.setup << 6) | (recoverbits[at.recover] << 3) | activebits[at.active];
113
 
114
        pci_write_config_byte(pdev, port, idetcr);
115
        pci_write_config_byte(pdev, port + 3, idefr);
116
        /* We use ap->private_data as a pointer to the device currently
117
           loaded for timing */
118
        ap->private_data = adev;
119
}
120
 
121
/**
122
 *      ns87410_qc_issue_prot   -       command issue
123
 *      @qc: command pending
124
 *
125
 *      Called when the libata layer is about to issue a command. We wrap
126
 *      this interface so that we can load the correct ATA timings if
127
 *      necessary.
128
 */
129
 
130
static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
131
{
132
        struct ata_port *ap = qc->ap;
133
        struct ata_device *adev = qc->dev;
134
 
135
        /* If modes have been configured and the channel data is not loaded
136
           then load it. We have to check if pio_mode is set as the core code
137
           does not set adev->pio_mode to XFER_PIO_0 while probing as would be
138
           logical */
139
 
140
        if (adev->pio_mode && adev != ap->private_data)
141
                ns87410_set_piomode(ap, adev);
142
 
143
        return ata_qc_issue_prot(qc);
144
}
145
 
146
static struct scsi_host_template ns87410_sht = {
147
        .module                 = THIS_MODULE,
148
        .name                   = DRV_NAME,
149
        .ioctl                  = ata_scsi_ioctl,
150
        .queuecommand           = ata_scsi_queuecmd,
151
        .can_queue              = ATA_DEF_QUEUE,
152
        .this_id                = ATA_SHT_THIS_ID,
153
        .sg_tablesize           = LIBATA_MAX_PRD,
154
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
155
        .emulated               = ATA_SHT_EMULATED,
156
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
157
        .proc_name              = DRV_NAME,
158
        .dma_boundary           = ATA_DMA_BOUNDARY,
159
        .slave_configure        = ata_scsi_slave_config,
160
        .slave_destroy          = ata_scsi_slave_destroy,
161
        .bios_param             = ata_std_bios_param,
162
};
163
 
164
static struct ata_port_operations ns87410_port_ops = {
165
        .set_piomode    = ns87410_set_piomode,
166
 
167
        .tf_load        = ata_tf_load,
168
        .tf_read        = ata_tf_read,
169
        .check_status   = ata_check_status,
170
        .exec_command   = ata_exec_command,
171
        .dev_select     = ata_std_dev_select,
172
 
173
        .freeze         = ata_bmdma_freeze,
174
        .thaw           = ata_bmdma_thaw,
175
        .error_handler  = ns87410_error_handler,
176
        .post_internal_cmd = ata_bmdma_post_internal_cmd,
177
        .cable_detect   = ata_cable_40wire,
178
 
179
        .qc_prep        = ata_qc_prep,
180
        .qc_issue       = ns87410_qc_issue_prot,
181
 
182
        .data_xfer      = ata_data_xfer,
183
 
184
        .irq_handler    = ata_interrupt,
185
        .irq_clear      = ata_bmdma_irq_clear,
186
        .irq_on         = ata_irq_on,
187
 
188
        .port_start     = ata_sff_port_start,
189
};
190
 
191
static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
192
{
193
        static const struct ata_port_info info = {
194
                .sht = &ns87410_sht,
195
                .flags = ATA_FLAG_SLAVE_POSS,
196
                .pio_mask = 0x0F,
197
                .port_ops = &ns87410_port_ops
198
        };
199
        const struct ata_port_info *ppi[] = { &info, NULL };
200
        return ata_pci_init_one(dev, ppi);
201
}
202
 
203
static const struct pci_device_id ns87410[] = {
204
        { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), },
205
 
206
        { },
207
};
208
 
209
static struct pci_driver ns87410_pci_driver = {
210
        .name           = DRV_NAME,
211
        .id_table       = ns87410,
212
        .probe          = ns87410_init_one,
213
        .remove         = ata_pci_remove_one,
214
#ifdef CONFIG_PM
215
        .suspend        = ata_pci_device_suspend,
216
        .resume         = ata_pci_device_resume,
217
#endif
218
};
219
 
220
static int __init ns87410_init(void)
221
{
222
        return pci_register_driver(&ns87410_pci_driver);
223
}
224
 
225
static void __exit ns87410_exit(void)
226
{
227
        pci_unregister_driver(&ns87410_pci_driver);
228
}
229
 
230
MODULE_AUTHOR("Alan Cox");
231
MODULE_DESCRIPTION("low-level driver for Nat Semi 87410");
232
MODULE_LICENSE("GPL");
233
MODULE_DEVICE_TABLE(pci, ns87410);
234
MODULE_VERSION(DRV_VERSION);
235
 
236
module_init(ns87410_init);
237
module_exit(ns87410_exit);

powered by: WebSVN 2.1.0

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