diff options
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r-- | drivers/ata/sata_via.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 1cfa74535d91..5b72e734300a 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -70,6 +70,7 @@ enum { | |||
70 | static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 70 | static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
71 | static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); | 71 | static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); |
72 | static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); | 72 | static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); |
73 | static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); | ||
73 | static void svia_noop_freeze(struct ata_port *ap); | 74 | static void svia_noop_freeze(struct ata_port *ap); |
74 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); | 75 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); |
75 | static int vt6421_pata_cable_detect(struct ata_port *ap); | 76 | static int vt6421_pata_cable_detect(struct ata_port *ap); |
@@ -103,21 +104,26 @@ static struct scsi_host_template svia_sht = { | |||
103 | ATA_BMDMA_SHT(DRV_NAME), | 104 | ATA_BMDMA_SHT(DRV_NAME), |
104 | }; | 105 | }; |
105 | 106 | ||
106 | static struct ata_port_operations vt6420_sata_ops = { | 107 | static struct ata_port_operations svia_base_ops = { |
107 | .inherits = &ata_bmdma_port_ops, | 108 | .inherits = &ata_bmdma_port_ops, |
109 | .sff_tf_load = svia_tf_load, | ||
110 | }; | ||
111 | |||
112 | static struct ata_port_operations vt6420_sata_ops = { | ||
113 | .inherits = &svia_base_ops, | ||
108 | .freeze = svia_noop_freeze, | 114 | .freeze = svia_noop_freeze, |
109 | .prereset = vt6420_prereset, | 115 | .prereset = vt6420_prereset, |
110 | }; | 116 | }; |
111 | 117 | ||
112 | static struct ata_port_operations vt6421_pata_ops = { | 118 | static struct ata_port_operations vt6421_pata_ops = { |
113 | .inherits = &ata_bmdma_port_ops, | 119 | .inherits = &svia_base_ops, |
114 | .cable_detect = vt6421_pata_cable_detect, | 120 | .cable_detect = vt6421_pata_cable_detect, |
115 | .set_piomode = vt6421_set_pio_mode, | 121 | .set_piomode = vt6421_set_pio_mode, |
116 | .set_dmamode = vt6421_set_dma_mode, | 122 | .set_dmamode = vt6421_set_dma_mode, |
117 | }; | 123 | }; |
118 | 124 | ||
119 | static struct ata_port_operations vt6421_sata_ops = { | 125 | static struct ata_port_operations vt6421_sata_ops = { |
120 | .inherits = &ata_bmdma_port_ops, | 126 | .inherits = &svia_base_ops, |
121 | .scr_read = svia_scr_read, | 127 | .scr_read = svia_scr_read, |
122 | .scr_write = svia_scr_write, | 128 | .scr_write = svia_scr_write, |
123 | }; | 129 | }; |
@@ -168,6 +174,29 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) | |||
168 | return 0; | 174 | return 0; |
169 | } | 175 | } |
170 | 176 | ||
177 | /** | ||
178 | * svia_tf_load - send taskfile registers to host controller | ||
179 | * @ap: Port to which output is sent | ||
180 | * @tf: ATA taskfile register set | ||
181 | * | ||
182 | * Outputs ATA taskfile to standard ATA host controller. | ||
183 | * | ||
184 | * This is to fix the internal bug of via chipsets, which will | ||
185 | * reset the device register after changing the IEN bit on ctl | ||
186 | * register. | ||
187 | */ | ||
188 | static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) | ||
189 | { | ||
190 | struct ata_taskfile ttf; | ||
191 | |||
192 | if (tf->ctl != ap->last_ctl) { | ||
193 | ttf = *tf; | ||
194 | ttf.flags |= ATA_TFLAG_DEVICE; | ||
195 | tf = &ttf; | ||
196 | } | ||
197 | ata_sff_tf_load(ap, tf); | ||
198 | } | ||
199 | |||
171 | static void svia_noop_freeze(struct ata_port *ap) | 200 | static void svia_noop_freeze(struct ata_port *ap) |
172 | { | 201 | { |
173 | /* Some VIA controllers choke if ATA_NIEN is manipulated in | 202 | /* Some VIA controllers choke if ATA_NIEN is manipulated in |