aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ide-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r--drivers/scsi/ide-scsi.c81
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 */
134static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, 134static 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
171static 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;