diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 81 |
1 files changed, 24 insertions, 57 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 08807070e083..36c2c3bf111d 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -129,51 +129,15 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive) | |||
129 | #define IDESCSI_PC_RQ 90 | 129 | #define IDESCSI_PC_RQ 90 |
130 | 130 | ||
131 | /* | 131 | /* |
132 | * PIO data transfer routines using the scatter gather table. | 132 | * PIO data transfer routine using the scatter gather table. |
133 | */ | 133 | */ |
134 | static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 134 | static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
135 | unsigned int bcount) | 135 | unsigned int bcount, int write) |
136 | { | 136 | { |
137 | ide_hwif_t *hwif = drive->hwif; | 137 | ide_hwif_t *hwif = drive->hwif; |
138 | int count; | 138 | xfer_func_t *xf = write ? hwif->output_data : hwif->input_data; |
139 | char *buf; | 139 | char *buf; |
140 | |||
141 | while (bcount) { | ||
142 | count = min(pc->sg->length - pc->b_count, bcount); | ||
143 | if (PageHighMem(sg_page(pc->sg))) { | ||
144 | unsigned long flags; | ||
145 | |||
146 | local_irq_save(flags); | ||
147 | buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + | ||
148 | pc->sg->offset; | ||
149 | hwif->input_data(drive, NULL, buf + pc->b_count, count); | ||
150 | kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); | ||
151 | local_irq_restore(flags); | ||
152 | } else { | ||
153 | buf = sg_virt(pc->sg); | ||
154 | hwif->input_data(drive, NULL, buf + pc->b_count, count); | ||
155 | } | ||
156 | bcount -= count; pc->b_count += count; | ||
157 | if (pc->b_count == pc->sg->length) { | ||
158 | if (!--pc->sg_cnt) | ||
159 | break; | ||
160 | pc->sg = sg_next(pc->sg); | ||
161 | pc->b_count = 0; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | if (bcount) { | ||
166 | printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); | ||
167 | ide_pad_transfer(drive, 0, bcount); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
172 | unsigned int bcount) | ||
173 | { | ||
174 | ide_hwif_t *hwif = drive->hwif; | ||
175 | int count; | 140 | int count; |
176 | char *buf; | ||
177 | 141 | ||
178 | while (bcount) { | 142 | while (bcount) { |
179 | count = min(pc->sg->length - pc->b_count, bcount); | 143 | count = min(pc->sg->length - pc->b_count, bcount); |
@@ -182,13 +146,13 @@ static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
182 | 146 | ||
183 | local_irq_save(flags); | 147 | local_irq_save(flags); |
184 | buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + | 148 | buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + |
185 | pc->sg->offset; | 149 | pc->sg->offset; |
186 | hwif->output_data(drive, NULL, buf + pc->b_count, count); | 150 | xf(drive, NULL, buf + pc->b_count, count); |
187 | kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); | 151 | kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); |
188 | local_irq_restore(flags); | 152 | local_irq_restore(flags); |
189 | } else { | 153 | } else { |
190 | buf = sg_virt(pc->sg); | 154 | buf = sg_virt(pc->sg); |
191 | hwif->output_data(drive, NULL, buf + pc->b_count, count); | 155 | xf(drive, NULL, buf + pc->b_count, count); |
192 | } | 156 | } |
193 | bcount -= count; pc->b_count += count; | 157 | bcount -= count; pc->b_count += count; |
194 | if (pc->b_count == pc->sg->length) { | 158 | if (pc->b_count == pc->sg->length) { |
@@ -200,8 +164,10 @@ static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
200 | } | 164 | } |
201 | 165 | ||
202 | if (bcount) { | 166 | if (bcount) { |
203 | printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); | 167 | printk(KERN_ERR "%s: scatter gather table too small, %s\n", |
204 | ide_pad_transfer(drive, 1, bcount); | 168 | drive->name, write ? "padding with zeros" |
169 | : "discarding data"); | ||
170 | ide_pad_transfer(drive, write, bcount); | ||
205 | } | 171 | } |
206 | } | 172 | } |
207 | 173 | ||
@@ -370,6 +336,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) | |||
370 | ide_hwif_t *hwif = drive->hwif; | 336 | ide_hwif_t *hwif = drive->hwif; |
371 | struct ide_atapi_pc *pc = scsi->pc; | 337 | struct ide_atapi_pc *pc = scsi->pc; |
372 | struct request *rq = pc->rq; | 338 | struct request *rq = pc->rq; |
339 | xfer_func_t *xferfunc; | ||
373 | unsigned int temp; | 340 | unsigned int temp; |
374 | u16 bcount; | 341 | u16 bcount; |
375 | u8 stat, ireason; | 342 | u8 stat, ireason; |
@@ -445,8 +412,8 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) | |||
445 | temp = pc->buf_size - pc->xferred; | 412 | temp = pc->buf_size - pc->xferred; |
446 | if (temp) { | 413 | if (temp) { |
447 | if (pc->sg) | 414 | if (pc->sg) |
448 | idescsi_input_buffers(drive, pc, | 415 | ide_scsi_io_buffers(drive, pc, |
449 | temp); | 416 | temp, 0); |
450 | else | 417 | else |
451 | hwif->input_data(drive, NULL, | 418 | hwif->input_data(drive, NULL, |
452 | pc->cur_pos, temp); | 419 | pc->cur_pos, temp); |
@@ -464,16 +431,16 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) | |||
464 | printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); | 431 | printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); |
465 | #endif /* IDESCSI_DEBUG_LOG */ | 432 | #endif /* IDESCSI_DEBUG_LOG */ |
466 | } | 433 | } |
467 | if (pc->sg) | 434 | xferfunc = hwif->input_data; |
468 | idescsi_input_buffers(drive, pc, bcount); | 435 | } else |
469 | else | 436 | xferfunc = hwif->output_data; |
470 | hwif->input_data(drive, NULL, pc->cur_pos, bcount); | 437 | |
471 | } else { | 438 | if (pc->sg) |
472 | if (pc->sg) | 439 | ide_scsi_io_buffers(drive, pc, bcount, |
473 | idescsi_output_buffers(drive, pc, bcount); | 440 | !!(pc->flags & PC_FLAG_WRITING)); |
474 | else | 441 | else |
475 | hwif->output_data(drive, NULL, pc->cur_pos, bcount); | 442 | xferfunc(drive, NULL, pc->cur_pos, bcount); |
476 | } | 443 | |
477 | /* Update the current position */ | 444 | /* Update the current position */ |
478 | pc->xferred += bcount; | 445 | pc->xferred += bcount; |
479 | pc->cur_pos += bcount; | 446 | pc->cur_pos += bcount; |