~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/ata/pata_serverworks.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pata_serverworks.c   - Serverworks PATA for new ATA layer
 
3
 *                        (C) 2005 Red Hat Inc
 
4
 *                        (C) 2010 Bartlomiej Zolnierkiewicz
 
5
 *
 
6
 * based upon
 
7
 *
 
8
 * serverworks.c
 
9
 *
 
10
 * Copyright (C) 1998-2000 Michel Aubry
 
11
 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
 
12
 * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
 
13
 * Portions copyright (c) 2001 Sun Microsystems
 
14
 *
 
15
 *
 
16
 * RCC/ServerWorks IDE driver for Linux
 
17
 *
 
18
 *   OSB4: `Open South Bridge' IDE Interface (fn 1)
 
19
 *         supports UDMA mode 2 (33 MB/s)
 
20
 *
 
21
 *   CSB5: `Champion South Bridge' IDE Interface (fn 1)
 
22
 *         all revisions support UDMA mode 4 (66 MB/s)
 
23
 *         revision A2.0 and up support UDMA mode 5 (100 MB/s)
 
24
 *
 
25
 *         *** The CSB5 does not provide ANY register ***
 
26
 *         *** to detect 80-conductor cable presence. ***
 
27
 *
 
28
 *   CSB6: `Champion South Bridge' IDE Interface (optional: third channel)
 
29
 *
 
30
 * Documentation:
 
31
 *      Available under NDA only. Errata info very hard to get.
 
32
 */
 
33
 
 
34
#include <linux/kernel.h>
 
35
#include <linux/module.h>
 
36
#include <linux/pci.h>
 
37
#include <linux/init.h>
 
38
#include <linux/blkdev.h>
 
39
#include <linux/delay.h>
 
40
#include <scsi/scsi_host.h>
 
41
#include <linux/libata.h>
 
42
 
 
43
#define DRV_NAME "pata_serverworks"
 
44
#define DRV_VERSION "0.4.3"
 
45
 
 
46
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
 
47
#define SVWKS_CSB6_REVISION     0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
 
48
 
 
49
/* Seagate Barracuda ATA IV Family drives in UDMA mode 5
 
50
 * can overrun their FIFOs when used with the CSB5 */
 
51
 
 
52
static const char *csb_bad_ata100[] = {
 
53
        "ST320011A",
 
54
        "ST340016A",
 
55
        "ST360021A",
 
56
        "ST380021A",
 
57
        NULL
 
58
};
 
59
 
 
60
/**
 
61
 *      oem_cable       -       Dell/Sun serverworks cable detection
 
62
 *      @ap: ATA port to do cable detect
 
63
 *
 
64
 *      Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select
 
65
 *      for their interfaces in the top two bits of the subsystem ID.
 
66
 */
 
67
 
 
68
static int oem_cable(struct ata_port *ap)
 
69
{
 
70
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
71
 
 
72
        if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
 
73
                return ATA_CBL_PATA80;
 
74
        return ATA_CBL_PATA40;
 
75
}
 
76
 
 
77
struct sv_cable_table {
 
78
        int device;
 
79
        int subvendor;
 
80
        int (*cable_detect)(struct ata_port *ap);
 
81
};
 
82
 
 
83
static struct sv_cable_table cable_detect[] = {
 
84
        { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_DELL, oem_cable },
 
85
        { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_VENDOR_ID_DELL, oem_cable },
 
86
        { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_SUN,  oem_cable },
 
87
        { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE,   PCI_ANY_ID, ata_cable_40wire  },
 
88
        { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_ANY_ID, ata_cable_unknown },
 
89
        { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_ANY_ID, ata_cable_unknown },
 
90
        { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2,  PCI_ANY_ID, ata_cable_unknown },
 
91
        { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown },
 
92
        { }
 
93
};
 
94
 
 
95
/**
 
96
 *      serverworks_cable_detect        -       cable detection
 
97
 *      @ap: ATA port
 
98
 *
 
99
 *      Perform cable detection according to the device and subvendor
 
100
 *      identifications
 
101
 */
 
102
 
 
103
static int serverworks_cable_detect(struct ata_port *ap)
 
104
{
 
105
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
106
        struct sv_cable_table *cb = cable_detect;
 
107
 
 
108
        while(cb->device) {
 
109
                if (cb->device == pdev->device &&
 
110
                    (cb->subvendor == pdev->subsystem_vendor ||
 
111
                      cb->subvendor == PCI_ANY_ID)) {
 
112
                        return cb->cable_detect(ap);
 
113
                }
 
114
                cb++;
 
115
        }
 
116
 
 
117
        BUG();
 
118
        return -1;      /* kill compiler warning */
 
119
}
 
120
 
 
121
/**
 
122
 *      serverworks_is_csb      -       Check for CSB or OSB
 
123
 *      @pdev: PCI device to check
 
124
 *
 
125
 *      Returns true if the device being checked is known to be a CSB
 
126
 *      series device.
 
127
 */
 
128
 
 
129
static u8 serverworks_is_csb(struct pci_dev *pdev)
 
130
{
 
131
        switch (pdev->device) {
 
132
                case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
 
133
                case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
 
134
                case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
 
135
                case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
 
136
                        return 1;
 
137
                default:
 
138
                        break;
 
139
        }
 
140
        return 0;
 
141
}
 
142
 
 
143
/**
 
144
 *      serverworks_osb4_filter -       mode selection filter
 
145
 *      @adev: ATA device
 
146
 *      @mask: Mask of proposed modes
 
147
 *
 
148
 *      Filter the offered modes for the device to apply controller
 
149
 *      specific rules. OSB4 requires no UDMA for disks due to a FIFO
 
150
 *      bug we hit.
 
151
 */
 
152
 
 
153
static unsigned long serverworks_osb4_filter(struct ata_device *adev, unsigned long mask)
 
154
{
 
155
        if (adev->class == ATA_DEV_ATA)
 
156
                mask &= ~ATA_MASK_UDMA;
 
157
        return mask;
 
158
}
 
159
 
 
160
 
 
161
/**
 
162
 *      serverworks_csb_filter  -       mode selection filter
 
163
 *      @adev: ATA device
 
164
 *      @mask: Mask of proposed modes
 
165
 *
 
166
 *      Check the blacklist and disable UDMA5 if matched
 
167
 */
 
168
 
 
169
static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned long mask)
 
170
{
 
171
        const char *p;
 
172
        char model_num[ATA_ID_PROD_LEN + 1];
 
173
        int i;
 
174
 
 
175
        /* Disk, UDMA */
 
176
        if (adev->class != ATA_DEV_ATA)
 
177
                return mask;
 
178
 
 
179
        /* Actually do need to check */
 
180
        ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
181
 
 
182
        for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) {
 
183
                if (!strcmp(p, model_num))
 
184
                        mask &= ~(0xE0 << ATA_SHIFT_UDMA);
 
185
        }
 
186
        return mask;
 
187
}
 
188
 
 
189
/**
 
190
 *      serverworks_set_piomode -       set initial PIO mode data
 
191
 *      @ap: ATA interface
 
192
 *      @adev: ATA device
 
193
 *
 
194
 *      Program the OSB4/CSB5 timing registers for PIO. The PIO register
 
195
 *      load is done as a simple lookup.
 
196
 */
 
197
static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev)
 
198
{
 
199
        static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
 
200
        int offset = 1 + 2 * ap->port_no - adev->devno;
 
201
        int devbits = (2 * ap->port_no + adev->devno) * 4;
 
202
        u16 csb5_pio;
 
203
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
204
        int pio = adev->pio_mode - XFER_PIO_0;
 
205
 
 
206
        pci_write_config_byte(pdev, 0x40 + offset, pio_mode[pio]);
 
207
 
 
208
        /* The OSB4 just requires the timing but the CSB series want the
 
209
           mode number as well */
 
210
        if (serverworks_is_csb(pdev)) {
 
211
                pci_read_config_word(pdev, 0x4A, &csb5_pio);
 
212
                csb5_pio &= ~(0x0F << devbits);
 
213
                pci_write_config_word(pdev, 0x4A, csb5_pio | (pio << devbits));
 
214
        }
 
215
}
 
216
 
 
217
/**
 
218
 *      serverworks_set_dmamode -       set initial DMA mode data
 
219
 *      @ap: ATA interface
 
220
 *      @adev: ATA device
 
221
 *
 
222
 *      Program the MWDMA/UDMA modes for the serverworks OSB4/CSB5
 
223
 *      chipset. The MWDMA mode values are pulled from a lookup table
 
224
 *      while the chipset uses mode number for UDMA.
 
225
 */
 
226
 
 
227
static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 
228
{
 
229
        static const u8 dma_mode[] = { 0x77, 0x21, 0x20 };
 
230
        int offset = 1 + 2 * ap->port_no - adev->devno;
 
231
        int devbits = 2 * ap->port_no + adev->devno;
 
232
        u8 ultra;
 
233
        u8 ultra_cfg;
 
234
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
235
 
 
236
        pci_read_config_byte(pdev, 0x54, &ultra_cfg);
 
237
        pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra);
 
238
        ultra &= ~(0x0F << (adev->devno * 4));
 
239
 
 
240
        if (adev->dma_mode >= XFER_UDMA_0) {
 
241
                pci_write_config_byte(pdev, 0x44 + offset,  0x20);
 
242
 
 
243
                ultra |= (adev->dma_mode - XFER_UDMA_0)
 
244
                                        << (adev->devno * 4);
 
245
                ultra_cfg |=  (1 << devbits);
 
246
        } else {
 
247
                pci_write_config_byte(pdev, 0x44 + offset,
 
248
                        dma_mode[adev->dma_mode - XFER_MW_DMA_0]);
 
249
                ultra_cfg &= ~(1 << devbits);
 
250
        }
 
251
        pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra);
 
252
        pci_write_config_byte(pdev, 0x54, ultra_cfg);
 
253
}
 
254
 
 
255
static struct scsi_host_template serverworks_sht = {
 
256
        ATA_BMDMA_SHT(DRV_NAME),
 
257
};
 
258
 
 
259
static struct ata_port_operations serverworks_osb4_port_ops = {
 
260
        .inherits       = &ata_bmdma_port_ops,
 
261
        .cable_detect   = serverworks_cable_detect,
 
262
        .mode_filter    = serverworks_osb4_filter,
 
263
        .set_piomode    = serverworks_set_piomode,
 
264
        .set_dmamode    = serverworks_set_dmamode,
 
265
};
 
266
 
 
267
static struct ata_port_operations serverworks_csb_port_ops = {
 
268
        .inherits       = &serverworks_osb4_port_ops,
 
269
        .mode_filter    = serverworks_csb_filter,
 
270
};
 
271
 
 
272
static int serverworks_fixup_osb4(struct pci_dev *pdev)
 
273
{
 
274
        u32 reg;
 
275
        struct pci_dev *isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
 
276
                  PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
 
277
        if (isa_dev) {
 
278
                pci_read_config_dword(isa_dev, 0x64, &reg);
 
279
                reg &= ~0x00002000; /* disable 600ns interrupt mask */
 
280
                if (!(reg & 0x00004000))
 
281
                        printk(KERN_DEBUG DRV_NAME ": UDMA not BIOS enabled.\n");
 
282
                reg |=  0x00004000; /* enable UDMA/33 support */
 
283
                pci_write_config_dword(isa_dev, 0x64, reg);
 
284
                pci_dev_put(isa_dev);
 
285
                return 0;
 
286
        }
 
287
        printk(KERN_WARNING DRV_NAME ": Unable to find bridge.\n");
 
288
        return -ENODEV;
 
289
}
 
290
 
 
291
static int serverworks_fixup_csb(struct pci_dev *pdev)
 
292
{
 
293
        u8 btr;
 
294
 
 
295
        /* Third Channel Test */
 
296
        if (!(PCI_FUNC(pdev->devfn) & 1)) {
 
297
                struct pci_dev * findev = NULL;
 
298
                u32 reg4c = 0;
 
299
                findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
 
300
                        PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
 
301
                if (findev) {
 
302
                        pci_read_config_dword(findev, 0x4C, &reg4c);
 
303
                        reg4c &= ~0x000007FF;
 
304
                        reg4c |=  0x00000040;
 
305
                        reg4c |=  0x00000020;
 
306
                        pci_write_config_dword(findev, 0x4C, reg4c);
 
307
                        pci_dev_put(findev);
 
308
                }
 
309
        } else {
 
310
                struct pci_dev * findev = NULL;
 
311
                u8 reg41 = 0;
 
312
 
 
313
                findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
 
314
                                PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL);
 
315
                if (findev) {
 
316
                        pci_read_config_byte(findev, 0x41, &reg41);
 
317
                        reg41 &= ~0x40;
 
318
                        pci_write_config_byte(findev, 0x41, reg41);
 
319
                        pci_dev_put(findev);
 
320
                }
 
321
        }
 
322
        /* setup the UDMA Control register
 
323
         *
 
324
         * 1. clear bit 6 to enable DMA
 
325
         * 2. enable DMA modes with bits 0-1
 
326
         *      00 : legacy
 
327
         *      01 : udma2
 
328
         *      10 : udma2/udma4
 
329
         *      11 : udma2/udma4/udma5
 
330
         */
 
331
        pci_read_config_byte(pdev, 0x5A, &btr);
 
332
        btr &= ~0x40;
 
333
        if (!(PCI_FUNC(pdev->devfn) & 1))
 
334
                btr |= 0x2;
 
335
        else
 
336
                btr |= (pdev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
 
337
        pci_write_config_byte(pdev, 0x5A, btr);
 
338
 
 
339
        return btr;
 
340
}
 
341
 
 
342
static void serverworks_fixup_ht1000(struct pci_dev *pdev)
 
343
{
 
344
        u8 btr;
 
345
        /* Setup HT1000 SouthBridge Controller - Single Channel Only */
 
346
        pci_read_config_byte(pdev, 0x5A, &btr);
 
347
        btr &= ~0x40;
 
348
        btr |= 0x3;
 
349
        pci_write_config_byte(pdev, 0x5A, btr);
 
350
}
 
351
 
 
352
static int serverworks_fixup(struct pci_dev *pdev)
 
353
{
 
354
        int rc = 0;
 
355
 
 
356
        /* Force master latency timer to 64 PCI clocks */
 
357
        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
 
358
 
 
359
        switch (pdev->device) {
 
360
        case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
 
361
                rc = serverworks_fixup_osb4(pdev);
 
362
                break;
 
363
        case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
 
364
                ata_pci_bmdma_clear_simplex(pdev);
 
365
                /* fall through */
 
366
        case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
 
367
        case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
 
368
                rc = serverworks_fixup_csb(pdev);
 
369
                break;
 
370
        case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
 
371
                serverworks_fixup_ht1000(pdev);
 
372
                break;
 
373
        }
 
374
 
 
375
        return rc;
 
376
}
 
377
 
 
378
static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
379
{
 
380
        static const struct ata_port_info info[4] = {
 
381
                { /* OSB4 */
 
382
                        .flags = ATA_FLAG_SLAVE_POSS,
 
383
                        .pio_mask = ATA_PIO4,
 
384
                        .mwdma_mask = ATA_MWDMA2,
 
385
                        .udma_mask = ATA_UDMA2,
 
386
                        .port_ops = &serverworks_osb4_port_ops
 
387
                }, { /* OSB4 no UDMA */
 
388
                        .flags = ATA_FLAG_SLAVE_POSS,
 
389
                        .pio_mask = ATA_PIO4,
 
390
                        .mwdma_mask = ATA_MWDMA2,
 
391
                        /* No UDMA */
 
392
                        .port_ops = &serverworks_osb4_port_ops
 
393
                }, { /* CSB5 */
 
394
                        .flags = ATA_FLAG_SLAVE_POSS,
 
395
                        .pio_mask = ATA_PIO4,
 
396
                        .mwdma_mask = ATA_MWDMA2,
 
397
                        .udma_mask = ATA_UDMA4,
 
398
                        .port_ops = &serverworks_csb_port_ops
 
399
                }, { /* CSB5 - later revisions*/
 
400
                        .flags = ATA_FLAG_SLAVE_POSS,
 
401
                        .pio_mask = ATA_PIO4,
 
402
                        .mwdma_mask = ATA_MWDMA2,
 
403
                        .udma_mask = ATA_UDMA5,
 
404
                        .port_ops = &serverworks_csb_port_ops
 
405
                }
 
406
        };
 
407
        const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL };
 
408
        int rc;
 
409
 
 
410
        rc = pcim_enable_device(pdev);
 
411
        if (rc)
 
412
                return rc;
 
413
 
 
414
        rc = serverworks_fixup(pdev);
 
415
 
 
416
        /* OSB4 : South Bridge and IDE */
 
417
        if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
 
418
                /* Select non UDMA capable OSB4 if we can't do fixups */
 
419
                if (rc < 0)
 
420
                        ppi[0] = &info[1];
 
421
        }
 
422
        /* setup CSB5/CSB6 : South Bridge and IDE option RAID */
 
423
        else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ||
 
424
                 (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
 
425
                 (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
 
426
 
 
427
                 /* If the returned btr is the newer revision then
 
428
                    select the right info block */
 
429
                 if (rc == 3)
 
430
                        ppi[0] = &info[3];
 
431
 
 
432
                /* Is this the 3rd channel CSB6 IDE ? */
 
433
                if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)
 
434
                        ppi[1] = &ata_dummy_port_info;
 
435
        }
 
436
 
 
437
        return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
 
438
}
 
439
 
 
440
#ifdef CONFIG_PM
 
441
static int serverworks_reinit_one(struct pci_dev *pdev)
 
442
{
 
443
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
 
444
        int rc;
 
445
 
 
446
        rc = ata_pci_device_do_resume(pdev);
 
447
        if (rc)
 
448
                return rc;
 
449
 
 
450
        (void)serverworks_fixup(pdev);
 
451
 
 
452
        ata_host_resume(host);
 
453
        return 0;
 
454
}
 
455
#endif
 
456
 
 
457
static const struct pci_device_id serverworks[] = {
 
458
        { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0},
 
459
        { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 2},
 
460
        { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2},
 
461
        { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 2},
 
462
        { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 2},
 
463
 
 
464
        { },
 
465
};
 
466
 
 
467
static struct pci_driver serverworks_pci_driver = {
 
468
        .name           = DRV_NAME,
 
469
        .id_table       = serverworks,
 
470
        .probe          = serverworks_init_one,
 
471
        .remove         = ata_pci_remove_one,
 
472
#ifdef CONFIG_PM
 
473
        .suspend        = ata_pci_device_suspend,
 
474
        .resume         = serverworks_reinit_one,
 
475
#endif
 
476
};
 
477
 
 
478
static int __init serverworks_init(void)
 
479
{
 
480
        return pci_register_driver(&serverworks_pci_driver);
 
481
}
 
482
 
 
483
static void __exit serverworks_exit(void)
 
484
{
 
485
        pci_unregister_driver(&serverworks_pci_driver);
 
486
}
 
487
 
 
488
MODULE_AUTHOR("Alan Cox");
 
489
MODULE_DESCRIPTION("low-level driver for Serverworks OSB4/CSB5/CSB6");
 
490
MODULE_LICENSE("GPL");
 
491
MODULE_DEVICE_TABLE(pci, serverworks);
 
492
MODULE_VERSION(DRV_VERSION);
 
493
 
 
494
module_init(serverworks_init);
 
495
module_exit(serverworks_exit);