diff options
| -rw-r--r-- | drivers/ide/ide-tape.c | 75 |
1 files changed, 22 insertions, 53 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 58c4c1bc35cd..a7670fbd470d 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
| @@ -333,32 +333,6 @@ typedef struct idetape_stage_s { | |||
| 333 | } idetape_stage_t; | 333 | } idetape_stage_t; |
| 334 | 334 | ||
| 335 | /* | 335 | /* |
| 336 | * REQUEST SENSE packet command result - Data Format. | ||
| 337 | */ | ||
| 338 | typedef struct { | ||
| 339 | unsigned error_code :7; /* Current of deferred errors */ | ||
| 340 | unsigned valid :1; /* The information field conforms to QIC-157C */ | ||
| 341 | __u8 reserved1 :8; /* Segment Number - Reserved */ | ||
| 342 | unsigned sense_key :4; /* Sense Key */ | ||
| 343 | unsigned reserved2_4 :1; /* Reserved */ | ||
| 344 | unsigned ili :1; /* Incorrect Length Indicator */ | ||
| 345 | unsigned eom :1; /* End Of Medium */ | ||
| 346 | unsigned filemark :1; /* Filemark */ | ||
| 347 | __u32 information __attribute__ ((packed)); | ||
| 348 | __u8 asl; /* Additional sense length (n-7) */ | ||
| 349 | __u32 command_specific; /* Additional command specific information */ | ||
| 350 | __u8 asc; /* Additional Sense Code */ | ||
| 351 | __u8 ascq; /* Additional Sense Code Qualifier */ | ||
| 352 | __u8 replaceable_unit_code; /* Field Replaceable Unit Code */ | ||
| 353 | unsigned sk_specific1 :7; /* Sense Key Specific */ | ||
| 354 | unsigned sksv :1; /* Sense Key Specific information is valid */ | ||
| 355 | __u8 sk_specific2; /* Sense Key Specific */ | ||
| 356 | __u8 sk_specific3; /* Sense Key Specific */ | ||
| 357 | __u8 pad[2]; /* Padding to 20 bytes */ | ||
| 358 | } idetape_request_sense_result_t; | ||
| 359 | |||
| 360 | |||
| 361 | /* | ||
| 362 | * Most of our global data which we need to save even as we leave the | 336 | * Most of our global data which we need to save even as we leave the |
| 363 | * driver due to an interrupt or a timer event is stored in a variable | 337 | * driver due to an interrupt or a timer event is stored in a variable |
| 364 | * of type idetape_tape_t, defined below. | 338 | * of type idetape_tape_t, defined below. |
| @@ -512,9 +486,6 @@ typedef struct ide_tape_obj { | |||
| 512 | int avg_size; | 486 | int avg_size; |
| 513 | int avg_speed; | 487 | int avg_speed; |
| 514 | 488 | ||
| 515 | /* last sense information */ | ||
| 516 | idetape_request_sense_result_t sense; | ||
| 517 | |||
| 518 | char vendor_id[10]; | 489 | char vendor_id[10]; |
| 519 | char product_id[18]; | 490 | char product_id[18]; |
| 520 | char firmware_revision[6]; | 491 | char firmware_revision[6]; |
| @@ -1025,36 +996,34 @@ static void idetape_init_pc (idetape_pc_t *pc) | |||
| 1025 | } | 996 | } |
| 1026 | 997 | ||
| 1027 | /* | 998 | /* |
| 1028 | * idetape_analyze_error is called on each failed packet command retry | 999 | * called on each failed packet command retry to analyze the request sense. We |
| 1029 | * to analyze the request sense. We currently do not utilize this | 1000 | * currently do not utilize this information. |
| 1030 | * information. | ||
| 1031 | */ | 1001 | */ |
| 1032 | static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_result_t *result) | 1002 | static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) |
| 1033 | { | 1003 | { |
| 1034 | idetape_tape_t *tape = drive->driver_data; | 1004 | idetape_tape_t *tape = drive->driver_data; |
| 1035 | idetape_pc_t *pc = tape->failed_pc; | 1005 | idetape_pc_t *pc = tape->failed_pc; |
| 1036 | 1006 | ||
| 1037 | tape->sense = *result; | 1007 | tape->sense_key = sense[2] & 0xF; |
| 1038 | tape->sense_key = result->sense_key; | 1008 | tape->asc = sense[12]; |
| 1039 | tape->asc = result->asc; | 1009 | tape->ascq = sense[13]; |
| 1040 | tape->ascq = result->ascq; | ||
| 1041 | #if IDETAPE_DEBUG_LOG | 1010 | #if IDETAPE_DEBUG_LOG |
| 1042 | /* | 1011 | /* |
| 1043 | * Without debugging, we only log an error if we decided to | 1012 | * Without debugging, we only log an error if we decided to give up |
| 1044 | * give up retrying. | 1013 | * retrying. |
| 1045 | */ | 1014 | */ |
| 1046 | if (tape->debug_level >= 1) | 1015 | if (tape->debug_level >= 1) |
| 1047 | printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, " | 1016 | printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, " |
| 1048 | "asc = %x, ascq = %x\n", | 1017 | "asc = %x, ascq = %x\n", |
| 1049 | pc->c[0], result->sense_key, | 1018 | pc->c[0], tape->sense_key, |
| 1050 | result->asc, result->ascq); | 1019 | tape->asc, tape->ascq); |
| 1051 | #endif /* IDETAPE_DEBUG_LOG */ | 1020 | #endif /* IDETAPE_DEBUG_LOG */ |
| 1052 | 1021 | ||
| 1053 | /* | 1022 | /* Correct pc->actually_transferred by asking the tape. */ |
| 1054 | * Correct pc->actually_transferred by asking the tape. | ||
| 1055 | */ | ||
| 1056 | if (test_bit(PC_DMA_ERROR, &pc->flags)) { | 1023 | if (test_bit(PC_DMA_ERROR, &pc->flags)) { |
| 1057 | pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information)); | 1024 | pc->actually_transferred = pc->request_transfer - |
| 1025 | tape->tape_block_size * | ||
| 1026 | ntohl(get_unaligned((u32 *)&sense[3])); | ||
| 1058 | idetape_update_buffers(pc); | 1027 | idetape_update_buffers(pc); |
| 1059 | } | 1028 | } |
| 1060 | 1029 | ||
| @@ -1064,28 +1033,28 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res | |||
| 1064 | * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes. | 1033 | * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes. |
| 1065 | */ | 1034 | */ |
| 1066 | if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) | 1035 | if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) |
| 1067 | && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { /* length==0 */ | 1036 | /* length == 0 */ |
| 1068 | if (result->sense_key == 5) { | 1037 | && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { |
| 1038 | if (tape->sense_key == 5) { | ||
| 1069 | /* don't report an error, everything's ok */ | 1039 | /* don't report an error, everything's ok */ |
| 1070 | pc->error = 0; | 1040 | pc->error = 0; |
| 1071 | /* don't retry read/write */ | 1041 | /* don't retry read/write */ |
| 1072 | set_bit(PC_ABORT, &pc->flags); | 1042 | set_bit(PC_ABORT, &pc->flags); |
| 1073 | } | 1043 | } |
| 1074 | } | 1044 | } |
| 1075 | if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { | 1045 | if (pc->c[0] == IDETAPE_READ_CMD && (sense[2] & 0x80)) { |
| 1076 | pc->error = IDETAPE_ERROR_FILEMARK; | 1046 | pc->error = IDETAPE_ERROR_FILEMARK; |
| 1077 | set_bit(PC_ABORT, &pc->flags); | 1047 | set_bit(PC_ABORT, &pc->flags); |
| 1078 | } | 1048 | } |
| 1079 | if (pc->c[0] == IDETAPE_WRITE_CMD) { | 1049 | if (pc->c[0] == IDETAPE_WRITE_CMD) { |
| 1080 | if (result->eom || | 1050 | if ((sense[2] & 0x40) || (tape->sense_key == 0xd |
| 1081 | (result->sense_key == 0xd && result->asc == 0x0 && | 1051 | && tape->asc == 0x0 && tape->ascq == 0x2)) { |
| 1082 | result->ascq == 0x2)) { | ||
| 1083 | pc->error = IDETAPE_ERROR_EOD; | 1052 | pc->error = IDETAPE_ERROR_EOD; |
| 1084 | set_bit(PC_ABORT, &pc->flags); | 1053 | set_bit(PC_ABORT, &pc->flags); |
| 1085 | } | 1054 | } |
| 1086 | } | 1055 | } |
| 1087 | if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) { | 1056 | if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) { |
| 1088 | if (result->sense_key == 8) { | 1057 | if (tape->sense_key == 8) { |
| 1089 | pc->error = IDETAPE_ERROR_EOD; | 1058 | pc->error = IDETAPE_ERROR_EOD; |
| 1090 | set_bit(PC_ABORT, &pc->flags); | 1059 | set_bit(PC_ABORT, &pc->flags); |
| 1091 | } | 1060 | } |
| @@ -1327,7 +1296,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) | |||
| 1327 | printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); | 1296 | printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); |
| 1328 | #endif /* IDETAPE_DEBUG_LOG */ | 1297 | #endif /* IDETAPE_DEBUG_LOG */ |
| 1329 | if (!tape->pc->error) { | 1298 | if (!tape->pc->error) { |
| 1330 | idetape_analyze_error(drive, (idetape_request_sense_result_t *) tape->pc->buffer); | 1299 | idetape_analyze_error(drive, tape->pc->buffer); |
| 1331 | idetape_end_request(drive, 1, 0); | 1300 | idetape_end_request(drive, 1, 0); |
| 1332 | } else { | 1301 | } else { |
| 1333 | printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); | 1302 | printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); |
