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.c67
1 files changed, 62 insertions, 5 deletions
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 0f67f1abbbd3..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.
@@ -185,10 +234,11 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
185 * MW1 80 50 50 150 C 234 * MW1 80 50 50 150 C
186 * MW2 70 25 25 120 C 235 * MW2 70 25 25 120 C
187 */ 236 */
188static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) 237static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
189{ 238{
190 unsigned long cycle_time; 239 unsigned long cycle_time;
191 int use_dma_info = 0; 240 int use_dma_info = 0;
241 const u8 xfer_mode = drive->dma_mode;
192 242
193 switch (xfer_mode) { 243 switch (xfer_mode) {
194 case XFER_MW_DMA_2: 244 case XFER_MW_DMA_2:
@@ -228,6 +278,7 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
228 278
229static const struct ide_port_ops icside_v6_port_ops = { 279static const struct ide_port_ops icside_v6_port_ops = {
230 .set_dma_mode = icside_set_dma_mode, 280 .set_dma_mode = icside_set_dma_mode,
281 .maskproc = icside_maskproc,
231}; 282};
232 283
233static void icside_dma_host_set(ide_drive_t *drive, int on) 284static void icside_dma_host_set(ide_drive_t *drive, int on)
@@ -272,6 +323,11 @@ static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
272 BUG_ON(dma_channel_active(ec->dma)); 323 BUG_ON(dma_channel_active(ec->dma));
273 324
274 /* 325 /*
326 * Ensure that we have the right interrupt routed.
327 */
328 icside_maskproc(drive, 0);
329
330 /*
275 * Route the DMA signals to the correct interface. 331 * Route the DMA signals to the correct interface.
276 */ 332 */
277 writeb(state->sel | hwif->channel, state->ioc_base); 333 writeb(state->sel | hwif->channel, state->ioc_base);
@@ -399,6 +455,7 @@ err_free:
399 455
400static const struct ide_port_info icside_v6_port_info __initdata = { 456static const struct ide_port_info icside_v6_port_info __initdata = {
401 .init_dma = icside_dma_off_init, 457 .init_dma = icside_dma_off_init,
458 .port_ops = &icside_v6_no_dma_port_ops,
402 .dma_ops = &icside_v6_dma_ops, 459 .dma_ops = &icside_v6_dma_ops,
403 .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, 460 .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
404 .mwdma_mask = ATA_MWDMA2, 461 .mwdma_mask = ATA_MWDMA2,