aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/hd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/hd.c')
-rw-r--r--drivers/block/hd.c106
1 files changed, 55 insertions, 51 deletions
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index baaa9e486e50..f65b3f369eb0 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -98,10 +98,9 @@
98 98
99static DEFINE_SPINLOCK(hd_lock); 99static DEFINE_SPINLOCK(hd_lock);
100static struct request_queue *hd_queue; 100static struct request_queue *hd_queue;
101static struct request *hd_req;
101 102
102#define MAJOR_NR HD_MAJOR 103#define MAJOR_NR HD_MAJOR
103#define QUEUE (hd_queue)
104#define CURRENT elv_next_request(hd_queue)
105 104
106#define TIMEOUT_VALUE (6*HZ) 105#define TIMEOUT_VALUE (6*HZ)
107#define HD_DELAY 0 106#define HD_DELAY 0
@@ -195,11 +194,24 @@ static void __init hd_setup(char *str, int *ints)
195 NR_HD = hdind+1; 194 NR_HD = hdind+1;
196} 195}
197 196
197static bool hd_end_request(int err, unsigned int bytes)
198{
199 if (__blk_end_request(hd_req, err, bytes))
200 return true;
201 hd_req = NULL;
202 return false;
203}
204
205static bool hd_end_request_cur(int err)
206{
207 return hd_end_request(err, blk_rq_cur_bytes(hd_req));
208}
209
198static void dump_status(const char *msg, unsigned int stat) 210static void dump_status(const char *msg, unsigned int stat)
199{ 211{
200 char *name = "hd?"; 212 char *name = "hd?";
201 if (CURRENT) 213 if (hd_req)
202 name = CURRENT->rq_disk->disk_name; 214 name = hd_req->rq_disk->disk_name;
203 215
204#ifdef VERBOSE_ERRORS 216#ifdef VERBOSE_ERRORS
205 printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); 217 printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
@@ -227,8 +239,8 @@ static void dump_status(const char *msg, unsigned int stat)
227 if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { 239 if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
228 printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), 240 printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
229 inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); 241 inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
230 if (CURRENT) 242 if (hd_req)
231 printk(", sector=%ld", CURRENT->sector); 243 printk(", sector=%ld", blk_rq_pos(hd_req));
232 } 244 }
233 printk("\n"); 245 printk("\n");
234 } 246 }
@@ -406,11 +418,12 @@ static void unexpected_hd_interrupt(void)
406 */ 418 */
407static void bad_rw_intr(void) 419static void bad_rw_intr(void)
408{ 420{
409 struct request *req = CURRENT; 421 struct request *req = hd_req;
422
410 if (req != NULL) { 423 if (req != NULL) {
411 struct hd_i_struct *disk = req->rq_disk->private_data; 424 struct hd_i_struct *disk = req->rq_disk->private_data;
412 if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { 425 if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
413 end_request(req, 0); 426 hd_end_request_cur(-EIO);
414 disk->special_op = disk->recalibrate = 1; 427 disk->special_op = disk->recalibrate = 1;
415 } else if (req->errors % RESET_FREQ == 0) 428 } else if (req->errors % RESET_FREQ == 0)
416 reset = 1; 429 reset = 1;
@@ -452,37 +465,30 @@ static void read_intr(void)
452 bad_rw_intr(); 465 bad_rw_intr();
453 hd_request(); 466 hd_request();
454 return; 467 return;
468
455ok_to_read: 469ok_to_read:
456 req = CURRENT; 470 req = hd_req;
457 insw(HD_DATA, req->buffer, 256); 471 insw(HD_DATA, req->buffer, 256);
458 req->sector++;
459 req->buffer += 512;
460 req->errors = 0;
461 i = --req->nr_sectors;
462 --req->current_nr_sectors;
463#ifdef DEBUG 472#ifdef DEBUG
464 printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n", 473 printk("%s: read: sector %ld, remaining = %u, buffer=%p\n",
465 req->rq_disk->disk_name, req->sector, req->nr_sectors, 474 req->rq_disk->disk_name, blk_rq_pos(req) + 1,
466 req->buffer+512); 475 blk_rq_sectors(req) - 1, req->buffer+512);
467#endif 476#endif
468 if (req->current_nr_sectors <= 0) 477 if (hd_end_request(0, 512)) {
469 end_request(req, 1);
470 if (i > 0) {
471 SET_HANDLER(&read_intr); 478 SET_HANDLER(&read_intr);
472 return; 479 return;
473 } 480 }
481
474 (void) inb_p(HD_STATUS); 482 (void) inb_p(HD_STATUS);
475#if (HD_DELAY > 0) 483#if (HD_DELAY > 0)
476 last_req = read_timer(); 484 last_req = read_timer();
477#endif 485#endif
478 if (elv_next_request(QUEUE)) 486 hd_request();
479 hd_request();
480 return;
481} 487}
482 488
483static void write_intr(void) 489static void write_intr(void)
484{ 490{
485 struct request *req = CURRENT; 491 struct request *req = hd_req;
486 int i; 492 int i;
487 int retries = 100000; 493 int retries = 100000;
488 494
@@ -492,30 +498,25 @@ static void write_intr(void)
492 continue; 498 continue;
493 if (!OK_STATUS(i)) 499 if (!OK_STATUS(i))
494 break; 500 break;
495 if ((req->nr_sectors <= 1) || (i & DRQ_STAT)) 501 if ((blk_rq_sectors(req) <= 1) || (i & DRQ_STAT))
496 goto ok_to_write; 502 goto ok_to_write;
497 } while (--retries > 0); 503 } while (--retries > 0);
498 dump_status("write_intr", i); 504 dump_status("write_intr", i);
499 bad_rw_intr(); 505 bad_rw_intr();
500 hd_request(); 506 hd_request();
501 return; 507 return;
508
502ok_to_write: 509ok_to_write:
503 req->sector++; 510 if (hd_end_request(0, 512)) {
504 i = --req->nr_sectors;
505 --req->current_nr_sectors;
506 req->buffer += 512;
507 if (!i || (req->bio && req->current_nr_sectors <= 0))
508 end_request(req, 1);
509 if (i > 0) {
510 SET_HANDLER(&write_intr); 511 SET_HANDLER(&write_intr);
511 outsw(HD_DATA, req->buffer, 256); 512 outsw(HD_DATA, req->buffer, 256);
512 } else { 513 return;
514 }
515
513#if (HD_DELAY > 0) 516#if (HD_DELAY > 0)
514 last_req = read_timer(); 517 last_req = read_timer();
515#endif 518#endif
516 hd_request(); 519 hd_request();
517 }
518 return;
519} 520}
520 521
521static void recal_intr(void) 522static void recal_intr(void)
@@ -537,18 +538,18 @@ static void hd_times_out(unsigned long dummy)
537 538
538 do_hd = NULL; 539 do_hd = NULL;
539 540
540 if (!CURRENT) 541 if (!hd_req)
541 return; 542 return;
542 543
543 spin_lock_irq(hd_queue->queue_lock); 544 spin_lock_irq(hd_queue->queue_lock);
544 reset = 1; 545 reset = 1;
545 name = CURRENT->rq_disk->disk_name; 546 name = hd_req->rq_disk->disk_name;
546 printk("%s: timeout\n", name); 547 printk("%s: timeout\n", name);
547 if (++CURRENT->errors >= MAX_ERRORS) { 548 if (++hd_req->errors >= MAX_ERRORS) {
548#ifdef DEBUG 549#ifdef DEBUG
549 printk("%s: too many errors\n", name); 550 printk("%s: too many errors\n", name);
550#endif 551#endif
551 end_request(CURRENT, 0); 552 hd_end_request_cur(-EIO);
552 } 553 }
553 hd_request(); 554 hd_request();
554 spin_unlock_irq(hd_queue->queue_lock); 555 spin_unlock_irq(hd_queue->queue_lock);
@@ -563,7 +564,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
563 } 564 }
564 if (disk->head > 16) { 565 if (disk->head > 16) {
565 printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); 566 printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
566 end_request(req, 0); 567 hd_end_request_cur(-EIO);
567 } 568 }
568 disk->special_op = 0; 569 disk->special_op = 0;
569 return 1; 570 return 1;
@@ -590,24 +591,27 @@ static void hd_request(void)
590repeat: 591repeat:
591 del_timer(&device_timer); 592 del_timer(&device_timer);
592 593
593 req = CURRENT; 594 if (!hd_req) {
594 if (!req) { 595 hd_req = blk_fetch_request(hd_queue);
595 do_hd = NULL; 596 if (!hd_req) {
596 return; 597 do_hd = NULL;
598 return;
599 }
597 } 600 }
601 req = hd_req;
598 602
599 if (reset) { 603 if (reset) {
600 reset_hd(); 604 reset_hd();
601 return; 605 return;
602 } 606 }
603 disk = req->rq_disk->private_data; 607 disk = req->rq_disk->private_data;
604 block = req->sector; 608 block = blk_rq_pos(req);
605 nsect = req->nr_sectors; 609 nsect = blk_rq_sectors(req);
606 if (block >= get_capacity(req->rq_disk) || 610 if (block >= get_capacity(req->rq_disk) ||
607 ((block+nsect) > get_capacity(req->rq_disk))) { 611 ((block+nsect) > get_capacity(req->rq_disk))) {
608 printk("%s: bad access: block=%d, count=%d\n", 612 printk("%s: bad access: block=%d, count=%d\n",
609 req->rq_disk->disk_name, block, nsect); 613 req->rq_disk->disk_name, block, nsect);
610 end_request(req, 0); 614 hd_end_request_cur(-EIO);
611 goto repeat; 615 goto repeat;
612 } 616 }
613 617
@@ -647,7 +651,7 @@ repeat:
647 break; 651 break;
648 default: 652 default:
649 printk("unknown hd-command\n"); 653 printk("unknown hd-command\n");
650 end_request(req, 0); 654 hd_end_request_cur(-EIO);
651 break; 655 break;
652 } 656 }
653 } 657 }
@@ -720,7 +724,7 @@ static int __init hd_init(void)
720 blk_queue_max_sectors(hd_queue, 255); 724 blk_queue_max_sectors(hd_queue, 255);
721 init_timer(&device_timer); 725 init_timer(&device_timer);
722 device_timer.function = hd_times_out; 726 device_timer.function = hd_times_out;
723 blk_queue_hardsect_size(hd_queue, 512); 727 blk_queue_logical_block_size(hd_queue, 512);
724 728
725 if (!NR_HD) { 729 if (!NR_HD) {
726 /* 730 /*