Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/ata/pata_jmicron.c
15109 views
1
/*
2
* pata_jmicron.c - JMicron ATA driver for non AHCI mode. This drives the
3
* PATA port of the controller. The SATA ports are
4
* driven by AHCI in the usual configuration although
5
* this driver can handle other setups if we need it.
6
*
7
* (c) 2006 Red Hat
8
*/
9
10
#include <linux/kernel.h>
11
#include <linux/module.h>
12
#include <linux/pci.h>
13
#include <linux/init.h>
14
#include <linux/blkdev.h>
15
#include <linux/delay.h>
16
#include <linux/device.h>
17
#include <scsi/scsi_host.h>
18
#include <linux/libata.h>
19
#include <linux/ata.h>
20
21
#define DRV_NAME "pata_jmicron"
22
#define DRV_VERSION "0.1.5"
23
24
typedef enum {
25
PORT_PATA0 = 0,
26
PORT_PATA1 = 1,
27
PORT_SATA = 2,
28
} port_type;
29
30
/**
31
* jmicron_pre_reset - check for 40/80 pin
32
* @link: ATA link
33
* @deadline: deadline jiffies for the operation
34
*
35
* Perform the PATA port setup we need.
36
*
37
* On the Jmicron 361/363 there is a single PATA port that can be mapped
38
* either as primary or secondary (or neither). We don't do any policy
39
* and setup here. We assume that has been done by init_one and the
40
* BIOS.
41
*/
42
static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
43
{
44
struct ata_port *ap = link->ap;
45
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
46
u32 control;
47
u32 control5;
48
int port_mask = 1<< (4 * ap->port_no);
49
int port = ap->port_no;
50
port_type port_map[2];
51
52
/* Check if our port is enabled */
53
pci_read_config_dword(pdev, 0x40, &control);
54
if ((control & port_mask) == 0)
55
return -ENOENT;
56
57
/* There are two basic mappings. One has the two SATA ports merged
58
as master/slave and the secondary as PATA, the other has only the
59
SATA port mapped */
60
if (control & (1 << 23)) {
61
port_map[0] = PORT_SATA;
62
port_map[1] = PORT_PATA0;
63
} else {
64
port_map[0] = PORT_SATA;
65
port_map[1] = PORT_SATA;
66
}
67
68
/* The 365/366 may have this bit set to map the second PATA port
69
as the internal primary channel */
70
pci_read_config_dword(pdev, 0x80, &control5);
71
if (control5 & (1<<24))
72
port_map[0] = PORT_PATA1;
73
74
/* The two ports may then be logically swapped by the firmware */
75
if (control & (1 << 22))
76
port = port ^ 1;
77
78
/*
79
* Now we know which physical port we are talking about we can
80
* actually do our cable checking etc. Thankfully we don't need
81
* to do the plumbing for other cases.
82
*/
83
switch (port_map[port]) {
84
case PORT_PATA0:
85
if ((control & (1 << 5)) == 0)
86
return -ENOENT;
87
if (control & (1 << 3)) /* 40/80 pin primary */
88
ap->cbl = ATA_CBL_PATA40;
89
else
90
ap->cbl = ATA_CBL_PATA80;
91
break;
92
case PORT_PATA1:
93
/* Bit 21 is set if the port is enabled */
94
if ((control5 & (1 << 21)) == 0)
95
return -ENOENT;
96
if (control5 & (1 << 19)) /* 40/80 pin secondary */
97
ap->cbl = ATA_CBL_PATA40;
98
else
99
ap->cbl = ATA_CBL_PATA80;
100
break;
101
case PORT_SATA:
102
ap->cbl = ATA_CBL_SATA;
103
break;
104
}
105
return ata_sff_prereset(link, deadline);
106
}
107
108
/* No PIO or DMA methods needed for this device */
109
110
static struct scsi_host_template jmicron_sht = {
111
ATA_BMDMA_SHT(DRV_NAME),
112
};
113
114
static struct ata_port_operations jmicron_ops = {
115
.inherits = &ata_bmdma_port_ops,
116
.prereset = jmicron_pre_reset,
117
};
118
119
120
/**
121
* jmicron_init_one - Register Jmicron ATA PCI device with kernel services
122
* @pdev: PCI device to register
123
* @ent: Entry in jmicron_pci_tbl matching with @pdev
124
*
125
* Called from kernel PCI layer.
126
*
127
* LOCKING:
128
* Inherited from PCI layer (may sleep).
129
*
130
* RETURNS:
131
* Zero on success, or -ERRNO value.
132
*/
133
134
static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
135
{
136
static const struct ata_port_info info = {
137
.flags = ATA_FLAG_SLAVE_POSS,
138
139
.pio_mask = ATA_PIO4,
140
.mwdma_mask = ATA_MWDMA2,
141
.udma_mask = ATA_UDMA5,
142
143
.port_ops = &jmicron_ops,
144
};
145
const struct ata_port_info *ppi[] = { &info, NULL };
146
147
return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
148
}
149
150
static const struct pci_device_id jmicron_pci_tbl[] = {
151
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
152
PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
153
{ } /* terminate list */
154
};
155
156
static struct pci_driver jmicron_pci_driver = {
157
.name = DRV_NAME,
158
.id_table = jmicron_pci_tbl,
159
.probe = jmicron_init_one,
160
.remove = ata_pci_remove_one,
161
#ifdef CONFIG_PM
162
.suspend = ata_pci_device_suspend,
163
.resume = ata_pci_device_resume,
164
#endif
165
};
166
167
static int __init jmicron_init(void)
168
{
169
return pci_register_driver(&jmicron_pci_driver);
170
}
171
172
static void __exit jmicron_exit(void)
173
{
174
pci_unregister_driver(&jmicron_pci_driver);
175
}
176
177
module_init(jmicron_init);
178
module_exit(jmicron_exit);
179
180
MODULE_AUTHOR("Alan Cox");
181
MODULE_DESCRIPTION("SCSI low-level driver for Jmicron PATA ports");
182
MODULE_LICENSE("GPL");
183
MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
184
MODULE_VERSION(DRV_VERSION);
185
186
187