diff options
Diffstat (limited to 'drivers/ata/pata_efar.c')
-rw-r--r-- | drivers/ata/pata_efar.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 2a6412f5d117..3bac0e079691 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * pata_efar.c - EFAR PIIX clone controller driver | 2 | * pata_efar.c - EFAR PIIX clone controller driver |
3 | * | 3 | * |
4 | * (C) 2005 Red Hat | 4 | * (C) 2005 Red Hat |
5 | * (C) 2009-2010 Bartlomiej Zolnierkiewicz | ||
5 | * | 6 | * |
6 | * Some parts based on ata_piix.c by Jeff Garzik and others. | 7 | * Some parts based on ata_piix.c by Jeff Garzik and others. |
7 | * | 8 | * |
@@ -67,6 +68,8 @@ static int efar_cable_detect(struct ata_port *ap) | |||
67 | return ATA_CBL_PATA80; | 68 | return ATA_CBL_PATA80; |
68 | } | 69 | } |
69 | 70 | ||
71 | static DEFINE_SPINLOCK(efar_lock); | ||
72 | |||
70 | /** | 73 | /** |
71 | * efar_set_piomode - Initialize host controller PATA PIO timings | 74 | * efar_set_piomode - Initialize host controller PATA PIO timings |
72 | * @ap: Port whose timings we are configuring | 75 | * @ap: Port whose timings we are configuring |
@@ -83,7 +86,9 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
83 | unsigned int pio = adev->pio_mode - XFER_PIO_0; | 86 | unsigned int pio = adev->pio_mode - XFER_PIO_0; |
84 | struct pci_dev *dev = to_pci_dev(ap->host->dev); | 87 | struct pci_dev *dev = to_pci_dev(ap->host->dev); |
85 | unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; | 88 | unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; |
89 | unsigned long flags; | ||
86 | u16 idetm_data; | 90 | u16 idetm_data; |
91 | u8 udma_enable; | ||
87 | int control = 0; | 92 | int control = 0; |
88 | 93 | ||
89 | /* | 94 | /* |
@@ -106,6 +111,8 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
106 | if (adev->class == ATA_DEV_ATA) | 111 | if (adev->class == ATA_DEV_ATA) |
107 | control |= 4; /* PPE */ | 112 | control |= 4; /* PPE */ |
108 | 113 | ||
114 | spin_lock_irqsave(&efar_lock, flags); | ||
115 | |||
109 | pci_read_config_word(dev, idetm_port, &idetm_data); | 116 | pci_read_config_word(dev, idetm_port, &idetm_data); |
110 | 117 | ||
111 | /* Set PPE, IE, and TIME as appropriate */ | 118 | /* Set PPE, IE, and TIME as appropriate */ |
@@ -118,18 +125,23 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
118 | int shift = 4 * ap->port_no; | 125 | int shift = 4 * ap->port_no; |
119 | u8 slave_data; | 126 | u8 slave_data; |
120 | 127 | ||
121 | idetm_data &= 0xCC0F; | 128 | idetm_data &= 0xFF0F; |
122 | idetm_data |= (control << 4); | 129 | idetm_data |= (control << 4); |
123 | 130 | ||
124 | /* Slave timing in separate register */ | 131 | /* Slave timing in separate register */ |
125 | pci_read_config_byte(dev, 0x44, &slave_data); | 132 | pci_read_config_byte(dev, 0x44, &slave_data); |
126 | slave_data &= 0x0F << shift; | 133 | slave_data &= ap->port_no ? 0x0F : 0xF0; |
127 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift; | 134 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift; |
128 | pci_write_config_byte(dev, 0x44, slave_data); | 135 | pci_write_config_byte(dev, 0x44, slave_data); |
129 | } | 136 | } |
130 | 137 | ||
131 | idetm_data |= 0x4000; /* Ensure SITRE is set */ | 138 | idetm_data |= 0x4000; /* Ensure SITRE is set */ |
132 | pci_write_config_word(dev, idetm_port, idetm_data); | 139 | pci_write_config_word(dev, idetm_port, idetm_data); |
140 | |||
141 | pci_read_config_byte(dev, 0x48, &udma_enable); | ||
142 | udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); | ||
143 | pci_write_config_byte(dev, 0x48, udma_enable); | ||
144 | spin_unlock_irqrestore(&efar_lock, flags); | ||
133 | } | 145 | } |
134 | 146 | ||
135 | /** | 147 | /** |
@@ -150,6 +162,7 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
150 | u16 master_data; | 162 | u16 master_data; |
151 | u8 speed = adev->dma_mode; | 163 | u8 speed = adev->dma_mode; |
152 | int devid = adev->devno + 2 * ap->port_no; | 164 | int devid = adev->devno + 2 * ap->port_no; |
165 | unsigned long flags; | ||
153 | u8 udma_enable; | 166 | u8 udma_enable; |
154 | 167 | ||
155 | static const /* ISP RTC */ | 168 | static const /* ISP RTC */ |
@@ -159,6 +172,8 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
159 | { 2, 1 }, | 172 | { 2, 1 }, |
160 | { 2, 3 }, }; | 173 | { 2, 3 }, }; |
161 | 174 | ||
175 | spin_lock_irqsave(&efar_lock, flags); | ||
176 | |||
162 | pci_read_config_word(dev, master_port, &master_data); | 177 | pci_read_config_word(dev, master_port, &master_data); |
163 | pci_read_config_byte(dev, 0x48, &udma_enable); | 178 | pci_read_config_byte(dev, 0x48, &udma_enable); |
164 | 179 | ||
@@ -200,7 +215,7 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
200 | master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ | 215 | master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ |
201 | master_data |= control << 4; | 216 | master_data |= control << 4; |
202 | pci_read_config_byte(dev, 0x44, &slave_data); | 217 | pci_read_config_byte(dev, 0x44, &slave_data); |
203 | slave_data &= (0x0F + 0xE1 * ap->port_no); | 218 | slave_data &= ap->port_no ? 0x0F : 0xF0; |
204 | /* Load the matching timing */ | 219 | /* Load the matching timing */ |
205 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); | 220 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); |
206 | pci_write_config_byte(dev, 0x44, slave_data); | 221 | pci_write_config_byte(dev, 0x44, slave_data); |
@@ -216,6 +231,7 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
216 | pci_write_config_word(dev, master_port, master_data); | 231 | pci_write_config_word(dev, master_port, master_data); |
217 | } | 232 | } |
218 | pci_write_config_byte(dev, 0x48, udma_enable); | 233 | pci_write_config_byte(dev, 0x48, udma_enable); |
234 | spin_unlock_irqrestore(&efar_lock, flags); | ||
219 | } | 235 | } |
220 | 236 | ||
221 | static struct scsi_host_template efar_sht = { | 237 | static struct scsi_host_template efar_sht = { |
@@ -251,17 +267,18 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
251 | static const struct ata_port_info info = { | 267 | static const struct ata_port_info info = { |
252 | .flags = ATA_FLAG_SLAVE_POSS, | 268 | .flags = ATA_FLAG_SLAVE_POSS, |
253 | .pio_mask = ATA_PIO4, | 269 | .pio_mask = ATA_PIO4, |
254 | .mwdma_mask = ATA_MWDMA2, | 270 | .mwdma_mask = ATA_MWDMA12_ONLY, |
255 | .udma_mask = ATA_UDMA4, | 271 | .udma_mask = ATA_UDMA4, |
256 | .port_ops = &efar_ops, | 272 | .port_ops = &efar_ops, |
257 | }; | 273 | }; |
258 | const struct ata_port_info *ppi[] = { &info, NULL }; | 274 | const struct ata_port_info *ppi[] = { &info, &info }; |
259 | 275 | ||
260 | if (!printed_version++) | 276 | if (!printed_version++) |
261 | dev_printk(KERN_DEBUG, &pdev->dev, | 277 | dev_printk(KERN_DEBUG, &pdev->dev, |
262 | "version " DRV_VERSION "\n"); | 278 | "version " DRV_VERSION "\n"); |
263 | 279 | ||
264 | return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL); | 280 | return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL, |
281 | ATA_HOST_PARALLEL_SCAN); | ||
265 | } | 282 | } |
266 | 283 | ||
267 | static const struct pci_device_id efar_pci_tbl[] = { | 284 | static const struct pci_device_id efar_pci_tbl[] = { |