aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/icside.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/icside.c')
-rw-r--r--drivers/ide/icside.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 26b6c0a1f772..4a697a238e28 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -65,6 +65,8 @@ static struct cardinfo icside_cardinfo_v6_2 = {
65}; 65};
66 66
67struct icside_state { 67struct icside_state {
68 unsigned int channel;
69 unsigned int enabled;
68 void __iomem *irq_port; 70 void __iomem *irq_port;
69 void __iomem *ioc_base; 71 void __iomem *ioc_base;
70 unsigned int sel; 72 unsigned int sel;
@@ -114,11 +116,18 @@ static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
114 struct icside_state *state = ec->irq_data; 116 struct icside_state *state = ec->irq_data;
115 void __iomem *base = state->irq_port; 117 void __iomem *base = state->irq_port;
116 118
117 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); 119 state->enabled = 1;
118 readb(base + ICS_ARCIN_V6_INTROFFSET_2);
119 120
120 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); 121 switch (state->channel) {
121 readb(base + ICS_ARCIN_V6_INTROFFSET_1); 122 case 0:
123 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
124 readb(base + ICS_ARCIN_V6_INTROFFSET_2);
125 break;
126 case 1:
127 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
128 readb(base + ICS_ARCIN_V6_INTROFFSET_1);
129 break;
130 }
122} 131}
123 132
124/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) 133/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
@@ -128,6 +137,8 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
128{ 137{
129 struct icside_state *state = ec->irq_data; 138 struct icside_state *state = ec->irq_data;
130 139
140 state->enabled = 0;
141
131 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); 142 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
132 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); 143 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
133} 144}
@@ -149,6 +160,44 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
149 .irqpending = icside_irqpending_arcin_v6, 160 .irqpending = icside_irqpending_arcin_v6,
150}; 161};
151 162
163/*
164 * Handle routing of interrupts. This is called before
165 * we write the command to the drive.
166 */
167static void icside_maskproc(ide_drive_t *drive, int mask)
168{
169 ide_hwif_t *hwif = drive->hwif;
170 struct expansion_card *ec = ECARD_DEV(hwif->dev);
171 struct icside_state *state = ecard_get_drvdata(ec);
172 unsigned long flags;
173
174 local_irq_save(flags);
175
176 state->channel = hwif->channel;
177
178 if (state->enabled && !mask) {
179 switch (hwif->channel) {
180 case 0:
181 writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
182 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
183 break;
184 case 1:
185 writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
186 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
187 break;
188 }
189 } else {
190 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
191 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
192 }
193
194 local_irq_restore(flags);
195}
196
197static const struct ide_port_ops icside_v6_no_dma_port_ops = {
198 .maskproc = icside_maskproc,
199};
200
152#ifdef CONFIG_BLK_DEV_IDEDMA_ICS 201#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
153/* 202/*
154 * SG-DMA support. 203 * SG-DMA support.
@@ -229,6 +278,7 @@ static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
229 278
230static const struct ide_port_ops icside_v6_port_ops = { 279static const struct ide_port_ops icside_v6_port_ops = {
231 .set_dma_mode = icside_set_dma_mode, 280 .set_dma_mode = icside_set_dma_mode,
281 .maskproc = icside_maskproc,
232}; 282};
233 283
234static void icside_dma_host_set(ide_drive_t *drive, int on) 284static void icside_dma_host_set(ide_drive_t *drive, int on)
@@ -273,6 +323,11 @@ static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
273 BUG_ON(dma_channel_active(ec->dma)); 323 BUG_ON(dma_channel_active(ec->dma));
274 324
275 /* 325 /*
326 * Ensure that we have the right interrupt routed.
327 */
328 icside_maskproc(drive, 0);
329
330 /*
276 * Route the DMA signals to the correct interface. 331 * Route the DMA signals to the correct interface.
277 */ 332 */
278 writeb(state->sel | hwif->channel, state->ioc_base); 333 writeb(state->sel | hwif->channel, state->ioc_base);
@@ -400,6 +455,7 @@ err_free:
400 455
401static const struct ide_port_info icside_v6_port_info __initdata = { 456static const struct ide_port_info icside_v6_port_info __initdata = {
402 .init_dma = icside_dma_off_init, 457 .init_dma = icside_dma_off_init,
458 .port_ops = &icside_v6_no_dma_port_ops,
403 .dma_ops = &icside_v6_dma_ops, 459 .dma_ops = &icside_v6_dma_ops,
404 .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, 460 .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
405 .mwdma_mask = ATA_MWDMA2, 461 .mwdma_mask = ATA_MWDMA2,