diff options
| -rw-r--r-- | drivers/scsi/a3000.c | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index 7f09d89100a1..d9468027fb61 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c | |||
| @@ -17,11 +17,16 @@ | |||
| 17 | #include "a3000.h" | 17 | #include "a3000.h" |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | struct a3000_hostdata { | ||
| 21 | struct WD33C93_hostdata wh; | ||
| 22 | struct a3000_scsiregs *regs; | ||
| 23 | }; | ||
| 24 | |||
| 20 | static irqreturn_t a3000_intr(int irq, void *data) | 25 | static irqreturn_t a3000_intr(int irq, void *data) |
| 21 | { | 26 | { |
| 22 | struct Scsi_Host *instance = data; | 27 | struct Scsi_Host *instance = data; |
| 23 | struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); | 28 | struct a3000_hostdata *hdata = shost_priv(instance); |
| 24 | unsigned int status = regs->ISTR; | 29 | unsigned int status = hdata->regs->ISTR; |
| 25 | unsigned long flags; | 30 | unsigned long flags; |
| 26 | 31 | ||
| 27 | if (!(status & ISTR_INT_P)) | 32 | if (!(status & ISTR_INT_P)) |
| @@ -39,8 +44,9 @@ static irqreturn_t a3000_intr(int irq, void *data) | |||
| 39 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | 44 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) |
| 40 | { | 45 | { |
| 41 | struct Scsi_Host *instance = cmd->device->host; | 46 | struct Scsi_Host *instance = cmd->device->host; |
| 42 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 47 | struct a3000_hostdata *hdata = shost_priv(instance); |
| 43 | struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); | 48 | struct WD33C93_hostdata *wh = &hdata->wh; |
| 49 | struct a3000_scsiregs *regs = hdata->regs; | ||
| 44 | unsigned short cntr = CNTR_PDMD | CNTR_INTEN; | 50 | unsigned short cntr = CNTR_PDMD | CNTR_INTEN; |
| 45 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); | 51 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); |
| 46 | 52 | ||
| @@ -51,23 +57,23 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
| 51 | * buffer | 57 | * buffer |
| 52 | */ | 58 | */ |
| 53 | if (addr & A3000_XFER_MASK) { | 59 | if (addr & A3000_XFER_MASK) { |
| 54 | hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; | 60 | wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; |
| 55 | hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, | 61 | wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len, |
| 56 | GFP_KERNEL); | 62 | GFP_KERNEL); |
| 57 | 63 | ||
| 58 | /* can't allocate memory; use PIO */ | 64 | /* can't allocate memory; use PIO */ |
| 59 | if (!hdata->dma_bounce_buffer) { | 65 | if (!wh->dma_bounce_buffer) { |
| 60 | hdata->dma_bounce_len = 0; | 66 | wh->dma_bounce_len = 0; |
| 61 | return 1; | 67 | return 1; |
| 62 | } | 68 | } |
| 63 | 69 | ||
| 64 | if (!dir_in) { | 70 | if (!dir_in) { |
| 65 | /* copy to bounce buffer for a write */ | 71 | /* copy to bounce buffer for a write */ |
| 66 | memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, | 72 | memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, |
| 67 | cmd->SCp.this_residual); | 73 | cmd->SCp.this_residual); |
| 68 | } | 74 | } |
| 69 | 75 | ||
| 70 | addr = virt_to_bus(hdata->dma_bounce_buffer); | 76 | addr = virt_to_bus(wh->dma_bounce_buffer); |
| 71 | } | 77 | } |
| 72 | 78 | ||
| 73 | /* setup dma direction */ | 79 | /* setup dma direction */ |
| @@ -75,7 +81,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
| 75 | cntr |= CNTR_DDIR; | 81 | cntr |= CNTR_DDIR; |
| 76 | 82 | ||
| 77 | /* remember direction */ | 83 | /* remember direction */ |
| 78 | hdata->dma_dir = dir_in; | 84 | wh->dma_dir = dir_in; |
| 79 | 85 | ||
| 80 | regs->CNTR = cntr; | 86 | regs->CNTR = cntr; |
| 81 | 87 | ||
| @@ -102,20 +108,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
| 102 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | 108 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, |
| 103 | int status) | 109 | int status) |
| 104 | { | 110 | { |
| 105 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 111 | struct a3000_hostdata *hdata = shost_priv(instance); |
| 106 | struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); | 112 | struct WD33C93_hostdata *wh = &hdata->wh; |
| 113 | struct a3000_scsiregs *regs = hdata->regs; | ||
| 107 | 114 | ||
| 108 | /* disable SCSI interrupts */ | 115 | /* disable SCSI interrupts */ |
| 109 | unsigned short cntr = CNTR_PDMD; | 116 | unsigned short cntr = CNTR_PDMD; |
| 110 | 117 | ||
| 111 | if (!hdata->dma_dir) | 118 | if (!wh->dma_dir) |
| 112 | cntr |= CNTR_DDIR; | 119 | cntr |= CNTR_DDIR; |
| 113 | 120 | ||
| 114 | regs->CNTR = cntr; | 121 | regs->CNTR = cntr; |
| 115 | mb(); /* make sure CNTR is updated before next IO */ | 122 | mb(); /* make sure CNTR is updated before next IO */ |
| 116 | 123 | ||
| 117 | /* flush if we were reading */ | 124 | /* flush if we were reading */ |
| 118 | if (hdata->dma_dir) { | 125 | if (wh->dma_dir) { |
| 119 | regs->FLUSH = 1; | 126 | regs->FLUSH = 1; |
| 120 | mb(); /* don't allow prefetch */ | 127 | mb(); /* don't allow prefetch */ |
| 121 | while (!(regs->ISTR & ISTR_FE_FLG)) | 128 | while (!(regs->ISTR & ISTR_FE_FLG)) |
| @@ -138,19 +145,18 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
| 138 | mb(); /* make sure CNTR is updated before next IO */ | 145 | mb(); /* make sure CNTR is updated before next IO */ |
| 139 | 146 | ||
| 140 | /* copy from a bounce buffer, if necessary */ | 147 | /* copy from a bounce buffer, if necessary */ |
| 141 | if (status && hdata->dma_bounce_buffer) { | 148 | if (status && wh->dma_bounce_buffer) { |
| 142 | if (SCpnt) { | 149 | if (SCpnt) { |
| 143 | if (hdata->dma_dir && SCpnt) | 150 | if (wh->dma_dir && SCpnt) |
| 144 | memcpy(SCpnt->SCp.ptr, | 151 | memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, |
| 145 | hdata->dma_bounce_buffer, | ||
| 146 | SCpnt->SCp.this_residual); | 152 | SCpnt->SCp.this_residual); |
| 147 | kfree(hdata->dma_bounce_buffer); | 153 | kfree(wh->dma_bounce_buffer); |
| 148 | hdata->dma_bounce_buffer = NULL; | 154 | wh->dma_bounce_buffer = NULL; |
| 149 | hdata->dma_bounce_len = 0; | 155 | wh->dma_bounce_len = 0; |
| 150 | } else { | 156 | } else { |
| 151 | kfree(hdata->dma_bounce_buffer); | 157 | kfree(wh->dma_bounce_buffer); |
| 152 | hdata->dma_bounce_buffer = NULL; | 158 | wh->dma_bounce_buffer = NULL; |
| 153 | hdata->dma_bounce_len = 0; | 159 | wh->dma_bounce_len = 0; |
| 154 | } | 160 | } |
| 155 | } | 161 | } |
| 156 | } | 162 | } |
| @@ -194,7 +200,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) | |||
| 194 | int error; | 200 | int error; |
| 195 | struct a3000_scsiregs *regs; | 201 | struct a3000_scsiregs *regs; |
| 196 | wd33c93_regs wdregs; | 202 | wd33c93_regs wdregs; |
| 197 | struct WD33C93_hostdata *hdata; | 203 | struct a3000_hostdata *hdata; |
| 198 | 204 | ||
| 199 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 205 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 200 | if (!res) | 206 | if (!res) |
| @@ -204,25 +210,25 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) | |||
| 204 | return -EBUSY; | 210 | return -EBUSY; |
| 205 | 211 | ||
| 206 | instance = scsi_host_alloc(&amiga_a3000_scsi_template, | 212 | instance = scsi_host_alloc(&amiga_a3000_scsi_template, |
| 207 | sizeof(struct WD33C93_hostdata)); | 213 | sizeof(struct a3000_hostdata)); |
| 208 | if (!instance) { | 214 | if (!instance) { |
| 209 | error = -ENOMEM; | 215 | error = -ENOMEM; |
| 210 | goto fail_alloc; | 216 | goto fail_alloc; |
| 211 | } | 217 | } |
| 212 | 218 | ||
| 213 | instance->base = ZTWO_VADDR(res->start); | ||
| 214 | instance->irq = IRQ_AMIGA_PORTS; | 219 | instance->irq = IRQ_AMIGA_PORTS; |
| 215 | 220 | ||
| 216 | regs = (struct a3000_scsiregs *)(instance->base); | 221 | regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start); |
| 217 | regs->DAWR = DAWR_A3000; | 222 | regs->DAWR = DAWR_A3000; |
| 218 | 223 | ||
| 219 | wdregs.SASR = ®s->SASR; | 224 | wdregs.SASR = ®s->SASR; |
| 220 | wdregs.SCMD = ®s->SCMD; | 225 | wdregs.SCMD = ®s->SCMD; |
| 221 | 226 | ||
| 222 | hdata = shost_priv(instance); | 227 | hdata = shost_priv(instance); |
| 223 | hdata->no_sync = 0xff; | 228 | hdata->wh.no_sync = 0xff; |
| 224 | hdata->fast = 0; | 229 | hdata->wh.fast = 0; |
| 225 | hdata->dma_mode = CTRL_DMA; | 230 | hdata->wh.dma_mode = CTRL_DMA; |
| 231 | hdata->regs = regs; | ||
| 226 | 232 | ||
| 227 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); | 233 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); |
| 228 | error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, | 234 | error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, |
| @@ -253,10 +259,10 @@ fail_alloc: | |||
| 253 | static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev) | 259 | static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev) |
| 254 | { | 260 | { |
| 255 | struct Scsi_Host *instance = platform_get_drvdata(pdev); | 261 | struct Scsi_Host *instance = platform_get_drvdata(pdev); |
| 256 | struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); | 262 | struct a3000_hostdata *hdata = shost_priv(instance); |
| 257 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 263 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 258 | 264 | ||
| 259 | regs->CNTR = 0; | 265 | hdata->regs->CNTR = 0; |
| 260 | scsi_remove_host(instance); | 266 | scsi_remove_host(instance); |
| 261 | free_irq(IRQ_AMIGA_PORTS, instance); | 267 | free_irq(IRQ_AMIGA_PORTS, instance); |
| 262 | scsi_host_put(instance); | 268 | scsi_host_put(instance); |
