diff -urN -X exclude /ata/linux-2.5.3-pre1/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- /ata/linux-2.5.3-pre1/drivers/block/ll_rw_blk.c Thu Jan 10 19:15:38 2002 +++ linux/drivers/block/ll_rw_blk.c Wed Jan 16 04:01:52 2002 @@ -302,8 +303,8 @@ static char *rq_flags[] = { "REQ_RW", "REQ_RW_AHEAD", "REQ_BARRIER", "REQ_CMD", "REQ_NOMERGE", "REQ_STARTED", "REQ_DONTPREP", "REQ_DRIVE_CMD", "REQ_DRIVE_TASK", - "REQ_PC", "REQ_BLOCK_PC", "REQ_SENSE", - "REQ_SPECIAL" }; + "REQ_DRIVE_ACB", "REQ_PC", "REQ_BLOCK_PC", + "REQ_SENSE", "REQ_SPECIAL" }; void blk_dump_rq_flags(struct request *rq, char *msg) { diff -urN -X exclude /ata/linux-2.5.3-pre1/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c --- /ata/linux-2.5.3-pre1/drivers/ide/ide-disk.c Thu Jan 17 06:32:54 2002 +++ linux/drivers/ide/ide-disk.c Thu Jan 17 03:53:09 2002 @@ -123,12 +123,10 @@ */ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - if (rq_data_dir(rq) == READ) - goto good_command; - if (rq_data_dir(rq) == WRITE) + if (rq->flags & REQ_CMD) goto good_command; - printk(KERN_ERR "%s: bad command: %lx\n", drive->name, rq->flags); + blk_dump_rq_flags(rq, "do_rw_disk, bad command"); ide_end_request(0, HWGROUP(drive)); return ide_stopped; @@ -179,8 +177,10 @@ struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq_data_dir(rq)); + unsigned int track = (block / drive->sect); unsigned int sect = (block % drive->sect) + 1; unsigned int head = (track % drive->head); @@ -189,7 +189,16 @@ memset(&taskfile, 0, sizeof(task_struct_t)); memset(&hobfile, 0, sizeof(hob_struct_t)); - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; + sectors = rq->nr_sectors; + if (sectors == 256) + sectors = 0; + if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) { + sectors = drive->mult_count; + if (sectors > rq->current_nr_sectors) + sectors = rq->current_nr_sectors; + } + + taskfile.sector_count = sectors; taskfile.sector_number = sect; taskfile.low_cylinder = cyl; taskfile.high_cylinder = (cyl>>8); @@ -225,13 +234,23 @@ struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq_data_dir(rq)); + sectors = rq->nr_sectors; + if (sectors == 256) + sectors = 0; + if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) { + sectors = drive->mult_count; + if (sectors > rq->current_nr_sectors) + sectors = rq->current_nr_sectors; + } + memset(&taskfile, 0, sizeof(task_struct_t)); memset(&hobfile, 0, sizeof(hob_struct_t)); - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; + taskfile.sector_count = sectors; taskfile.sector_number = block; taskfile.low_cylinder = (block>>=8); taskfile.high_cylinder = (block>>=8); @@ -273,14 +292,24 @@ struct hd_drive_task_hdr taskfile; struct hd_drive_hob_hdr hobfile; ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq_data_dir(rq)); memset(&taskfile, 0, sizeof(task_struct_t)); memset(&hobfile, 0, sizeof(hob_struct_t)); - taskfile.sector_count = rq->nr_sectors; - hobfile.sector_count = (rq->nr_sectors>>8); + sectors = rq->nr_sectors; + if (sectors == 256) + sectors = 0; + if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) { + sectors = drive->mult_count; + if (sectors > rq->current_nr_sectors) + sectors = rq->current_nr_sectors; + } + + taskfile.sector_count = sectors; + hobfile.sector_count = sectors >> 8; if (rq->nr_sectors == 65536) { taskfile.sector_count = 0x00; @@ -652,7 +681,7 @@ memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); taskfile.sector_count = drive->mult_req; taskfile.command = WIN_SETMULT; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); + do_taskfile(drive, &taskfile, &hobfile, &set_multmode_intr); } } else if (s->all) { int special = s->all; @@ -789,23 +818,12 @@ #endif /* CONFIG_PROC_FS */ +/* + * This is tightly woven into the driver->do_special can not touch. + * DON'T do it again until a total personality rewrite is committed. + */ static int set_multcount(ide_drive_t *drive, int arg) { -#if 1 - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - - if (drive->special.b.set_multmode) - return -EBUSY; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -#else struct request rq; if (drive->special.b.set_multmode) @@ -814,7 +832,6 @@ drive->mult_req = arg; drive->special.b.set_multmode = 1; (void) ide_do_drive_cmd (drive, &rq, ide_wait); -#endif return (drive->mult_count == arg) ? 0 : -EIO; } diff -urN -X exclude /ata/linux-2.5.3-pre1/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c --- /ata/linux-2.5.3-pre1/drivers/ide/ide-taskfile.c Thu Jan 17 06:32:54 2002 +++ linux/drivers/ide/ide-taskfile.c Thu Jan 17 07:29:10 2002 @@ -706,8 +706,8 @@ ide__sti(); /* local CPU only */ if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */ - + return ide_error(drive, "task_no_data_intr", stat); + /* calls ide_end_drive_cmd */ if (args) ide_end_drive_cmd (drive, stat, GET_ERR()); @@ -723,6 +723,7 @@ byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned long flags; if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { @@ -735,17 +736,21 @@ } } DTF("stat: %02x\n", stat); - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + pBuf = ide_map_rq(rq, &flags); DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); drive->io_32bit = 0; taskfile_input_data(drive, pBuf, SECTOR_WORDS); + ide_unmap_rq(rq, pBuf, &flags); drive->io_32bit = io_32bit; if (--rq->current_nr_sectors <= 0) { /* (hs): swapped next 2 lines */ DTF("Request Ended stat: %02x\n", GET_STAT()); - ide_end_request(1, HWGROUP(drive)); + if (ide_end_request(1, HWGROUP(drive))) { + ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); + return ide_started; + } } else { ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); return ide_started; @@ -809,13 +814,14 @@ byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned long flags; if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { return ide_error(drive, "task_mulin_intr", stat); } /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); + ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); return ide_started; } @@ -834,10 +840,11 @@ */ nsect = 1; while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + pBuf = ide_map_rq(rq, &flags); DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); drive->io_32bit = 0; taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); + ide_unmap_rq(rq, pBuf, &flags); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors -= nsect; @@ -848,22 +855,34 @@ } #endif /* ALTSTAT_SCREW_UP */ - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + do { + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; - DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (rq->current_nr_sectors != 0) { - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); - return ide_started; - } - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; + pBuf = ide_map_rq(rq, &flags); + + DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + drive->io_32bit = 0; + taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); + ide_unmap_rq(rq, pBuf, &flags); + drive->io_32bit = io_32bit; + rq->errors = 0; + rq->current_nr_sectors -= nsect; + msect -= nsect; + if (!rq->current_nr_sectors) { + if (!ide_end_request(1, HWGROUP(drive))) + return ide_stopped; + } + } while (msect); + + + /* + * more data left + */ + ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + return ide_started; } ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) @@ -879,10 +898,12 @@ /* (ks/hs): Fixed Multi Write */ if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) && (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) { + unsigned long flags; + char *buf = ide_map_rq(rq, &flags); /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); + taskfile_output_data(drive, buf, SECTOR_WORDS); rq->current_nr_sectors--; - return ide_started; + ide_unmap_rq(rq, buf, &flags); } else { /* * (ks/hs): Stuff the first sector(s) @@ -913,8 +934,10 @@ byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned long flags; if (!rq->current_nr_sectors) { + printk("task_out_intr: should not trigger\n"); ide_end_request(1, HWGROUP(drive)); return ide_stopped; } @@ -922,19 +945,24 @@ if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { return ide_error(drive, "task_out_intr", stat); } + if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) { rq = HWGROUP(drive)->rq; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + pBuf = ide_map_rq(rq, &flags); DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); drive->io_32bit = 0; taskfile_output_data(drive, pBuf, SECTOR_WORDS); + ide_unmap_rq(rq, pBuf, &flags); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors--; } if (rq->current_nr_sectors <= 0) { - ide_end_request(1, HWGROUP(drive)); + if (ide_end_request(1, HWGROUP(drive))) { + ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); + return ide_started; + } } else { ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); return ide_started; @@ -961,14 +989,20 @@ struct request *rq = HWGROUP(drive)->rq; ide_hwgroup_t *hwgroup = HWGROUP(drive); char *pBuf = NULL; + unsigned long flags; /* * (ks/hs): Handle last IRQ on multi-sector transfer, - * occurs after all data was sent + * occurs after all data was sent in this chunk */ if (rq->current_nr_sectors == 0) { if (stat & (ERR_STAT|DRQ_STAT)) return ide_error(drive, "task_mulout_intr", stat); + + /* + * there may be more, ide_do_request will restart it if + * necessary + */ ide_end_request(1, HWGROUP(drive)); return ide_stopped; } @@ -994,10 +1028,11 @@ if (!msect) { nsect = 1; while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + pBuf = ide_map_rq(rq, &flags); DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); drive->io_32bit = 0; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + ide_unmap_rq(pBuf, &flags); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors -= nsect; @@ -1008,12 +1043,16 @@ } #endif /* ALTSTAT_SCREW_UP */ - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; + + pBuf = ide_map_rq(rq, &flags); DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); drive->io_32bit = 0; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + ide_unmap_rq(rq, pBuf, &flags); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors -= nsect; diff -urN -X exclude /ata/linux-2.5.3-pre1/drivers/ide/ide.c linux/drivers/ide/ide.c --- /ata/linux-2.5.3-pre1/drivers/ide/ide.c Thu Jan 17 06:32:54 2002 +++ linux/drivers/ide/ide.c Thu Jan 17 03:07:23 2002 @@ -1458,14 +1458,11 @@ HWGROUP(drive)->rq = NULL; rq->errors = 0; - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_sectors(rq->bio); - - /* - * just to make sure... - */ - if (rq->bio) + if (rq->bio) { + rq->sector = rq->bio->bi_sector; + rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; rq->buffer = NULL; + } } /* diff -urN -X exclude /ata/linux-2.5.3-pre1/include/linux/ide.h linux/include/linux/ide.h --- /ata/linux-2.5.3-pre1/include/linux/ide.h Thu Jan 17 06:32:55 2002 +++ linux/include/linux/ide.h Thu Jan 17 03:22:45 2002 @@ -884,6 +884,9 @@ */ #define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) +#define task_rq_offset(rq) \ + (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE) + extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags) { return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); @@ -892,6 +895,24 @@ extern inline void ide_unmap_buffer(char *buffer, unsigned long *flags) { bio_kunmap_irq(buffer, flags); +} + +/* + * for now, taskfile requests are special :/ + */ +extern inline char *ide_map_rq(struct request *rq, unsigned long *flags) +{ + if (rq->bio) + return ide_map_buffer(rq, flags); + else + return rq->buffer + task_rq_offset(rq); +} + +extern inline void ide_unmap_rq(struct request *rq, char *buf, + unsigned long *flags) +{ + if (rq->bio) + ide_unmap_buffer(buf, flags); } /*