diff options
Diffstat (limited to 'drivers/scsi')
63 files changed, 2876 insertions, 7160 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index ccdf440021fb..83bfab73ff65 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -133,6 +133,7 @@ struct inquiry_data { | |||
133 | 133 | ||
134 | static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); | 134 | static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); |
135 | static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); | 135 | static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); |
136 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg); | ||
136 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); | 137 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); |
137 | #ifdef AAC_DETAILED_STATUS_INFO | 138 | #ifdef AAC_DETAILED_STATUS_INFO |
138 | static char *aac_get_status_string(u32 status); | 139 | static char *aac_get_status_string(u32 status); |
@@ -348,6 +349,27 @@ static void aac_io_done(struct scsi_cmnd * scsicmd) | |||
348 | spin_unlock_irqrestore(host->host_lock, cpu_flags); | 349 | spin_unlock_irqrestore(host->host_lock, cpu_flags); |
349 | } | 350 | } |
350 | 351 | ||
352 | static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len) | ||
353 | { | ||
354 | void *buf; | ||
355 | unsigned int transfer_len; | ||
356 | struct scatterlist *sg = scsicmd->request_buffer; | ||
357 | |||
358 | if (scsicmd->use_sg) { | ||
359 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
360 | transfer_len = min(sg->length, len + offset); | ||
361 | } else { | ||
362 | buf = scsicmd->request_buffer; | ||
363 | transfer_len = min(scsicmd->request_bufflen, len + offset); | ||
364 | } | ||
365 | |||
366 | memcpy(buf + offset, data, transfer_len - offset); | ||
367 | |||
368 | if (scsicmd->use_sg) | ||
369 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
370 | |||
371 | } | ||
372 | |||
351 | static void get_container_name_callback(void *context, struct fib * fibptr) | 373 | static void get_container_name_callback(void *context, struct fib * fibptr) |
352 | { | 374 | { |
353 | struct aac_get_name_resp * get_name_reply; | 375 | struct aac_get_name_resp * get_name_reply; |
@@ -363,18 +385,22 @@ static void get_container_name_callback(void *context, struct fib * fibptr) | |||
363 | /* Failure is irrelevant, using default value instead */ | 385 | /* Failure is irrelevant, using default value instead */ |
364 | if ((le32_to_cpu(get_name_reply->status) == CT_OK) | 386 | if ((le32_to_cpu(get_name_reply->status) == CT_OK) |
365 | && (get_name_reply->data[0] != '\0')) { | 387 | && (get_name_reply->data[0] != '\0')) { |
366 | int count; | 388 | char *sp = get_name_reply->data; |
367 | char * dp; | ||
368 | char * sp = get_name_reply->data; | ||
369 | sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; | 389 | sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; |
370 | while (*sp == ' ') | 390 | while (*sp == ' ') |
371 | ++sp; | 391 | ++sp; |
372 | count = sizeof(((struct inquiry_data *)NULL)->inqd_pid); | 392 | if (*sp) { |
373 | dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid; | 393 | char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)]; |
374 | if (*sp) do { | 394 | int count = sizeof(d); |
375 | *dp++ = (*sp) ? *sp++ : ' '; | 395 | char *dp = d; |
376 | } while (--count > 0); | 396 | do { |
397 | *dp++ = (*sp) ? *sp++ : ' '; | ||
398 | } while (--count > 0); | ||
399 | aac_internal_transfer(scsicmd, d, | ||
400 | offsetof(struct inquiry_data, inqd_pid), sizeof(d)); | ||
401 | } | ||
377 | } | 402 | } |
403 | |||
378 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 404 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
379 | 405 | ||
380 | fib_complete(fibptr); | 406 | fib_complete(fibptr); |
@@ -777,34 +803,36 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
777 | /* | 803 | /* |
778 | * 57 scatter gather elements | 804 | * 57 scatter gather elements |
779 | */ | 805 | */ |
780 | dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - | 806 | if (!(dev->raw_io_interface)) { |
781 | sizeof(struct aac_fibhdr) - | 807 | dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - |
782 | sizeof(struct aac_write) + sizeof(struct sgmap)) / | ||
783 | sizeof(struct sgmap); | ||
784 | if (dev->dac_support) { | ||
785 | /* | ||
786 | * 38 scatter gather elements | ||
787 | */ | ||
788 | dev->scsi_host_ptr->sg_tablesize = | ||
789 | (dev->max_fib_size - | ||
790 | sizeof(struct aac_fibhdr) - | 808 | sizeof(struct aac_fibhdr) - |
791 | sizeof(struct aac_write64) + | 809 | sizeof(struct aac_write) + sizeof(struct sgmap)) / |
792 | sizeof(struct sgmap64)) / | 810 | sizeof(struct sgmap); |
793 | sizeof(struct sgmap64); | 811 | if (dev->dac_support) { |
794 | } | 812 | /* |
795 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; | 813 | * 38 scatter gather elements |
796 | if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { | 814 | */ |
797 | /* | 815 | dev->scsi_host_ptr->sg_tablesize = |
798 | * Worst case size that could cause sg overflow when | 816 | (dev->max_fib_size - |
799 | * we break up SG elements that are larger than 64KB. | 817 | sizeof(struct aac_fibhdr) - |
800 | * Would be nice if we could tell the SCSI layer what | 818 | sizeof(struct aac_write64) + |
801 | * the maximum SG element size can be. Worst case is | 819 | sizeof(struct sgmap64)) / |
802 | * (sg_tablesize-1) 4KB elements with one 64KB | 820 | sizeof(struct sgmap64); |
803 | * element. | 821 | } |
804 | * 32bit -> 468 or 238KB 64bit -> 424 or 212KB | 822 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; |
805 | */ | 823 | if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { |
806 | dev->scsi_host_ptr->max_sectors = | 824 | /* |
807 | (dev->scsi_host_ptr->sg_tablesize * 8) + 112; | 825 | * Worst case size that could cause sg overflow when |
826 | * we break up SG elements that are larger than 64KB. | ||
827 | * Would be nice if we could tell the SCSI layer what | ||
828 | * the maximum SG element size can be. Worst case is | ||
829 | * (sg_tablesize-1) 4KB elements with one 64KB | ||
830 | * element. | ||
831 | * 32bit -> 468 or 238KB 64bit -> 424 or 212KB | ||
832 | */ | ||
833 | dev->scsi_host_ptr->max_sectors = | ||
834 | (dev->scsi_host_ptr->sg_tablesize * 8) + 112; | ||
835 | } | ||
808 | } | 836 | } |
809 | 837 | ||
810 | fib_complete(fibptr); | 838 | fib_complete(fibptr); |
@@ -814,12 +842,11 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
814 | } | 842 | } |
815 | 843 | ||
816 | 844 | ||
817 | static void read_callback(void *context, struct fib * fibptr) | 845 | static void io_callback(void *context, struct fib * fibptr) |
818 | { | 846 | { |
819 | struct aac_dev *dev; | 847 | struct aac_dev *dev; |
820 | struct aac_read_reply *readreply; | 848 | struct aac_read_reply *readreply; |
821 | struct scsi_cmnd *scsicmd; | 849 | struct scsi_cmnd *scsicmd; |
822 | u32 lba; | ||
823 | u32 cid; | 850 | u32 cid; |
824 | 851 | ||
825 | scsicmd = (struct scsi_cmnd *) context; | 852 | scsicmd = (struct scsi_cmnd *) context; |
@@ -827,8 +854,7 @@ static void read_callback(void *context, struct fib * fibptr) | |||
827 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | 854 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; |
828 | cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); | 855 | cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); |
829 | 856 | ||
830 | lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; | 857 | dprintk((KERN_DEBUG "io_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3], jiffies)); |
831 | dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); | ||
832 | 858 | ||
833 | if (fibptr == NULL) | 859 | if (fibptr == NULL) |
834 | BUG(); | 860 | BUG(); |
@@ -847,7 +873,7 @@ static void read_callback(void *context, struct fib * fibptr) | |||
847 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 873 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
848 | else { | 874 | else { |
849 | #ifdef AAC_DETAILED_STATUS_INFO | 875 | #ifdef AAC_DETAILED_STATUS_INFO |
850 | printk(KERN_WARNING "read_callback: io failed, status = %d\n", | 876 | printk(KERN_WARNING "io_callback: io failed, status = %d\n", |
851 | le32_to_cpu(readreply->status)); | 877 | le32_to_cpu(readreply->status)); |
852 | #endif | 878 | #endif |
853 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; | 879 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; |
@@ -867,53 +893,6 @@ static void read_callback(void *context, struct fib * fibptr) | |||
867 | aac_io_done(scsicmd); | 893 | aac_io_done(scsicmd); |
868 | } | 894 | } |
869 | 895 | ||
870 | static void write_callback(void *context, struct fib * fibptr) | ||
871 | { | ||
872 | struct aac_dev *dev; | ||
873 | struct aac_write_reply *writereply; | ||
874 | struct scsi_cmnd *scsicmd; | ||
875 | u32 lba; | ||
876 | u32 cid; | ||
877 | |||
878 | scsicmd = (struct scsi_cmnd *) context; | ||
879 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | ||
880 | cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); | ||
881 | |||
882 | lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; | ||
883 | dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); | ||
884 | if (fibptr == NULL) | ||
885 | BUG(); | ||
886 | |||
887 | if(scsicmd->use_sg) | ||
888 | pci_unmap_sg(dev->pdev, | ||
889 | (struct scatterlist *)scsicmd->buffer, | ||
890 | scsicmd->use_sg, | ||
891 | scsicmd->sc_data_direction); | ||
892 | else if(scsicmd->request_bufflen) | ||
893 | pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, | ||
894 | scsicmd->request_bufflen, | ||
895 | scsicmd->sc_data_direction); | ||
896 | |||
897 | writereply = (struct aac_write_reply *) fib_data(fibptr); | ||
898 | if (le32_to_cpu(writereply->status) == ST_OK) | ||
899 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | ||
900 | else { | ||
901 | printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status); | ||
902 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; | ||
903 | set_sense((u8 *) &dev->fsa_dev[cid].sense_data, | ||
904 | HARDWARE_ERROR, | ||
905 | SENCODE_INTERNAL_TARGET_FAILURE, | ||
906 | ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, | ||
907 | 0, 0); | ||
908 | memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | ||
909 | sizeof(struct sense_data)); | ||
910 | } | ||
911 | |||
912 | fib_complete(fibptr); | ||
913 | fib_free(fibptr); | ||
914 | aac_io_done(scsicmd); | ||
915 | } | ||
916 | |||
917 | static int aac_read(struct scsi_cmnd * scsicmd, int cid) | 896 | static int aac_read(struct scsi_cmnd * scsicmd, int cid) |
918 | { | 897 | { |
919 | u32 lba; | 898 | u32 lba; |
@@ -954,7 +933,32 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
954 | 933 | ||
955 | fib_init(cmd_fibcontext); | 934 | fib_init(cmd_fibcontext); |
956 | 935 | ||
957 | if (dev->dac_support == 1) { | 936 | if (dev->raw_io_interface) { |
937 | struct aac_raw_io *readcmd; | ||
938 | readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); | ||
939 | readcmd->block[0] = cpu_to_le32(lba); | ||
940 | readcmd->block[1] = 0; | ||
941 | readcmd->count = cpu_to_le32(count<<9); | ||
942 | readcmd->cid = cpu_to_le16(cid); | ||
943 | readcmd->flags = cpu_to_le16(1); | ||
944 | readcmd->bpTotal = 0; | ||
945 | readcmd->bpComplete = 0; | ||
946 | |||
947 | aac_build_sgraw(scsicmd, &readcmd->sg); | ||
948 | fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); | ||
949 | if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) | ||
950 | BUG(); | ||
951 | /* | ||
952 | * Now send the Fib to the adapter | ||
953 | */ | ||
954 | status = fib_send(ContainerRawIo, | ||
955 | cmd_fibcontext, | ||
956 | fibsize, | ||
957 | FsaNormal, | ||
958 | 0, 1, | ||
959 | (fib_callback) io_callback, | ||
960 | (void *) scsicmd); | ||
961 | } else if (dev->dac_support == 1) { | ||
958 | struct aac_read64 *readcmd; | 962 | struct aac_read64 *readcmd; |
959 | readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); | 963 | readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); |
960 | readcmd->command = cpu_to_le32(VM_CtHostRead64); | 964 | readcmd->command = cpu_to_le32(VM_CtHostRead64); |
@@ -978,7 +982,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
978 | fibsize, | 982 | fibsize, |
979 | FsaNormal, | 983 | FsaNormal, |
980 | 0, 1, | 984 | 0, 1, |
981 | (fib_callback) read_callback, | 985 | (fib_callback) io_callback, |
982 | (void *) scsicmd); | 986 | (void *) scsicmd); |
983 | } else { | 987 | } else { |
984 | struct aac_read *readcmd; | 988 | struct aac_read *readcmd; |
@@ -1002,7 +1006,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
1002 | fibsize, | 1006 | fibsize, |
1003 | FsaNormal, | 1007 | FsaNormal, |
1004 | 0, 1, | 1008 | 0, 1, |
1005 | (fib_callback) read_callback, | 1009 | (fib_callback) io_callback, |
1006 | (void *) scsicmd); | 1010 | (void *) scsicmd); |
1007 | } | 1011 | } |
1008 | 1012 | ||
@@ -1061,7 +1065,32 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) | |||
1061 | } | 1065 | } |
1062 | fib_init(cmd_fibcontext); | 1066 | fib_init(cmd_fibcontext); |
1063 | 1067 | ||
1064 | if(dev->dac_support == 1) { | 1068 | if (dev->raw_io_interface) { |
1069 | struct aac_raw_io *writecmd; | ||
1070 | writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); | ||
1071 | writecmd->block[0] = cpu_to_le32(lba); | ||
1072 | writecmd->block[1] = 0; | ||
1073 | writecmd->count = cpu_to_le32(count<<9); | ||
1074 | writecmd->cid = cpu_to_le16(cid); | ||
1075 | writecmd->flags = 0; | ||
1076 | writecmd->bpTotal = 0; | ||
1077 | writecmd->bpComplete = 0; | ||
1078 | |||
1079 | aac_build_sgraw(scsicmd, &writecmd->sg); | ||
1080 | fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); | ||
1081 | if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) | ||
1082 | BUG(); | ||
1083 | /* | ||
1084 | * Now send the Fib to the adapter | ||
1085 | */ | ||
1086 | status = fib_send(ContainerRawIo, | ||
1087 | cmd_fibcontext, | ||
1088 | fibsize, | ||
1089 | FsaNormal, | ||
1090 | 0, 1, | ||
1091 | (fib_callback) io_callback, | ||
1092 | (void *) scsicmd); | ||
1093 | } else if (dev->dac_support == 1) { | ||
1065 | struct aac_write64 *writecmd; | 1094 | struct aac_write64 *writecmd; |
1066 | writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); | 1095 | writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); |
1067 | writecmd->command = cpu_to_le32(VM_CtHostWrite64); | 1096 | writecmd->command = cpu_to_le32(VM_CtHostWrite64); |
@@ -1085,7 +1114,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) | |||
1085 | fibsize, | 1114 | fibsize, |
1086 | FsaNormal, | 1115 | FsaNormal, |
1087 | 0, 1, | 1116 | 0, 1, |
1088 | (fib_callback) write_callback, | 1117 | (fib_callback) io_callback, |
1089 | (void *) scsicmd); | 1118 | (void *) scsicmd); |
1090 | } else { | 1119 | } else { |
1091 | struct aac_write *writecmd; | 1120 | struct aac_write *writecmd; |
@@ -1111,7 +1140,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) | |||
1111 | fibsize, | 1140 | fibsize, |
1112 | FsaNormal, | 1141 | FsaNormal, |
1113 | 0, 1, | 1142 | 0, 1, |
1114 | (fib_callback) write_callback, | 1143 | (fib_callback) io_callback, |
1115 | (void *) scsicmd); | 1144 | (void *) scsicmd); |
1116 | } | 1145 | } |
1117 | 1146 | ||
@@ -1340,44 +1369,45 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1340 | switch (scsicmd->cmnd[0]) { | 1369 | switch (scsicmd->cmnd[0]) { |
1341 | case INQUIRY: | 1370 | case INQUIRY: |
1342 | { | 1371 | { |
1343 | struct inquiry_data *inq_data_ptr; | 1372 | struct inquiry_data inq_data; |
1344 | 1373 | ||
1345 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id)); | 1374 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id)); |
1346 | inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; | 1375 | memset(&inq_data, 0, sizeof (struct inquiry_data)); |
1347 | memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); | ||
1348 | 1376 | ||
1349 | inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ | 1377 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ |
1350 | inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ | 1378 | inq_data.inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ |
1351 | inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ | 1379 | inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ |
1352 | inq_data_ptr->inqd_len = 31; | 1380 | inq_data.inqd_len = 31; |
1353 | /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ | 1381 | /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ |
1354 | inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ | 1382 | inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ |
1355 | /* | 1383 | /* |
1356 | * Set the Vendor, Product, and Revision Level | 1384 | * Set the Vendor, Product, and Revision Level |
1357 | * see: <vendor>.c i.e. aac.c | 1385 | * see: <vendor>.c i.e. aac.c |
1358 | */ | 1386 | */ |
1359 | if (scsicmd->device->id == host->this_id) { | 1387 | if (scsicmd->device->id == host->this_id) { |
1360 | setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *))); | 1388 | setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *))); |
1361 | inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ | 1389 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ |
1390 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | ||
1362 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1391 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1363 | scsicmd->scsi_done(scsicmd); | 1392 | scsicmd->scsi_done(scsicmd); |
1364 | return 0; | 1393 | return 0; |
1365 | } | 1394 | } |
1366 | setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type); | 1395 | setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); |
1367 | inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ | 1396 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ |
1397 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | ||
1368 | return aac_get_container_name(scsicmd, cid); | 1398 | return aac_get_container_name(scsicmd, cid); |
1369 | } | 1399 | } |
1370 | case READ_CAPACITY: | 1400 | case READ_CAPACITY: |
1371 | { | 1401 | { |
1372 | u32 capacity; | 1402 | u32 capacity; |
1373 | char *cp; | 1403 | char cp[8]; |
1374 | 1404 | ||
1375 | dprintk((KERN_DEBUG "READ CAPACITY command.\n")); | 1405 | dprintk((KERN_DEBUG "READ CAPACITY command.\n")); |
1376 | if (fsa_dev_ptr[cid].size <= 0x100000000LL) | 1406 | if (fsa_dev_ptr[cid].size <= 0x100000000LL) |
1377 | capacity = fsa_dev_ptr[cid].size - 1; | 1407 | capacity = fsa_dev_ptr[cid].size - 1; |
1378 | else | 1408 | else |
1379 | capacity = (u32)-1; | 1409 | capacity = (u32)-1; |
1380 | cp = scsicmd->request_buffer; | 1410 | |
1381 | cp[0] = (capacity >> 24) & 0xff; | 1411 | cp[0] = (capacity >> 24) & 0xff; |
1382 | cp[1] = (capacity >> 16) & 0xff; | 1412 | cp[1] = (capacity >> 16) & 0xff; |
1383 | cp[2] = (capacity >> 8) & 0xff; | 1413 | cp[2] = (capacity >> 8) & 0xff; |
@@ -1386,6 +1416,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1386 | cp[5] = 0; | 1416 | cp[5] = 0; |
1387 | cp[6] = 2; | 1417 | cp[6] = 2; |
1388 | cp[7] = 0; | 1418 | cp[7] = 0; |
1419 | aac_internal_transfer(scsicmd, cp, 0, sizeof(cp)); | ||
1389 | 1420 | ||
1390 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1421 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1391 | scsicmd->scsi_done(scsicmd); | 1422 | scsicmd->scsi_done(scsicmd); |
@@ -1395,15 +1426,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1395 | 1426 | ||
1396 | case MODE_SENSE: | 1427 | case MODE_SENSE: |
1397 | { | 1428 | { |
1398 | char *mode_buf; | 1429 | char mode_buf[4]; |
1399 | 1430 | ||
1400 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); | 1431 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); |
1401 | mode_buf = scsicmd->request_buffer; | ||
1402 | mode_buf[0] = 3; /* Mode data length */ | 1432 | mode_buf[0] = 3; /* Mode data length */ |
1403 | mode_buf[1] = 0; /* Medium type - default */ | 1433 | mode_buf[1] = 0; /* Medium type - default */ |
1404 | mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ | 1434 | mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ |
1405 | mode_buf[3] = 0; /* Block descriptor length */ | 1435 | mode_buf[3] = 0; /* Block descriptor length */ |
1406 | 1436 | ||
1437 | aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); | ||
1407 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1438 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1408 | scsicmd->scsi_done(scsicmd); | 1439 | scsicmd->scsi_done(scsicmd); |
1409 | 1440 | ||
@@ -1411,10 +1442,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1411 | } | 1442 | } |
1412 | case MODE_SENSE_10: | 1443 | case MODE_SENSE_10: |
1413 | { | 1444 | { |
1414 | char *mode_buf; | 1445 | char mode_buf[8]; |
1415 | 1446 | ||
1416 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); | 1447 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); |
1417 | mode_buf = scsicmd->request_buffer; | ||
1418 | mode_buf[0] = 0; /* Mode data length (MSB) */ | 1448 | mode_buf[0] = 0; /* Mode data length (MSB) */ |
1419 | mode_buf[1] = 6; /* Mode data length (LSB) */ | 1449 | mode_buf[1] = 6; /* Mode data length (LSB) */ |
1420 | mode_buf[2] = 0; /* Medium type - default */ | 1450 | mode_buf[2] = 0; /* Medium type - default */ |
@@ -1423,6 +1453,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1423 | mode_buf[5] = 0; /* reserved */ | 1453 | mode_buf[5] = 0; /* reserved */ |
1424 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ | 1454 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ |
1425 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ | 1455 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ |
1456 | aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); | ||
1426 | 1457 | ||
1427 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1458 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1428 | scsicmd->scsi_done(scsicmd); | 1459 | scsicmd->scsi_done(scsicmd); |
@@ -1894,7 +1925,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) | |||
1894 | srbcmd->id = cpu_to_le32(scsicmd->device->id); | 1925 | srbcmd->id = cpu_to_le32(scsicmd->device->id); |
1895 | srbcmd->lun = cpu_to_le32(scsicmd->device->lun); | 1926 | srbcmd->lun = cpu_to_le32(scsicmd->device->lun); |
1896 | srbcmd->flags = cpu_to_le32(flag); | 1927 | srbcmd->flags = cpu_to_le32(flag); |
1897 | timeout = (scsicmd->timeout-jiffies)/HZ; | 1928 | timeout = scsicmd->timeout_per_command/HZ; |
1898 | if(timeout == 0){ | 1929 | if(timeout == 0){ |
1899 | timeout = 1; | 1930 | timeout = 1; |
1900 | } | 1931 | } |
@@ -2077,6 +2108,76 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p | |||
2077 | return byte_count; | 2108 | return byte_count; |
2078 | } | 2109 | } |
2079 | 2110 | ||
2111 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg) | ||
2112 | { | ||
2113 | struct Scsi_Host *host = scsicmd->device->host; | ||
2114 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | ||
2115 | unsigned long byte_count = 0; | ||
2116 | |||
2117 | // Get rid of old data | ||
2118 | psg->count = 0; | ||
2119 | psg->sg[0].next = 0; | ||
2120 | psg->sg[0].prev = 0; | ||
2121 | psg->sg[0].addr[0] = 0; | ||
2122 | psg->sg[0].addr[1] = 0; | ||
2123 | psg->sg[0].count = 0; | ||
2124 | psg->sg[0].flags = 0; | ||
2125 | if (scsicmd->use_sg) { | ||
2126 | struct scatterlist *sg; | ||
2127 | int i; | ||
2128 | int sg_count; | ||
2129 | sg = (struct scatterlist *) scsicmd->request_buffer; | ||
2130 | |||
2131 | sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, | ||
2132 | scsicmd->sc_data_direction); | ||
2133 | |||
2134 | for (i = 0; i < sg_count; i++) { | ||
2135 | int count = sg_dma_len(sg); | ||
2136 | u64 addr = sg_dma_address(sg); | ||
2137 | psg->sg[i].next = 0; | ||
2138 | psg->sg[i].prev = 0; | ||
2139 | psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32)); | ||
2140 | psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | ||
2141 | psg->sg[i].count = cpu_to_le32(count); | ||
2142 | psg->sg[i].flags = 0; | ||
2143 | byte_count += count; | ||
2144 | sg++; | ||
2145 | } | ||
2146 | psg->count = cpu_to_le32(sg_count); | ||
2147 | /* hba wants the size to be exact */ | ||
2148 | if(byte_count > scsicmd->request_bufflen){ | ||
2149 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - | ||
2150 | (byte_count - scsicmd->request_bufflen); | ||
2151 | psg->sg[i-1].count = cpu_to_le32(temp); | ||
2152 | byte_count = scsicmd->request_bufflen; | ||
2153 | } | ||
2154 | /* Check for command underflow */ | ||
2155 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ | ||
2156 | printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", | ||
2157 | byte_count, scsicmd->underflow); | ||
2158 | } | ||
2159 | } | ||
2160 | else if(scsicmd->request_bufflen) { | ||
2161 | int count; | ||
2162 | u64 addr; | ||
2163 | scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, | ||
2164 | scsicmd->request_buffer, | ||
2165 | scsicmd->request_bufflen, | ||
2166 | scsicmd->sc_data_direction); | ||
2167 | addr = scsicmd->SCp.dma_handle; | ||
2168 | count = scsicmd->request_bufflen; | ||
2169 | psg->count = cpu_to_le32(1); | ||
2170 | psg->sg[0].next = 0; | ||
2171 | psg->sg[0].prev = 0; | ||
2172 | psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32)); | ||
2173 | psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | ||
2174 | psg->sg[0].count = cpu_to_le32(count); | ||
2175 | psg->sg[0].flags = 0; | ||
2176 | byte_count = scsicmd->request_bufflen; | ||
2177 | } | ||
2178 | return byte_count; | ||
2179 | } | ||
2180 | |||
2080 | #ifdef AAC_DETAILED_STATUS_INFO | 2181 | #ifdef AAC_DETAILED_STATUS_INFO |
2081 | 2182 | ||
2082 | struct aac_srb_status_info { | 2183 | struct aac_srb_status_info { |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 4ab07861b457..e40528185d48 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -110,6 +110,22 @@ struct user_sgentry64 { | |||
110 | u32 count; /* Length. */ | 110 | u32 count; /* Length. */ |
111 | }; | 111 | }; |
112 | 112 | ||
113 | struct sgentryraw { | ||
114 | __le32 next; /* reserved for F/W use */ | ||
115 | __le32 prev; /* reserved for F/W use */ | ||
116 | __le32 addr[2]; | ||
117 | __le32 count; | ||
118 | __le32 flags; /* reserved for F/W use */ | ||
119 | }; | ||
120 | |||
121 | struct user_sgentryraw { | ||
122 | u32 next; /* reserved for F/W use */ | ||
123 | u32 prev; /* reserved for F/W use */ | ||
124 | u32 addr[2]; | ||
125 | u32 count; | ||
126 | u32 flags; /* reserved for F/W use */ | ||
127 | }; | ||
128 | |||
113 | /* | 129 | /* |
114 | * SGMAP | 130 | * SGMAP |
115 | * | 131 | * |
@@ -137,6 +153,16 @@ struct user_sgmap64 { | |||
137 | struct user_sgentry64 sg[1]; | 153 | struct user_sgentry64 sg[1]; |
138 | }; | 154 | }; |
139 | 155 | ||
156 | struct sgmapraw { | ||
157 | __le32 count; | ||
158 | struct sgentryraw sg[1]; | ||
159 | }; | ||
160 | |||
161 | struct user_sgmapraw { | ||
162 | u32 count; | ||
163 | struct user_sgentryraw sg[1]; | ||
164 | }; | ||
165 | |||
140 | struct creation_info | 166 | struct creation_info |
141 | { | 167 | { |
142 | u8 buildnum; /* e.g., 588 */ | 168 | u8 buildnum; /* e.g., 588 */ |
@@ -351,6 +377,7 @@ struct hw_fib { | |||
351 | */ | 377 | */ |
352 | #define ContainerCommand 500 | 378 | #define ContainerCommand 500 |
353 | #define ContainerCommand64 501 | 379 | #define ContainerCommand64 501 |
380 | #define ContainerRawIo 502 | ||
354 | /* | 381 | /* |
355 | * Cluster Commands | 382 | * Cluster Commands |
356 | */ | 383 | */ |
@@ -456,6 +483,7 @@ struct adapter_ops | |||
456 | { | 483 | { |
457 | void (*adapter_interrupt)(struct aac_dev *dev); | 484 | void (*adapter_interrupt)(struct aac_dev *dev); |
458 | void (*adapter_notify)(struct aac_dev *dev, u32 event); | 485 | void (*adapter_notify)(struct aac_dev *dev, u32 event); |
486 | void (*adapter_disable_int)(struct aac_dev *dev); | ||
459 | int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); | 487 | int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); |
460 | int (*adapter_check_health)(struct aac_dev *dev); | 488 | int (*adapter_check_health)(struct aac_dev *dev); |
461 | }; | 489 | }; |
@@ -981,6 +1009,9 @@ struct aac_dev | |||
981 | u8 nondasd_support; | 1009 | u8 nondasd_support; |
982 | u8 dac_support; | 1010 | u8 dac_support; |
983 | u8 raid_scsi_mode; | 1011 | u8 raid_scsi_mode; |
1012 | /* macro side-effects BEWARE */ | ||
1013 | # define raw_io_interface \ | ||
1014 | init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) | ||
984 | u8 printf_enabled; | 1015 | u8 printf_enabled; |
985 | }; | 1016 | }; |
986 | 1017 | ||
@@ -990,6 +1021,9 @@ struct aac_dev | |||
990 | #define aac_adapter_notify(dev, event) \ | 1021 | #define aac_adapter_notify(dev, event) \ |
991 | (dev)->a_ops.adapter_notify(dev, event) | 1022 | (dev)->a_ops.adapter_notify(dev, event) |
992 | 1023 | ||
1024 | #define aac_adapter_disable_int(dev) \ | ||
1025 | (dev)->a_ops.adapter_disable_int(dev) | ||
1026 | |||
993 | #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \ | 1027 | #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \ |
994 | (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) | 1028 | (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) |
995 | 1029 | ||
@@ -1156,6 +1190,17 @@ struct aac_write_reply | |||
1156 | __le32 committed; | 1190 | __le32 committed; |
1157 | }; | 1191 | }; |
1158 | 1192 | ||
1193 | struct aac_raw_io | ||
1194 | { | ||
1195 | __le32 block[2]; | ||
1196 | __le32 count; | ||
1197 | __le16 cid; | ||
1198 | __le16 flags; /* 00 W, 01 R */ | ||
1199 | __le16 bpTotal; /* reserved for F/W use */ | ||
1200 | __le16 bpComplete; /* reserved for F/W use */ | ||
1201 | struct sgmapraw sg; | ||
1202 | }; | ||
1203 | |||
1159 | #define CT_FLUSH_CACHE 129 | 1204 | #define CT_FLUSH_CACHE 129 |
1160 | struct aac_synchronize { | 1205 | struct aac_synchronize { |
1161 | __le32 command; /* VM_ContainerConfig */ | 1206 | __le32 command; /* VM_ContainerConfig */ |
@@ -1196,7 +1241,7 @@ struct aac_srb | |||
1196 | }; | 1241 | }; |
1197 | 1242 | ||
1198 | /* | 1243 | /* |
1199 | * This and assocated data structs are used by the | 1244 | * This and associated data structs are used by the |
1200 | * ioctl caller and are in cpu order. | 1245 | * ioctl caller and are in cpu order. |
1201 | */ | 1246 | */ |
1202 | struct user_aac_srb | 1247 | struct user_aac_srb |
@@ -1508,11 +1553,12 @@ struct fib_ioctl | |||
1508 | 1553 | ||
1509 | struct revision | 1554 | struct revision |
1510 | { | 1555 | { |
1511 | u32 compat; | 1556 | __le32 compat; |
1512 | u32 version; | 1557 | __le32 version; |
1513 | u32 build; | 1558 | __le32 build; |
1514 | }; | 1559 | }; |
1515 | 1560 | ||
1561 | |||
1516 | /* | 1562 | /* |
1517 | * Ugly - non Linux like ioctl coding for back compat. | 1563 | * Ugly - non Linux like ioctl coding for back compat. |
1518 | */ | 1564 | */ |
@@ -1733,3 +1779,4 @@ int aac_get_adapter_info(struct aac_dev* dev); | |||
1733 | int aac_send_shutdown(struct aac_dev *dev); | 1779 | int aac_send_shutdown(struct aac_dev *dev); |
1734 | extern int numacb; | 1780 | extern int numacb; |
1735 | extern int acbsize; | 1781 | extern int acbsize; |
1782 | extern char aac_driver_version[]; | ||
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 85387099aab2..71f1cad9b5f0 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -287,7 +287,6 @@ return_fib: | |||
287 | kfree(fib->hw_fib); | 287 | kfree(fib->hw_fib); |
288 | kfree(fib); | 288 | kfree(fib); |
289 | status = 0; | 289 | status = 0; |
290 | fibctx->jiffies = jiffies/HZ; | ||
291 | } else { | 290 | } else { |
292 | spin_unlock_irqrestore(&dev->fib_lock, flags); | 291 | spin_unlock_irqrestore(&dev->fib_lock, flags); |
293 | if (f.wait) { | 292 | if (f.wait) { |
@@ -302,6 +301,7 @@ return_fib: | |||
302 | status = -EAGAIN; | 301 | status = -EAGAIN; |
303 | } | 302 | } |
304 | } | 303 | } |
304 | fibctx->jiffies = jiffies/HZ; | ||
305 | return status; | 305 | return status; |
306 | } | 306 | } |
307 | 307 | ||
@@ -405,10 +405,20 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg) | |||
405 | static int check_revision(struct aac_dev *dev, void __user *arg) | 405 | static int check_revision(struct aac_dev *dev, void __user *arg) |
406 | { | 406 | { |
407 | struct revision response; | 407 | struct revision response; |
408 | 408 | char *driver_version = aac_driver_version; | |
409 | response.compat = 1; | 409 | u32 version; |
410 | response.version = le32_to_cpu(dev->adapter_info.kernelrev); | 410 | |
411 | response.build = le32_to_cpu(dev->adapter_info.kernelbuild); | 411 | response.compat = cpu_to_le32(1); |
412 | version = (simple_strtol(driver_version, | ||
413 | &driver_version, 10) << 24) | 0x00000400; | ||
414 | version += simple_strtol(driver_version + 1, &driver_version, 10) << 16; | ||
415 | version += simple_strtol(driver_version + 1, NULL, 10); | ||
416 | response.version = cpu_to_le32(version); | ||
417 | # if (defined(AAC_DRIVER_BUILD)) | ||
418 | response.build = cpu_to_le32(AAC_DRIVER_BUILD); | ||
419 | # else | ||
420 | response.build = cpu_to_le32(9999); | ||
421 | # endif | ||
412 | 422 | ||
413 | if (copy_to_user(arg, &response, sizeof(response))) | 423 | if (copy_to_user(arg, &response, sizeof(response))) |
414 | return -EFAULT; | 424 | return -EFAULT; |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 43557bf661f6..75abd0453289 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -44,7 +44,9 @@ | |||
44 | 44 | ||
45 | #include "aacraid.h" | 45 | #include "aacraid.h" |
46 | 46 | ||
47 | struct aac_common aac_config; | 47 | struct aac_common aac_config = { |
48 | .irq_mod = 1 | ||
49 | }; | ||
48 | 50 | ||
49 | static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign) | 51 | static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign) |
50 | { | 52 | { |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 5322865942e2..a1d303f03480 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -254,6 +254,7 @@ static void fib_dealloc(struct fib * fibptr) | |||
254 | static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify) | 254 | static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify) |
255 | { | 255 | { |
256 | struct aac_queue * q; | 256 | struct aac_queue * q; |
257 | unsigned long idx; | ||
257 | 258 | ||
258 | /* | 259 | /* |
259 | * All of the queues wrap when they reach the end, so we check | 260 | * All of the queues wrap when they reach the end, so we check |
@@ -263,10 +264,23 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr | |||
263 | */ | 264 | */ |
264 | 265 | ||
265 | q = &dev->queues->queue[qid]; | 266 | q = &dev->queues->queue[qid]; |
266 | 267 | ||
267 | *index = le32_to_cpu(*(q->headers.producer)); | 268 | idx = *index = le32_to_cpu(*(q->headers.producer)); |
268 | if ((*index - 2) == le32_to_cpu(*(q->headers.consumer))) | 269 | /* Interrupt Moderation, only interrupt for first two entries */ |
270 | if (idx != le32_to_cpu(*(q->headers.consumer))) { | ||
271 | if (--idx == 0) { | ||
272 | if (qid == AdapHighCmdQueue) | ||
273 | idx = ADAP_HIGH_CMD_ENTRIES; | ||
274 | else if (qid == AdapNormCmdQueue) | ||
275 | idx = ADAP_NORM_CMD_ENTRIES; | ||
276 | else if (qid == AdapHighRespQueue) | ||
277 | idx = ADAP_HIGH_RESP_ENTRIES; | ||
278 | else if (qid == AdapNormRespQueue) | ||
279 | idx = ADAP_NORM_RESP_ENTRIES; | ||
280 | } | ||
281 | if (idx != le32_to_cpu(*(q->headers.consumer))) | ||
269 | *nonotify = 1; | 282 | *nonotify = 1; |
283 | } | ||
270 | 284 | ||
271 | if (qid == AdapHighCmdQueue) { | 285 | if (qid == AdapHighCmdQueue) { |
272 | if (*index >= ADAP_HIGH_CMD_ENTRIES) | 286 | if (*index >= ADAP_HIGH_CMD_ENTRIES) |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 562da90480a1..4ff29d7f5825 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -27,8 +27,11 @@ | |||
27 | * Abstract: Linux Driver entry module for Adaptec RAID Array Controller | 27 | * Abstract: Linux Driver entry module for Adaptec RAID Array Controller |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #define AAC_DRIVER_VERSION "1.1.2-lk2" | 30 | #define AAC_DRIVER_VERSION "1.1-4" |
31 | #define AAC_DRIVER_BUILD_DATE __DATE__ | 31 | #ifndef AAC_DRIVER_BRANCH |
32 | #define AAC_DRIVER_BRANCH "" | ||
33 | #endif | ||
34 | #define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ | ||
32 | #define AAC_DRIVERNAME "aacraid" | 35 | #define AAC_DRIVERNAME "aacraid" |
33 | 36 | ||
34 | #include <linux/compat.h> | 37 | #include <linux/compat.h> |
@@ -58,16 +61,24 @@ | |||
58 | 61 | ||
59 | #include "aacraid.h" | 62 | #include "aacraid.h" |
60 | 63 | ||
64 | #ifdef AAC_DRIVER_BUILD | ||
65 | #define _str(x) #x | ||
66 | #define str(x) _str(x) | ||
67 | #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH | ||
68 | #else | ||
69 | #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE | ||
70 | #endif | ||
61 | 71 | ||
62 | MODULE_AUTHOR("Red Hat Inc and Adaptec"); | 72 | MODULE_AUTHOR("Red Hat Inc and Adaptec"); |
63 | MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, " | 73 | MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, " |
64 | "Adaptec Advanced Raid Products, " | 74 | "Adaptec Advanced Raid Products, " |
65 | "and HP NetRAID-4M SCSI driver"); | 75 | "and HP NetRAID-4M SCSI driver"); |
66 | MODULE_LICENSE("GPL"); | 76 | MODULE_LICENSE("GPL"); |
67 | MODULE_VERSION(AAC_DRIVER_VERSION); | 77 | MODULE_VERSION(AAC_DRIVER_FULL_VERSION); |
68 | 78 | ||
69 | static LIST_HEAD(aac_devices); | 79 | static LIST_HEAD(aac_devices); |
70 | static int aac_cfg_major = -1; | 80 | static int aac_cfg_major = -1; |
81 | char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; | ||
71 | 82 | ||
72 | /* | 83 | /* |
73 | * Because of the way Linux names scsi devices, the order in this table has | 84 | * Because of the way Linux names scsi devices, the order in this table has |
@@ -109,36 +120,39 @@ static struct pci_device_id aac_pci_tbl[] = { | |||
109 | { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */ | 120 | { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */ |
110 | { 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */ | 121 | { 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */ |
111 | { 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */ | 122 | { 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */ |
112 | { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 32 }, /* Themisto Jupiter Platform */ | 123 | { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */ |
113 | { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 32 }, /* Themisto Jupiter Platform */ | 124 | { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 33 }, /* Themisto Jupiter Platform */ |
114 | { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 33 }, /* Callisto Jupiter Platform */ | 125 | { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 33 }, /* Themisto Jupiter Platform */ |
115 | { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 34 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ | 126 | { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 34 }, /* Callisto Jupiter Platform */ |
116 | { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 35 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ | 127 | { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 35 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ |
117 | { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 36 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ | 128 | { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 36 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ |
118 | { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 37 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ | 129 | { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 37 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ |
119 | { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 38 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ | 130 | { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 38 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ |
120 | { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 39 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ | 131 | { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 39 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ |
121 | { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 40 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ | 132 | { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 40 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ |
122 | { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 41 }, /* AAR-2610SA PCI SATA 6ch */ | 133 | { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ |
123 | { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 42 }, /* ASR-2240S (SabreExpress) */ | 134 | { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */ |
124 | { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 43 }, /* ASR-4005SAS */ | 135 | { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */ |
125 | { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 44 }, /* IBM 8i (AvonPark) */ | 136 | { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */ |
126 | { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 44 }, /* IBM 8i (AvonPark Lite) */ | 137 | { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */ |
127 | { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 45 }, /* ASR-4000SAS (BlackBird) */ | 138 | { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */ |
128 | { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 46 }, /* ASR-4800SAS (Marauder-X) */ | 139 | { 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */ |
129 | { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 47 }, /* ASR-4805SAS (Marauder-E) */ | 140 | { 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */ |
130 | { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 48 }, /* ASR-4810SAS (Hurricane */ | 141 | { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */ |
131 | 142 | { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */ | |
132 | { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 49 }, /* Perc 320/DC*/ | 143 | { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */ |
133 | { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 50 }, /* Adaptec 5400S (Mustang)*/ | 144 | { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */ |
134 | { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 51 }, /* Adaptec 5400S (Mustang)*/ | 145 | |
135 | { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 52 }, /* Dell PERC2/QC */ | 146 | { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/ |
136 | { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 53 }, /* HP NetRAID-4M */ | 147 | { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/ |
137 | 148 | { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 54 }, /* Adaptec 5400S (Mustang)*/ | |
138 | { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 54 }, /* Dell Catchall */ | 149 | { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 55 }, /* Dell PERC2/QC */ |
139 | { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 55 }, /* Legend Catchall */ | 150 | { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 56 }, /* HP NetRAID-4M */ |
140 | { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 56 }, /* Adaptec Catch All */ | 151 | |
141 | { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 57 }, /* Adaptec Rocket Catch All */ | 152 | { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 57 }, /* Dell Catchall */ |
153 | { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */ | ||
154 | { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ | ||
155 | { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ | ||
142 | { 0,} | 156 | { 0,} |
143 | }; | 157 | }; |
144 | MODULE_DEVICE_TABLE(pci, aac_pci_tbl); | 158 | MODULE_DEVICE_TABLE(pci, aac_pci_tbl); |
@@ -180,8 +194,9 @@ static struct aac_driver_ident aac_drivers[] = { | |||
180 | { aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */ | 194 | { aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */ |
181 | { aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */ | 195 | { aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */ |
182 | { aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */ | 196 | { aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */ |
183 | { aac_rkt_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */ | 197 | { aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */ |
184 | { aac_rkt_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */ | 198 | { aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */ |
199 | { aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */ | ||
185 | { NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */ | 200 | { NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */ |
186 | { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ | 201 | { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ |
187 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ | 202 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ |
@@ -195,10 +210,12 @@ static struct aac_driver_ident aac_drivers[] = { | |||
195 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ | 210 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ |
196 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */ | 211 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */ |
197 | { aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */ | 212 | { aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */ |
213 | { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */ | ||
214 | { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */ | ||
198 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */ | 215 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */ |
199 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */ | 216 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */ |
200 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */ | 217 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */ |
201 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */ | 218 | { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */ |
202 | 219 | ||
203 | { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ | 220 | { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ |
204 | { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ | 221 | { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ |
@@ -839,11 +856,12 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
839 | 856 | ||
840 | return 0; | 857 | return 0; |
841 | 858 | ||
842 | out_deinit: | 859 | out_deinit: |
843 | kill_proc(aac->thread_pid, SIGKILL, 0); | 860 | kill_proc(aac->thread_pid, SIGKILL, 0); |
844 | wait_for_completion(&aac->aif_completion); | 861 | wait_for_completion(&aac->aif_completion); |
845 | 862 | ||
846 | aac_send_shutdown(aac); | 863 | aac_send_shutdown(aac); |
864 | aac_adapter_disable_int(aac); | ||
847 | fib_map_free(aac); | 865 | fib_map_free(aac); |
848 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); | 866 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); |
849 | kfree(aac->queues); | 867 | kfree(aac->queues); |
@@ -860,6 +878,13 @@ out_deinit: | |||
860 | return error; | 878 | return error; |
861 | } | 879 | } |
862 | 880 | ||
881 | static void aac_shutdown(struct pci_dev *dev) | ||
882 | { | ||
883 | struct Scsi_Host *shost = pci_get_drvdata(dev); | ||
884 | struct aac_dev *aac = (struct aac_dev *)shost->hostdata; | ||
885 | aac_send_shutdown(aac); | ||
886 | } | ||
887 | |||
863 | static void __devexit aac_remove_one(struct pci_dev *pdev) | 888 | static void __devexit aac_remove_one(struct pci_dev *pdev) |
864 | { | 889 | { |
865 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 890 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
@@ -871,6 +896,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) | |||
871 | wait_for_completion(&aac->aif_completion); | 896 | wait_for_completion(&aac->aif_completion); |
872 | 897 | ||
873 | aac_send_shutdown(aac); | 898 | aac_send_shutdown(aac); |
899 | aac_adapter_disable_int(aac); | ||
874 | fib_map_free(aac); | 900 | fib_map_free(aac); |
875 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, | 901 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, |
876 | aac->comm_phys); | 902 | aac->comm_phys); |
@@ -891,14 +917,15 @@ static struct pci_driver aac_pci_driver = { | |||
891 | .id_table = aac_pci_tbl, | 917 | .id_table = aac_pci_tbl, |
892 | .probe = aac_probe_one, | 918 | .probe = aac_probe_one, |
893 | .remove = __devexit_p(aac_remove_one), | 919 | .remove = __devexit_p(aac_remove_one), |
920 | .shutdown = aac_shutdown, | ||
894 | }; | 921 | }; |
895 | 922 | ||
896 | static int __init aac_init(void) | 923 | static int __init aac_init(void) |
897 | { | 924 | { |
898 | int error; | 925 | int error; |
899 | 926 | ||
900 | printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n", | 927 | printk(KERN_INFO "Adaptec %s driver (%s)\n", |
901 | AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE); | 928 | AAC_DRIVERNAME, aac_driver_version); |
902 | 929 | ||
903 | error = pci_module_init(&aac_pci_driver); | 930 | error = pci_module_init(&aac_pci_driver); |
904 | if (error) | 931 | if (error) |
@@ -909,6 +936,7 @@ static int __init aac_init(void) | |||
909 | printk(KERN_WARNING | 936 | printk(KERN_WARNING |
910 | "aacraid: unable to register \"aac\" device.\n"); | 937 | "aacraid: unable to register \"aac\" device.\n"); |
911 | } | 938 | } |
939 | |||
912 | return 0; | 940 | return 0; |
913 | } | 941 | } |
914 | 942 | ||
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 7d68b7825137..557287a0b80b 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c | |||
@@ -88,6 +88,16 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * aac_rkt_disable_interrupt - Disable interrupts | ||
92 | * @dev: Adapter | ||
93 | */ | ||
94 | |||
95 | static void aac_rkt_disable_interrupt(struct aac_dev *dev) | ||
96 | { | ||
97 | rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); | ||
98 | } | ||
99 | |||
100 | /** | ||
91 | * rkt_sync_cmd - send a command and wait | 101 | * rkt_sync_cmd - send a command and wait |
92 | * @dev: Adapter | 102 | * @dev: Adapter |
93 | * @command: Command to execute | 103 | * @command: Command to execute |
@@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev) | |||
412 | * Fill in the function dispatch table. | 422 | * Fill in the function dispatch table. |
413 | */ | 423 | */ |
414 | dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; | 424 | dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; |
425 | dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt; | ||
415 | dev->a_ops.adapter_notify = aac_rkt_notify_adapter; | 426 | dev->a_ops.adapter_notify = aac_rkt_notify_adapter; |
416 | dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; | 427 | dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; |
417 | dev->a_ops.adapter_check_health = aac_rkt_check_health; | 428 | dev->a_ops.adapter_check_health = aac_rkt_check_health; |
418 | 429 | ||
430 | /* | ||
431 | * First clear out all interrupts. Then enable the one's that we | ||
432 | * can handle. | ||
433 | */ | ||
434 | rkt_writeb(dev, MUnit.OIMR, 0xff); | ||
435 | rkt_writel(dev, MUnit.ODR, 0xffffffff); | ||
436 | rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); | ||
437 | |||
419 | if (aac_init_adapter(dev) == NULL) | 438 | if (aac_init_adapter(dev) == NULL) |
420 | goto error_irq; | 439 | goto error_irq; |
421 | /* | 440 | /* |
@@ -438,6 +457,7 @@ error_kfree: | |||
438 | kfree(dev->queues); | 457 | kfree(dev->queues); |
439 | 458 | ||
440 | error_irq: | 459 | error_irq: |
460 | rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); | ||
441 | free_irq(dev->scsi_host_ptr->irq, (void *)dev); | 461 | free_irq(dev->scsi_host_ptr->irq, (void *)dev); |
442 | 462 | ||
443 | error_iounmap: | 463 | error_iounmap: |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 1ff25f49fada..a8459faf87ca 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -88,6 +88,16 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * aac_rx_disable_interrupt - Disable interrupts | ||
92 | * @dev: Adapter | ||
93 | */ | ||
94 | |||
95 | static void aac_rx_disable_interrupt(struct aac_dev *dev) | ||
96 | { | ||
97 | rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); | ||
98 | } | ||
99 | |||
100 | /** | ||
91 | * rx_sync_cmd - send a command and wait | 101 | * rx_sync_cmd - send a command and wait |
92 | * @dev: Adapter | 102 | * @dev: Adapter |
93 | * @command: Command to execute | 103 | * @command: Command to execute |
@@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev) | |||
412 | * Fill in the function dispatch table. | 422 | * Fill in the function dispatch table. |
413 | */ | 423 | */ |
414 | dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; | 424 | dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; |
425 | dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; | ||
415 | dev->a_ops.adapter_notify = aac_rx_notify_adapter; | 426 | dev->a_ops.adapter_notify = aac_rx_notify_adapter; |
416 | dev->a_ops.adapter_sync_cmd = rx_sync_cmd; | 427 | dev->a_ops.adapter_sync_cmd = rx_sync_cmd; |
417 | dev->a_ops.adapter_check_health = aac_rx_check_health; | 428 | dev->a_ops.adapter_check_health = aac_rx_check_health; |
418 | 429 | ||
430 | /* | ||
431 | * First clear out all interrupts. Then enable the one's that we | ||
432 | * can handle. | ||
433 | */ | ||
434 | rx_writeb(dev, MUnit.OIMR, 0xff); | ||
435 | rx_writel(dev, MUnit.ODR, 0xffffffff); | ||
436 | rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); | ||
437 | |||
419 | if (aac_init_adapter(dev) == NULL) | 438 | if (aac_init_adapter(dev) == NULL) |
420 | goto error_irq; | 439 | goto error_irq; |
421 | /* | 440 | /* |
@@ -438,6 +457,7 @@ error_kfree: | |||
438 | kfree(dev->queues); | 457 | kfree(dev->queues); |
439 | 458 | ||
440 | error_irq: | 459 | error_irq: |
460 | rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); | ||
441 | free_irq(dev->scsi_host_ptr->irq, (void *)dev); | 461 | free_irq(dev->scsi_host_ptr->irq, (void *)dev); |
442 | 462 | ||
443 | error_iounmap: | 463 | error_iounmap: |
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 0680249ab861..3900abc5850d 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c | |||
@@ -82,6 +82,16 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * aac_sa_disable_interrupt - disable interrupt | ||
86 | * @dev: Which adapter to enable. | ||
87 | */ | ||
88 | |||
89 | static void aac_sa_disable_interrupt (struct aac_dev *dev) | ||
90 | { | ||
91 | sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); | ||
92 | } | ||
93 | |||
94 | /** | ||
85 | * aac_sa_notify_adapter - handle adapter notification | 95 | * aac_sa_notify_adapter - handle adapter notification |
86 | * @dev: Adapter that notification is for | 96 | * @dev: Adapter that notification is for |
87 | * @event: Event to notidy | 97 | * @event: Event to notidy |
@@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, | |||
214 | 224 | ||
215 | static void aac_sa_interrupt_adapter (struct aac_dev *dev) | 225 | static void aac_sa_interrupt_adapter (struct aac_dev *dev) |
216 | { | 226 | { |
217 | u32 ret; | ||
218 | sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, | 227 | sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, |
219 | &ret, NULL, NULL, NULL, NULL); | 228 | NULL, NULL, NULL, NULL, NULL); |
220 | } | 229 | } |
221 | 230 | ||
222 | /** | 231 | /** |
@@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev) | |||
352 | */ | 361 | */ |
353 | 362 | ||
354 | dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; | 363 | dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; |
364 | dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; | ||
355 | dev->a_ops.adapter_notify = aac_sa_notify_adapter; | 365 | dev->a_ops.adapter_notify = aac_sa_notify_adapter; |
356 | dev->a_ops.adapter_sync_cmd = sa_sync_cmd; | 366 | dev->a_ops.adapter_sync_cmd = sa_sync_cmd; |
357 | dev->a_ops.adapter_check_health = aac_sa_check_health; | 367 | dev->a_ops.adapter_check_health = aac_sa_check_health; |
358 | 368 | ||
369 | /* | ||
370 | * First clear out all interrupts. Then enable the one's that | ||
371 | * we can handle. | ||
372 | */ | ||
373 | sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); | ||
374 | sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | | ||
375 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); | ||
359 | 376 | ||
360 | if(aac_init_adapter(dev) == NULL) | 377 | if(aac_init_adapter(dev) == NULL) |
361 | goto error_irq; | 378 | goto error_irq; |
@@ -381,6 +398,7 @@ error_kfree: | |||
381 | kfree(dev->queues); | 398 | kfree(dev->queues); |
382 | 399 | ||
383 | error_irq: | 400 | error_irq: |
401 | sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); | ||
384 | free_irq(dev->scsi_host_ptr->irq, (void *)dev); | 402 | free_irq(dev->scsi_host_ptr->irq, (void *)dev); |
385 | 403 | ||
386 | error_iounmap: | 404 | error_iounmap: |
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 0fb93363eb22..37ec5411e325 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -9200,8 +9200,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s) | |||
9200 | (unsigned) s->serial_number, s->retries, s->allowed); | 9200 | (unsigned) s->serial_number, s->retries, s->allowed); |
9201 | 9201 | ||
9202 | printk( | 9202 | printk( |
9203 | " timeout_per_command %d, timeout_total %d, timeout %d\n", | 9203 | " timeout_per_command %d\n", |
9204 | s->timeout_per_command, s->timeout_total, s->timeout); | 9204 | s->timeout_per_command); |
9205 | 9205 | ||
9206 | printk( | 9206 | printk( |
9207 | " scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", | 9207 | " scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", |
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index c2523a30a7f5..69ed77fcb71f 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx | |||
@@ -5,6 +5,7 @@ | |||
5 | config SCSI_AIC79XX | 5 | config SCSI_AIC79XX |
6 | tristate "Adaptec AIC79xx U320 support" | 6 | tristate "Adaptec AIC79xx U320 support" |
7 | depends on PCI && SCSI | 7 | depends on PCI && SCSI |
8 | select SCSI_SPI_ATTRS | ||
8 | help | 9 | help |
9 | This driver supports all of Adaptec's Ultra 320 PCI-X | 10 | This driver supports all of Adaptec's Ultra 320 PCI-X |
10 | based SCSI controllers. | 11 | based SCSI controllers. |
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index 00f3bd1e181e..527efd36f5c1 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c | |||
@@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id) | |||
126 | int | 126 | int |
127 | aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) | 127 | aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) |
128 | { | 128 | { |
129 | u_long l; | ||
130 | int error; | 129 | int error; |
131 | int have_seeprom; | 130 | int have_seeprom; |
132 | u_int hostconf; | 131 | u_int hostconf; |
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index fd4b2f3eb0c2..653fb0b42aea 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h | |||
@@ -1247,9 +1247,6 @@ struct ahd_softc { | |||
1247 | uint16_t user_tagenable;/* Tagged Queuing allowed */ | 1247 | uint16_t user_tagenable;/* Tagged Queuing allowed */ |
1248 | }; | 1248 | }; |
1249 | 1249 | ||
1250 | TAILQ_HEAD(ahd_softc_tailq, ahd_softc); | ||
1251 | extern struct ahd_softc_tailq ahd_tailq; | ||
1252 | |||
1253 | /*************************** IO Cell Configuration ****************************/ | 1250 | /*************************** IO Cell Configuration ****************************/ |
1254 | #define AHD_PRECOMP_SLEW_INDEX \ | 1251 | #define AHD_PRECOMP_SLEW_INDEX \ |
1255 | (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0) | 1252 | (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0) |
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd, | |||
1374 | void ahd_pause_and_flushwork(struct ahd_softc *ahd); | 1371 | void ahd_pause_and_flushwork(struct ahd_softc *ahd); |
1375 | int ahd_suspend(struct ahd_softc *ahd); | 1372 | int ahd_suspend(struct ahd_softc *ahd); |
1376 | int ahd_resume(struct ahd_softc *ahd); | 1373 | int ahd_resume(struct ahd_softc *ahd); |
1377 | void ahd_softc_insert(struct ahd_softc *); | ||
1378 | struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd); | ||
1379 | void ahd_set_unit(struct ahd_softc *, int); | 1374 | void ahd_set_unit(struct ahd_softc *, int); |
1380 | void ahd_set_name(struct ahd_softc *, char *); | 1375 | void ahd_set_name(struct ahd_softc *, char *); |
1381 | struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); | 1376 | struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); |
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb); | |||
1524 | void ahd_print_devinfo(struct ahd_softc *ahd, | 1519 | void ahd_print_devinfo(struct ahd_softc *ahd, |
1525 | struct ahd_devinfo *devinfo); | 1520 | struct ahd_devinfo *devinfo); |
1526 | void ahd_dump_sglist(struct scb *scb); | 1521 | void ahd_dump_sglist(struct scb *scb); |
1527 | void ahd_dump_all_cards_state(void); | ||
1528 | void ahd_dump_card_state(struct ahd_softc *ahd); | 1522 | void ahd_dump_card_state(struct ahd_softc *ahd); |
1529 | int ahd_print_register(ahd_reg_parse_entry_t *table, | 1523 | int ahd_print_register(ahd_reg_parse_entry_t *table, |
1530 | u_int num_entries, | 1524 | u_int num_entries, |
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 137fb1a37dd1..4e8f00df978d 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c | |||
@@ -52,8 +52,6 @@ | |||
52 | #include <dev/aic7xxx/aicasm/aicasm_insformat.h> | 52 | #include <dev/aic7xxx/aicasm/aicasm_insformat.h> |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /******************************** Globals *************************************/ | ||
56 | struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq); | ||
57 | 55 | ||
58 | /***************************** Lookup Tables **********************************/ | 56 | /***************************** Lookup Tables **********************************/ |
59 | char *ahd_chip_names[] = | 57 | char *ahd_chip_names[] = |
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd) | |||
5180 | } | 5178 | } |
5181 | 5179 | ||
5182 | void | 5180 | void |
5183 | ahd_softc_insert(struct ahd_softc *ahd) | ||
5184 | { | ||
5185 | struct ahd_softc *list_ahd; | ||
5186 | |||
5187 | #if AHD_PCI_CONFIG > 0 | ||
5188 | /* | ||
5189 | * Second Function PCI devices need to inherit some | ||
5190 | * settings from function 0. | ||
5191 | */ | ||
5192 | if ((ahd->features & AHD_MULTI_FUNC) != 0) { | ||
5193 | TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { | ||
5194 | ahd_dev_softc_t list_pci; | ||
5195 | ahd_dev_softc_t pci; | ||
5196 | |||
5197 | list_pci = list_ahd->dev_softc; | ||
5198 | pci = ahd->dev_softc; | ||
5199 | if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci) | ||
5200 | && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) { | ||
5201 | struct ahd_softc *master; | ||
5202 | struct ahd_softc *slave; | ||
5203 | |||
5204 | if (ahd_get_pci_function(list_pci) == 0) { | ||
5205 | master = list_ahd; | ||
5206 | slave = ahd; | ||
5207 | } else { | ||
5208 | master = ahd; | ||
5209 | slave = list_ahd; | ||
5210 | } | ||
5211 | slave->flags &= ~AHD_BIOS_ENABLED; | ||
5212 | slave->flags |= | ||
5213 | master->flags & AHD_BIOS_ENABLED; | ||
5214 | break; | ||
5215 | } | ||
5216 | } | ||
5217 | } | ||
5218 | #endif | ||
5219 | |||
5220 | /* | ||
5221 | * Insertion sort into our list of softcs. | ||
5222 | */ | ||
5223 | list_ahd = TAILQ_FIRST(&ahd_tailq); | ||
5224 | while (list_ahd != NULL | ||
5225 | && ahd_softc_comp(ahd, list_ahd) <= 0) | ||
5226 | list_ahd = TAILQ_NEXT(list_ahd, links); | ||
5227 | if (list_ahd != NULL) | ||
5228 | TAILQ_INSERT_BEFORE(list_ahd, ahd, links); | ||
5229 | else | ||
5230 | TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links); | ||
5231 | ahd->init_level++; | ||
5232 | } | ||
5233 | |||
5234 | /* | ||
5235 | * Verify that the passed in softc pointer is for a | ||
5236 | * controller that is still configured. | ||
5237 | */ | ||
5238 | struct ahd_softc * | ||
5239 | ahd_find_softc(struct ahd_softc *ahd) | ||
5240 | { | ||
5241 | struct ahd_softc *list_ahd; | ||
5242 | |||
5243 | TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { | ||
5244 | if (list_ahd == ahd) | ||
5245 | return (ahd); | ||
5246 | } | ||
5247 | return (NULL); | ||
5248 | } | ||
5249 | |||
5250 | void | ||
5251 | ahd_set_unit(struct ahd_softc *ahd, int unit) | 5181 | ahd_set_unit(struct ahd_softc *ahd, int unit) |
5252 | { | 5182 | { |
5253 | ahd->unit = unit; | 5183 | ahd->unit = unit; |
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
7902 | static void | 7832 | static void |
7903 | ahd_reset_poll(void *arg) | 7833 | ahd_reset_poll(void *arg) |
7904 | { | 7834 | { |
7905 | struct ahd_softc *ahd; | 7835 | struct ahd_softc *ahd = arg; |
7906 | u_int scsiseq1; | 7836 | u_int scsiseq1; |
7907 | u_long l; | ||
7908 | u_long s; | 7837 | u_long s; |
7909 | 7838 | ||
7910 | ahd_list_lock(&l); | ||
7911 | ahd = ahd_find_softc((struct ahd_softc *)arg); | ||
7912 | if (ahd == NULL) { | ||
7913 | printf("ahd_reset_poll: Instance %p no longer exists\n", arg); | ||
7914 | ahd_list_unlock(&l); | ||
7915 | return; | ||
7916 | } | ||
7917 | ahd_lock(ahd, &s); | 7839 | ahd_lock(ahd, &s); |
7918 | ahd_pause(ahd); | 7840 | ahd_pause(ahd); |
7919 | ahd_update_modes(ahd); | 7841 | ahd_update_modes(ahd); |
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg) | |||
7924 | ahd_reset_poll, ahd); | 7846 | ahd_reset_poll, ahd); |
7925 | ahd_unpause(ahd); | 7847 | ahd_unpause(ahd); |
7926 | ahd_unlock(ahd, &s); | 7848 | ahd_unlock(ahd, &s); |
7927 | ahd_list_unlock(&l); | ||
7928 | return; | 7849 | return; |
7929 | } | 7850 | } |
7930 | 7851 | ||
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg) | |||
7936 | ahd->flags &= ~AHD_RESET_POLL_ACTIVE; | 7857 | ahd->flags &= ~AHD_RESET_POLL_ACTIVE; |
7937 | ahd_unlock(ahd, &s); | 7858 | ahd_unlock(ahd, &s); |
7938 | ahd_release_simq(ahd); | 7859 | ahd_release_simq(ahd); |
7939 | ahd_list_unlock(&l); | ||
7940 | } | 7860 | } |
7941 | 7861 | ||
7942 | /**************************** Statistics Processing ***************************/ | 7862 | /**************************** Statistics Processing ***************************/ |
7943 | static void | 7863 | static void |
7944 | ahd_stat_timer(void *arg) | 7864 | ahd_stat_timer(void *arg) |
7945 | { | 7865 | { |
7946 | struct ahd_softc *ahd; | 7866 | struct ahd_softc *ahd = arg; |
7947 | u_long l; | ||
7948 | u_long s; | 7867 | u_long s; |
7949 | int enint_coal; | 7868 | int enint_coal; |
7950 | 7869 | ||
7951 | ahd_list_lock(&l); | ||
7952 | ahd = ahd_find_softc((struct ahd_softc *)arg); | ||
7953 | if (ahd == NULL) { | ||
7954 | printf("ahd_stat_timer: Instance %p no longer exists\n", arg); | ||
7955 | ahd_list_unlock(&l); | ||
7956 | return; | ||
7957 | } | ||
7958 | ahd_lock(ahd, &s); | 7870 | ahd_lock(ahd, &s); |
7959 | 7871 | ||
7960 | enint_coal = ahd->hs_mailbox & ENINT_COALESCE; | 7872 | enint_coal = ahd->hs_mailbox & ENINT_COALESCE; |
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg) | |||
7981 | ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, | 7893 | ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, |
7982 | ahd_stat_timer, ahd); | 7894 | ahd_stat_timer, ahd); |
7983 | ahd_unlock(ahd, &s); | 7895 | ahd_unlock(ahd, &s); |
7984 | ahd_list_unlock(&l); | ||
7985 | } | 7896 | } |
7986 | 7897 | ||
7987 | /****************************** Status Processing *****************************/ | 7898 | /****************************** Status Processing *****************************/ |
@@ -8745,16 +8656,6 @@ sized: | |||
8745 | return (last_probe); | 8656 | return (last_probe); |
8746 | } | 8657 | } |
8747 | 8658 | ||
8748 | void | ||
8749 | ahd_dump_all_cards_state(void) | ||
8750 | { | ||
8751 | struct ahd_softc *list_ahd; | ||
8752 | |||
8753 | TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { | ||
8754 | ahd_dump_card_state(list_ahd); | ||
8755 | } | ||
8756 | } | ||
8757 | |||
8758 | int | 8659 | int |
8759 | ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, | 8660 | ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, |
8760 | const char *name, u_int address, u_int value, | 8661 | const char *name, u_int address, u_int value, |
@@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ahd) | |||
9039 | ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF); | 8940 | ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF); |
9040 | } | 8941 | } |
9041 | printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); | 8942 | printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); |
9042 | ahd_platform_dump_card_state(ahd); | ||
9043 | ahd_restore_modes(ahd, saved_modes); | 8943 | ahd_restore_modes(ahd, saved_modes); |
9044 | if (paused == 0) | 8944 | if (paused == 0) |
9045 | ahd_unpause(ahd); | 8945 | ahd_unpause(ahd); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 329cb2331339..3feb739cd554 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include "aic79xx_inline.h" | 46 | #include "aic79xx_inline.h" |
47 | #include <scsi/scsicam.h> | 47 | #include <scsi/scsicam.h> |
48 | 48 | ||
49 | static struct scsi_transport_template *ahd_linux_transport_template = NULL; | ||
50 | |||
49 | /* | 51 | /* |
50 | * Include aiclib.c as part of our | 52 | * Include aiclib.c as part of our |
51 | * "module dependencies are hard" work around. | 53 | * "module dependencies are hard" work around. |
@@ -53,25 +55,11 @@ | |||
53 | #include "aiclib.c" | 55 | #include "aiclib.c" |
54 | 56 | ||
55 | #include <linux/init.h> /* __setup */ | 57 | #include <linux/init.h> /* __setup */ |
56 | |||
57 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
58 | #include "sd.h" /* For geometry detection */ | ||
59 | #endif | ||
60 | |||
61 | #include <linux/mm.h> /* For fetching system memory size */ | 58 | #include <linux/mm.h> /* For fetching system memory size */ |
59 | #include <linux/blkdev.h> /* For block_size() */ | ||
62 | #include <linux/delay.h> /* For ssleep/msleep */ | 60 | #include <linux/delay.h> /* For ssleep/msleep */ |
63 | 61 | ||
64 | /* | 62 | /* |
65 | * Lock protecting manipulation of the ahd softc list. | ||
66 | */ | ||
67 | spinlock_t ahd_list_spinlock; | ||
68 | |||
69 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
70 | /* For dynamic sglist size calculation. */ | ||
71 | u_int ahd_linux_nseg; | ||
72 | #endif | ||
73 | |||
74 | /* | ||
75 | * Bucket size for counting good commands in between bad ones. | 63 | * Bucket size for counting good commands in between bad ones. |
76 | */ | 64 | */ |
77 | #define AHD_LINUX_ERR_THRESH 1000 | 65 | #define AHD_LINUX_ERR_THRESH 1000 |
@@ -188,71 +176,6 @@ static adapter_tag_info_t aic79xx_tag_info[] = | |||
188 | }; | 176 | }; |
189 | 177 | ||
190 | /* | 178 | /* |
191 | * By default, read streaming is disabled. In theory, | ||
192 | * read streaming should enhance performance, but early | ||
193 | * U320 drive firmware actually performs slower with | ||
194 | * read streaming enabled. | ||
195 | */ | ||
196 | #ifdef CONFIG_AIC79XX_ENABLE_RD_STRM | ||
197 | #define AIC79XX_CONFIGED_RD_STRM 0xFFFF | ||
198 | #else | ||
199 | #define AIC79XX_CONFIGED_RD_STRM 0 | ||
200 | #endif | ||
201 | |||
202 | static uint16_t aic79xx_rd_strm_info[] = | ||
203 | { | ||
204 | AIC79XX_CONFIGED_RD_STRM, | ||
205 | AIC79XX_CONFIGED_RD_STRM, | ||
206 | AIC79XX_CONFIGED_RD_STRM, | ||
207 | AIC79XX_CONFIGED_RD_STRM, | ||
208 | AIC79XX_CONFIGED_RD_STRM, | ||
209 | AIC79XX_CONFIGED_RD_STRM, | ||
210 | AIC79XX_CONFIGED_RD_STRM, | ||
211 | AIC79XX_CONFIGED_RD_STRM, | ||
212 | AIC79XX_CONFIGED_RD_STRM, | ||
213 | AIC79XX_CONFIGED_RD_STRM, | ||
214 | AIC79XX_CONFIGED_RD_STRM, | ||
215 | AIC79XX_CONFIGED_RD_STRM, | ||
216 | AIC79XX_CONFIGED_RD_STRM, | ||
217 | AIC79XX_CONFIGED_RD_STRM, | ||
218 | AIC79XX_CONFIGED_RD_STRM, | ||
219 | AIC79XX_CONFIGED_RD_STRM | ||
220 | }; | ||
221 | |||
222 | /* | ||
223 | * DV option: | ||
224 | * | ||
225 | * positive value = DV Enabled | ||
226 | * zero = DV Disabled | ||
227 | * negative value = DV Default for adapter type/seeprom | ||
228 | */ | ||
229 | #ifdef CONFIG_AIC79XX_DV_SETTING | ||
230 | #define AIC79XX_CONFIGED_DV CONFIG_AIC79XX_DV_SETTING | ||
231 | #else | ||
232 | #define AIC79XX_CONFIGED_DV -1 | ||
233 | #endif | ||
234 | |||
235 | static int8_t aic79xx_dv_settings[] = | ||
236 | { | ||
237 | AIC79XX_CONFIGED_DV, | ||
238 | AIC79XX_CONFIGED_DV, | ||
239 | AIC79XX_CONFIGED_DV, | ||
240 | AIC79XX_CONFIGED_DV, | ||
241 | AIC79XX_CONFIGED_DV, | ||
242 | AIC79XX_CONFIGED_DV, | ||
243 | AIC79XX_CONFIGED_DV, | ||
244 | AIC79XX_CONFIGED_DV, | ||
245 | AIC79XX_CONFIGED_DV, | ||
246 | AIC79XX_CONFIGED_DV, | ||
247 | AIC79XX_CONFIGED_DV, | ||
248 | AIC79XX_CONFIGED_DV, | ||
249 | AIC79XX_CONFIGED_DV, | ||
250 | AIC79XX_CONFIGED_DV, | ||
251 | AIC79XX_CONFIGED_DV, | ||
252 | AIC79XX_CONFIGED_DV | ||
253 | }; | ||
254 | |||
255 | /* | ||
256 | * The I/O cell on the chip is very configurable in respect to its analog | 179 | * The I/O cell on the chip is very configurable in respect to its analog |
257 | * characteristics. Set the defaults here; they can be overriden with | 180 | * characteristics. Set the defaults here; they can be overriden with |
258 | * the proper insmod parameters. | 181 | * the proper insmod parameters. |
@@ -375,13 +298,6 @@ static uint32_t aic79xx_pci_parity = ~0; | |||
375 | uint32_t aic79xx_allow_memio = ~0; | 298 | uint32_t aic79xx_allow_memio = ~0; |
376 | 299 | ||
377 | /* | 300 | /* |
378 | * aic79xx_detect() has been run, so register all device arrivals | ||
379 | * immediately with the system rather than deferring to the sorted | ||
380 | * attachment performed by aic79xx_detect(). | ||
381 | */ | ||
382 | int aic79xx_detect_complete; | ||
383 | |||
384 | /* | ||
385 | * So that we can set how long each device is given as a selection timeout. | 301 | * So that we can set how long each device is given as a selection timeout. |
386 | * The table of values goes like this: | 302 | * The table of values goes like this: |
387 | * 0 - 256ms | 303 | * 0 - 256ms |
@@ -412,7 +328,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>"); | |||
412 | MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); | 328 | MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); |
413 | MODULE_LICENSE("Dual BSD/GPL"); | 329 | MODULE_LICENSE("Dual BSD/GPL"); |
414 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); | 330 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); |
415 | module_param(aic79xx, charp, 0); | 331 | module_param(aic79xx, charp, 0444); |
416 | MODULE_PARM_DESC(aic79xx, | 332 | MODULE_PARM_DESC(aic79xx, |
417 | "period delimited, options string.\n" | 333 | "period delimited, options string.\n" |
418 | " verbose Enable verbose/diagnostic logging\n" | 334 | " verbose Enable verbose/diagnostic logging\n" |
@@ -427,8 +343,6 @@ MODULE_PARM_DESC(aic79xx, | |||
427 | " reverse_scan Sort PCI devices highest Bus/Slot to lowest\n" | 343 | " reverse_scan Sort PCI devices highest Bus/Slot to lowest\n" |
428 | " tag_info:<tag_str> Set per-target tag depth\n" | 344 | " tag_info:<tag_str> Set per-target tag depth\n" |
429 | " global_tag_depth:<int> Global tag depth for all targets on all buses\n" | 345 | " global_tag_depth:<int> Global tag depth for all targets on all buses\n" |
430 | " rd_strm:<rd_strm_masks> Set per-target read streaming setting.\n" | ||
431 | " dv:<dv_settings> Set per-controller Domain Validation Setting.\n" | ||
432 | " slewrate:<slewrate_list>Set the signal slew rate (0-15).\n" | 346 | " slewrate:<slewrate_list>Set the signal slew rate (0-15).\n" |
433 | " precomp:<pcomp_list> Set the signal precompensation (0-7).\n" | 347 | " precomp:<pcomp_list> Set the signal precompensation (0-7).\n" |
434 | " amplitude:<int> Set the signal amplitude (0-7).\n" | 348 | " amplitude:<int> Set the signal amplitude (0-7).\n" |
@@ -441,249 +355,37 @@ MODULE_PARM_DESC(aic79xx, | |||
441 | " Shorten the selection timeout to 128ms\n" | 355 | " Shorten the selection timeout to 128ms\n" |
442 | "\n" | 356 | "\n" |
443 | " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" | 357 | " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" |
444 | "\n" | 358 | "\n"); |
445 | " Sample /etc/modprobe.conf line:\n" | ||
446 | " Change Read Streaming for Controller's 2 and 3\n" | ||
447 | "\n" | ||
448 | " options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'"); | ||
449 | 359 | ||
450 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, | 360 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, |
451 | struct ahd_linux_device *, | 361 | struct scsi_device *, |
452 | struct scb *); | 362 | struct scb *); |
453 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, | 363 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, |
454 | Scsi_Cmnd *cmd); | 364 | struct scsi_cmnd *cmd); |
455 | static void ahd_linux_filter_inquiry(struct ahd_softc *ahd, | ||
456 | struct ahd_devinfo *devinfo); | ||
457 | static void ahd_linux_dev_timed_unfreeze(u_long arg); | ||
458 | static void ahd_linux_sem_timeout(u_long arg); | 365 | static void ahd_linux_sem_timeout(u_long arg); |
366 | static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); | ||
459 | static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); | 367 | static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); |
460 | static void ahd_linux_size_nseg(void); | ||
461 | static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd); | ||
462 | static void ahd_linux_start_dv(struct ahd_softc *ahd); | ||
463 | static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); | ||
464 | static int ahd_linux_dv_thread(void *data); | ||
465 | static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd); | ||
466 | static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target); | ||
467 | static void ahd_linux_dv_transition(struct ahd_softc *ahd, | ||
468 | struct scsi_cmnd *cmd, | ||
469 | struct ahd_devinfo *devinfo, | ||
470 | struct ahd_linux_target *targ); | ||
471 | static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, | ||
472 | struct scsi_cmnd *cmd, | ||
473 | struct ahd_devinfo *devinfo); | ||
474 | static void ahd_linux_dv_inq(struct ahd_softc *ahd, | ||
475 | struct scsi_cmnd *cmd, | ||
476 | struct ahd_devinfo *devinfo, | ||
477 | struct ahd_linux_target *targ, | ||
478 | u_int request_length); | ||
479 | static void ahd_linux_dv_tur(struct ahd_softc *ahd, | ||
480 | struct scsi_cmnd *cmd, | ||
481 | struct ahd_devinfo *devinfo); | ||
482 | static void ahd_linux_dv_rebd(struct ahd_softc *ahd, | ||
483 | struct scsi_cmnd *cmd, | ||
484 | struct ahd_devinfo *devinfo, | ||
485 | struct ahd_linux_target *targ); | ||
486 | static void ahd_linux_dv_web(struct ahd_softc *ahd, | ||
487 | struct scsi_cmnd *cmd, | ||
488 | struct ahd_devinfo *devinfo, | ||
489 | struct ahd_linux_target *targ); | ||
490 | static void ahd_linux_dv_reb(struct ahd_softc *ahd, | ||
491 | struct scsi_cmnd *cmd, | ||
492 | struct ahd_devinfo *devinfo, | ||
493 | struct ahd_linux_target *targ); | ||
494 | static void ahd_linux_dv_su(struct ahd_softc *ahd, | ||
495 | struct scsi_cmnd *cmd, | ||
496 | struct ahd_devinfo *devinfo, | ||
497 | struct ahd_linux_target *targ); | ||
498 | static int ahd_linux_fallback(struct ahd_softc *ahd, | ||
499 | struct ahd_devinfo *devinfo); | ||
500 | static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, | ||
501 | struct ahd_devinfo *devinfo); | ||
502 | static void ahd_linux_dv_complete(Scsi_Cmnd *cmd); | ||
503 | static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ); | ||
504 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, | 368 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, |
505 | struct ahd_devinfo *devinfo); | 369 | struct ahd_devinfo *devinfo); |
506 | static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd); | 370 | static void ahd_linux_device_queue_depth(struct scsi_device *); |
507 | static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd); | 371 | static int ahd_linux_run_command(struct ahd_softc*, |
508 | static void ahd_linux_device_queue_depth(struct ahd_softc *ahd, | 372 | struct ahd_linux_device *, |
509 | struct ahd_linux_device *dev); | 373 | struct scsi_cmnd *); |
510 | static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*, | ||
511 | u_int, u_int); | ||
512 | static void ahd_linux_free_target(struct ahd_softc*, | ||
513 | struct ahd_linux_target*); | ||
514 | static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*, | ||
515 | struct ahd_linux_target*, | ||
516 | u_int); | ||
517 | static void ahd_linux_free_device(struct ahd_softc*, | ||
518 | struct ahd_linux_device*); | ||
519 | static void ahd_linux_run_device_queue(struct ahd_softc*, | ||
520 | struct ahd_linux_device*); | ||
521 | static void ahd_linux_setup_tag_info_global(char *p); | 374 | static void ahd_linux_setup_tag_info_global(char *p); |
522 | static aic_option_callback_t ahd_linux_setup_tag_info; | 375 | static aic_option_callback_t ahd_linux_setup_tag_info; |
523 | static aic_option_callback_t ahd_linux_setup_rd_strm_info; | ||
524 | static aic_option_callback_t ahd_linux_setup_dv; | ||
525 | static aic_option_callback_t ahd_linux_setup_iocell_info; | 376 | static aic_option_callback_t ahd_linux_setup_iocell_info; |
526 | static int ahd_linux_next_unit(void); | 377 | static int aic79xx_setup(char *c); |
527 | static void ahd_runq_tasklet(unsigned long data); | ||
528 | static int aic79xx_setup(char *c); | ||
529 | |||
530 | /****************************** Inlines ***************************************/ | ||
531 | static __inline void ahd_schedule_completeq(struct ahd_softc *ahd); | ||
532 | static __inline void ahd_schedule_runq(struct ahd_softc *ahd); | ||
533 | static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd); | ||
534 | static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd); | ||
535 | static __inline struct ahd_linux_device* | ||
536 | ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, | ||
537 | u_int target, u_int lun, int alloc); | ||
538 | static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd); | ||
539 | static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, | ||
540 | struct ahd_linux_device *dev); | ||
541 | static __inline struct ahd_linux_device * | ||
542 | ahd_linux_next_device_to_run(struct ahd_softc *ahd); | ||
543 | static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd); | ||
544 | static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); | ||
545 | |||
546 | static __inline void | ||
547 | ahd_schedule_completeq(struct ahd_softc *ahd) | ||
548 | { | ||
549 | if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) { | ||
550 | ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER; | ||
551 | ahd->platform_data->completeq_timer.expires = jiffies; | ||
552 | add_timer(&ahd->platform_data->completeq_timer); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * Must be called with our lock held. | ||
558 | */ | ||
559 | static __inline void | ||
560 | ahd_schedule_runq(struct ahd_softc *ahd) | ||
561 | { | ||
562 | tasklet_schedule(&ahd->platform_data->runq_tasklet); | ||
563 | } | ||
564 | |||
565 | static __inline | ||
566 | void ahd_setup_runq_tasklet(struct ahd_softc *ahd) | ||
567 | { | ||
568 | tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet, | ||
569 | (unsigned long)ahd); | ||
570 | } | ||
571 | 378 | ||
572 | static __inline void | 379 | static int ahd_linux_unit; |
573 | ahd_teardown_runq_tasklet(struct ahd_softc *ahd) | ||
574 | { | ||
575 | tasklet_kill(&ahd->platform_data->runq_tasklet); | ||
576 | } | ||
577 | 380 | ||
578 | static __inline struct ahd_linux_device* | ||
579 | ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, | ||
580 | u_int lun, int alloc) | ||
581 | { | ||
582 | struct ahd_linux_target *targ; | ||
583 | struct ahd_linux_device *dev; | ||
584 | u_int target_offset; | ||
585 | 381 | ||
586 | target_offset = target; | 382 | /****************************** Inlines ***************************************/ |
587 | if (channel != 0) | 383 | static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); |
588 | target_offset += 8; | ||
589 | targ = ahd->platform_data->targets[target_offset]; | ||
590 | if (targ == NULL) { | ||
591 | if (alloc != 0) { | ||
592 | targ = ahd_linux_alloc_target(ahd, channel, target); | ||
593 | if (targ == NULL) | ||
594 | return (NULL); | ||
595 | } else | ||
596 | return (NULL); | ||
597 | } | ||
598 | dev = targ->devices[lun]; | ||
599 | if (dev == NULL && alloc != 0) | ||
600 | dev = ahd_linux_alloc_device(ahd, targ, lun); | ||
601 | return (dev); | ||
602 | } | ||
603 | |||
604 | #define AHD_LINUX_MAX_RETURNED_ERRORS 4 | ||
605 | static struct ahd_cmd * | ||
606 | ahd_linux_run_complete_queue(struct ahd_softc *ahd) | ||
607 | { | ||
608 | struct ahd_cmd *acmd; | ||
609 | u_long done_flags; | ||
610 | int with_errors; | ||
611 | |||
612 | with_errors = 0; | ||
613 | ahd_done_lock(ahd, &done_flags); | ||
614 | while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) { | ||
615 | Scsi_Cmnd *cmd; | ||
616 | |||
617 | if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) { | ||
618 | /* | ||
619 | * Linux uses stack recursion to requeue | ||
620 | * commands that need to be retried. Avoid | ||
621 | * blowing out the stack by "spoon feeding" | ||
622 | * commands that completed with error back | ||
623 | * the operating system in case they are going | ||
624 | * to be retried. "ick" | ||
625 | */ | ||
626 | ahd_schedule_completeq(ahd); | ||
627 | break; | ||
628 | } | ||
629 | TAILQ_REMOVE(&ahd->platform_data->completeq, | ||
630 | acmd, acmd_links.tqe); | ||
631 | cmd = &acmd_scsi_cmd(acmd); | ||
632 | cmd->host_scribble = NULL; | ||
633 | if (ahd_cmd_get_transaction_status(cmd) != DID_OK | ||
634 | || (cmd->result & 0xFF) != SCSI_STATUS_OK) | ||
635 | with_errors++; | ||
636 | |||
637 | cmd->scsi_done(cmd); | ||
638 | } | ||
639 | ahd_done_unlock(ahd, &done_flags); | ||
640 | return (acmd); | ||
641 | } | ||
642 | |||
643 | static __inline void | ||
644 | ahd_linux_check_device_queue(struct ahd_softc *ahd, | ||
645 | struct ahd_linux_device *dev) | ||
646 | { | ||
647 | if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0 | ||
648 | && dev->active == 0) { | ||
649 | dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY; | ||
650 | dev->qfrozen--; | ||
651 | } | ||
652 | |||
653 | if (TAILQ_FIRST(&dev->busyq) == NULL | ||
654 | || dev->openings == 0 || dev->qfrozen != 0) | ||
655 | return; | ||
656 | |||
657 | ahd_linux_run_device_queue(ahd, dev); | ||
658 | } | ||
659 | |||
660 | static __inline struct ahd_linux_device * | ||
661 | ahd_linux_next_device_to_run(struct ahd_softc *ahd) | ||
662 | { | ||
663 | |||
664 | if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0 | ||
665 | || (ahd->platform_data->qfrozen != 0 | ||
666 | && AHD_DV_SIMQ_FROZEN(ahd) == 0)) | ||
667 | return (NULL); | ||
668 | return (TAILQ_FIRST(&ahd->platform_data->device_runq)); | ||
669 | } | ||
670 | |||
671 | static __inline void | ||
672 | ahd_linux_run_device_queues(struct ahd_softc *ahd) | ||
673 | { | ||
674 | struct ahd_linux_device *dev; | ||
675 | |||
676 | while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { | ||
677 | TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); | ||
678 | dev->flags &= ~AHD_DEV_ON_RUN_LIST; | ||
679 | ahd_linux_check_device_queue(ahd, dev); | ||
680 | } | ||
681 | } | ||
682 | 384 | ||
683 | static __inline void | 385 | static __inline void |
684 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) | 386 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) |
685 | { | 387 | { |
686 | Scsi_Cmnd *cmd; | 388 | struct scsi_cmnd *cmd; |
687 | int direction; | 389 | int direction; |
688 | 390 | ||
689 | cmd = scb->io_ctx; | 391 | cmd = scb->io_ctx; |
@@ -705,197 +407,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) | |||
705 | #define BUILD_SCSIID(ahd, cmd) \ | 407 | #define BUILD_SCSIID(ahd, cmd) \ |
706 | ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id) | 408 | ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id) |
707 | 409 | ||
708 | /************************ Host template entry points *************************/ | ||
709 | static int ahd_linux_detect(Scsi_Host_Template *); | ||
710 | static const char *ahd_linux_info(struct Scsi_Host *); | ||
711 | static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); | ||
712 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
713 | static int ahd_linux_slave_alloc(Scsi_Device *); | ||
714 | static int ahd_linux_slave_configure(Scsi_Device *); | ||
715 | static void ahd_linux_slave_destroy(Scsi_Device *); | ||
716 | #if defined(__i386__) | ||
717 | static int ahd_linux_biosparam(struct scsi_device*, | ||
718 | struct block_device*, sector_t, int[]); | ||
719 | #endif | ||
720 | #else | ||
721 | static int ahd_linux_release(struct Scsi_Host *); | ||
722 | static void ahd_linux_select_queue_depth(struct Scsi_Host *host, | ||
723 | Scsi_Device *scsi_devs); | ||
724 | #if defined(__i386__) | ||
725 | static int ahd_linux_biosparam(Disk *, kdev_t, int[]); | ||
726 | #endif | ||
727 | #endif | ||
728 | static int ahd_linux_bus_reset(Scsi_Cmnd *); | ||
729 | static int ahd_linux_dev_reset(Scsi_Cmnd *); | ||
730 | static int ahd_linux_abort(Scsi_Cmnd *); | ||
731 | |||
732 | /* | ||
733 | * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg). | ||
734 | * | ||
735 | * In pre-2.5.X... | ||
736 | * The midlayer allocates an S/G array dynamically when a command is issued | ||
737 | * using SCSI malloc. This array, which is in an OS dependent format that | ||
738 | * must later be copied to our private S/G list, is sized to house just the | ||
739 | * number of segments needed for the current transfer. Since the code that | ||
740 | * sizes the SCSI malloc pool does not take into consideration fragmentation | ||
741 | * of the pool, executing transactions numbering just a fraction of our | ||
742 | * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will | ||
743 | * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the | ||
744 | * mid-layer does not properly handle this scsi malloc failures for the S/G | ||
745 | * array and the result can be a lockup of the I/O subsystem. We try to size | ||
746 | * our S/G list so that it satisfies our drivers allocation requirements in | ||
747 | * addition to avoiding fragmentation of the SCSI malloc pool. | ||
748 | */ | ||
749 | static void | ||
750 | ahd_linux_size_nseg(void) | ||
751 | { | ||
752 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
753 | u_int cur_size; | ||
754 | u_int best_size; | ||
755 | |||
756 | /* | ||
757 | * The SCSI allocator rounds to the nearest 512 bytes | ||
758 | * an cannot allocate across a page boundary. Our algorithm | ||
759 | * is to start at 1K of scsi malloc space per-command and | ||
760 | * loop through all factors of the PAGE_SIZE and pick the best. | ||
761 | */ | ||
762 | best_size = 0; | ||
763 | for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) { | ||
764 | u_int nseg; | ||
765 | |||
766 | nseg = cur_size / sizeof(struct scatterlist); | ||
767 | if (nseg < AHD_LINUX_MIN_NSEG) | ||
768 | continue; | ||
769 | |||
770 | if (best_size == 0) { | ||
771 | best_size = cur_size; | ||
772 | ahd_linux_nseg = nseg; | ||
773 | } else { | ||
774 | u_int best_rem; | ||
775 | u_int cur_rem; | ||
776 | |||
777 | /* | ||
778 | * Compare the traits of the current "best_size" | ||
779 | * with the current size to determine if the | ||
780 | * current size is a better size. | ||
781 | */ | ||
782 | best_rem = best_size % sizeof(struct scatterlist); | ||
783 | cur_rem = cur_size % sizeof(struct scatterlist); | ||
784 | if (cur_rem < best_rem) { | ||
785 | best_size = cur_size; | ||
786 | ahd_linux_nseg = nseg; | ||
787 | } | ||
788 | } | ||
789 | } | ||
790 | #endif | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | * Try to detect an Adaptec 79XX controller. | ||
795 | */ | ||
796 | static int | ||
797 | ahd_linux_detect(Scsi_Host_Template *template) | ||
798 | { | ||
799 | struct ahd_softc *ahd; | ||
800 | int found; | ||
801 | int error = 0; | ||
802 | |||
803 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
804 | /* | ||
805 | * It is a bug that the upper layer takes | ||
806 | * this lock just prior to calling us. | ||
807 | */ | ||
808 | spin_unlock_irq(&io_request_lock); | ||
809 | #endif | ||
810 | |||
811 | /* | ||
812 | * Sanity checking of Linux SCSI data structures so | ||
813 | * that some of our hacks^H^H^H^H^Hassumptions aren't | ||
814 | * violated. | ||
815 | */ | ||
816 | if (offsetof(struct ahd_cmd_internal, end) | ||
817 | > offsetof(struct scsi_cmnd, host_scribble)) { | ||
818 | printf("ahd_linux_detect: SCSI data structures changed.\n"); | ||
819 | printf("ahd_linux_detect: Unable to attach\n"); | ||
820 | return (0); | ||
821 | } | ||
822 | /* | ||
823 | * Determine an appropriate size for our Scatter Gatther lists. | ||
824 | */ | ||
825 | ahd_linux_size_nseg(); | ||
826 | #ifdef MODULE | ||
827 | /* | ||
828 | * If we've been passed any parameters, process them now. | ||
829 | */ | ||
830 | if (aic79xx) | ||
831 | aic79xx_setup(aic79xx); | ||
832 | #endif | ||
833 | |||
834 | template->proc_name = "aic79xx"; | ||
835 | |||
836 | /* | ||
837 | * Initialize our softc list lock prior to | ||
838 | * probing for any adapters. | ||
839 | */ | ||
840 | ahd_list_lockinit(); | ||
841 | |||
842 | #ifdef CONFIG_PCI | ||
843 | error = ahd_linux_pci_init(); | ||
844 | if (error) | ||
845 | return error; | ||
846 | #endif | ||
847 | |||
848 | /* | ||
849 | * Register with the SCSI layer all | ||
850 | * controllers we've found. | ||
851 | */ | ||
852 | found = 0; | ||
853 | TAILQ_FOREACH(ahd, &ahd_tailq, links) { | ||
854 | |||
855 | if (ahd_linux_register_host(ahd, template) == 0) | ||
856 | found++; | ||
857 | } | ||
858 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
859 | spin_lock_irq(&io_request_lock); | ||
860 | #endif | ||
861 | aic79xx_detect_complete++; | ||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
866 | /* | ||
867 | * Free the passed in Scsi_Host memory structures prior to unloading the | ||
868 | * module. | ||
869 | */ | ||
870 | static int | ||
871 | ahd_linux_release(struct Scsi_Host * host) | ||
872 | { | ||
873 | struct ahd_softc *ahd; | ||
874 | u_long l; | ||
875 | |||
876 | ahd_list_lock(&l); | ||
877 | if (host != NULL) { | ||
878 | |||
879 | /* | ||
880 | * We should be able to just perform | ||
881 | * the free directly, but check our | ||
882 | * list for extra sanity. | ||
883 | */ | ||
884 | ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata); | ||
885 | if (ahd != NULL) { | ||
886 | u_long s; | ||
887 | |||
888 | ahd_lock(ahd, &s); | ||
889 | ahd_intr_enable(ahd, FALSE); | ||
890 | ahd_unlock(ahd, &s); | ||
891 | ahd_free(ahd); | ||
892 | } | ||
893 | } | ||
894 | ahd_list_unlock(&l); | ||
895 | return (0); | ||
896 | } | ||
897 | #endif | ||
898 | |||
899 | /* | 410 | /* |
900 | * Return a string describing the driver. | 411 | * Return a string describing the driver. |
901 | */ | 412 | */ |
@@ -928,220 +439,177 @@ ahd_linux_info(struct Scsi_Host *host) | |||
928 | * Queue an SCB to the controller. | 439 | * Queue an SCB to the controller. |
929 | */ | 440 | */ |
930 | static int | 441 | static int |
931 | ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | 442 | ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) |
932 | { | 443 | { |
933 | struct ahd_softc *ahd; | 444 | struct ahd_softc *ahd; |
934 | struct ahd_linux_device *dev; | 445 | struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device); |
935 | u_long flags; | ||
936 | 446 | ||
937 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | 447 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
938 | 448 | ||
939 | /* | 449 | /* |
940 | * Save the callback on completion function. | ||
941 | */ | ||
942 | cmd->scsi_done = scsi_done; | ||
943 | |||
944 | ahd_midlayer_entrypoint_lock(ahd, &flags); | ||
945 | |||
946 | /* | ||
947 | * Close the race of a command that was in the process of | 450 | * Close the race of a command that was in the process of |
948 | * being queued to us just as our simq was frozen. Let | 451 | * being queued to us just as our simq was frozen. Let |
949 | * DV commands through so long as we are only frozen to | 452 | * DV commands through so long as we are only frozen to |
950 | * perform DV. | 453 | * perform DV. |
951 | */ | 454 | */ |
952 | if (ahd->platform_data->qfrozen != 0 | 455 | if (ahd->platform_data->qfrozen != 0) { |
953 | && AHD_DV_CMD(cmd) == 0) { | 456 | printf("%s: queue frozen\n", ahd_name(ahd)); |
954 | 457 | ||
955 | ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); | 458 | return SCSI_MLQUEUE_HOST_BUSY; |
956 | ahd_linux_queue_cmd_complete(ahd, cmd); | ||
957 | ahd_schedule_completeq(ahd); | ||
958 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | ||
959 | return (0); | ||
960 | } | ||
961 | dev = ahd_linux_get_device(ahd, cmd->device->channel, | ||
962 | cmd->device->id, cmd->device->lun, | ||
963 | /*alloc*/TRUE); | ||
964 | if (dev == NULL) { | ||
965 | ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); | ||
966 | ahd_linux_queue_cmd_complete(ahd, cmd); | ||
967 | ahd_schedule_completeq(ahd); | ||
968 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | ||
969 | printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", | ||
970 | ahd_name(ahd)); | ||
971 | return (0); | ||
972 | } | 459 | } |
973 | if (cmd->cmd_len > MAX_CDB_LEN) | 460 | |
974 | return (-EINVAL); | 461 | /* |
462 | * Save the callback on completion function. | ||
463 | */ | ||
464 | cmd->scsi_done = scsi_done; | ||
465 | |||
975 | cmd->result = CAM_REQ_INPROG << 16; | 466 | cmd->result = CAM_REQ_INPROG << 16; |
976 | TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe); | 467 | |
977 | if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { | 468 | return ahd_linux_run_command(ahd, dev, cmd); |
978 | TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); | 469 | } |
979 | dev->flags |= AHD_DEV_ON_RUN_LIST; | 470 | |
980 | ahd_linux_run_device_queues(ahd); | 471 | static inline struct scsi_target ** |
981 | } | 472 | ahd_linux_target_in_softc(struct scsi_target *starget) |
982 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | 473 | { |
983 | return (0); | 474 | struct ahd_softc *ahd = |
475 | *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); | ||
476 | unsigned int target_offset; | ||
477 | |||
478 | target_offset = starget->id; | ||
479 | if (starget->channel != 0) | ||
480 | target_offset += 8; | ||
481 | |||
482 | return &ahd->platform_data->starget[target_offset]; | ||
984 | } | 483 | } |
985 | 484 | ||
986 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
987 | static int | 485 | static int |
988 | ahd_linux_slave_alloc(Scsi_Device *device) | 486 | ahd_linux_target_alloc(struct scsi_target *starget) |
989 | { | 487 | { |
990 | struct ahd_softc *ahd; | 488 | struct ahd_softc *ahd = |
489 | *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); | ||
490 | unsigned long flags; | ||
491 | struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); | ||
492 | struct ahd_linux_target *targ = scsi_transport_target_data(starget); | ||
493 | struct ahd_devinfo devinfo; | ||
494 | struct ahd_initiator_tinfo *tinfo; | ||
495 | struct ahd_tmode_tstate *tstate; | ||
496 | char channel = starget->channel + 'A'; | ||
991 | 497 | ||
992 | ahd = *((struct ahd_softc **)device->host->hostdata); | 498 | ahd_lock(ahd, &flags); |
993 | if (bootverbose) | 499 | |
994 | printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id); | 500 | BUG_ON(*ahd_targp != NULL); |
995 | return (0); | 501 | |
502 | *ahd_targp = starget; | ||
503 | memset(targ, 0, sizeof(*targ)); | ||
504 | |||
505 | tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, | ||
506 | starget->id, &tstate); | ||
507 | ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id, | ||
508 | CAM_LUN_WILDCARD, channel, | ||
509 | ROLE_INITIATOR); | ||
510 | spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */ | ||
511 | if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) | ||
512 | spi_max_offset(starget) = MAX_OFFSET_PACED_BUG; | ||
513 | else | ||
514 | spi_max_offset(starget) = MAX_OFFSET_PACED; | ||
515 | spi_max_width(starget) = ahd->features & AHD_WIDE; | ||
516 | |||
517 | ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, | ||
518 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
519 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, | ||
520 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
521 | ahd_unlock(ahd, &flags); | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static void | ||
527 | ahd_linux_target_destroy(struct scsi_target *starget) | ||
528 | { | ||
529 | struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); | ||
530 | |||
531 | *ahd_targp = NULL; | ||
996 | } | 532 | } |
997 | 533 | ||
998 | static int | 534 | static int |
999 | ahd_linux_slave_configure(Scsi_Device *device) | 535 | ahd_linux_slave_alloc(struct scsi_device *sdev) |
1000 | { | 536 | { |
1001 | struct ahd_softc *ahd; | 537 | struct ahd_softc *ahd = |
1002 | struct ahd_linux_device *dev; | 538 | *((struct ahd_softc **)sdev->host->hostdata); |
1003 | u_long flags; | 539 | struct scsi_target *starget = sdev->sdev_target; |
540 | struct ahd_linux_target *targ = scsi_transport_target_data(starget); | ||
541 | struct ahd_linux_device *dev; | ||
1004 | 542 | ||
1005 | ahd = *((struct ahd_softc **)device->host->hostdata); | ||
1006 | if (bootverbose) | 543 | if (bootverbose) |
1007 | printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id); | 544 | printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id); |
1008 | ahd_midlayer_entrypoint_lock(ahd, &flags); | 545 | |
546 | BUG_ON(targ->sdev[sdev->lun] != NULL); | ||
547 | |||
548 | dev = scsi_transport_device_data(sdev); | ||
549 | memset(dev, 0, sizeof(*dev)); | ||
550 | |||
1009 | /* | 551 | /* |
1010 | * Since Linux has attached to the device, configure | 552 | * We start out life using untagged |
1011 | * it so we don't free and allocate the device | 553 | * transactions of which we allow one. |
1012 | * structure on every command. | ||
1013 | */ | 554 | */ |
1014 | dev = ahd_linux_get_device(ahd, device->channel, | 555 | dev->openings = 1; |
1015 | device->id, device->lun, | 556 | |
1016 | /*alloc*/TRUE); | 557 | /* |
1017 | if (dev != NULL) { | 558 | * Set maxtags to 0. This will be changed if we |
1018 | dev->flags &= ~AHD_DEV_UNCONFIGURED; | 559 | * later determine that we are dealing with |
1019 | dev->flags |= AHD_DEV_SLAVE_CONFIGURED; | 560 | * a tagged queuing capable device. |
1020 | dev->scsi_device = device; | 561 | */ |
1021 | ahd_linux_device_queue_depth(ahd, dev); | 562 | dev->maxtags = 0; |
1022 | } | 563 | |
1023 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | 564 | targ->sdev[sdev->lun] = sdev; |
565 | |||
1024 | return (0); | 566 | return (0); |
1025 | } | 567 | } |
1026 | 568 | ||
1027 | static void | 569 | static int |
1028 | ahd_linux_slave_destroy(Scsi_Device *device) | 570 | ahd_linux_slave_configure(struct scsi_device *sdev) |
1029 | { | 571 | { |
1030 | struct ahd_softc *ahd; | 572 | struct ahd_softc *ahd; |
1031 | struct ahd_linux_device *dev; | ||
1032 | u_long flags; | ||
1033 | 573 | ||
1034 | ahd = *((struct ahd_softc **)device->host->hostdata); | 574 | ahd = *((struct ahd_softc **)sdev->host->hostdata); |
1035 | if (bootverbose) | 575 | if (bootverbose) |
1036 | printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id); | 576 | printf("%s: Slave Configure %d\n", ahd_name(ahd), sdev->id); |
1037 | ahd_midlayer_entrypoint_lock(ahd, &flags); | ||
1038 | dev = ahd_linux_get_device(ahd, device->channel, | ||
1039 | device->id, device->lun, | ||
1040 | /*alloc*/FALSE); | ||
1041 | 577 | ||
1042 | /* | 578 | ahd_linux_device_queue_depth(sdev); |
1043 | * Filter out "silly" deletions of real devices by only | 579 | |
1044 | * deleting devices that have had slave_configure() | 580 | /* Initial Domain Validation */ |
1045 | * called on them. All other devices that have not | 581 | if (!spi_initial_dv(sdev->sdev_target)) |
1046 | * been configured will automatically be deleted by | 582 | spi_dv_device(sdev); |
1047 | * the refcounting process. | 583 | |
1048 | */ | 584 | return 0; |
1049 | if (dev != NULL | ||
1050 | && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) { | ||
1051 | dev->flags |= AHD_DEV_UNCONFIGURED; | ||
1052 | if (TAILQ_EMPTY(&dev->busyq) | ||
1053 | && dev->active == 0 | ||
1054 | && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) | ||
1055 | ahd_linux_free_device(ahd, dev); | ||
1056 | } | ||
1057 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | ||
1058 | } | 585 | } |
1059 | #else | 586 | |
1060 | /* | ||
1061 | * Sets the queue depth for each SCSI device hanging | ||
1062 | * off the input host adapter. | ||
1063 | */ | ||
1064 | static void | 587 | static void |
1065 | ahd_linux_select_queue_depth(struct Scsi_Host * host, | 588 | ahd_linux_slave_destroy(struct scsi_device *sdev) |
1066 | Scsi_Device * scsi_devs) | ||
1067 | { | 589 | { |
1068 | Scsi_Device *device; | ||
1069 | Scsi_Device *ldev; | ||
1070 | struct ahd_softc *ahd; | 590 | struct ahd_softc *ahd; |
1071 | u_long flags; | 591 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); |
592 | struct ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target); | ||
1072 | 593 | ||
1073 | ahd = *((struct ahd_softc **)host->hostdata); | 594 | ahd = *((struct ahd_softc **)sdev->host->hostdata); |
1074 | ahd_lock(ahd, &flags); | 595 | if (bootverbose) |
1075 | for (device = scsi_devs; device != NULL; device = device->next) { | 596 | printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id); |
1076 | 597 | ||
1077 | /* | 598 | BUG_ON(dev->active); |
1078 | * Watch out for duplicate devices. This works around | ||
1079 | * some quirks in how the SCSI scanning code does its | ||
1080 | * device management. | ||
1081 | */ | ||
1082 | for (ldev = scsi_devs; ldev != device; ldev = ldev->next) { | ||
1083 | if (ldev->host == device->host | ||
1084 | && ldev->channel == device->channel | ||
1085 | && ldev->id == device->id | ||
1086 | && ldev->lun == device->lun) | ||
1087 | break; | ||
1088 | } | ||
1089 | /* Skip duplicate. */ | ||
1090 | if (ldev != device) | ||
1091 | continue; | ||
1092 | 599 | ||
1093 | if (device->host == host) { | 600 | targ->sdev[sdev->lun] = NULL; |
1094 | struct ahd_linux_device *dev; | ||
1095 | 601 | ||
1096 | /* | ||
1097 | * Since Linux has attached to the device, configure | ||
1098 | * it so we don't free and allocate the device | ||
1099 | * structure on every command. | ||
1100 | */ | ||
1101 | dev = ahd_linux_get_device(ahd, device->channel, | ||
1102 | device->id, device->lun, | ||
1103 | /*alloc*/TRUE); | ||
1104 | if (dev != NULL) { | ||
1105 | dev->flags &= ~AHD_DEV_UNCONFIGURED; | ||
1106 | dev->scsi_device = device; | ||
1107 | ahd_linux_device_queue_depth(ahd, dev); | ||
1108 | device->queue_depth = dev->openings | ||
1109 | + dev->active; | ||
1110 | if ((dev->flags & (AHD_DEV_Q_BASIC | ||
1111 | | AHD_DEV_Q_TAGGED)) == 0) { | ||
1112 | /* | ||
1113 | * We allow the OS to queue 2 untagged | ||
1114 | * transactions to us at any time even | ||
1115 | * though we can only execute them | ||
1116 | * serially on the controller/device. | ||
1117 | * This should remove some latency. | ||
1118 | */ | ||
1119 | device->queue_depth = 2; | ||
1120 | } | ||
1121 | } | ||
1122 | } | ||
1123 | } | ||
1124 | ahd_unlock(ahd, &flags); | ||
1125 | } | 602 | } |
1126 | #endif | ||
1127 | 603 | ||
1128 | #if defined(__i386__) | 604 | #if defined(__i386__) |
1129 | /* | 605 | /* |
1130 | * Return the disk geometry for the given SCSI device. | 606 | * Return the disk geometry for the given SCSI device. |
1131 | */ | 607 | */ |
1132 | static int | 608 | static int |
1133 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1134 | ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, | 609 | ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, |
1135 | sector_t capacity, int geom[]) | 610 | sector_t capacity, int geom[]) |
1136 | { | 611 | { |
1137 | uint8_t *bh; | 612 | uint8_t *bh; |
1138 | #else | ||
1139 | ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) | ||
1140 | { | ||
1141 | struct scsi_device *sdev = disk->device; | ||
1142 | u_long capacity = disk->capacity; | ||
1143 | struct buffer_head *bh; | ||
1144 | #endif | ||
1145 | int heads; | 613 | int heads; |
1146 | int sectors; | 614 | int sectors; |
1147 | int cylinders; | 615 | int cylinders; |
@@ -1151,22 +619,11 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) | |||
1151 | 619 | ||
1152 | ahd = *((struct ahd_softc **)sdev->host->hostdata); | 620 | ahd = *((struct ahd_softc **)sdev->host->hostdata); |
1153 | 621 | ||
1154 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1155 | bh = scsi_bios_ptable(bdev); | 622 | bh = scsi_bios_ptable(bdev); |
1156 | #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17) | ||
1157 | bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev)); | ||
1158 | #else | ||
1159 | bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024); | ||
1160 | #endif | ||
1161 | |||
1162 | if (bh) { | 623 | if (bh) { |
1163 | ret = scsi_partsize(bh, capacity, | 624 | ret = scsi_partsize(bh, capacity, |
1164 | &geom[2], &geom[0], &geom[1]); | 625 | &geom[2], &geom[0], &geom[1]); |
1165 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1166 | kfree(bh); | 626 | kfree(bh); |
1167 | #else | ||
1168 | brelse(bh); | ||
1169 | #endif | ||
1170 | if (ret != -1) | 627 | if (ret != -1) |
1171 | return (ret); | 628 | return (ret); |
1172 | } | 629 | } |
@@ -1194,392 +651,35 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) | |||
1194 | * Abort the current SCSI command(s). | 651 | * Abort the current SCSI command(s). |
1195 | */ | 652 | */ |
1196 | static int | 653 | static int |
1197 | ahd_linux_abort(Scsi_Cmnd *cmd) | 654 | ahd_linux_abort(struct scsi_cmnd *cmd) |
1198 | { | 655 | { |
1199 | struct ahd_softc *ahd; | 656 | int error; |
1200 | struct ahd_cmd *acmd; | ||
1201 | struct ahd_cmd *list_acmd; | ||
1202 | struct ahd_linux_device *dev; | ||
1203 | struct scb *pending_scb; | ||
1204 | u_long s; | ||
1205 | u_int saved_scbptr; | ||
1206 | u_int active_scbptr; | ||
1207 | u_int last_phase; | ||
1208 | u_int cdb_byte; | ||
1209 | int retval; | ||
1210 | int was_paused; | ||
1211 | int paused; | ||
1212 | int wait; | ||
1213 | int disconnected; | ||
1214 | ahd_mode_state saved_modes; | ||
1215 | |||
1216 | pending_scb = NULL; | ||
1217 | paused = FALSE; | ||
1218 | wait = FALSE; | ||
1219 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | ||
1220 | acmd = (struct ahd_cmd *)cmd; | ||
1221 | |||
1222 | printf("%s:%d:%d:%d: Attempting to abort cmd %p:", | ||
1223 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1224 | cmd->device->lun, cmd); | ||
1225 | for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) | ||
1226 | printf(" 0x%x", cmd->cmnd[cdb_byte]); | ||
1227 | printf("\n"); | ||
1228 | |||
1229 | /* | ||
1230 | * In all versions of Linux, we have to work around | ||
1231 | * a major flaw in how the mid-layer is locked down | ||
1232 | * if we are to sleep successfully in our error handler | ||
1233 | * while allowing our interrupt handler to run. Since | ||
1234 | * the midlayer acquires either the io_request_lock or | ||
1235 | * our lock prior to calling us, we must use the | ||
1236 | * spin_unlock_irq() method for unlocking our lock. | ||
1237 | * This will force interrupts to be enabled on the | ||
1238 | * current CPU. Since the EH thread should not have | ||
1239 | * been running with CPU interrupts disabled other than | ||
1240 | * by acquiring either the io_request_lock or our own | ||
1241 | * lock, this *should* be safe. | ||
1242 | */ | ||
1243 | ahd_midlayer_entrypoint_lock(ahd, &s); | ||
1244 | |||
1245 | /* | ||
1246 | * First determine if we currently own this command. | ||
1247 | * Start by searching the device queue. If not found | ||
1248 | * there, check the pending_scb list. If not found | ||
1249 | * at all, and the system wanted us to just abort the | ||
1250 | * command, return success. | ||
1251 | */ | ||
1252 | dev = ahd_linux_get_device(ahd, cmd->device->channel, | ||
1253 | cmd->device->id, cmd->device->lun, | ||
1254 | /*alloc*/FALSE); | ||
1255 | |||
1256 | if (dev == NULL) { | ||
1257 | /* | ||
1258 | * No target device for this command exists, | ||
1259 | * so we must not still own the command. | ||
1260 | */ | ||
1261 | printf("%s:%d:%d:%d: Is not an active device\n", | ||
1262 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1263 | cmd->device->lun); | ||
1264 | retval = SUCCESS; | ||
1265 | goto no_cmd; | ||
1266 | } | ||
1267 | |||
1268 | TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) { | ||
1269 | if (list_acmd == acmd) | ||
1270 | break; | ||
1271 | } | ||
1272 | |||
1273 | if (list_acmd != NULL) { | ||
1274 | printf("%s:%d:%d:%d: Command found on device queue\n", | ||
1275 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1276 | cmd->device->lun); | ||
1277 | TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); | ||
1278 | cmd->result = DID_ABORT << 16; | ||
1279 | ahd_linux_queue_cmd_complete(ahd, cmd); | ||
1280 | retval = SUCCESS; | ||
1281 | goto done; | ||
1282 | } | ||
1283 | |||
1284 | /* | ||
1285 | * See if we can find a matching cmd in the pending list. | ||
1286 | */ | ||
1287 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | ||
1288 | if (pending_scb->io_ctx == cmd) | ||
1289 | break; | ||
1290 | } | ||
1291 | |||
1292 | if (pending_scb == NULL) { | ||
1293 | printf("%s:%d:%d:%d: Command not found\n", | ||
1294 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1295 | cmd->device->lun); | ||
1296 | goto no_cmd; | ||
1297 | } | ||
1298 | |||
1299 | if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { | ||
1300 | /* | ||
1301 | * We can't queue two recovery actions using the same SCB | ||
1302 | */ | ||
1303 | retval = FAILED; | ||
1304 | goto done; | ||
1305 | } | ||
1306 | |||
1307 | /* | ||
1308 | * Ensure that the card doesn't do anything | ||
1309 | * behind our back. Also make sure that we | ||
1310 | * didn't "just" miss an interrupt that would | ||
1311 | * affect this cmd. | ||
1312 | */ | ||
1313 | was_paused = ahd_is_paused(ahd); | ||
1314 | ahd_pause_and_flushwork(ahd); | ||
1315 | paused = TRUE; | ||
1316 | |||
1317 | if ((pending_scb->flags & SCB_ACTIVE) == 0) { | ||
1318 | printf("%s:%d:%d:%d: Command already completed\n", | ||
1319 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1320 | cmd->device->lun); | ||
1321 | goto no_cmd; | ||
1322 | } | ||
1323 | |||
1324 | printf("%s: At time of recovery, card was %spaused\n", | ||
1325 | ahd_name(ahd), was_paused ? "" : "not "); | ||
1326 | ahd_dump_card_state(ahd); | ||
1327 | |||
1328 | disconnected = TRUE; | ||
1329 | if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A', | ||
1330 | cmd->device->lun, SCB_GET_TAG(pending_scb), | ||
1331 | ROLE_INITIATOR, CAM_REQ_ABORTED, | ||
1332 | SEARCH_COMPLETE) > 0) { | ||
1333 | printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", | ||
1334 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1335 | cmd->device->lun); | ||
1336 | retval = SUCCESS; | ||
1337 | goto done; | ||
1338 | } | ||
1339 | |||
1340 | saved_modes = ahd_save_modes(ahd); | ||
1341 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
1342 | last_phase = ahd_inb(ahd, LASTPHASE); | ||
1343 | saved_scbptr = ahd_get_scbptr(ahd); | ||
1344 | active_scbptr = saved_scbptr; | ||
1345 | if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { | ||
1346 | struct scb *bus_scb; | ||
1347 | |||
1348 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); | ||
1349 | if (bus_scb == pending_scb) | ||
1350 | disconnected = FALSE; | ||
1351 | } | ||
1352 | |||
1353 | /* | ||
1354 | * At this point, pending_scb is the scb associated with the | ||
1355 | * passed in command. That command is currently active on the | ||
1356 | * bus or is in the disconnected state. | ||
1357 | */ | ||
1358 | if (last_phase != P_BUSFREE | ||
1359 | && SCB_GET_TAG(pending_scb) == active_scbptr) { | ||
1360 | |||
1361 | /* | ||
1362 | * We're active on the bus, so assert ATN | ||
1363 | * and hope that the target responds. | ||
1364 | */ | ||
1365 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); | ||
1366 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; | ||
1367 | ahd_outb(ahd, MSG_OUT, HOST_MSG); | ||
1368 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); | ||
1369 | printf("%s:%d:%d:%d: Device is active, asserting ATN\n", | ||
1370 | ahd_name(ahd), cmd->device->channel, | ||
1371 | cmd->device->id, cmd->device->lun); | ||
1372 | wait = TRUE; | ||
1373 | } else if (disconnected) { | ||
1374 | |||
1375 | /* | ||
1376 | * Actually re-queue this SCB in an attempt | ||
1377 | * to select the device before it reconnects. | ||
1378 | */ | ||
1379 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; | ||
1380 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); | ||
1381 | pending_scb->hscb->cdb_len = 0; | ||
1382 | pending_scb->hscb->task_attribute = 0; | ||
1383 | pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; | ||
1384 | |||
1385 | if ((pending_scb->flags & SCB_PACKETIZED) != 0) { | ||
1386 | /* | ||
1387 | * Mark the SCB has having an outstanding | ||
1388 | * task management function. Should the command | ||
1389 | * complete normally before the task management | ||
1390 | * function can be sent, the host will be notified | ||
1391 | * to abort our requeued SCB. | ||
1392 | */ | ||
1393 | ahd_outb(ahd, SCB_TASK_MANAGEMENT, | ||
1394 | pending_scb->hscb->task_management); | ||
1395 | } else { | ||
1396 | /* | ||
1397 | * If non-packetized, set the MK_MESSAGE control | ||
1398 | * bit indicating that we desire to send a message. | ||
1399 | * We also set the disconnected flag since there is | ||
1400 | * no guarantee that our SCB control byte matches | ||
1401 | * the version on the card. We don't want the | ||
1402 | * sequencer to abort the command thinking an | ||
1403 | * unsolicited reselection occurred. | ||
1404 | */ | ||
1405 | pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED; | ||
1406 | |||
1407 | /* | ||
1408 | * The sequencer will never re-reference the | ||
1409 | * in-core SCB. To make sure we are notified | ||
1410 | * during reslection, set the MK_MESSAGE flag in | ||
1411 | * the card's copy of the SCB. | ||
1412 | */ | ||
1413 | ahd_outb(ahd, SCB_CONTROL, | ||
1414 | ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); | ||
1415 | } | ||
1416 | |||
1417 | /* | ||
1418 | * Clear out any entries in the QINFIFO first | ||
1419 | * so we are the next SCB for this target | ||
1420 | * to run. | ||
1421 | */ | ||
1422 | ahd_search_qinfifo(ahd, cmd->device->id, | ||
1423 | cmd->device->channel + 'A', cmd->device->lun, | ||
1424 | SCB_LIST_NULL, ROLE_INITIATOR, | ||
1425 | CAM_REQUEUE_REQ, SEARCH_COMPLETE); | ||
1426 | ahd_qinfifo_requeue_tail(ahd, pending_scb); | ||
1427 | ahd_set_scbptr(ahd, saved_scbptr); | ||
1428 | ahd_print_path(ahd, pending_scb); | ||
1429 | printf("Device is disconnected, re-queuing SCB\n"); | ||
1430 | wait = TRUE; | ||
1431 | } else { | ||
1432 | printf("%s:%d:%d:%d: Unable to deliver message\n", | ||
1433 | ahd_name(ahd), cmd->device->channel, | ||
1434 | cmd->device->id, cmd->device->lun); | ||
1435 | retval = FAILED; | ||
1436 | goto done; | ||
1437 | } | ||
1438 | |||
1439 | no_cmd: | ||
1440 | /* | ||
1441 | * Our assumption is that if we don't have the command, no | ||
1442 | * recovery action was required, so we return success. Again, | ||
1443 | * the semantics of the mid-layer recovery engine are not | ||
1444 | * well defined, so this may change in time. | ||
1445 | */ | ||
1446 | retval = SUCCESS; | ||
1447 | done: | ||
1448 | if (paused) | ||
1449 | ahd_unpause(ahd); | ||
1450 | if (wait) { | ||
1451 | struct timer_list timer; | ||
1452 | int ret; | ||
1453 | 657 | ||
1454 | pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; | 658 | error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT); |
1455 | spin_unlock_irq(&ahd->platform_data->spin_lock); | 659 | if (error != 0) |
1456 | init_timer(&timer); | 660 | printf("aic79xx_abort returns 0x%x\n", error); |
1457 | timer.data = (u_long)pending_scb; | 661 | return error; |
1458 | timer.expires = jiffies + (5 * HZ); | ||
1459 | timer.function = ahd_linux_sem_timeout; | ||
1460 | add_timer(&timer); | ||
1461 | printf("Recovery code sleeping\n"); | ||
1462 | down(&ahd->platform_data->eh_sem); | ||
1463 | printf("Recovery code awake\n"); | ||
1464 | ret = del_timer_sync(&timer); | ||
1465 | if (ret == 0) { | ||
1466 | printf("Timer Expired\n"); | ||
1467 | retval = FAILED; | ||
1468 | } | ||
1469 | spin_lock_irq(&ahd->platform_data->spin_lock); | ||
1470 | } | ||
1471 | ahd_schedule_runq(ahd); | ||
1472 | ahd_linux_run_complete_queue(ahd); | ||
1473 | ahd_midlayer_entrypoint_unlock(ahd, &s); | ||
1474 | return (retval); | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | static void | ||
1479 | ahd_linux_dev_reset_complete(Scsi_Cmnd *cmd) | ||
1480 | { | ||
1481 | free(cmd, M_DEVBUF); | ||
1482 | } | 662 | } |
1483 | 663 | ||
1484 | /* | 664 | /* |
1485 | * Attempt to send a target reset message to the device that timed out. | 665 | * Attempt to send a target reset message to the device that timed out. |
1486 | */ | 666 | */ |
1487 | static int | 667 | static int |
1488 | ahd_linux_dev_reset(Scsi_Cmnd *cmd) | 668 | ahd_linux_dev_reset(struct scsi_cmnd *cmd) |
1489 | { | 669 | { |
1490 | struct ahd_softc *ahd; | 670 | int error; |
1491 | struct scsi_cmnd *recovery_cmd; | ||
1492 | struct ahd_linux_device *dev; | ||
1493 | struct ahd_initiator_tinfo *tinfo; | ||
1494 | struct ahd_tmode_tstate *tstate; | ||
1495 | struct scb *scb; | ||
1496 | struct hardware_scb *hscb; | ||
1497 | u_long s; | ||
1498 | struct timer_list timer; | ||
1499 | int retval; | ||
1500 | 671 | ||
1501 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | 672 | error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); |
1502 | recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK); | 673 | if (error != 0) |
1503 | if (!recovery_cmd) | 674 | printf("aic79xx_dev_reset returns 0x%x\n", error); |
1504 | return (FAILED); | 675 | return error; |
1505 | memset(recovery_cmd, 0, sizeof(struct scsi_cmnd)); | ||
1506 | recovery_cmd->device = cmd->device; | ||
1507 | recovery_cmd->scsi_done = ahd_linux_dev_reset_complete; | ||
1508 | #ifdef AHD_DEBUG | ||
1509 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) | ||
1510 | printf("%s:%d:%d:%d: Device reset called for cmd %p\n", | ||
1511 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
1512 | cmd->device->lun, cmd); | ||
1513 | #endif | ||
1514 | ahd_lock(ahd, &s); | ||
1515 | |||
1516 | dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id, | ||
1517 | cmd->device->lun, /*alloc*/FALSE); | ||
1518 | if (dev == NULL) { | ||
1519 | ahd_unlock(ahd, &s); | ||
1520 | kfree(recovery_cmd); | ||
1521 | return (FAILED); | ||
1522 | } | ||
1523 | if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) { | ||
1524 | ahd_unlock(ahd, &s); | ||
1525 | kfree(recovery_cmd); | ||
1526 | return (FAILED); | ||
1527 | } | ||
1528 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, | ||
1529 | cmd->device->id, &tstate); | ||
1530 | recovery_cmd->result = CAM_REQ_INPROG << 16; | ||
1531 | recovery_cmd->host_scribble = (char *)scb; | ||
1532 | scb->io_ctx = recovery_cmd; | ||
1533 | scb->platform_data->dev = dev; | ||
1534 | scb->sg_count = 0; | ||
1535 | ahd_set_residual(scb, 0); | ||
1536 | ahd_set_sense_residual(scb, 0); | ||
1537 | hscb = scb->hscb; | ||
1538 | hscb->control = 0; | ||
1539 | hscb->scsiid = BUILD_SCSIID(ahd, cmd); | ||
1540 | hscb->lun = cmd->device->lun; | ||
1541 | hscb->cdb_len = 0; | ||
1542 | hscb->task_management = SIU_TASKMGMT_LUN_RESET; | ||
1543 | scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE; | ||
1544 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
1545 | scb->flags |= SCB_PACKETIZED; | ||
1546 | } else { | ||
1547 | hscb->control |= MK_MESSAGE; | ||
1548 | } | ||
1549 | dev->openings--; | ||
1550 | dev->active++; | ||
1551 | dev->commands_issued++; | ||
1552 | LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); | ||
1553 | ahd_queue_scb(ahd, scb); | ||
1554 | |||
1555 | scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; | ||
1556 | ahd_unlock(ahd, &s); | ||
1557 | init_timer(&timer); | ||
1558 | timer.data = (u_long)scb; | ||
1559 | timer.expires = jiffies + (5 * HZ); | ||
1560 | timer.function = ahd_linux_sem_timeout; | ||
1561 | add_timer(&timer); | ||
1562 | printf("Recovery code sleeping\n"); | ||
1563 | down(&ahd->platform_data->eh_sem); | ||
1564 | printf("Recovery code awake\n"); | ||
1565 | retval = SUCCESS; | ||
1566 | if (del_timer_sync(&timer) == 0) { | ||
1567 | printf("Timer Expired\n"); | ||
1568 | retval = FAILED; | ||
1569 | } | ||
1570 | ahd_lock(ahd, &s); | ||
1571 | ahd_schedule_runq(ahd); | ||
1572 | ahd_linux_run_complete_queue(ahd); | ||
1573 | ahd_unlock(ahd, &s); | ||
1574 | printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); | ||
1575 | return (retval); | ||
1576 | } | 676 | } |
1577 | 677 | ||
1578 | /* | 678 | /* |
1579 | * Reset the SCSI bus. | 679 | * Reset the SCSI bus. |
1580 | */ | 680 | */ |
1581 | static int | 681 | static int |
1582 | ahd_linux_bus_reset(Scsi_Cmnd *cmd) | 682 | ahd_linux_bus_reset(struct scsi_cmnd *cmd) |
1583 | { | 683 | { |
1584 | struct ahd_softc *ahd; | 684 | struct ahd_softc *ahd; |
1585 | u_long s; | 685 | u_long s; |
@@ -1594,7 +694,6 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) | |||
1594 | ahd_lock(ahd, &s); | 694 | ahd_lock(ahd, &s); |
1595 | found = ahd_reset_channel(ahd, cmd->device->channel + 'A', | 695 | found = ahd_reset_channel(ahd, cmd->device->channel + 'A', |
1596 | /*initiate reset*/TRUE); | 696 | /*initiate reset*/TRUE); |
1597 | ahd_linux_run_complete_queue(ahd); | ||
1598 | ahd_unlock(ahd, &s); | 697 | ahd_unlock(ahd, &s); |
1599 | 698 | ||
1600 | if (bootverbose) | 699 | if (bootverbose) |
@@ -1604,9 +703,10 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) | |||
1604 | return (SUCCESS); | 703 | return (SUCCESS); |
1605 | } | 704 | } |
1606 | 705 | ||
1607 | Scsi_Host_Template aic79xx_driver_template = { | 706 | struct scsi_host_template aic79xx_driver_template = { |
1608 | .module = THIS_MODULE, | 707 | .module = THIS_MODULE, |
1609 | .name = "aic79xx", | 708 | .name = "aic79xx", |
709 | .proc_name = "aic79xx", | ||
1610 | .proc_info = ahd_linux_proc_info, | 710 | .proc_info = ahd_linux_proc_info, |
1611 | .info = ahd_linux_info, | 711 | .info = ahd_linux_info, |
1612 | .queuecommand = ahd_linux_queue, | 712 | .queuecommand = ahd_linux_queue, |
@@ -1623,37 +723,10 @@ Scsi_Host_Template aic79xx_driver_template = { | |||
1623 | .slave_alloc = ahd_linux_slave_alloc, | 723 | .slave_alloc = ahd_linux_slave_alloc, |
1624 | .slave_configure = ahd_linux_slave_configure, | 724 | .slave_configure = ahd_linux_slave_configure, |
1625 | .slave_destroy = ahd_linux_slave_destroy, | 725 | .slave_destroy = ahd_linux_slave_destroy, |
726 | .target_alloc = ahd_linux_target_alloc, | ||
727 | .target_destroy = ahd_linux_target_destroy, | ||
1626 | }; | 728 | }; |
1627 | 729 | ||
1628 | /**************************** Tasklet Handler *********************************/ | ||
1629 | |||
1630 | /* | ||
1631 | * In 2.4.X and above, this routine is called from a tasklet, | ||
1632 | * so we must re-acquire our lock prior to executing this code. | ||
1633 | * In all prior kernels, ahd_schedule_runq() calls this routine | ||
1634 | * directly and ahd_schedule_runq() is called with our lock held. | ||
1635 | */ | ||
1636 | static void | ||
1637 | ahd_runq_tasklet(unsigned long data) | ||
1638 | { | ||
1639 | struct ahd_softc* ahd; | ||
1640 | struct ahd_linux_device *dev; | ||
1641 | u_long flags; | ||
1642 | |||
1643 | ahd = (struct ahd_softc *)data; | ||
1644 | ahd_lock(ahd, &flags); | ||
1645 | while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { | ||
1646 | |||
1647 | TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); | ||
1648 | dev->flags &= ~AHD_DEV_ON_RUN_LIST; | ||
1649 | ahd_linux_check_device_queue(ahd, dev); | ||
1650 | /* Yeild to our interrupt handler */ | ||
1651 | ahd_unlock(ahd, &flags); | ||
1652 | ahd_lock(ahd, &flags); | ||
1653 | } | ||
1654 | ahd_unlock(ahd, &flags); | ||
1655 | } | ||
1656 | |||
1657 | /******************************** Bus DMA *************************************/ | 730 | /******************************** Bus DMA *************************************/ |
1658 | int | 731 | int |
1659 | ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, | 732 | ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, |
@@ -1693,36 +766,10 @@ int | |||
1693 | ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, | 766 | ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, |
1694 | int flags, bus_dmamap_t *mapp) | 767 | int flags, bus_dmamap_t *mapp) |
1695 | { | 768 | { |
1696 | bus_dmamap_t map; | ||
1697 | |||
1698 | map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); | ||
1699 | if (map == NULL) | ||
1700 | return (ENOMEM); | ||
1701 | /* | ||
1702 | * Although we can dma data above 4GB, our | ||
1703 | * "consistent" memory is below 4GB for | ||
1704 | * space efficiency reasons (only need a 4byte | ||
1705 | * address). For this reason, we have to reset | ||
1706 | * our dma mask when doing allocations. | ||
1707 | */ | ||
1708 | if (ahd->dev_softc != NULL) | ||
1709 | if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) { | ||
1710 | printk(KERN_WARNING "aic79xx: No suitable DMA available.\n"); | ||
1711 | kfree(map); | ||
1712 | return (ENODEV); | ||
1713 | } | ||
1714 | *vaddr = pci_alloc_consistent(ahd->dev_softc, | 769 | *vaddr = pci_alloc_consistent(ahd->dev_softc, |
1715 | dmat->maxsize, &map->bus_addr); | 770 | dmat->maxsize, mapp); |
1716 | if (ahd->dev_softc != NULL) | ||
1717 | if (pci_set_dma_mask(ahd->dev_softc, | ||
1718 | ahd->platform_data->hw_dma_mask)) { | ||
1719 | printk(KERN_WARNING "aic79xx: No suitable DMA available.\n"); | ||
1720 | kfree(map); | ||
1721 | return (ENODEV); | ||
1722 | } | ||
1723 | if (*vaddr == NULL) | 771 | if (*vaddr == NULL) |
1724 | return (ENOMEM); | 772 | return (ENOMEM); |
1725 | *mapp = map; | ||
1726 | return(0); | 773 | return(0); |
1727 | } | 774 | } |
1728 | 775 | ||
@@ -1731,7 +778,7 @@ ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, | |||
1731 | void* vaddr, bus_dmamap_t map) | 778 | void* vaddr, bus_dmamap_t map) |
1732 | { | 779 | { |
1733 | pci_free_consistent(ahd->dev_softc, dmat->maxsize, | 780 | pci_free_consistent(ahd->dev_softc, dmat->maxsize, |
1734 | vaddr, map->bus_addr); | 781 | vaddr, map); |
1735 | } | 782 | } |
1736 | 783 | ||
1737 | int | 784 | int |
@@ -1745,7 +792,7 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, | |||
1745 | */ | 792 | */ |
1746 | bus_dma_segment_t stack_sg; | 793 | bus_dma_segment_t stack_sg; |
1747 | 794 | ||
1748 | stack_sg.ds_addr = map->bus_addr; | 795 | stack_sg.ds_addr = map; |
1749 | stack_sg.ds_len = dmat->maxsize; | 796 | stack_sg.ds_len = dmat->maxsize; |
1750 | cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); | 797 | cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); |
1751 | return (0); | 798 | return (0); |
@@ -1754,11 +801,6 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, | |||
1754 | void | 801 | void |
1755 | ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) | 802 | ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) |
1756 | { | 803 | { |
1757 | /* | ||
1758 | * The map may is NULL in our < 2.3.X implementation. | ||
1759 | */ | ||
1760 | if (map != NULL) | ||
1761 | free(map, M_DEVBUF); | ||
1762 | } | 804 | } |
1763 | 805 | ||
1764 | int | 806 | int |
@@ -1823,41 +865,6 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) | |||
1823 | } | 865 | } |
1824 | 866 | ||
1825 | static void | 867 | static void |
1826 | ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | ||
1827 | { | ||
1828 | |||
1829 | if ((instance >= 0) && (targ >= 0) | ||
1830 | && (instance < NUM_ELEMENTS(aic79xx_tag_info)) | ||
1831 | && (targ < AHD_NUM_TARGETS)) { | ||
1832 | aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; | ||
1833 | if (bootverbose) | ||
1834 | printf("tag_info[%d:%d] = %d\n", instance, targ, value); | ||
1835 | } | ||
1836 | } | ||
1837 | |||
1838 | static void | ||
1839 | ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value) | ||
1840 | { | ||
1841 | if ((instance >= 0) | ||
1842 | && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) { | ||
1843 | aic79xx_rd_strm_info[instance] = value & 0xFFFF; | ||
1844 | if (bootverbose) | ||
1845 | printf("rd_strm[%d] = 0x%x\n", instance, value); | ||
1846 | } | ||
1847 | } | ||
1848 | |||
1849 | static void | ||
1850 | ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value) | ||
1851 | { | ||
1852 | if ((instance >= 0) | ||
1853 | && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) { | ||
1854 | aic79xx_dv_settings[instance] = value; | ||
1855 | if (bootverbose) | ||
1856 | printf("dv[%d] = %d\n", instance, value); | ||
1857 | } | ||
1858 | } | ||
1859 | |||
1860 | static void | ||
1861 | ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) | 868 | ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) |
1862 | { | 869 | { |
1863 | 870 | ||
@@ -1887,6 +894,19 @@ ahd_linux_setup_tag_info_global(char *p) | |||
1887 | } | 894 | } |
1888 | } | 895 | } |
1889 | 896 | ||
897 | static void | ||
898 | ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | ||
899 | { | ||
900 | |||
901 | if ((instance >= 0) && (targ >= 0) | ||
902 | && (instance < NUM_ELEMENTS(aic79xx_tag_info)) | ||
903 | && (targ < AHD_NUM_TARGETS)) { | ||
904 | aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; | ||
905 | if (bootverbose) | ||
906 | printf("tag_info[%d:%d] = %d\n", instance, targ, value); | ||
907 | } | ||
908 | } | ||
909 | |||
1890 | /* | 910 | /* |
1891 | * Handle Linux boot parameters. This routine allows for assigning a value | 911 | * Handle Linux boot parameters. This routine allows for assigning a value |
1892 | * to a parameter with a ':' between the parameter and the value. | 912 | * to a parameter with a ':' between the parameter and the value. |
@@ -1916,8 +936,6 @@ aic79xx_setup(char *s) | |||
1916 | { "seltime", &aic79xx_seltime }, | 936 | { "seltime", &aic79xx_seltime }, |
1917 | { "tag_info", NULL }, | 937 | { "tag_info", NULL }, |
1918 | { "global_tag_depth", NULL}, | 938 | { "global_tag_depth", NULL}, |
1919 | { "rd_strm", NULL }, | ||
1920 | { "dv", NULL }, | ||
1921 | { "slewrate", NULL }, | 939 | { "slewrate", NULL }, |
1922 | { "precomp", NULL }, | 940 | { "precomp", NULL }, |
1923 | { "amplitude", NULL }, | 941 | { "amplitude", NULL }, |
@@ -1948,12 +966,6 @@ aic79xx_setup(char *s) | |||
1948 | } else if (strncmp(p, "tag_info", n) == 0) { | 966 | } else if (strncmp(p, "tag_info", n) == 0) { |
1949 | s = aic_parse_brace_option("tag_info", p + n, end, | 967 | s = aic_parse_brace_option("tag_info", p + n, end, |
1950 | 2, ahd_linux_setup_tag_info, 0); | 968 | 2, ahd_linux_setup_tag_info, 0); |
1951 | } else if (strncmp(p, "rd_strm", n) == 0) { | ||
1952 | s = aic_parse_brace_option("rd_strm", p + n, end, | ||
1953 | 1, ahd_linux_setup_rd_strm_info, 0); | ||
1954 | } else if (strncmp(p, "dv", n) == 0) { | ||
1955 | s = aic_parse_brace_option("dv", p + n, end, 1, | ||
1956 | ahd_linux_setup_dv, 0); | ||
1957 | } else if (strncmp(p, "slewrate", n) == 0) { | 969 | } else if (strncmp(p, "slewrate", n) == 0) { |
1958 | s = aic_parse_brace_option("slewrate", | 970 | s = aic_parse_brace_option("slewrate", |
1959 | p + n, end, 1, ahd_linux_setup_iocell_info, | 971 | p + n, end, 1, ahd_linux_setup_iocell_info, |
@@ -1982,13 +994,12 @@ __setup("aic79xx=", aic79xx_setup); | |||
1982 | uint32_t aic79xx_verbose; | 994 | uint32_t aic79xx_verbose; |
1983 | 995 | ||
1984 | int | 996 | int |
1985 | ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | 997 | ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template) |
1986 | { | 998 | { |
1987 | char buf[80]; | 999 | char buf[80]; |
1988 | struct Scsi_Host *host; | 1000 | struct Scsi_Host *host; |
1989 | char *new_name; | 1001 | char *new_name; |
1990 | u_long s; | 1002 | u_long s; |
1991 | u_long target; | ||
1992 | 1003 | ||
1993 | template->name = ahd->description; | 1004 | template->name = ahd->description; |
1994 | host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); | 1005 | host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); |
@@ -1997,11 +1008,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | |||
1997 | 1008 | ||
1998 | *((struct ahd_softc **)host->hostdata) = ahd; | 1009 | *((struct ahd_softc **)host->hostdata) = ahd; |
1999 | ahd_lock(ahd, &s); | 1010 | ahd_lock(ahd, &s); |
2000 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
2001 | scsi_assign_lock(host, &ahd->platform_data->spin_lock); | 1011 | scsi_assign_lock(host, &ahd->platform_data->spin_lock); |
2002 | #elif AHD_SCSI_HAS_HOST_LOCK != 0 | ||
2003 | host->lock = &ahd->platform_data->spin_lock; | ||
2004 | #endif | ||
2005 | ahd->platform_data->host = host; | 1012 | ahd->platform_data->host = host; |
2006 | host->can_queue = AHD_MAX_QUEUE; | 1013 | host->can_queue = AHD_MAX_QUEUE; |
2007 | host->cmd_per_lun = 2; | 1014 | host->cmd_per_lun = 2; |
@@ -2012,7 +1019,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | |||
2012 | host->max_lun = AHD_NUM_LUNS; | 1019 | host->max_lun = AHD_NUM_LUNS; |
2013 | host->max_channel = 0; | 1020 | host->max_channel = 0; |
2014 | host->sg_tablesize = AHD_NSEG; | 1021 | host->sg_tablesize = AHD_NSEG; |
2015 | ahd_set_unit(ahd, ahd_linux_next_unit()); | 1022 | ahd_set_unit(ahd, ahd_linux_unit++); |
2016 | sprintf(buf, "scsi%d", host->host_no); | 1023 | sprintf(buf, "scsi%d", host->host_no); |
2017 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | 1024 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); |
2018 | if (new_name != NULL) { | 1025 | if (new_name != NULL) { |
@@ -2020,54 +1027,14 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | |||
2020 | ahd_set_name(ahd, new_name); | 1027 | ahd_set_name(ahd, new_name); |
2021 | } | 1028 | } |
2022 | host->unique_id = ahd->unit; | 1029 | host->unique_id = ahd->unit; |
2023 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
2024 | scsi_set_pci_device(host, ahd->dev_softc); | ||
2025 | #endif | ||
2026 | ahd_linux_setup_user_rd_strm_settings(ahd); | ||
2027 | ahd_linux_initialize_scsi_bus(ahd); | 1030 | ahd_linux_initialize_scsi_bus(ahd); |
2028 | ahd_unlock(ahd, &s); | ||
2029 | ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0); | ||
2030 | ahd_lock(ahd, &s); | ||
2031 | if (ahd->platform_data->dv_pid < 0) { | ||
2032 | printf("%s: Failed to create DV thread, error= %d\n", | ||
2033 | ahd_name(ahd), ahd->platform_data->dv_pid); | ||
2034 | return (-ahd->platform_data->dv_pid); | ||
2035 | } | ||
2036 | /* | ||
2037 | * Initially allocate *all* of our linux target objects | ||
2038 | * so that the DV thread will scan them all in parallel | ||
2039 | * just after driver initialization. Any device that | ||
2040 | * does not exist will have its target object destroyed | ||
2041 | * by the selection timeout handler. In the case of a | ||
2042 | * device that appears after the initial DV scan, async | ||
2043 | * negotiation will occur for the first command, and DV | ||
2044 | * will comence should that first command be successful. | ||
2045 | */ | ||
2046 | for (target = 0; target < host->max_id; target++) { | ||
2047 | |||
2048 | /* | ||
2049 | * Skip our own ID. Some Compaq/HP storage devices | ||
2050 | * have enclosure management devices that respond to | ||
2051 | * single bit selection (i.e. selecting ourselves). | ||
2052 | * It is expected that either an external application | ||
2053 | * or a modified kernel will be used to probe this | ||
2054 | * ID if it is appropriate. To accommodate these | ||
2055 | * installations, ahc_linux_alloc_target() will allocate | ||
2056 | * for our ID if asked to do so. | ||
2057 | */ | ||
2058 | if (target == ahd->our_id) | ||
2059 | continue; | ||
2060 | |||
2061 | ahd_linux_alloc_target(ahd, 0, target); | ||
2062 | } | ||
2063 | ahd_intr_enable(ahd, TRUE); | 1031 | ahd_intr_enable(ahd, TRUE); |
2064 | ahd_linux_start_dv(ahd); | ||
2065 | ahd_unlock(ahd, &s); | 1032 | ahd_unlock(ahd, &s); |
2066 | 1033 | ||
2067 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1034 | host->transportt = ahd_linux_transport_template; |
1035 | |||
2068 | scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */ | 1036 | scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */ |
2069 | scsi_scan_host(host); | 1037 | scsi_scan_host(host); |
2070 | #endif | ||
2071 | return (0); | 1038 | return (0); |
2072 | } | 1039 | } |
2073 | 1040 | ||
@@ -2081,29 +1048,6 @@ ahd_linux_get_memsize(void) | |||
2081 | } | 1048 | } |
2082 | 1049 | ||
2083 | /* | 1050 | /* |
2084 | * Find the smallest available unit number to use | ||
2085 | * for a new device. We don't just use a static | ||
2086 | * count to handle the "repeated hot-(un)plug" | ||
2087 | * scenario. | ||
2088 | */ | ||
2089 | static int | ||
2090 | ahd_linux_next_unit(void) | ||
2091 | { | ||
2092 | struct ahd_softc *ahd; | ||
2093 | int unit; | ||
2094 | |||
2095 | unit = 0; | ||
2096 | retry: | ||
2097 | TAILQ_FOREACH(ahd, &ahd_tailq, links) { | ||
2098 | if (ahd->unit == unit) { | ||
2099 | unit++; | ||
2100 | goto retry; | ||
2101 | } | ||
2102 | } | ||
2103 | return (unit); | ||
2104 | } | ||
2105 | |||
2106 | /* | ||
2107 | * Place the SCSI bus into a known state by either resetting it, | 1051 | * Place the SCSI bus into a known state by either resetting it, |
2108 | * or forcing transfer negotiations on the next command to any | 1052 | * or forcing transfer negotiations on the next command to any |
2109 | * target. | 1053 | * target. |
@@ -2162,20 +1106,9 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) | |||
2162 | if (ahd->platform_data == NULL) | 1106 | if (ahd->platform_data == NULL) |
2163 | return (ENOMEM); | 1107 | return (ENOMEM); |
2164 | memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); | 1108 | memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); |
2165 | TAILQ_INIT(&ahd->platform_data->completeq); | ||
2166 | TAILQ_INIT(&ahd->platform_data->device_runq); | ||
2167 | ahd->platform_data->irq = AHD_LINUX_NOIRQ; | 1109 | ahd->platform_data->irq = AHD_LINUX_NOIRQ; |
2168 | ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; | ||
2169 | ahd_lockinit(ahd); | 1110 | ahd_lockinit(ahd); |
2170 | ahd_done_lockinit(ahd); | ||
2171 | init_timer(&ahd->platform_data->completeq_timer); | ||
2172 | ahd->platform_data->completeq_timer.data = (u_long)ahd; | ||
2173 | ahd->platform_data->completeq_timer.function = | ||
2174 | (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue; | ||
2175 | init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); | 1111 | init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); |
2176 | init_MUTEX_LOCKED(&ahd->platform_data->dv_sem); | ||
2177 | init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem); | ||
2178 | ahd_setup_runq_tasklet(ahd); | ||
2179 | ahd->seltime = (aic79xx_seltime & 0x3) << 4; | 1112 | ahd->seltime = (aic79xx_seltime & 0x3) << 4; |
2180 | return (0); | 1113 | return (0); |
2181 | } | 1114 | } |
@@ -2183,39 +1116,27 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) | |||
2183 | void | 1116 | void |
2184 | ahd_platform_free(struct ahd_softc *ahd) | 1117 | ahd_platform_free(struct ahd_softc *ahd) |
2185 | { | 1118 | { |
2186 | struct ahd_linux_target *targ; | 1119 | struct scsi_target *starget; |
2187 | struct ahd_linux_device *dev; | ||
2188 | int i, j; | 1120 | int i, j; |
2189 | 1121 | ||
2190 | if (ahd->platform_data != NULL) { | 1122 | if (ahd->platform_data != NULL) { |
2191 | del_timer_sync(&ahd->platform_data->completeq_timer); | ||
2192 | ahd_linux_kill_dv_thread(ahd); | ||
2193 | ahd_teardown_runq_tasklet(ahd); | ||
2194 | if (ahd->platform_data->host != NULL) { | 1123 | if (ahd->platform_data->host != NULL) { |
2195 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
2196 | scsi_remove_host(ahd->platform_data->host); | 1124 | scsi_remove_host(ahd->platform_data->host); |
2197 | #endif | ||
2198 | scsi_host_put(ahd->platform_data->host); | 1125 | scsi_host_put(ahd->platform_data->host); |
2199 | } | 1126 | } |
2200 | 1127 | ||
2201 | /* destroy all of the device and target objects */ | 1128 | /* destroy all of the device and target objects */ |
2202 | for (i = 0; i < AHD_NUM_TARGETS; i++) { | 1129 | for (i = 0; i < AHD_NUM_TARGETS; i++) { |
2203 | targ = ahd->platform_data->targets[i]; | 1130 | starget = ahd->platform_data->starget[i]; |
2204 | if (targ != NULL) { | 1131 | if (starget != NULL) { |
2205 | /* Keep target around through the loop. */ | ||
2206 | targ->refcount++; | ||
2207 | for (j = 0; j < AHD_NUM_LUNS; j++) { | 1132 | for (j = 0; j < AHD_NUM_LUNS; j++) { |
2208 | 1133 | struct ahd_linux_target *targ = | |
2209 | if (targ->devices[j] == NULL) | 1134 | scsi_transport_target_data(starget); |
1135 | if (targ->sdev[j] == NULL) | ||
2210 | continue; | 1136 | continue; |
2211 | dev = targ->devices[j]; | 1137 | targ->sdev[j] = NULL; |
2212 | ahd_linux_free_device(ahd, dev); | ||
2213 | } | 1138 | } |
2214 | /* | 1139 | ahd->platform_data->starget[i] = NULL; |
2215 | * Forcibly free the target now that | ||
2216 | * all devices are gone. | ||
2217 | */ | ||
2218 | ahd_linux_free_target(ahd, targ); | ||
2219 | } | 1140 | } |
2220 | } | 1141 | } |
2221 | 1142 | ||
@@ -2233,16 +1154,6 @@ ahd_platform_free(struct ahd_softc *ahd) | |||
2233 | release_mem_region(ahd->platform_data->mem_busaddr, | 1154 | release_mem_region(ahd->platform_data->mem_busaddr, |
2234 | 0x1000); | 1155 | 0x1000); |
2235 | } | 1156 | } |
2236 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
2237 | /* | ||
2238 | * In 2.4 we detach from the scsi midlayer before the PCI | ||
2239 | * layer invokes our remove callback. No per-instance | ||
2240 | * detach is provided, so we must reach inside the PCI | ||
2241 | * subsystem's internals and detach our driver manually. | ||
2242 | */ | ||
2243 | if (ahd->dev_softc != NULL) | ||
2244 | ahd->dev_softc->driver = NULL; | ||
2245 | #endif | ||
2246 | free(ahd->platform_data, M_DEVBUF); | 1157 | free(ahd->platform_data, M_DEVBUF); |
2247 | } | 1158 | } |
2248 | } | 1159 | } |
@@ -2280,13 +1191,22 @@ void | |||
2280 | ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | 1191 | ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
2281 | ahd_queue_alg alg) | 1192 | ahd_queue_alg alg) |
2282 | { | 1193 | { |
1194 | struct scsi_target *starget; | ||
1195 | struct ahd_linux_target *targ; | ||
2283 | struct ahd_linux_device *dev; | 1196 | struct ahd_linux_device *dev; |
1197 | struct scsi_device *sdev; | ||
2284 | int was_queuing; | 1198 | int was_queuing; |
2285 | int now_queuing; | 1199 | int now_queuing; |
2286 | 1200 | ||
2287 | dev = ahd_linux_get_device(ahd, devinfo->channel - 'A', | 1201 | starget = ahd->platform_data->starget[devinfo->target]; |
2288 | devinfo->target, | 1202 | targ = scsi_transport_target_data(starget); |
2289 | devinfo->lun, /*alloc*/FALSE); | 1203 | BUG_ON(targ == NULL); |
1204 | sdev = targ->sdev[devinfo->lun]; | ||
1205 | if (sdev == NULL) | ||
1206 | return; | ||
1207 | |||
1208 | dev = scsi_transport_device_data(sdev); | ||
1209 | |||
2290 | if (dev == NULL) | 1210 | if (dev == NULL) |
2291 | return; | 1211 | return; |
2292 | was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); | 1212 | was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); |
@@ -2339,1434 +1259,37 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | |||
2339 | dev->maxtags = 0; | 1259 | dev->maxtags = 0; |
2340 | dev->openings = 1 - dev->active; | 1260 | dev->openings = 1 - dev->active; |
2341 | } | 1261 | } |
2342 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
2343 | if (dev->scsi_device != NULL) { | ||
2344 | switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { | ||
2345 | case AHD_DEV_Q_BASIC: | ||
2346 | scsi_adjust_queue_depth(dev->scsi_device, | ||
2347 | MSG_SIMPLE_TASK, | ||
2348 | dev->openings + dev->active); | ||
2349 | break; | ||
2350 | case AHD_DEV_Q_TAGGED: | ||
2351 | scsi_adjust_queue_depth(dev->scsi_device, | ||
2352 | MSG_ORDERED_TASK, | ||
2353 | dev->openings + dev->active); | ||
2354 | break; | ||
2355 | default: | ||
2356 | /* | ||
2357 | * We allow the OS to queue 2 untagged transactions to | ||
2358 | * us at any time even though we can only execute them | ||
2359 | * serially on the controller/device. This should | ||
2360 | * remove some latency. | ||
2361 | */ | ||
2362 | scsi_adjust_queue_depth(dev->scsi_device, | ||
2363 | /*NON-TAGGED*/0, | ||
2364 | /*queue depth*/2); | ||
2365 | break; | ||
2366 | } | ||
2367 | } | ||
2368 | #endif | ||
2369 | } | ||
2370 | |||
2371 | int | ||
2372 | ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, | ||
2373 | int lun, u_int tag, role_t role, uint32_t status) | ||
2374 | { | ||
2375 | int targ; | ||
2376 | int maxtarg; | ||
2377 | int maxlun; | ||
2378 | int clun; | ||
2379 | int count; | ||
2380 | |||
2381 | if (tag != SCB_LIST_NULL) | ||
2382 | return (0); | ||
2383 | |||
2384 | targ = 0; | ||
2385 | if (target != CAM_TARGET_WILDCARD) { | ||
2386 | targ = target; | ||
2387 | maxtarg = targ + 1; | ||
2388 | } else { | ||
2389 | maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8; | ||
2390 | } | ||
2391 | clun = 0; | ||
2392 | if (lun != CAM_LUN_WILDCARD) { | ||
2393 | clun = lun; | ||
2394 | maxlun = clun + 1; | ||
2395 | } else { | ||
2396 | maxlun = AHD_NUM_LUNS; | ||
2397 | } | ||
2398 | |||
2399 | count = 0; | ||
2400 | for (; targ < maxtarg; targ++) { | ||
2401 | |||
2402 | for (; clun < maxlun; clun++) { | ||
2403 | struct ahd_linux_device *dev; | ||
2404 | struct ahd_busyq *busyq; | ||
2405 | struct ahd_cmd *acmd; | ||
2406 | |||
2407 | dev = ahd_linux_get_device(ahd, /*chan*/0, targ, | ||
2408 | clun, /*alloc*/FALSE); | ||
2409 | if (dev == NULL) | ||
2410 | continue; | ||
2411 | |||
2412 | busyq = &dev->busyq; | ||
2413 | while ((acmd = TAILQ_FIRST(busyq)) != NULL) { | ||
2414 | Scsi_Cmnd *cmd; | ||
2415 | |||
2416 | cmd = &acmd_scsi_cmd(acmd); | ||
2417 | TAILQ_REMOVE(busyq, acmd, | ||
2418 | acmd_links.tqe); | ||
2419 | count++; | ||
2420 | cmd->result = status << 16; | ||
2421 | ahd_linux_queue_cmd_complete(ahd, cmd); | ||
2422 | } | ||
2423 | } | ||
2424 | } | ||
2425 | |||
2426 | return (count); | ||
2427 | } | ||
2428 | |||
2429 | static void | ||
2430 | ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd) | ||
2431 | { | ||
2432 | u_long flags; | ||
2433 | |||
2434 | ahd_lock(ahd, &flags); | ||
2435 | del_timer(&ahd->platform_data->completeq_timer); | ||
2436 | ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER; | ||
2437 | ahd_linux_run_complete_queue(ahd); | ||
2438 | ahd_unlock(ahd, &flags); | ||
2439 | } | ||
2440 | |||
2441 | static void | ||
2442 | ahd_linux_start_dv(struct ahd_softc *ahd) | ||
2443 | { | ||
2444 | |||
2445 | /* | ||
2446 | * Freeze the simq and signal ahd_linux_queue to not let any | ||
2447 | * more commands through | ||
2448 | */ | ||
2449 | if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) { | ||
2450 | #ifdef AHD_DEBUG | ||
2451 | if (ahd_debug & AHD_SHOW_DV) | ||
2452 | printf("%s: Starting DV\n", ahd_name(ahd)); | ||
2453 | #endif | ||
2454 | |||
2455 | ahd->platform_data->flags |= AHD_DV_ACTIVE; | ||
2456 | ahd_freeze_simq(ahd); | ||
2457 | |||
2458 | /* Wake up the DV kthread */ | ||
2459 | up(&ahd->platform_data->dv_sem); | ||
2460 | } | ||
2461 | } | ||
2462 | |||
2463 | static int | ||
2464 | ahd_linux_dv_thread(void *data) | ||
2465 | { | ||
2466 | struct ahd_softc *ahd; | ||
2467 | int target; | ||
2468 | u_long s; | ||
2469 | |||
2470 | ahd = (struct ahd_softc *)data; | ||
2471 | |||
2472 | #ifdef AHD_DEBUG | ||
2473 | if (ahd_debug & AHD_SHOW_DV) | ||
2474 | printf("In DV Thread\n"); | ||
2475 | #endif | ||
2476 | |||
2477 | /* | ||
2478 | * Complete thread creation. | ||
2479 | */ | ||
2480 | lock_kernel(); | ||
2481 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) | ||
2482 | /* | ||
2483 | * Don't care about any signals. | ||
2484 | */ | ||
2485 | siginitsetinv(¤t->blocked, 0); | ||
2486 | |||
2487 | daemonize(); | ||
2488 | sprintf(current->comm, "ahd_dv_%d", ahd->unit); | ||
2489 | #else | ||
2490 | daemonize("ahd_dv_%d", ahd->unit); | ||
2491 | current->flags |= PF_NOFREEZE; | ||
2492 | #endif | ||
2493 | unlock_kernel(); | ||
2494 | |||
2495 | while (1) { | ||
2496 | /* | ||
2497 | * Use down_interruptible() rather than down() to | ||
2498 | * avoid inclusion in the load average. | ||
2499 | */ | ||
2500 | down_interruptible(&ahd->platform_data->dv_sem); | ||
2501 | |||
2502 | /* Check to see if we've been signaled to exit */ | ||
2503 | ahd_lock(ahd, &s); | ||
2504 | if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) { | ||
2505 | ahd_unlock(ahd, &s); | ||
2506 | break; | ||
2507 | } | ||
2508 | ahd_unlock(ahd, &s); | ||
2509 | |||
2510 | #ifdef AHD_DEBUG | ||
2511 | if (ahd_debug & AHD_SHOW_DV) | ||
2512 | printf("%s: Beginning Domain Validation\n", | ||
2513 | ahd_name(ahd)); | ||
2514 | #endif | ||
2515 | |||
2516 | /* | ||
2517 | * Wait for any pending commands to drain before proceeding. | ||
2518 | */ | ||
2519 | ahd_lock(ahd, &s); | ||
2520 | while (LIST_FIRST(&ahd->pending_scbs) != NULL) { | ||
2521 | ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY; | ||
2522 | ahd_unlock(ahd, &s); | ||
2523 | down_interruptible(&ahd->platform_data->dv_sem); | ||
2524 | ahd_lock(ahd, &s); | ||
2525 | } | ||
2526 | |||
2527 | /* | ||
2528 | * Wait for the SIMQ to be released so that DV is the | ||
2529 | * only reason the queue is frozen. | ||
2530 | */ | ||
2531 | while (AHD_DV_SIMQ_FROZEN(ahd) == 0) { | ||
2532 | ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE; | ||
2533 | ahd_unlock(ahd, &s); | ||
2534 | down_interruptible(&ahd->platform_data->dv_sem); | ||
2535 | ahd_lock(ahd, &s); | ||
2536 | } | ||
2537 | ahd_unlock(ahd, &s); | ||
2538 | |||
2539 | for (target = 0; target < AHD_NUM_TARGETS; target++) | ||
2540 | ahd_linux_dv_target(ahd, target); | ||
2541 | |||
2542 | ahd_lock(ahd, &s); | ||
2543 | ahd->platform_data->flags &= ~AHD_DV_ACTIVE; | ||
2544 | ahd_unlock(ahd, &s); | ||
2545 | |||
2546 | /* | ||
2547 | * Release the SIMQ so that normal commands are | ||
2548 | * allowed to continue on the bus. | ||
2549 | */ | ||
2550 | ahd_release_simq(ahd); | ||
2551 | } | ||
2552 | up(&ahd->platform_data->eh_sem); | ||
2553 | return (0); | ||
2554 | } | ||
2555 | |||
2556 | static void | ||
2557 | ahd_linux_kill_dv_thread(struct ahd_softc *ahd) | ||
2558 | { | ||
2559 | u_long s; | ||
2560 | |||
2561 | ahd_lock(ahd, &s); | ||
2562 | if (ahd->platform_data->dv_pid != 0) { | ||
2563 | ahd->platform_data->flags |= AHD_DV_SHUTDOWN; | ||
2564 | ahd_unlock(ahd, &s); | ||
2565 | up(&ahd->platform_data->dv_sem); | ||
2566 | |||
2567 | /* | ||
2568 | * Use the eh_sem as an indicator that the | ||
2569 | * dv thread is exiting. Note that the dv | ||
2570 | * thread must still return after performing | ||
2571 | * the up on our semaphore before it has | ||
2572 | * completely exited this module. Unfortunately, | ||
2573 | * there seems to be no easy way to wait for the | ||
2574 | * exit of a thread for which you are not the | ||
2575 | * parent (dv threads are parented by init). | ||
2576 | * Cross your fingers... | ||
2577 | */ | ||
2578 | down(&ahd->platform_data->eh_sem); | ||
2579 | |||
2580 | /* | ||
2581 | * Mark the dv thread as already dead. This | ||
2582 | * avoids attempting to kill it a second time. | ||
2583 | * This is necessary because we must kill the | ||
2584 | * DV thread before calling ahd_free() in the | ||
2585 | * module shutdown case to avoid bogus locking | ||
2586 | * in the SCSI mid-layer, but we ahd_free() is | ||
2587 | * called without killing the DV thread in the | ||
2588 | * instance detach case, so ahd_platform_free() | ||
2589 | * calls us again to verify that the DV thread | ||
2590 | * is dead. | ||
2591 | */ | ||
2592 | ahd->platform_data->dv_pid = 0; | ||
2593 | } else { | ||
2594 | ahd_unlock(ahd, &s); | ||
2595 | } | ||
2596 | } | ||
2597 | |||
2598 | #define AHD_LINUX_DV_INQ_SHORT_LEN 36 | ||
2599 | #define AHD_LINUX_DV_INQ_LEN 256 | ||
2600 | #define AHD_LINUX_DV_TIMEOUT (HZ / 4) | ||
2601 | |||
2602 | #define AHD_SET_DV_STATE(ahd, targ, newstate) \ | ||
2603 | ahd_set_dv_state(ahd, targ, newstate, __LINE__) | ||
2604 | |||
2605 | static __inline void | ||
2606 | ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ, | ||
2607 | ahd_dv_state newstate, u_int line) | ||
2608 | { | ||
2609 | ahd_dv_state oldstate; | ||
2610 | |||
2611 | oldstate = targ->dv_state; | ||
2612 | #ifdef AHD_DEBUG | ||
2613 | if (ahd_debug & AHD_SHOW_DV) | ||
2614 | printf("%s:%d: Going from state %d to state %d\n", | ||
2615 | ahd_name(ahd), line, oldstate, newstate); | ||
2616 | #endif | ||
2617 | |||
2618 | if (oldstate == newstate) | ||
2619 | targ->dv_state_retry++; | ||
2620 | else | ||
2621 | targ->dv_state_retry = 0; | ||
2622 | targ->dv_state = newstate; | ||
2623 | } | ||
2624 | |||
2625 | static void | ||
2626 | ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset) | ||
2627 | { | ||
2628 | struct ahd_devinfo devinfo; | ||
2629 | struct ahd_linux_target *targ; | ||
2630 | struct scsi_cmnd *cmd; | ||
2631 | struct scsi_device *scsi_dev; | ||
2632 | struct scsi_sense_data *sense; | ||
2633 | uint8_t *buffer; | ||
2634 | u_long s; | ||
2635 | u_int timeout; | ||
2636 | int echo_size; | ||
2637 | |||
2638 | sense = NULL; | ||
2639 | buffer = NULL; | ||
2640 | echo_size = 0; | ||
2641 | ahd_lock(ahd, &s); | ||
2642 | targ = ahd->platform_data->targets[target_offset]; | ||
2643 | if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) { | ||
2644 | ahd_unlock(ahd, &s); | ||
2645 | return; | ||
2646 | } | ||
2647 | ahd_compile_devinfo(&devinfo, ahd->our_id, targ->target, /*lun*/0, | ||
2648 | targ->channel + 'A', ROLE_INITIATOR); | ||
2649 | #ifdef AHD_DEBUG | ||
2650 | if (ahd_debug & AHD_SHOW_DV) { | ||
2651 | ahd_print_devinfo(ahd, &devinfo); | ||
2652 | printf("Performing DV\n"); | ||
2653 | } | ||
2654 | #endif | ||
2655 | |||
2656 | ahd_unlock(ahd, &s); | ||
2657 | |||
2658 | cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK); | ||
2659 | scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK); | ||
2660 | scsi_dev->host = ahd->platform_data->host; | ||
2661 | scsi_dev->id = devinfo.target; | ||
2662 | scsi_dev->lun = devinfo.lun; | ||
2663 | scsi_dev->channel = devinfo.channel - 'A'; | ||
2664 | ahd->platform_data->dv_scsi_dev = scsi_dev; | ||
2665 | |||
2666 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
2667 | |||
2668 | while (targ->dv_state != AHD_DV_STATE_EXIT) { | ||
2669 | timeout = AHD_LINUX_DV_TIMEOUT; | ||
2670 | switch (targ->dv_state) { | ||
2671 | case AHD_DV_STATE_INQ_SHORT_ASYNC: | ||
2672 | case AHD_DV_STATE_INQ_ASYNC: | ||
2673 | case AHD_DV_STATE_INQ_ASYNC_VERIFY: | ||
2674 | /* | ||
2675 | * Set things to async narrow to reduce the | ||
2676 | * chance that the INQ will fail. | ||
2677 | */ | ||
2678 | ahd_lock(ahd, &s); | ||
2679 | ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, | ||
2680 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
2681 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, | ||
2682 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
2683 | ahd_unlock(ahd, &s); | ||
2684 | timeout = 10 * HZ; | ||
2685 | targ->flags &= ~AHD_INQ_VALID; | ||
2686 | /* FALLTHROUGH */ | ||
2687 | case AHD_DV_STATE_INQ_VERIFY: | ||
2688 | { | ||
2689 | u_int inq_len; | ||
2690 | |||
2691 | if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC) | ||
2692 | inq_len = AHD_LINUX_DV_INQ_SHORT_LEN; | ||
2693 | else | ||
2694 | inq_len = targ->inq_data->additional_length + 5; | ||
2695 | ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len); | ||
2696 | break; | ||
2697 | } | ||
2698 | case AHD_DV_STATE_TUR: | ||
2699 | case AHD_DV_STATE_BUSY: | ||
2700 | timeout = 5 * HZ; | ||
2701 | ahd_linux_dv_tur(ahd, cmd, &devinfo); | ||
2702 | break; | ||
2703 | case AHD_DV_STATE_REBD: | ||
2704 | ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ); | ||
2705 | break; | ||
2706 | case AHD_DV_STATE_WEB: | ||
2707 | ahd_linux_dv_web(ahd, cmd, &devinfo, targ); | ||
2708 | break; | ||
2709 | |||
2710 | case AHD_DV_STATE_REB: | ||
2711 | ahd_linux_dv_reb(ahd, cmd, &devinfo, targ); | ||
2712 | break; | ||
2713 | |||
2714 | case AHD_DV_STATE_SU: | ||
2715 | ahd_linux_dv_su(ahd, cmd, &devinfo, targ); | ||
2716 | timeout = 50 * HZ; | ||
2717 | break; | ||
2718 | |||
2719 | default: | ||
2720 | ahd_print_devinfo(ahd, &devinfo); | ||
2721 | printf("Unknown DV state %d\n", targ->dv_state); | ||
2722 | goto out; | ||
2723 | } | ||
2724 | |||
2725 | /* Queue the command and wait for it to complete */ | ||
2726 | /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */ | ||
2727 | init_timer(&cmd->eh_timeout); | ||
2728 | #ifdef AHD_DEBUG | ||
2729 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) | ||
2730 | /* | ||
2731 | * All of the printfs during negotiation | ||
2732 | * really slow down the negotiation. | ||
2733 | * Add a bit of time just to be safe. | ||
2734 | */ | ||
2735 | timeout += HZ; | ||
2736 | #endif | ||
2737 | scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout); | ||
2738 | /* | ||
2739 | * In 2.5.X, it is assumed that all calls from the | ||
2740 | * "midlayer" (which we are emulating) will have the | ||
2741 | * ahd host lock held. For other kernels, the | ||
2742 | * io_request_lock must be held. | ||
2743 | */ | ||
2744 | #if AHD_SCSI_HAS_HOST_LOCK != 0 | ||
2745 | ahd_lock(ahd, &s); | ||
2746 | #else | ||
2747 | spin_lock_irqsave(&io_request_lock, s); | ||
2748 | #endif | ||
2749 | ahd_linux_queue(cmd, ahd_linux_dv_complete); | ||
2750 | #if AHD_SCSI_HAS_HOST_LOCK != 0 | ||
2751 | ahd_unlock(ahd, &s); | ||
2752 | #else | ||
2753 | spin_unlock_irqrestore(&io_request_lock, s); | ||
2754 | #endif | ||
2755 | down_interruptible(&ahd->platform_data->dv_cmd_sem); | ||
2756 | /* | ||
2757 | * Wait for the SIMQ to be released so that DV is the | ||
2758 | * only reason the queue is frozen. | ||
2759 | */ | ||
2760 | ahd_lock(ahd, &s); | ||
2761 | while (AHD_DV_SIMQ_FROZEN(ahd) == 0) { | ||
2762 | ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE; | ||
2763 | ahd_unlock(ahd, &s); | ||
2764 | down_interruptible(&ahd->platform_data->dv_sem); | ||
2765 | ahd_lock(ahd, &s); | ||
2766 | } | ||
2767 | ahd_unlock(ahd, &s); | ||
2768 | |||
2769 | ahd_linux_dv_transition(ahd, cmd, &devinfo, targ); | ||
2770 | } | ||
2771 | |||
2772 | out: | ||
2773 | if ((targ->flags & AHD_INQ_VALID) != 0 | ||
2774 | && ahd_linux_get_device(ahd, devinfo.channel - 'A', | ||
2775 | devinfo.target, devinfo.lun, | ||
2776 | /*alloc*/FALSE) == NULL) { | ||
2777 | /* | ||
2778 | * The DV state machine failed to configure this device. | ||
2779 | * This is normal if DV is disabled. Since we have inquiry | ||
2780 | * data, filter it and use the "optimistic" negotiation | ||
2781 | * parameters found in the inquiry string. | ||
2782 | */ | ||
2783 | ahd_linux_filter_inquiry(ahd, &devinfo); | ||
2784 | if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) { | ||
2785 | ahd_print_devinfo(ahd, &devinfo); | ||
2786 | printf("DV failed to configure device. " | ||
2787 | "Please file a bug report against " | ||
2788 | "this driver.\n"); | ||
2789 | } | ||
2790 | } | ||
2791 | |||
2792 | if (cmd != NULL) | ||
2793 | free(cmd, M_DEVBUF); | ||
2794 | |||
2795 | if (ahd->platform_data->dv_scsi_dev != NULL) { | ||
2796 | free(ahd->platform_data->dv_scsi_dev, M_DEVBUF); | ||
2797 | ahd->platform_data->dv_scsi_dev = NULL; | ||
2798 | } | ||
2799 | |||
2800 | ahd_lock(ahd, &s); | ||
2801 | if (targ->dv_buffer != NULL) { | ||
2802 | free(targ->dv_buffer, M_DEVBUF); | ||
2803 | targ->dv_buffer = NULL; | ||
2804 | } | ||
2805 | if (targ->dv_buffer1 != NULL) { | ||
2806 | free(targ->dv_buffer1, M_DEVBUF); | ||
2807 | targ->dv_buffer1 = NULL; | ||
2808 | } | ||
2809 | targ->flags &= ~AHD_DV_REQUIRED; | ||
2810 | if (targ->refcount == 0) | ||
2811 | ahd_linux_free_target(ahd, targ); | ||
2812 | ahd_unlock(ahd, &s); | ||
2813 | } | ||
2814 | |||
2815 | static __inline int | ||
2816 | ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | ||
2817 | { | ||
2818 | u_long s; | ||
2819 | int retval; | ||
2820 | |||
2821 | ahd_lock(ahd, &s); | ||
2822 | retval = ahd_linux_fallback(ahd, devinfo); | ||
2823 | ahd_unlock(ahd, &s); | ||
2824 | |||
2825 | return (retval); | ||
2826 | } | ||
2827 | |||
2828 | static void | ||
2829 | ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
2830 | struct ahd_devinfo *devinfo, | ||
2831 | struct ahd_linux_target *targ) | ||
2832 | { | ||
2833 | u_int32_t status; | ||
2834 | |||
2835 | status = aic_error_action(cmd, targ->inq_data, | ||
2836 | ahd_cmd_get_transaction_status(cmd), | ||
2837 | ahd_cmd_get_scsi_status(cmd)); | ||
2838 | |||
2839 | |||
2840 | #ifdef AHD_DEBUG | ||
2841 | if (ahd_debug & AHD_SHOW_DV) { | ||
2842 | ahd_print_devinfo(ahd, devinfo); | ||
2843 | printf("Entering ahd_linux_dv_transition, state= %d, " | ||
2844 | "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state, | ||
2845 | status, cmd->result); | ||
2846 | } | ||
2847 | #endif | ||
2848 | |||
2849 | switch (targ->dv_state) { | ||
2850 | case AHD_DV_STATE_INQ_SHORT_ASYNC: | ||
2851 | case AHD_DV_STATE_INQ_ASYNC: | ||
2852 | switch (status & SS_MASK) { | ||
2853 | case SS_NOP: | ||
2854 | { | ||
2855 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1); | ||
2856 | break; | ||
2857 | } | ||
2858 | case SS_INQ_REFRESH: | ||
2859 | AHD_SET_DV_STATE(ahd, targ, | ||
2860 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
2861 | break; | ||
2862 | case SS_TUR: | ||
2863 | case SS_RETRY: | ||
2864 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
2865 | if (ahd_cmd_get_transaction_status(cmd) | ||
2866 | == CAM_REQUEUE_REQ) | ||
2867 | targ->dv_state_retry--; | ||
2868 | if ((status & SS_ERRMASK) == EBUSY) | ||
2869 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); | ||
2870 | if (targ->dv_state_retry < 10) | ||
2871 | break; | ||
2872 | /* FALLTHROUGH */ | ||
2873 | default: | ||
2874 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
2875 | #ifdef AHD_DEBUG | ||
2876 | if (ahd_debug & AHD_SHOW_DV) { | ||
2877 | ahd_print_devinfo(ahd, devinfo); | ||
2878 | printf("Failed DV inquiry, skipping\n"); | ||
2879 | } | ||
2880 | #endif | ||
2881 | break; | ||
2882 | } | ||
2883 | break; | ||
2884 | case AHD_DV_STATE_INQ_ASYNC_VERIFY: | ||
2885 | switch (status & SS_MASK) { | ||
2886 | case SS_NOP: | ||
2887 | { | ||
2888 | u_int xportflags; | ||
2889 | u_int spi3data; | ||
2890 | |||
2891 | if (memcmp(targ->inq_data, targ->dv_buffer, | ||
2892 | AHD_LINUX_DV_INQ_LEN) != 0) { | ||
2893 | /* | ||
2894 | * Inquiry data must have changed. | ||
2895 | * Try from the top again. | ||
2896 | */ | ||
2897 | AHD_SET_DV_STATE(ahd, targ, | ||
2898 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
2899 | break; | ||
2900 | } | ||
2901 | |||
2902 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1); | ||
2903 | targ->flags |= AHD_INQ_VALID; | ||
2904 | if (ahd_linux_user_dv_setting(ahd) == 0) | ||
2905 | break; | ||
2906 | |||
2907 | xportflags = targ->inq_data->flags; | ||
2908 | if ((xportflags & (SID_Sync|SID_WBus16)) == 0) | ||
2909 | break; | ||
2910 | |||
2911 | spi3data = targ->inq_data->spi3data; | ||
2912 | switch (spi3data & SID_SPI_CLOCK_DT_ST) { | ||
2913 | default: | ||
2914 | case SID_SPI_CLOCK_ST: | ||
2915 | /* Assume only basic DV is supported. */ | ||
2916 | targ->flags |= AHD_BASIC_DV; | ||
2917 | break; | ||
2918 | case SID_SPI_CLOCK_DT: | ||
2919 | case SID_SPI_CLOCK_DT_ST: | ||
2920 | targ->flags |= AHD_ENHANCED_DV; | ||
2921 | break; | ||
2922 | } | ||
2923 | break; | ||
2924 | } | ||
2925 | case SS_INQ_REFRESH: | ||
2926 | AHD_SET_DV_STATE(ahd, targ, | ||
2927 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
2928 | break; | ||
2929 | case SS_TUR: | ||
2930 | case SS_RETRY: | ||
2931 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
2932 | if (ahd_cmd_get_transaction_status(cmd) | ||
2933 | == CAM_REQUEUE_REQ) | ||
2934 | targ->dv_state_retry--; | ||
2935 | |||
2936 | if ((status & SS_ERRMASK) == EBUSY) | ||
2937 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); | ||
2938 | if (targ->dv_state_retry < 10) | ||
2939 | break; | ||
2940 | /* FALLTHROUGH */ | ||
2941 | default: | ||
2942 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
2943 | #ifdef AHD_DEBUG | ||
2944 | if (ahd_debug & AHD_SHOW_DV) { | ||
2945 | ahd_print_devinfo(ahd, devinfo); | ||
2946 | printf("Failed DV inquiry, skipping\n"); | ||
2947 | } | ||
2948 | #endif | ||
2949 | break; | ||
2950 | } | ||
2951 | break; | ||
2952 | case AHD_DV_STATE_INQ_VERIFY: | ||
2953 | switch (status & SS_MASK) { | ||
2954 | case SS_NOP: | ||
2955 | { | ||
2956 | |||
2957 | if (memcmp(targ->inq_data, targ->dv_buffer, | ||
2958 | AHD_LINUX_DV_INQ_LEN) == 0) { | ||
2959 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
2960 | break; | ||
2961 | } | ||
2962 | |||
2963 | #ifdef AHD_DEBUG | ||
2964 | if (ahd_debug & AHD_SHOW_DV) { | ||
2965 | int i; | ||
2966 | |||
2967 | ahd_print_devinfo(ahd, devinfo); | ||
2968 | printf("Inquiry buffer mismatch:"); | ||
2969 | for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) { | ||
2970 | if ((i & 0xF) == 0) | ||
2971 | printf("\n "); | ||
2972 | printf("0x%x:0x0%x ", | ||
2973 | ((uint8_t *)targ->inq_data)[i], | ||
2974 | targ->dv_buffer[i]); | ||
2975 | } | ||
2976 | printf("\n"); | ||
2977 | } | ||
2978 | #endif | ||
2979 | |||
2980 | if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { | ||
2981 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
2982 | break; | ||
2983 | } | ||
2984 | /* | ||
2985 | * Do not count "falling back" | ||
2986 | * against our retries. | ||
2987 | */ | ||
2988 | targ->dv_state_retry = 0; | ||
2989 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
2990 | break; | ||
2991 | } | ||
2992 | case SS_INQ_REFRESH: | ||
2993 | AHD_SET_DV_STATE(ahd, targ, | ||
2994 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
2995 | break; | ||
2996 | case SS_TUR: | ||
2997 | case SS_RETRY: | ||
2998 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
2999 | if (ahd_cmd_get_transaction_status(cmd) | ||
3000 | == CAM_REQUEUE_REQ) { | ||
3001 | targ->dv_state_retry--; | ||
3002 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
3003 | if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { | ||
3004 | AHD_SET_DV_STATE(ahd, targ, | ||
3005 | AHD_DV_STATE_EXIT); | ||
3006 | break; | ||
3007 | } | ||
3008 | /* | ||
3009 | * Do not count "falling back" | ||
3010 | * against our retries. | ||
3011 | */ | ||
3012 | targ->dv_state_retry = 0; | ||
3013 | } else if ((status & SS_ERRMASK) == EBUSY) | ||
3014 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); | ||
3015 | if (targ->dv_state_retry < 10) | ||
3016 | break; | ||
3017 | /* FALLTHROUGH */ | ||
3018 | default: | ||
3019 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3020 | #ifdef AHD_DEBUG | ||
3021 | if (ahd_debug & AHD_SHOW_DV) { | ||
3022 | ahd_print_devinfo(ahd, devinfo); | ||
3023 | printf("Failed DV inquiry, skipping\n"); | ||
3024 | } | ||
3025 | #endif | ||
3026 | break; | ||
3027 | } | ||
3028 | break; | ||
3029 | |||
3030 | case AHD_DV_STATE_TUR: | ||
3031 | switch (status & SS_MASK) { | ||
3032 | case SS_NOP: | ||
3033 | if ((targ->flags & AHD_BASIC_DV) != 0) { | ||
3034 | ahd_linux_filter_inquiry(ahd, devinfo); | ||
3035 | AHD_SET_DV_STATE(ahd, targ, | ||
3036 | AHD_DV_STATE_INQ_VERIFY); | ||
3037 | } else if ((targ->flags & AHD_ENHANCED_DV) != 0) { | ||
3038 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD); | ||
3039 | } else { | ||
3040 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3041 | } | ||
3042 | break; | ||
3043 | case SS_RETRY: | ||
3044 | case SS_TUR: | ||
3045 | if ((status & SS_ERRMASK) == EBUSY) { | ||
3046 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); | ||
3047 | break; | ||
3048 | } | ||
3049 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
3050 | if (ahd_cmd_get_transaction_status(cmd) | ||
3051 | == CAM_REQUEUE_REQ) { | ||
3052 | targ->dv_state_retry--; | ||
3053 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
3054 | if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { | ||
3055 | AHD_SET_DV_STATE(ahd, targ, | ||
3056 | AHD_DV_STATE_EXIT); | ||
3057 | break; | ||
3058 | } | ||
3059 | /* | ||
3060 | * Do not count "falling back" | ||
3061 | * against our retries. | ||
3062 | */ | ||
3063 | targ->dv_state_retry = 0; | ||
3064 | } | ||
3065 | if (targ->dv_state_retry >= 10) { | ||
3066 | #ifdef AHD_DEBUG | ||
3067 | if (ahd_debug & AHD_SHOW_DV) { | ||
3068 | ahd_print_devinfo(ahd, devinfo); | ||
3069 | printf("DV TUR reties exhausted\n"); | ||
3070 | } | ||
3071 | #endif | ||
3072 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3073 | break; | ||
3074 | } | ||
3075 | if (status & SSQ_DELAY) | ||
3076 | ssleep(1); | ||
3077 | 1262 | ||
3078 | break; | 1263 | switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { |
3079 | case SS_START: | 1264 | case AHD_DEV_Q_BASIC: |
3080 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU); | 1265 | scsi_adjust_queue_depth(sdev, |
3081 | break; | 1266 | MSG_SIMPLE_TASK, |
3082 | case SS_INQ_REFRESH: | 1267 | dev->openings + dev->active); |
3083 | AHD_SET_DV_STATE(ahd, targ, | ||
3084 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
3085 | break; | ||
3086 | default: | ||
3087 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3088 | break; | ||
3089 | } | ||
3090 | break; | 1268 | break; |
3091 | 1269 | case AHD_DEV_Q_TAGGED: | |
3092 | case AHD_DV_STATE_REBD: | 1270 | scsi_adjust_queue_depth(sdev, |
3093 | switch (status & SS_MASK) { | 1271 | MSG_ORDERED_TASK, |
3094 | case SS_NOP: | 1272 | dev->openings + dev->active); |
3095 | { | ||
3096 | uint32_t echo_size; | ||
3097 | |||
3098 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB); | ||
3099 | echo_size = scsi_3btoul(&targ->dv_buffer[1]); | ||
3100 | echo_size &= 0x1FFF; | ||
3101 | #ifdef AHD_DEBUG | ||
3102 | if (ahd_debug & AHD_SHOW_DV) { | ||
3103 | ahd_print_devinfo(ahd, devinfo); | ||
3104 | printf("Echo buffer size= %d\n", echo_size); | ||
3105 | } | ||
3106 | #endif | ||
3107 | if (echo_size == 0) { | ||
3108 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3109 | break; | ||
3110 | } | ||
3111 | |||
3112 | /* Generate the buffer pattern */ | ||
3113 | targ->dv_echo_size = echo_size; | ||
3114 | ahd_linux_generate_dv_pattern(targ); | ||
3115 | /* | ||
3116 | * Setup initial negotiation values. | ||
3117 | */ | ||
3118 | ahd_linux_filter_inquiry(ahd, devinfo); | ||
3119 | break; | ||
3120 | } | ||
3121 | case SS_INQ_REFRESH: | ||
3122 | AHD_SET_DV_STATE(ahd, targ, | ||
3123 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
3124 | break; | ||
3125 | case SS_RETRY: | ||
3126 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
3127 | if (ahd_cmd_get_transaction_status(cmd) | ||
3128 | == CAM_REQUEUE_REQ) | ||
3129 | targ->dv_state_retry--; | ||
3130 | if (targ->dv_state_retry <= 10) | ||
3131 | break; | ||
3132 | #ifdef AHD_DEBUG | ||
3133 | if (ahd_debug & AHD_SHOW_DV) { | ||
3134 | ahd_print_devinfo(ahd, devinfo); | ||
3135 | printf("DV REBD reties exhausted\n"); | ||
3136 | } | ||
3137 | #endif | ||
3138 | /* FALLTHROUGH */ | ||
3139 | case SS_FATAL: | ||
3140 | default: | ||
3141 | /* | ||
3142 | * Setup initial negotiation values | ||
3143 | * and try level 1 DV. | ||
3144 | */ | ||
3145 | ahd_linux_filter_inquiry(ahd, devinfo); | ||
3146 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY); | ||
3147 | targ->dv_echo_size = 0; | ||
3148 | break; | ||
3149 | } | ||
3150 | break; | ||
3151 | |||
3152 | case AHD_DV_STATE_WEB: | ||
3153 | switch (status & SS_MASK) { | ||
3154 | case SS_NOP: | ||
3155 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB); | ||
3156 | break; | ||
3157 | case SS_INQ_REFRESH: | ||
3158 | AHD_SET_DV_STATE(ahd, targ, | ||
3159 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
3160 | break; | ||
3161 | case SS_RETRY: | ||
3162 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
3163 | if (ahd_cmd_get_transaction_status(cmd) | ||
3164 | == CAM_REQUEUE_REQ) { | ||
3165 | targ->dv_state_retry--; | ||
3166 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
3167 | if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { | ||
3168 | AHD_SET_DV_STATE(ahd, targ, | ||
3169 | AHD_DV_STATE_EXIT); | ||
3170 | break; | ||
3171 | } | ||
3172 | /* | ||
3173 | * Do not count "falling back" | ||
3174 | * against our retries. | ||
3175 | */ | ||
3176 | targ->dv_state_retry = 0; | ||
3177 | } | ||
3178 | if (targ->dv_state_retry <= 10) | ||
3179 | break; | ||
3180 | /* FALLTHROUGH */ | ||
3181 | #ifdef AHD_DEBUG | ||
3182 | if (ahd_debug & AHD_SHOW_DV) { | ||
3183 | ahd_print_devinfo(ahd, devinfo); | ||
3184 | printf("DV WEB reties exhausted\n"); | ||
3185 | } | ||
3186 | #endif | ||
3187 | default: | ||
3188 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3189 | break; | ||
3190 | } | ||
3191 | break; | ||
3192 | |||
3193 | case AHD_DV_STATE_REB: | ||
3194 | switch (status & SS_MASK) { | ||
3195 | case SS_NOP: | ||
3196 | if (memcmp(targ->dv_buffer, targ->dv_buffer1, | ||
3197 | targ->dv_echo_size) != 0) { | ||
3198 | if (ahd_linux_dv_fallback(ahd, devinfo) != 0) | ||
3199 | AHD_SET_DV_STATE(ahd, targ, | ||
3200 | AHD_DV_STATE_EXIT); | ||
3201 | else | ||
3202 | AHD_SET_DV_STATE(ahd, targ, | ||
3203 | AHD_DV_STATE_WEB); | ||
3204 | break; | ||
3205 | } | ||
3206 | |||
3207 | if (targ->dv_buffer != NULL) { | ||
3208 | free(targ->dv_buffer, M_DEVBUF); | ||
3209 | targ->dv_buffer = NULL; | ||
3210 | } | ||
3211 | if (targ->dv_buffer1 != NULL) { | ||
3212 | free(targ->dv_buffer1, M_DEVBUF); | ||
3213 | targ->dv_buffer1 = NULL; | ||
3214 | } | ||
3215 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3216 | break; | ||
3217 | case SS_INQ_REFRESH: | ||
3218 | AHD_SET_DV_STATE(ahd, targ, | ||
3219 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
3220 | break; | ||
3221 | case SS_RETRY: | ||
3222 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
3223 | if (ahd_cmd_get_transaction_status(cmd) | ||
3224 | == CAM_REQUEUE_REQ) { | ||
3225 | targ->dv_state_retry--; | ||
3226 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
3227 | if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { | ||
3228 | AHD_SET_DV_STATE(ahd, targ, | ||
3229 | AHD_DV_STATE_EXIT); | ||
3230 | break; | ||
3231 | } | ||
3232 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB); | ||
3233 | } | ||
3234 | if (targ->dv_state_retry <= 10) { | ||
3235 | if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) | ||
3236 | msleep(ahd->our_id*1000/10); | ||
3237 | break; | ||
3238 | } | ||
3239 | #ifdef AHD_DEBUG | ||
3240 | if (ahd_debug & AHD_SHOW_DV) { | ||
3241 | ahd_print_devinfo(ahd, devinfo); | ||
3242 | printf("DV REB reties exhausted\n"); | ||
3243 | } | ||
3244 | #endif | ||
3245 | /* FALLTHROUGH */ | ||
3246 | default: | ||
3247 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3248 | break; | ||
3249 | } | ||
3250 | break; | ||
3251 | |||
3252 | case AHD_DV_STATE_SU: | ||
3253 | switch (status & SS_MASK) { | ||
3254 | case SS_NOP: | ||
3255 | case SS_INQ_REFRESH: | ||
3256 | AHD_SET_DV_STATE(ahd, targ, | ||
3257 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
3258 | break; | ||
3259 | default: | ||
3260 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3261 | break; | ||
3262 | } | ||
3263 | break; | ||
3264 | |||
3265 | case AHD_DV_STATE_BUSY: | ||
3266 | switch (status & SS_MASK) { | ||
3267 | case SS_NOP: | ||
3268 | case SS_INQ_REFRESH: | ||
3269 | AHD_SET_DV_STATE(ahd, targ, | ||
3270 | AHD_DV_STATE_INQ_SHORT_ASYNC); | ||
3271 | break; | ||
3272 | case SS_TUR: | ||
3273 | case SS_RETRY: | ||
3274 | AHD_SET_DV_STATE(ahd, targ, targ->dv_state); | ||
3275 | if (ahd_cmd_get_transaction_status(cmd) | ||
3276 | == CAM_REQUEUE_REQ) { | ||
3277 | targ->dv_state_retry--; | ||
3278 | } else if (targ->dv_state_retry < 60) { | ||
3279 | if ((status & SSQ_DELAY) != 0) | ||
3280 | ssleep(1); | ||
3281 | } else { | ||
3282 | #ifdef AHD_DEBUG | ||
3283 | if (ahd_debug & AHD_SHOW_DV) { | ||
3284 | ahd_print_devinfo(ahd, devinfo); | ||
3285 | printf("DV BUSY reties exhausted\n"); | ||
3286 | } | ||
3287 | #endif | ||
3288 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3289 | } | ||
3290 | break; | ||
3291 | default: | ||
3292 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3293 | break; | ||
3294 | } | ||
3295 | break; | 1273 | break; |
3296 | |||
3297 | default: | 1274 | default: |
3298 | printf("%s: Invalid DV completion state %d\n", ahd_name(ahd), | ||
3299 | targ->dv_state); | ||
3300 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); | ||
3301 | break; | ||
3302 | } | ||
3303 | } | ||
3304 | |||
3305 | static void | ||
3306 | ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3307 | struct ahd_devinfo *devinfo) | ||
3308 | { | ||
3309 | memset(cmd, 0, sizeof(struct scsi_cmnd)); | ||
3310 | cmd->device = ahd->platform_data->dv_scsi_dev; | ||
3311 | cmd->scsi_done = ahd_linux_dv_complete; | ||
3312 | } | ||
3313 | |||
3314 | /* | ||
3315 | * Synthesize an inquiry command. On the return trip, it'll be | ||
3316 | * sniffed and the device transfer settings set for us. | ||
3317 | */ | ||
3318 | static void | ||
3319 | ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3320 | struct ahd_devinfo *devinfo, struct ahd_linux_target *targ, | ||
3321 | u_int request_length) | ||
3322 | { | ||
3323 | |||
3324 | #ifdef AHD_DEBUG | ||
3325 | if (ahd_debug & AHD_SHOW_DV) { | ||
3326 | ahd_print_devinfo(ahd, devinfo); | ||
3327 | printf("Sending INQ\n"); | ||
3328 | } | ||
3329 | #endif | ||
3330 | if (targ->inq_data == NULL) | ||
3331 | targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN, | ||
3332 | M_DEVBUF, M_WAITOK); | ||
3333 | if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) { | ||
3334 | if (targ->dv_buffer != NULL) | ||
3335 | free(targ->dv_buffer, M_DEVBUF); | ||
3336 | targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN, | ||
3337 | M_DEVBUF, M_WAITOK); | ||
3338 | } | ||
3339 | |||
3340 | ahd_linux_dv_fill_cmd(ahd, cmd, devinfo); | ||
3341 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
3342 | cmd->cmd_len = 6; | ||
3343 | cmd->cmnd[0] = INQUIRY; | ||
3344 | cmd->cmnd[4] = request_length; | ||
3345 | cmd->request_bufflen = request_length; | ||
3346 | if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) | ||
3347 | cmd->request_buffer = targ->dv_buffer; | ||
3348 | else | ||
3349 | cmd->request_buffer = targ->inq_data; | ||
3350 | memset(cmd->request_buffer, 0, AHD_LINUX_DV_INQ_LEN); | ||
3351 | } | ||
3352 | |||
3353 | static void | ||
3354 | ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3355 | struct ahd_devinfo *devinfo) | ||
3356 | { | ||
3357 | |||
3358 | #ifdef AHD_DEBUG | ||
3359 | if (ahd_debug & AHD_SHOW_DV) { | ||
3360 | ahd_print_devinfo(ahd, devinfo); | ||
3361 | printf("Sending TUR\n"); | ||
3362 | } | ||
3363 | #endif | ||
3364 | /* Do a TUR to clear out any non-fatal transitional state */ | ||
3365 | ahd_linux_dv_fill_cmd(ahd, cmd, devinfo); | ||
3366 | cmd->sc_data_direction = DMA_NONE; | ||
3367 | cmd->cmd_len = 6; | ||
3368 | cmd->cmnd[0] = TEST_UNIT_READY; | ||
3369 | } | ||
3370 | |||
3371 | #define AHD_REBD_LEN 4 | ||
3372 | |||
3373 | static void | ||
3374 | ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3375 | struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) | ||
3376 | { | ||
3377 | |||
3378 | #ifdef AHD_DEBUG | ||
3379 | if (ahd_debug & AHD_SHOW_DV) { | ||
3380 | ahd_print_devinfo(ahd, devinfo); | ||
3381 | printf("Sending REBD\n"); | ||
3382 | } | ||
3383 | #endif | ||
3384 | if (targ->dv_buffer != NULL) | ||
3385 | free(targ->dv_buffer, M_DEVBUF); | ||
3386 | targ->dv_buffer = malloc(AHD_REBD_LEN, M_DEVBUF, M_WAITOK); | ||
3387 | ahd_linux_dv_fill_cmd(ahd, cmd, devinfo); | ||
3388 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
3389 | cmd->cmd_len = 10; | ||
3390 | cmd->cmnd[0] = READ_BUFFER; | ||
3391 | cmd->cmnd[1] = 0x0b; | ||
3392 | scsi_ulto3b(AHD_REBD_LEN, &cmd->cmnd[6]); | ||
3393 | cmd->request_bufflen = AHD_REBD_LEN; | ||
3394 | cmd->underflow = cmd->request_bufflen; | ||
3395 | cmd->request_buffer = targ->dv_buffer; | ||
3396 | } | ||
3397 | |||
3398 | static void | ||
3399 | ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3400 | struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) | ||
3401 | { | ||
3402 | |||
3403 | #ifdef AHD_DEBUG | ||
3404 | if (ahd_debug & AHD_SHOW_DV) { | ||
3405 | ahd_print_devinfo(ahd, devinfo); | ||
3406 | printf("Sending WEB\n"); | ||
3407 | } | ||
3408 | #endif | ||
3409 | ahd_linux_dv_fill_cmd(ahd, cmd, devinfo); | ||
3410 | cmd->sc_data_direction = DMA_TO_DEVICE; | ||
3411 | cmd->cmd_len = 10; | ||
3412 | cmd->cmnd[0] = WRITE_BUFFER; | ||
3413 | cmd->cmnd[1] = 0x0a; | ||
3414 | scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]); | ||
3415 | cmd->request_bufflen = targ->dv_echo_size; | ||
3416 | cmd->underflow = cmd->request_bufflen; | ||
3417 | cmd->request_buffer = targ->dv_buffer; | ||
3418 | } | ||
3419 | |||
3420 | static void | ||
3421 | ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3422 | struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) | ||
3423 | { | ||
3424 | |||
3425 | #ifdef AHD_DEBUG | ||
3426 | if (ahd_debug & AHD_SHOW_DV) { | ||
3427 | ahd_print_devinfo(ahd, devinfo); | ||
3428 | printf("Sending REB\n"); | ||
3429 | } | ||
3430 | #endif | ||
3431 | ahd_linux_dv_fill_cmd(ahd, cmd, devinfo); | ||
3432 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
3433 | cmd->cmd_len = 10; | ||
3434 | cmd->cmnd[0] = READ_BUFFER; | ||
3435 | cmd->cmnd[1] = 0x0a; | ||
3436 | scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]); | ||
3437 | cmd->request_bufflen = targ->dv_echo_size; | ||
3438 | cmd->underflow = cmd->request_bufflen; | ||
3439 | cmd->request_buffer = targ->dv_buffer1; | ||
3440 | } | ||
3441 | |||
3442 | static void | ||
3443 | ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, | ||
3444 | struct ahd_devinfo *devinfo, | ||
3445 | struct ahd_linux_target *targ) | ||
3446 | { | ||
3447 | u_int le; | ||
3448 | |||
3449 | le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0; | ||
3450 | |||
3451 | #ifdef AHD_DEBUG | ||
3452 | if (ahd_debug & AHD_SHOW_DV) { | ||
3453 | ahd_print_devinfo(ahd, devinfo); | ||
3454 | printf("Sending SU\n"); | ||
3455 | } | ||
3456 | #endif | ||
3457 | ahd_linux_dv_fill_cmd(ahd, cmd, devinfo); | ||
3458 | cmd->sc_data_direction = DMA_NONE; | ||
3459 | cmd->cmd_len = 6; | ||
3460 | cmd->cmnd[0] = START_STOP_UNIT; | ||
3461 | cmd->cmnd[4] = le | SSS_START; | ||
3462 | } | ||
3463 | |||
3464 | static int | ||
3465 | ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | ||
3466 | { | ||
3467 | struct ahd_linux_target *targ; | ||
3468 | struct ahd_initiator_tinfo *tinfo; | ||
3469 | struct ahd_transinfo *goal; | ||
3470 | struct ahd_tmode_tstate *tstate; | ||
3471 | u_int width; | ||
3472 | u_int period; | ||
3473 | u_int offset; | ||
3474 | u_int ppr_options; | ||
3475 | u_int cur_speed; | ||
3476 | u_int wide_speed; | ||
3477 | u_int narrow_speed; | ||
3478 | u_int fallback_speed; | ||
3479 | |||
3480 | #ifdef AHD_DEBUG | ||
3481 | if (ahd_debug & AHD_SHOW_DV) { | ||
3482 | ahd_print_devinfo(ahd, devinfo); | ||
3483 | printf("Trying to fallback\n"); | ||
3484 | } | ||
3485 | #endif | ||
3486 | targ = ahd->platform_data->targets[devinfo->target_offset]; | ||
3487 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, | ||
3488 | devinfo->our_scsiid, | ||
3489 | devinfo->target, &tstate); | ||
3490 | goal = &tinfo->goal; | ||
3491 | width = goal->width; | ||
3492 | period = goal->period; | ||
3493 | offset = goal->offset; | ||
3494 | ppr_options = goal->ppr_options; | ||
3495 | if (offset == 0) | ||
3496 | period = AHD_ASYNC_XFER_PERIOD; | ||
3497 | if (targ->dv_next_narrow_period == 0) | ||
3498 | targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2); | ||
3499 | if (targ->dv_next_wide_period == 0) | ||
3500 | targ->dv_next_wide_period = period; | ||
3501 | if (targ->dv_max_width == 0) | ||
3502 | targ->dv_max_width = width; | ||
3503 | if (targ->dv_max_ppr_options == 0) | ||
3504 | targ->dv_max_ppr_options = ppr_options; | ||
3505 | if (targ->dv_last_ppr_options == 0) | ||
3506 | targ->dv_last_ppr_options = ppr_options; | ||
3507 | |||
3508 | cur_speed = aic_calc_speed(width, period, offset, AHD_SYNCRATE_MIN); | ||
3509 | wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT, | ||
3510 | targ->dv_next_wide_period, | ||
3511 | MAX_OFFSET, AHD_SYNCRATE_MIN); | ||
3512 | narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT, | ||
3513 | targ->dv_next_narrow_period, | ||
3514 | MAX_OFFSET, AHD_SYNCRATE_MIN); | ||
3515 | fallback_speed = aic_calc_speed(width, period+1, offset, | ||
3516 | AHD_SYNCRATE_MIN); | ||
3517 | #ifdef AHD_DEBUG | ||
3518 | if (ahd_debug & AHD_SHOW_DV) { | ||
3519 | printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, " | ||
3520 | "fallback_speed= %d\n", cur_speed, wide_speed, | ||
3521 | narrow_speed, fallback_speed); | ||
3522 | } | ||
3523 | #endif | ||
3524 | |||
3525 | if (cur_speed > 160000) { | ||
3526 | /* | 1275 | /* |
3527 | * Paced/DT/IU_REQ only transfer speeds. All we | 1276 | * We allow the OS to queue 2 untagged transactions to |
3528 | * can do is fallback in terms of syncrate. | 1277 | * us at any time even though we can only execute them |
1278 | * serially on the controller/device. This should | ||
1279 | * remove some latency. | ||
3529 | */ | 1280 | */ |
3530 | period++; | 1281 | scsi_adjust_queue_depth(sdev, |
3531 | } else if (cur_speed > 80000) { | 1282 | /*NON-TAGGED*/0, |
3532 | if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | 1283 | /*queue depth*/2); |
3533 | /* | 1284 | break; |
3534 | * Try without IU_REQ as it may be confusing | ||
3535 | * an expander. | ||
3536 | */ | ||
3537 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | ||
3538 | } else { | ||
3539 | /* | ||
3540 | * Paced/DT only transfer speeds. All we | ||
3541 | * can do is fallback in terms of syncrate. | ||
3542 | */ | ||
3543 | period++; | ||
3544 | ppr_options = targ->dv_max_ppr_options; | ||
3545 | } | ||
3546 | } else if (cur_speed > 3300) { | ||
3547 | |||
3548 | /* | ||
3549 | * In this range we the following | ||
3550 | * options ordered from highest to | ||
3551 | * lowest desireability: | ||
3552 | * | ||
3553 | * o Wide/DT | ||
3554 | * o Wide/non-DT | ||
3555 | * o Narrow at a potentally higher sync rate. | ||
3556 | * | ||
3557 | * All modes are tested with and without IU_REQ | ||
3558 | * set since using IUs may confuse an expander. | ||
3559 | */ | ||
3560 | if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
3561 | |||
3562 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | ||
3563 | } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { | ||
3564 | /* | ||
3565 | * Try going non-DT. | ||
3566 | */ | ||
3567 | ppr_options = targ->dv_max_ppr_options; | ||
3568 | ppr_options &= ~MSG_EXT_PPR_DT_REQ; | ||
3569 | } else if (targ->dv_last_ppr_options != 0) { | ||
3570 | /* | ||
3571 | * Try without QAS or any other PPR options. | ||
3572 | * We may need a non-PPR message to work with | ||
3573 | * an expander. We look at the "last PPR options" | ||
3574 | * so we will perform this fallback even if the | ||
3575 | * target responded to our PPR negotiation with | ||
3576 | * no option bits set. | ||
3577 | */ | ||
3578 | ppr_options = 0; | ||
3579 | } else if (width == MSG_EXT_WDTR_BUS_16_BIT) { | ||
3580 | /* | ||
3581 | * If the next narrow speed is greater than | ||
3582 | * the next wide speed, fallback to narrow. | ||
3583 | * Otherwise fallback to the next DT/Wide setting. | ||
3584 | * The narrow async speed will always be smaller | ||
3585 | * than the wide async speed, so handle this case | ||
3586 | * specifically. | ||
3587 | */ | ||
3588 | ppr_options = targ->dv_max_ppr_options; | ||
3589 | if (narrow_speed > fallback_speed | ||
3590 | || period >= AHD_ASYNC_XFER_PERIOD) { | ||
3591 | targ->dv_next_wide_period = period+1; | ||
3592 | width = MSG_EXT_WDTR_BUS_8_BIT; | ||
3593 | period = targ->dv_next_narrow_period; | ||
3594 | } else { | ||
3595 | period++; | ||
3596 | } | ||
3597 | } else if ((ahd->features & AHD_WIDE) != 0 | ||
3598 | && targ->dv_max_width != 0 | ||
3599 | && wide_speed >= fallback_speed | ||
3600 | && (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD | ||
3601 | || period >= AHD_ASYNC_XFER_PERIOD)) { | ||
3602 | |||
3603 | /* | ||
3604 | * We are narrow. Try falling back | ||
3605 | * to the next wide speed with | ||
3606 | * all supported ppr options set. | ||
3607 | */ | ||
3608 | targ->dv_next_narrow_period = period+1; | ||
3609 | width = MSG_EXT_WDTR_BUS_16_BIT; | ||
3610 | period = targ->dv_next_wide_period; | ||
3611 | ppr_options = targ->dv_max_ppr_options; | ||
3612 | } else { | ||
3613 | /* Only narrow fallback is allowed. */ | ||
3614 | period++; | ||
3615 | ppr_options = targ->dv_max_ppr_options; | ||
3616 | } | ||
3617 | } else { | ||
3618 | return (-1); | ||
3619 | } | ||
3620 | offset = MAX_OFFSET; | ||
3621 | ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_PACED); | ||
3622 | ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, FALSE); | ||
3623 | if (period == 0) { | ||
3624 | period = 0; | ||
3625 | offset = 0; | ||
3626 | ppr_options = 0; | ||
3627 | if (width == MSG_EXT_WDTR_BUS_8_BIT) | ||
3628 | targ->dv_next_narrow_period = AHD_ASYNC_XFER_PERIOD; | ||
3629 | else | ||
3630 | targ->dv_next_wide_period = AHD_ASYNC_XFER_PERIOD; | ||
3631 | } | ||
3632 | ahd_set_syncrate(ahd, devinfo, period, offset, | ||
3633 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
3634 | targ->dv_last_ppr_options = ppr_options; | ||
3635 | return (0); | ||
3636 | } | ||
3637 | |||
3638 | static void | ||
3639 | ahd_linux_dv_timeout(struct scsi_cmnd *cmd) | ||
3640 | { | ||
3641 | struct ahd_softc *ahd; | ||
3642 | struct scb *scb; | ||
3643 | u_long flags; | ||
3644 | |||
3645 | ahd = *((struct ahd_softc **)cmd->device->host->hostdata); | ||
3646 | ahd_lock(ahd, &flags); | ||
3647 | |||
3648 | #ifdef AHD_DEBUG | ||
3649 | if (ahd_debug & AHD_SHOW_DV) { | ||
3650 | printf("%s: Timeout while doing DV command %x.\n", | ||
3651 | ahd_name(ahd), cmd->cmnd[0]); | ||
3652 | ahd_dump_card_state(ahd); | ||
3653 | } | ||
3654 | #endif | ||
3655 | |||
3656 | /* | ||
3657 | * Guard against "done race". No action is | ||
3658 | * required if we just completed. | ||
3659 | */ | ||
3660 | if ((scb = (struct scb *)cmd->host_scribble) == NULL) { | ||
3661 | ahd_unlock(ahd, &flags); | ||
3662 | return; | ||
3663 | } | 1285 | } |
3664 | |||
3665 | /* | ||
3666 | * Command has not completed. Mark this | ||
3667 | * SCB as having failing status prior to | ||
3668 | * resetting the bus, so we get the correct | ||
3669 | * error code. | ||
3670 | */ | ||
3671 | if ((scb->flags & SCB_SENSE) != 0) | ||
3672 | ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); | ||
3673 | else | ||
3674 | ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); | ||
3675 | ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE); | ||
3676 | |||
3677 | /* | ||
3678 | * Add a minimal bus settle delay for devices that are slow to | ||
3679 | * respond after bus resets. | ||
3680 | */ | ||
3681 | ahd_freeze_simq(ahd); | ||
3682 | init_timer(&ahd->platform_data->reset_timer); | ||
3683 | ahd->platform_data->reset_timer.data = (u_long)ahd; | ||
3684 | ahd->platform_data->reset_timer.expires = jiffies + HZ / 2; | ||
3685 | ahd->platform_data->reset_timer.function = | ||
3686 | (ahd_linux_callback_t *)ahd_release_simq; | ||
3687 | add_timer(&ahd->platform_data->reset_timer); | ||
3688 | if (ahd_linux_next_device_to_run(ahd) != NULL) | ||
3689 | ahd_schedule_runq(ahd); | ||
3690 | ahd_linux_run_complete_queue(ahd); | ||
3691 | ahd_unlock(ahd, &flags); | ||
3692 | } | ||
3693 | |||
3694 | static void | ||
3695 | ahd_linux_dv_complete(struct scsi_cmnd *cmd) | ||
3696 | { | ||
3697 | struct ahd_softc *ahd; | ||
3698 | |||
3699 | ahd = *((struct ahd_softc **)cmd->device->host->hostdata); | ||
3700 | |||
3701 | /* Delete the DV timer before it goes off! */ | ||
3702 | scsi_delete_timer(cmd); | ||
3703 | |||
3704 | #ifdef AHD_DEBUG | ||
3705 | if (ahd_debug & AHD_SHOW_DV) | ||
3706 | printf("%s:%c:%d: Command completed, status= 0x%x\n", | ||
3707 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
3708 | cmd->result); | ||
3709 | #endif | ||
3710 | |||
3711 | /* Wake up the state machine */ | ||
3712 | up(&ahd->platform_data->dv_cmd_sem); | ||
3713 | } | 1286 | } |
3714 | 1287 | ||
3715 | static void | 1288 | int |
3716 | ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ) | 1289 | ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, |
1290 | int lun, u_int tag, role_t role, uint32_t status) | ||
3717 | { | 1291 | { |
3718 | uint16_t b; | 1292 | return 0; |
3719 | u_int i; | ||
3720 | u_int j; | ||
3721 | |||
3722 | if (targ->dv_buffer != NULL) | ||
3723 | free(targ->dv_buffer, M_DEVBUF); | ||
3724 | targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK); | ||
3725 | if (targ->dv_buffer1 != NULL) | ||
3726 | free(targ->dv_buffer1, M_DEVBUF); | ||
3727 | targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK); | ||
3728 | |||
3729 | i = 0; | ||
3730 | |||
3731 | b = 0x0001; | ||
3732 | for (j = 0 ; i < targ->dv_echo_size; j++) { | ||
3733 | if (j < 32) { | ||
3734 | /* | ||
3735 | * 32bytes of sequential numbers. | ||
3736 | */ | ||
3737 | targ->dv_buffer[i++] = j & 0xff; | ||
3738 | } else if (j < 48) { | ||
3739 | /* | ||
3740 | * 32bytes of repeating 0x0000, 0xffff. | ||
3741 | */ | ||
3742 | targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00; | ||
3743 | } else if (j < 64) { | ||
3744 | /* | ||
3745 | * 32bytes of repeating 0x5555, 0xaaaa. | ||
3746 | */ | ||
3747 | targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55; | ||
3748 | } else { | ||
3749 | /* | ||
3750 | * Remaining buffer is filled with a repeating | ||
3751 | * patter of: | ||
3752 | * | ||
3753 | * 0xffff | ||
3754 | * ~0x0001 << shifted once in each loop. | ||
3755 | */ | ||
3756 | if (j & 0x02) { | ||
3757 | if (j & 0x01) { | ||
3758 | targ->dv_buffer[i++] = ~(b >> 8) & 0xff; | ||
3759 | b <<= 1; | ||
3760 | if (b == 0x0000) | ||
3761 | b = 0x0001; | ||
3762 | } else { | ||
3763 | targ->dv_buffer[i++] = (~b & 0xff); | ||
3764 | } | ||
3765 | } else { | ||
3766 | targ->dv_buffer[i++] = 0xff; | ||
3767 | } | ||
3768 | } | ||
3769 | } | ||
3770 | } | 1293 | } |
3771 | 1294 | ||
3772 | static u_int | 1295 | static u_int |
@@ -3800,100 +1323,23 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | |||
3800 | return (tags); | 1323 | return (tags); |
3801 | } | 1324 | } |
3802 | 1325 | ||
3803 | static u_int | ||
3804 | ahd_linux_user_dv_setting(struct ahd_softc *ahd) | ||
3805 | { | ||
3806 | static int warned_user; | ||
3807 | int dv; | ||
3808 | |||
3809 | if (ahd->unit >= NUM_ELEMENTS(aic79xx_dv_settings)) { | ||
3810 | |||
3811 | if (warned_user == 0) { | ||
3812 | printf(KERN_WARNING | ||
3813 | "aic79xx: WARNING: Insufficient dv settings instances\n" | ||
3814 | "aic79xx: for installed controllers. Using defaults\n" | ||
3815 | "aic79xx: Please update the aic79xx_dv_settings array in" | ||
3816 | "aic79xx: the aic79xx_osm.c source file.\n"); | ||
3817 | warned_user++; | ||
3818 | } | ||
3819 | dv = -1; | ||
3820 | } else { | ||
3821 | |||
3822 | dv = aic79xx_dv_settings[ahd->unit]; | ||
3823 | } | ||
3824 | |||
3825 | if (dv < 0) { | ||
3826 | /* | ||
3827 | * Apply the default. | ||
3828 | */ | ||
3829 | dv = 1; | ||
3830 | if (ahd->seep_config != 0) | ||
3831 | dv = (ahd->seep_config->bios_control & CFENABLEDV); | ||
3832 | } | ||
3833 | return (dv); | ||
3834 | } | ||
3835 | |||
3836 | static void | ||
3837 | ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd) | ||
3838 | { | ||
3839 | static int warned_user; | ||
3840 | u_int rd_strm_mask; | ||
3841 | u_int target_id; | ||
3842 | |||
3843 | /* | ||
3844 | * If we have specific read streaming info for this controller, | ||
3845 | * apply it. Otherwise use the defaults. | ||
3846 | */ | ||
3847 | if (ahd->unit >= NUM_ELEMENTS(aic79xx_rd_strm_info)) { | ||
3848 | |||
3849 | if (warned_user == 0) { | ||
3850 | |||
3851 | printf(KERN_WARNING | ||
3852 | "aic79xx: WARNING: Insufficient rd_strm instances\n" | ||
3853 | "aic79xx: for installed controllers. Using defaults\n" | ||
3854 | "aic79xx: Please update the aic79xx_rd_strm_info array\n" | ||
3855 | "aic79xx: in the aic79xx_osm.c source file.\n"); | ||
3856 | warned_user++; | ||
3857 | } | ||
3858 | rd_strm_mask = AIC79XX_CONFIGED_RD_STRM; | ||
3859 | } else { | ||
3860 | |||
3861 | rd_strm_mask = aic79xx_rd_strm_info[ahd->unit]; | ||
3862 | } | ||
3863 | for (target_id = 0; target_id < 16; target_id++) { | ||
3864 | struct ahd_devinfo devinfo; | ||
3865 | struct ahd_initiator_tinfo *tinfo; | ||
3866 | struct ahd_tmode_tstate *tstate; | ||
3867 | |||
3868 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, | ||
3869 | target_id, &tstate); | ||
3870 | ahd_compile_devinfo(&devinfo, ahd->our_id, target_id, | ||
3871 | CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR); | ||
3872 | tinfo->user.ppr_options &= ~MSG_EXT_PPR_RD_STRM; | ||
3873 | if ((rd_strm_mask & devinfo.target_mask) != 0) | ||
3874 | tinfo->user.ppr_options |= MSG_EXT_PPR_RD_STRM; | ||
3875 | } | ||
3876 | } | ||
3877 | |||
3878 | /* | 1326 | /* |
3879 | * Determines the queue depth for a given device. | 1327 | * Determines the queue depth for a given device. |
3880 | */ | 1328 | */ |
3881 | static void | 1329 | static void |
3882 | ahd_linux_device_queue_depth(struct ahd_softc *ahd, | 1330 | ahd_linux_device_queue_depth(struct scsi_device *sdev) |
3883 | struct ahd_linux_device *dev) | ||
3884 | { | 1331 | { |
3885 | struct ahd_devinfo devinfo; | 1332 | struct ahd_devinfo devinfo; |
3886 | u_int tags; | 1333 | u_int tags; |
1334 | struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata); | ||
3887 | 1335 | ||
3888 | ahd_compile_devinfo(&devinfo, | 1336 | ahd_compile_devinfo(&devinfo, |
3889 | ahd->our_id, | 1337 | ahd->our_id, |
3890 | dev->target->target, dev->lun, | 1338 | sdev->sdev_target->id, sdev->lun, |
3891 | dev->target->channel == 0 ? 'A' : 'B', | 1339 | sdev->sdev_target->channel == 0 ? 'A' : 'B', |
3892 | ROLE_INITIATOR); | 1340 | ROLE_INITIATOR); |
3893 | tags = ahd_linux_user_tagdepth(ahd, &devinfo); | 1341 | tags = ahd_linux_user_tagdepth(ahd, &devinfo); |
3894 | if (tags != 0 | 1342 | if (tags != 0 && sdev->tagged_supported != 0) { |
3895 | && dev->scsi_device != NULL | ||
3896 | && dev->scsi_device->tagged_supported != 0) { | ||
3897 | 1343 | ||
3898 | ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); | 1344 | ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); |
3899 | ahd_print_devinfo(ahd, &devinfo); | 1345 | ahd_print_devinfo(ahd, &devinfo); |
@@ -3903,11 +1349,10 @@ ahd_linux_device_queue_depth(struct ahd_softc *ahd, | |||
3903 | } | 1349 | } |
3904 | } | 1350 | } |
3905 | 1351 | ||
3906 | static void | 1352 | static int |
3907 | ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) | 1353 | ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, |
1354 | struct scsi_cmnd *cmd) | ||
3908 | { | 1355 | { |
3909 | struct ahd_cmd *acmd; | ||
3910 | struct scsi_cmnd *cmd; | ||
3911 | struct scb *scb; | 1356 | struct scb *scb; |
3912 | struct hardware_scb *hscb; | 1357 | struct hardware_scb *hscb; |
3913 | struct ahd_initiator_tinfo *tinfo; | 1358 | struct ahd_initiator_tinfo *tinfo; |
@@ -3915,157 +1360,122 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) | |||
3915 | u_int col_idx; | 1360 | u_int col_idx; |
3916 | uint16_t mask; | 1361 | uint16_t mask; |
3917 | 1362 | ||
3918 | if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0) | 1363 | /* |
3919 | panic("running device on run list"); | 1364 | * Get an scb to use. |
3920 | 1365 | */ | |
3921 | while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL | 1366 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, |
3922 | && dev->openings > 0 && dev->qfrozen == 0) { | 1367 | cmd->device->id, &tstate); |
3923 | 1368 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0 | |
3924 | /* | 1369 | || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { |
3925 | * Schedule us to run later. The only reason we are not | 1370 | col_idx = AHD_NEVER_COL_IDX; |
3926 | * running is because the whole controller Q is frozen. | 1371 | } else { |
3927 | */ | 1372 | col_idx = AHD_BUILD_COL_IDX(cmd->device->id, |
3928 | if (ahd->platform_data->qfrozen != 0 | 1373 | cmd->device->lun); |
3929 | && AHD_DV_SIMQ_FROZEN(ahd) == 0) { | 1374 | } |
3930 | 1375 | if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { | |
3931 | TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, | 1376 | ahd->flags |= AHD_RESOURCE_SHORTAGE; |
3932 | dev, links); | 1377 | return SCSI_MLQUEUE_HOST_BUSY; |
3933 | dev->flags |= AHD_DEV_ON_RUN_LIST; | 1378 | } |
3934 | return; | ||
3935 | } | ||
3936 | |||
3937 | cmd = &acmd_scsi_cmd(acmd); | ||
3938 | 1379 | ||
3939 | /* | 1380 | scb->io_ctx = cmd; |
3940 | * Get an scb to use. | 1381 | scb->platform_data->dev = dev; |
3941 | */ | 1382 | hscb = scb->hscb; |
3942 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, | 1383 | cmd->host_scribble = (char *)scb; |
3943 | cmd->device->id, &tstate); | ||
3944 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0 | ||
3945 | || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
3946 | col_idx = AHD_NEVER_COL_IDX; | ||
3947 | } else { | ||
3948 | col_idx = AHD_BUILD_COL_IDX(cmd->device->id, | ||
3949 | cmd->device->lun); | ||
3950 | } | ||
3951 | if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { | ||
3952 | TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, | ||
3953 | dev, links); | ||
3954 | dev->flags |= AHD_DEV_ON_RUN_LIST; | ||
3955 | ahd->flags |= AHD_RESOURCE_SHORTAGE; | ||
3956 | return; | ||
3957 | } | ||
3958 | TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); | ||
3959 | scb->io_ctx = cmd; | ||
3960 | scb->platform_data->dev = dev; | ||
3961 | hscb = scb->hscb; | ||
3962 | cmd->host_scribble = (char *)scb; | ||
3963 | 1384 | ||
3964 | /* | 1385 | /* |
3965 | * Fill out basics of the HSCB. | 1386 | * Fill out basics of the HSCB. |
3966 | */ | 1387 | */ |
3967 | hscb->control = 0; | 1388 | hscb->control = 0; |
3968 | hscb->scsiid = BUILD_SCSIID(ahd, cmd); | 1389 | hscb->scsiid = BUILD_SCSIID(ahd, cmd); |
3969 | hscb->lun = cmd->device->lun; | 1390 | hscb->lun = cmd->device->lun; |
3970 | scb->hscb->task_management = 0; | 1391 | scb->hscb->task_management = 0; |
3971 | mask = SCB_GET_TARGET_MASK(ahd, scb); | 1392 | mask = SCB_GET_TARGET_MASK(ahd, scb); |
3972 | 1393 | ||
3973 | if ((ahd->user_discenable & mask) != 0) | 1394 | if ((ahd->user_discenable & mask) != 0) |
3974 | hscb->control |= DISCENB; | 1395 | hscb->control |= DISCENB; |
3975 | 1396 | ||
3976 | if (AHD_DV_CMD(cmd) != 0) | 1397 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) |
3977 | scb->flags |= SCB_SILENT; | 1398 | scb->flags |= SCB_PACKETIZED; |
3978 | 1399 | ||
3979 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) | 1400 | if ((tstate->auto_negotiate & mask) != 0) { |
3980 | scb->flags |= SCB_PACKETIZED; | 1401 | scb->flags |= SCB_AUTO_NEGOTIATE; |
1402 | scb->hscb->control |= MK_MESSAGE; | ||
1403 | } | ||
3981 | 1404 | ||
3982 | if ((tstate->auto_negotiate & mask) != 0) { | 1405 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { |
3983 | scb->flags |= SCB_AUTO_NEGOTIATE; | 1406 | int msg_bytes; |
3984 | scb->hscb->control |= MK_MESSAGE; | 1407 | uint8_t tag_msgs[2]; |
3985 | } | ||
3986 | 1408 | ||
3987 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { | 1409 | msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs); |
3988 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1410 | if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) { |
3989 | int msg_bytes; | 1411 | hscb->control |= tag_msgs[0]; |
3990 | uint8_t tag_msgs[2]; | 1412 | if (tag_msgs[0] == MSG_ORDERED_TASK) |
3991 | |||
3992 | msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs); | ||
3993 | if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) { | ||
3994 | hscb->control |= tag_msgs[0]; | ||
3995 | if (tag_msgs[0] == MSG_ORDERED_TASK) | ||
3996 | dev->commands_since_idle_or_otag = 0; | ||
3997 | } else | ||
3998 | #endif | ||
3999 | if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH | ||
4000 | && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { | ||
4001 | hscb->control |= MSG_ORDERED_TASK; | ||
4002 | dev->commands_since_idle_or_otag = 0; | 1413 | dev->commands_since_idle_or_otag = 0; |
4003 | } else { | 1414 | } else |
4004 | hscb->control |= MSG_SIMPLE_TASK; | 1415 | if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH |
4005 | } | 1416 | && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { |
1417 | hscb->control |= MSG_ORDERED_TASK; | ||
1418 | dev->commands_since_idle_or_otag = 0; | ||
1419 | } else { | ||
1420 | hscb->control |= MSG_SIMPLE_TASK; | ||
4006 | } | 1421 | } |
1422 | } | ||
4007 | 1423 | ||
4008 | hscb->cdb_len = cmd->cmd_len; | 1424 | hscb->cdb_len = cmd->cmd_len; |
4009 | memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); | 1425 | memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); |
4010 | 1426 | ||
4011 | scb->sg_count = 0; | 1427 | scb->platform_data->xfer_len = 0; |
4012 | ahd_set_residual(scb, 0); | 1428 | ahd_set_residual(scb, 0); |
4013 | ahd_set_sense_residual(scb, 0); | 1429 | ahd_set_sense_residual(scb, 0); |
4014 | if (cmd->use_sg != 0) { | 1430 | scb->sg_count = 0; |
4015 | void *sg; | 1431 | if (cmd->use_sg != 0) { |
4016 | struct scatterlist *cur_seg; | 1432 | void *sg; |
4017 | u_int nseg; | 1433 | struct scatterlist *cur_seg; |
4018 | int dir; | 1434 | u_int nseg; |
4019 | 1435 | int dir; | |
4020 | cur_seg = (struct scatterlist *)cmd->request_buffer; | 1436 | |
4021 | dir = cmd->sc_data_direction; | 1437 | cur_seg = (struct scatterlist *)cmd->request_buffer; |
4022 | nseg = pci_map_sg(ahd->dev_softc, cur_seg, | 1438 | dir = cmd->sc_data_direction; |
4023 | cmd->use_sg, dir); | 1439 | nseg = pci_map_sg(ahd->dev_softc, cur_seg, |
4024 | scb->platform_data->xfer_len = 0; | 1440 | cmd->use_sg, dir); |
4025 | for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { | 1441 | scb->platform_data->xfer_len = 0; |
4026 | dma_addr_t addr; | 1442 | for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { |
4027 | bus_size_t len; | ||
4028 | |||
4029 | addr = sg_dma_address(cur_seg); | ||
4030 | len = sg_dma_len(cur_seg); | ||
4031 | scb->platform_data->xfer_len += len; | ||
4032 | sg = ahd_sg_setup(ahd, scb, sg, addr, len, | ||
4033 | /*last*/nseg == 1); | ||
4034 | } | ||
4035 | } else if (cmd->request_bufflen != 0) { | ||
4036 | void *sg; | ||
4037 | dma_addr_t addr; | 1443 | dma_addr_t addr; |
4038 | int dir; | 1444 | bus_size_t len; |
4039 | |||
4040 | sg = scb->sg_list; | ||
4041 | dir = cmd->sc_data_direction; | ||
4042 | addr = pci_map_single(ahd->dev_softc, | ||
4043 | cmd->request_buffer, | ||
4044 | cmd->request_bufflen, dir); | ||
4045 | scb->platform_data->xfer_len = cmd->request_bufflen; | ||
4046 | scb->platform_data->buf_busaddr = addr; | ||
4047 | sg = ahd_sg_setup(ahd, scb, sg, addr, | ||
4048 | cmd->request_bufflen, /*last*/TRUE); | ||
4049 | } | ||
4050 | 1445 | ||
4051 | LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); | 1446 | addr = sg_dma_address(cur_seg); |
4052 | dev->openings--; | 1447 | len = sg_dma_len(cur_seg); |
4053 | dev->active++; | 1448 | scb->platform_data->xfer_len += len; |
4054 | dev->commands_issued++; | 1449 | sg = ahd_sg_setup(ahd, scb, sg, addr, len, |
4055 | 1450 | /*last*/nseg == 1); | |
4056 | /* Update the error counting bucket and dump if needed */ | ||
4057 | if (dev->target->cmds_since_error) { | ||
4058 | dev->target->cmds_since_error++; | ||
4059 | if (dev->target->cmds_since_error > | ||
4060 | AHD_LINUX_ERR_THRESH) | ||
4061 | dev->target->cmds_since_error = 0; | ||
4062 | } | 1451 | } |
1452 | } else if (cmd->request_bufflen != 0) { | ||
1453 | void *sg; | ||
1454 | dma_addr_t addr; | ||
1455 | int dir; | ||
4063 | 1456 | ||
4064 | if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) | 1457 | sg = scb->sg_list; |
4065 | dev->commands_since_idle_or_otag++; | 1458 | dir = cmd->sc_data_direction; |
4066 | scb->flags |= SCB_ACTIVE; | 1459 | addr = pci_map_single(ahd->dev_softc, |
4067 | ahd_queue_scb(ahd, scb); | 1460 | cmd->request_buffer, |
1461 | cmd->request_bufflen, dir); | ||
1462 | scb->platform_data->xfer_len = cmd->request_bufflen; | ||
1463 | scb->platform_data->buf_busaddr = addr; | ||
1464 | sg = ahd_sg_setup(ahd, scb, sg, addr, | ||
1465 | cmd->request_bufflen, /*last*/TRUE); | ||
4068 | } | 1466 | } |
1467 | |||
1468 | LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); | ||
1469 | dev->openings--; | ||
1470 | dev->active++; | ||
1471 | dev->commands_issued++; | ||
1472 | |||
1473 | if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) | ||
1474 | dev->commands_since_idle_or_otag++; | ||
1475 | scb->flags |= SCB_ACTIVE; | ||
1476 | ahd_queue_scb(ahd, scb); | ||
1477 | |||
1478 | return 0; | ||
4069 | } | 1479 | } |
4070 | 1480 | ||
4071 | /* | 1481 | /* |
@@ -4081,9 +1491,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs) | |||
4081 | ahd = (struct ahd_softc *) dev_id; | 1491 | ahd = (struct ahd_softc *) dev_id; |
4082 | ahd_lock(ahd, &flags); | 1492 | ahd_lock(ahd, &flags); |
4083 | ours = ahd_intr(ahd); | 1493 | ours = ahd_intr(ahd); |
4084 | if (ahd_linux_next_device_to_run(ahd) != NULL) | ||
4085 | ahd_schedule_runq(ahd); | ||
4086 | ahd_linux_run_complete_queue(ahd); | ||
4087 | ahd_unlock(ahd, &flags); | 1494 | ahd_unlock(ahd, &flags); |
4088 | return IRQ_RETVAL(ours); | 1495 | return IRQ_RETVAL(ours); |
4089 | } | 1496 | } |
@@ -4092,111 +1499,6 @@ void | |||
4092 | ahd_platform_flushwork(struct ahd_softc *ahd) | 1499 | ahd_platform_flushwork(struct ahd_softc *ahd) |
4093 | { | 1500 | { |
4094 | 1501 | ||
4095 | while (ahd_linux_run_complete_queue(ahd) != NULL) | ||
4096 | ; | ||
4097 | } | ||
4098 | |||
4099 | static struct ahd_linux_target* | ||
4100 | ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target) | ||
4101 | { | ||
4102 | struct ahd_linux_target *targ; | ||
4103 | |||
4104 | targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT); | ||
4105 | if (targ == NULL) | ||
4106 | return (NULL); | ||
4107 | memset(targ, 0, sizeof(*targ)); | ||
4108 | targ->channel = channel; | ||
4109 | targ->target = target; | ||
4110 | targ->ahd = ahd; | ||
4111 | targ->flags = AHD_DV_REQUIRED; | ||
4112 | ahd->platform_data->targets[target] = targ; | ||
4113 | return (targ); | ||
4114 | } | ||
4115 | |||
4116 | static void | ||
4117 | ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ) | ||
4118 | { | ||
4119 | struct ahd_devinfo devinfo; | ||
4120 | struct ahd_initiator_tinfo *tinfo; | ||
4121 | struct ahd_tmode_tstate *tstate; | ||
4122 | u_int our_id; | ||
4123 | u_int target_offset; | ||
4124 | char channel; | ||
4125 | |||
4126 | /* | ||
4127 | * Force a negotiation to async/narrow on any | ||
4128 | * future command to this device unless a bus | ||
4129 | * reset occurs between now and that command. | ||
4130 | */ | ||
4131 | channel = 'A' + targ->channel; | ||
4132 | our_id = ahd->our_id; | ||
4133 | target_offset = targ->target; | ||
4134 | tinfo = ahd_fetch_transinfo(ahd, channel, our_id, | ||
4135 | targ->target, &tstate); | ||
4136 | ahd_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD, | ||
4137 | channel, ROLE_INITIATOR); | ||
4138 | ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, | ||
4139 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
4140 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, | ||
4141 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
4142 | ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS); | ||
4143 | ahd->platform_data->targets[target_offset] = NULL; | ||
4144 | if (targ->inq_data != NULL) | ||
4145 | free(targ->inq_data, M_DEVBUF); | ||
4146 | if (targ->dv_buffer != NULL) | ||
4147 | free(targ->dv_buffer, M_DEVBUF); | ||
4148 | if (targ->dv_buffer1 != NULL) | ||
4149 | free(targ->dv_buffer1, M_DEVBUF); | ||
4150 | free(targ, M_DEVBUF); | ||
4151 | } | ||
4152 | |||
4153 | static struct ahd_linux_device* | ||
4154 | ahd_linux_alloc_device(struct ahd_softc *ahd, | ||
4155 | struct ahd_linux_target *targ, u_int lun) | ||
4156 | { | ||
4157 | struct ahd_linux_device *dev; | ||
4158 | |||
4159 | dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); | ||
4160 | if (dev == NULL) | ||
4161 | return (NULL); | ||
4162 | memset(dev, 0, sizeof(*dev)); | ||
4163 | init_timer(&dev->timer); | ||
4164 | TAILQ_INIT(&dev->busyq); | ||
4165 | dev->flags = AHD_DEV_UNCONFIGURED; | ||
4166 | dev->lun = lun; | ||
4167 | dev->target = targ; | ||
4168 | |||
4169 | /* | ||
4170 | * We start out life using untagged | ||
4171 | * transactions of which we allow one. | ||
4172 | */ | ||
4173 | dev->openings = 1; | ||
4174 | |||
4175 | /* | ||
4176 | * Set maxtags to 0. This will be changed if we | ||
4177 | * later determine that we are dealing with | ||
4178 | * a tagged queuing capable device. | ||
4179 | */ | ||
4180 | dev->maxtags = 0; | ||
4181 | |||
4182 | targ->refcount++; | ||
4183 | targ->devices[lun] = dev; | ||
4184 | return (dev); | ||
4185 | } | ||
4186 | |||
4187 | static void | ||
4188 | ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev) | ||
4189 | { | ||
4190 | struct ahd_linux_target *targ; | ||
4191 | |||
4192 | del_timer(&dev->timer); | ||
4193 | targ = dev->target; | ||
4194 | targ->devices[dev->lun] = NULL; | ||
4195 | free(dev, M_DEVBUF); | ||
4196 | targ->refcount--; | ||
4197 | if (targ->refcount == 0 | ||
4198 | && (targ->flags & AHD_DV_REQUIRED) == 0) | ||
4199 | ahd_linux_free_target(ahd, targ); | ||
4200 | } | 1502 | } |
4201 | 1503 | ||
4202 | void | 1504 | void |
@@ -4207,10 +1509,14 @@ ahd_send_async(struct ahd_softc *ahd, char channel, | |||
4207 | case AC_TRANSFER_NEG: | 1509 | case AC_TRANSFER_NEG: |
4208 | { | 1510 | { |
4209 | char buf[80]; | 1511 | char buf[80]; |
1512 | struct scsi_target *starget; | ||
4210 | struct ahd_linux_target *targ; | 1513 | struct ahd_linux_target *targ; |
4211 | struct info_str info; | 1514 | struct info_str info; |
4212 | struct ahd_initiator_tinfo *tinfo; | 1515 | struct ahd_initiator_tinfo *tinfo; |
4213 | struct ahd_tmode_tstate *tstate; | 1516 | struct ahd_tmode_tstate *tstate; |
1517 | unsigned int target_ppr_options; | ||
1518 | |||
1519 | BUG_ON(target == CAM_TARGET_WILDCARD); | ||
4214 | 1520 | ||
4215 | info.buffer = buf; | 1521 | info.buffer = buf; |
4216 | info.length = sizeof(buf); | 1522 | info.length = sizeof(buf); |
@@ -4234,58 +1540,47 @@ ahd_send_async(struct ahd_softc *ahd, char channel, | |||
4234 | * Don't bother reporting results that | 1540 | * Don't bother reporting results that |
4235 | * are identical to those last reported. | 1541 | * are identical to those last reported. |
4236 | */ | 1542 | */ |
4237 | targ = ahd->platform_data->targets[target]; | 1543 | starget = ahd->platform_data->starget[target]; |
4238 | if (targ == NULL) | 1544 | if (starget == NULL) |
4239 | break; | 1545 | break; |
4240 | if (tinfo->curr.period == targ->last_tinfo.period | 1546 | targ = scsi_transport_target_data(starget); |
4241 | && tinfo->curr.width == targ->last_tinfo.width | 1547 | |
4242 | && tinfo->curr.offset == targ->last_tinfo.offset | 1548 | target_ppr_options = |
4243 | && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options) | 1549 | (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) |
1550 | + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0) | ||
1551 | + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0) | ||
1552 | + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0) | ||
1553 | + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0) | ||
1554 | + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0) | ||
1555 | + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0) | ||
1556 | + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0); | ||
1557 | |||
1558 | if (tinfo->curr.period == spi_period(starget) | ||
1559 | && tinfo->curr.width == spi_width(starget) | ||
1560 | && tinfo->curr.offset == spi_offset(starget) | ||
1561 | && tinfo->curr.ppr_options == target_ppr_options) | ||
4244 | if (bootverbose == 0) | 1562 | if (bootverbose == 0) |
4245 | break; | 1563 | break; |
4246 | 1564 | ||
4247 | targ->last_tinfo.period = tinfo->curr.period; | 1565 | spi_period(starget) = tinfo->curr.period; |
4248 | targ->last_tinfo.width = tinfo->curr.width; | 1566 | spi_width(starget) = tinfo->curr.width; |
4249 | targ->last_tinfo.offset = tinfo->curr.offset; | 1567 | spi_offset(starget) = tinfo->curr.offset; |
4250 | targ->last_tinfo.ppr_options = tinfo->curr.ppr_options; | 1568 | spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0; |
4251 | 1569 | spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0; | |
4252 | printf("(%s:%c:", ahd_name(ahd), channel); | 1570 | spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0; |
4253 | if (target == CAM_TARGET_WILDCARD) | 1571 | spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0; |
4254 | printf("*): "); | 1572 | spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0; |
4255 | else | 1573 | spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0; |
4256 | printf("%d): ", target); | 1574 | spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0; |
4257 | ahd_format_transinfo(&info, &tinfo->curr); | 1575 | spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0; |
4258 | if (info.pos < info.length) | 1576 | spi_display_xfer_agreement(starget); |
4259 | *info.buffer = '\0'; | ||
4260 | else | ||
4261 | buf[info.length - 1] = '\0'; | ||
4262 | printf("%s", buf); | ||
4263 | break; | 1577 | break; |
4264 | } | 1578 | } |
4265 | case AC_SENT_BDR: | 1579 | case AC_SENT_BDR: |
4266 | { | 1580 | { |
4267 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
4268 | WARN_ON(lun != CAM_LUN_WILDCARD); | 1581 | WARN_ON(lun != CAM_LUN_WILDCARD); |
4269 | scsi_report_device_reset(ahd->platform_data->host, | 1582 | scsi_report_device_reset(ahd->platform_data->host, |
4270 | channel - 'A', target); | 1583 | channel - 'A', target); |
4271 | #else | ||
4272 | Scsi_Device *scsi_dev; | ||
4273 | |||
4274 | /* | ||
4275 | * Find the SCSI device associated with this | ||
4276 | * request and indicate that a UA is expected. | ||
4277 | */ | ||
4278 | for (scsi_dev = ahd->platform_data->host->host_queue; | ||
4279 | scsi_dev != NULL; scsi_dev = scsi_dev->next) { | ||
4280 | if (channel - 'A' == scsi_dev->channel | ||
4281 | && target == scsi_dev->id | ||
4282 | && (lun == CAM_LUN_WILDCARD | ||
4283 | || lun == scsi_dev->lun)) { | ||
4284 | scsi_dev->was_reset = 1; | ||
4285 | scsi_dev->expecting_cc_ua = 1; | ||
4286 | } | ||
4287 | } | ||
4288 | #endif | ||
4289 | break; | 1584 | break; |
4290 | } | 1585 | } |
4291 | case AC_BUS_RESET: | 1586 | case AC_BUS_RESET: |
@@ -4305,7 +1600,7 @@ ahd_send_async(struct ahd_softc *ahd, char channel, | |||
4305 | void | 1600 | void |
4306 | ahd_done(struct ahd_softc *ahd, struct scb *scb) | 1601 | ahd_done(struct ahd_softc *ahd, struct scb *scb) |
4307 | { | 1602 | { |
4308 | Scsi_Cmnd *cmd; | 1603 | struct scsi_cmnd *cmd; |
4309 | struct ahd_linux_device *dev; | 1604 | struct ahd_linux_device *dev; |
4310 | 1605 | ||
4311 | if ((scb->flags & SCB_ACTIVE) == 0) { | 1606 | if ((scb->flags & SCB_ACTIVE) == 0) { |
@@ -4373,19 +1668,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) | |||
4373 | ahd_set_transaction_status(scb, CAM_REQ_CMP); | 1668 | ahd_set_transaction_status(scb, CAM_REQ_CMP); |
4374 | } | 1669 | } |
4375 | } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { | 1670 | } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { |
4376 | ahd_linux_handle_scsi_status(ahd, dev, scb); | 1671 | ahd_linux_handle_scsi_status(ahd, cmd->device, scb); |
4377 | } else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { | ||
4378 | dev->flags |= AHD_DEV_UNCONFIGURED; | ||
4379 | if (AHD_DV_CMD(cmd) == FALSE) | ||
4380 | dev->target->flags &= ~AHD_DV_REQUIRED; | ||
4381 | } | 1672 | } |
4382 | /* | ||
4383 | * Start DV for devices that require it assuming the first command | ||
4384 | * sent does not result in a selection timeout. | ||
4385 | */ | ||
4386 | if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT | ||
4387 | && (dev->target->flags & AHD_DV_REQUIRED) != 0) | ||
4388 | ahd_linux_start_dv(ahd); | ||
4389 | 1673 | ||
4390 | if (dev->openings == 1 | 1674 | if (dev->openings == 1 |
4391 | && ahd_get_transaction_status(scb) == CAM_REQ_CMP | 1675 | && ahd_get_transaction_status(scb) == CAM_REQ_CMP |
@@ -4406,47 +1690,32 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) | |||
4406 | if (dev->active == 0) | 1690 | if (dev->active == 0) |
4407 | dev->commands_since_idle_or_otag = 0; | 1691 | dev->commands_since_idle_or_otag = 0; |
4408 | 1692 | ||
4409 | if (TAILQ_EMPTY(&dev->busyq)) { | ||
4410 | if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 | ||
4411 | && dev->active == 0 | ||
4412 | && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) | ||
4413 | ahd_linux_free_device(ahd, dev); | ||
4414 | } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { | ||
4415 | TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); | ||
4416 | dev->flags |= AHD_DEV_ON_RUN_LIST; | ||
4417 | } | ||
4418 | |||
4419 | if ((scb->flags & SCB_RECOVERY_SCB) != 0) { | 1693 | if ((scb->flags & SCB_RECOVERY_SCB) != 0) { |
4420 | printf("Recovery SCB completes\n"); | 1694 | printf("Recovery SCB completes\n"); |
4421 | if (ahd_get_transaction_status(scb) == CAM_BDR_SENT | 1695 | if (ahd_get_transaction_status(scb) == CAM_BDR_SENT |
4422 | || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) | 1696 | || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) |
4423 | ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); | 1697 | ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); |
4424 | if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { | 1698 | if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { |
4425 | scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; | 1699 | ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; |
4426 | up(&ahd->platform_data->eh_sem); | 1700 | up(&ahd->platform_data->eh_sem); |
4427 | } | 1701 | } |
4428 | } | 1702 | } |
4429 | 1703 | ||
4430 | ahd_free_scb(ahd, scb); | 1704 | ahd_free_scb(ahd, scb); |
4431 | ahd_linux_queue_cmd_complete(ahd, cmd); | 1705 | ahd_linux_queue_cmd_complete(ahd, cmd); |
4432 | |||
4433 | if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0 | ||
4434 | && LIST_FIRST(&ahd->pending_scbs) == NULL) { | ||
4435 | ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY; | ||
4436 | up(&ahd->platform_data->dv_sem); | ||
4437 | } | ||
4438 | } | 1706 | } |
4439 | 1707 | ||
4440 | static void | 1708 | static void |
4441 | ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | 1709 | ahd_linux_handle_scsi_status(struct ahd_softc *ahd, |
4442 | struct ahd_linux_device *dev, struct scb *scb) | 1710 | struct scsi_device *sdev, struct scb *scb) |
4443 | { | 1711 | { |
4444 | struct ahd_devinfo devinfo; | 1712 | struct ahd_devinfo devinfo; |
1713 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); | ||
4445 | 1714 | ||
4446 | ahd_compile_devinfo(&devinfo, | 1715 | ahd_compile_devinfo(&devinfo, |
4447 | ahd->our_id, | 1716 | ahd->our_id, |
4448 | dev->target->target, dev->lun, | 1717 | sdev->sdev_target->id, sdev->lun, |
4449 | dev->target->channel == 0 ? 'A' : 'B', | 1718 | sdev->sdev_target->channel == 0 ? 'A' : 'B', |
4450 | ROLE_INITIATOR); | 1719 | ROLE_INITIATOR); |
4451 | 1720 | ||
4452 | /* | 1721 | /* |
@@ -4465,7 +1734,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
4465 | case SCSI_STATUS_CHECK_COND: | 1734 | case SCSI_STATUS_CHECK_COND: |
4466 | case SCSI_STATUS_CMD_TERMINATED: | 1735 | case SCSI_STATUS_CMD_TERMINATED: |
4467 | { | 1736 | { |
4468 | Scsi_Cmnd *cmd; | 1737 | struct scsi_cmnd *cmd; |
4469 | 1738 | ||
4470 | /* | 1739 | /* |
4471 | * Copy sense information to the OS's cmd | 1740 | * Copy sense information to the OS's cmd |
@@ -4518,7 +1787,6 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
4518 | break; | 1787 | break; |
4519 | } | 1788 | } |
4520 | case SCSI_STATUS_QUEUE_FULL: | 1789 | case SCSI_STATUS_QUEUE_FULL: |
4521 | { | ||
4522 | /* | 1790 | /* |
4523 | * By the time the core driver has returned this | 1791 | * By the time the core driver has returned this |
4524 | * command, all other commands that were queued | 1792 | * command, all other commands that were queued |
@@ -4579,98 +1847,23 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
4579 | (dev->flags & AHD_DEV_Q_BASIC) | 1847 | (dev->flags & AHD_DEV_Q_BASIC) |
4580 | ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); | 1848 | ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); |
4581 | ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); | 1849 | ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); |
4582 | /* FALLTHROUGH */ | ||
4583 | } | ||
4584 | case SCSI_STATUS_BUSY: | ||
4585 | /* | ||
4586 | * Set a short timer to defer sending commands for | ||
4587 | * a bit since Linux will not delay in this case. | ||
4588 | */ | ||
4589 | if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) { | ||
4590 | printf("%s:%c:%d: Device Timer still active during " | ||
4591 | "busy processing\n", ahd_name(ahd), | ||
4592 | dev->target->channel, dev->target->target); | ||
4593 | break; | ||
4594 | } | ||
4595 | dev->flags |= AHD_DEV_TIMER_ACTIVE; | ||
4596 | dev->qfrozen++; | ||
4597 | init_timer(&dev->timer); | ||
4598 | dev->timer.data = (u_long)dev; | ||
4599 | dev->timer.expires = jiffies + (HZ/2); | ||
4600 | dev->timer.function = ahd_linux_dev_timed_unfreeze; | ||
4601 | add_timer(&dev->timer); | ||
4602 | break; | ||
4603 | } | 1850 | } |
4604 | } | 1851 | } |
4605 | 1852 | ||
4606 | static void | 1853 | static void |
4607 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd) | 1854 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) |
4608 | { | 1855 | { |
4609 | /* | 1856 | /* |
4610 | * Typically, the complete queue has very few entries | ||
4611 | * queued to it before the queue is emptied by | ||
4612 | * ahd_linux_run_complete_queue, so sorting the entries | ||
4613 | * by generation number should be inexpensive. | ||
4614 | * We perform the sort so that commands that complete | ||
4615 | * with an error are retuned in the order origionally | ||
4616 | * queued to the controller so that any subsequent retries | ||
4617 | * are performed in order. The underlying ahd routines do | ||
4618 | * not guarantee the order that aborted commands will be | ||
4619 | * returned to us. | ||
4620 | */ | ||
4621 | struct ahd_completeq *completeq; | ||
4622 | struct ahd_cmd *list_cmd; | ||
4623 | struct ahd_cmd *acmd; | ||
4624 | |||
4625 | /* | ||
4626 | * Map CAM error codes into Linux Error codes. We | 1857 | * Map CAM error codes into Linux Error codes. We |
4627 | * avoid the conversion so that the DV code has the | 1858 | * avoid the conversion so that the DV code has the |
4628 | * full error information available when making | 1859 | * full error information available when making |
4629 | * state change decisions. | 1860 | * state change decisions. |
4630 | */ | 1861 | */ |
4631 | if (AHD_DV_CMD(cmd) == FALSE) { | 1862 | { |
4632 | uint32_t status; | 1863 | uint32_t status; |
4633 | u_int new_status; | 1864 | u_int new_status; |
4634 | 1865 | ||
4635 | status = ahd_cmd_get_transaction_status(cmd); | 1866 | status = ahd_cmd_get_transaction_status(cmd); |
4636 | if (status != CAM_REQ_CMP) { | ||
4637 | struct ahd_linux_device *dev; | ||
4638 | struct ahd_devinfo devinfo; | ||
4639 | cam_status cam_status; | ||
4640 | uint32_t action; | ||
4641 | u_int scsi_status; | ||
4642 | |||
4643 | dev = ahd_linux_get_device(ahd, cmd->device->channel, | ||
4644 | cmd->device->id, | ||
4645 | cmd->device->lun, | ||
4646 | /*alloc*/FALSE); | ||
4647 | |||
4648 | if (dev == NULL) | ||
4649 | goto no_fallback; | ||
4650 | |||
4651 | ahd_compile_devinfo(&devinfo, | ||
4652 | ahd->our_id, | ||
4653 | dev->target->target, dev->lun, | ||
4654 | dev->target->channel == 0 ? 'A':'B', | ||
4655 | ROLE_INITIATOR); | ||
4656 | |||
4657 | scsi_status = ahd_cmd_get_scsi_status(cmd); | ||
4658 | cam_status = ahd_cmd_get_transaction_status(cmd); | ||
4659 | action = aic_error_action(cmd, dev->target->inq_data, | ||
4660 | cam_status, scsi_status); | ||
4661 | if ((action & SSQ_FALLBACK) != 0) { | ||
4662 | |||
4663 | /* Update stats */ | ||
4664 | dev->target->errors_detected++; | ||
4665 | if (dev->target->cmds_since_error == 0) | ||
4666 | dev->target->cmds_since_error++; | ||
4667 | else { | ||
4668 | dev->target->cmds_since_error = 0; | ||
4669 | ahd_linux_fallback(ahd, &devinfo); | ||
4670 | } | ||
4671 | } | ||
4672 | } | ||
4673 | no_fallback: | ||
4674 | switch (status) { | 1867 | switch (status) { |
4675 | case CAM_REQ_INPROG: | 1868 | case CAM_REQ_INPROG: |
4676 | case CAM_REQ_CMP: | 1869 | case CAM_REQ_CMP: |
@@ -4715,26 +1908,7 @@ no_fallback: | |||
4715 | new_status = DID_ERROR; | 1908 | new_status = DID_ERROR; |
4716 | break; | 1909 | break; |
4717 | case CAM_REQUEUE_REQ: | 1910 | case CAM_REQUEUE_REQ: |
4718 | /* | 1911 | new_status = DID_REQUEUE; |
4719 | * If we want the request requeued, make sure there | ||
4720 | * are sufficent retries. In the old scsi error code, | ||
4721 | * we used to be able to specify a result code that | ||
4722 | * bypassed the retry count. Now we must use this | ||
4723 | * hack. We also "fake" a check condition with | ||
4724 | * a sense code of ABORTED COMMAND. This seems to | ||
4725 | * evoke a retry even if this command is being sent | ||
4726 | * via the eh thread. Ick! Ick! Ick! | ||
4727 | */ | ||
4728 | if (cmd->retries > 0) | ||
4729 | cmd->retries--; | ||
4730 | new_status = DID_OK; | ||
4731 | ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); | ||
4732 | cmd->result |= (DRIVER_SENSE << 24); | ||
4733 | memset(cmd->sense_buffer, 0, | ||
4734 | sizeof(cmd->sense_buffer)); | ||
4735 | cmd->sense_buffer[0] = SSD_ERRCODE_VALID | ||
4736 | | SSD_CURRENT_ERROR; | ||
4737 | cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND; | ||
4738 | break; | 1912 | break; |
4739 | default: | 1913 | default: |
4740 | /* We should never get here */ | 1914 | /* We should never get here */ |
@@ -4745,116 +1919,23 @@ no_fallback: | |||
4745 | ahd_cmd_set_transaction_status(cmd, new_status); | 1919 | ahd_cmd_set_transaction_status(cmd, new_status); |
4746 | } | 1920 | } |
4747 | 1921 | ||
4748 | completeq = &ahd->platform_data->completeq; | 1922 | cmd->scsi_done(cmd); |
4749 | list_cmd = TAILQ_FIRST(completeq); | ||
4750 | acmd = (struct ahd_cmd *)cmd; | ||
4751 | while (list_cmd != NULL | ||
4752 | && acmd_scsi_cmd(list_cmd).serial_number | ||
4753 | < acmd_scsi_cmd(acmd).serial_number) | ||
4754 | list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); | ||
4755 | if (list_cmd != NULL) | ||
4756 | TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); | ||
4757 | else | ||
4758 | TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); | ||
4759 | } | 1923 | } |
4760 | 1924 | ||
4761 | static void | 1925 | static void |
4762 | ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | 1926 | ahd_linux_sem_timeout(u_long arg) |
4763 | { | 1927 | { |
4764 | struct scsi_inquiry_data *sid; | 1928 | struct ahd_softc *ahd; |
4765 | struct ahd_initiator_tinfo *tinfo; | 1929 | u_long s; |
4766 | struct ahd_transinfo *user; | ||
4767 | struct ahd_transinfo *goal; | ||
4768 | struct ahd_transinfo *curr; | ||
4769 | struct ahd_tmode_tstate *tstate; | ||
4770 | struct ahd_linux_device *dev; | ||
4771 | u_int width; | ||
4772 | u_int period; | ||
4773 | u_int offset; | ||
4774 | u_int ppr_options; | ||
4775 | u_int trans_version; | ||
4776 | u_int prot_version; | ||
4777 | |||
4778 | /* | ||
4779 | * Determine if this lun actually exists. If so, | ||
4780 | * hold on to its corresponding device structure. | ||
4781 | * If not, make sure we release the device and | ||
4782 | * don't bother processing the rest of this inquiry | ||
4783 | * command. | ||
4784 | */ | ||
4785 | dev = ahd_linux_get_device(ahd, devinfo->channel - 'A', | ||
4786 | devinfo->target, devinfo->lun, | ||
4787 | /*alloc*/TRUE); | ||
4788 | |||
4789 | sid = (struct scsi_inquiry_data *)dev->target->inq_data; | ||
4790 | if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { | ||
4791 | |||
4792 | dev->flags &= ~AHD_DEV_UNCONFIGURED; | ||
4793 | } else { | ||
4794 | dev->flags |= AHD_DEV_UNCONFIGURED; | ||
4795 | return; | ||
4796 | } | ||
4797 | 1930 | ||
4798 | /* | 1931 | ahd = (struct ahd_softc *)arg; |
4799 | * Update our notion of this device's transfer | ||
4800 | * negotiation capabilities. | ||
4801 | */ | ||
4802 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, | ||
4803 | devinfo->our_scsiid, | ||
4804 | devinfo->target, &tstate); | ||
4805 | user = &tinfo->user; | ||
4806 | goal = &tinfo->goal; | ||
4807 | curr = &tinfo->curr; | ||
4808 | width = user->width; | ||
4809 | period = user->period; | ||
4810 | offset = user->offset; | ||
4811 | ppr_options = user->ppr_options; | ||
4812 | trans_version = user->transport_version; | ||
4813 | prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid)); | ||
4814 | 1932 | ||
4815 | /* | 1933 | ahd_lock(ahd, &s); |
4816 | * Only attempt SPI3/4 once we've verified that | 1934 | if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { |
4817 | * the device claims to support SPI3/4 features. | 1935 | ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; |
4818 | */ | 1936 | up(&ahd->platform_data->eh_sem); |
4819 | if (prot_version < SCSI_REV_2) | ||
4820 | trans_version = SID_ANSI_REV(sid); | ||
4821 | else | ||
4822 | trans_version = SCSI_REV_2; | ||
4823 | |||
4824 | if ((sid->flags & SID_WBus16) == 0) | ||
4825 | width = MSG_EXT_WDTR_BUS_8_BIT; | ||
4826 | if ((sid->flags & SID_Sync) == 0) { | ||
4827 | period = 0; | ||
4828 | offset = 0; | ||
4829 | ppr_options = 0; | ||
4830 | } | ||
4831 | if ((sid->spi3data & SID_SPI_QAS) == 0) | ||
4832 | ppr_options &= ~MSG_EXT_PPR_QAS_REQ; | ||
4833 | if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0) | ||
4834 | ppr_options &= MSG_EXT_PPR_QAS_REQ; | ||
4835 | if ((sid->spi3data & SID_SPI_IUS) == 0) | ||
4836 | ppr_options &= (MSG_EXT_PPR_DT_REQ | ||
4837 | | MSG_EXT_PPR_QAS_REQ); | ||
4838 | |||
4839 | if (prot_version > SCSI_REV_2 | ||
4840 | && ppr_options != 0) | ||
4841 | trans_version = user->transport_version; | ||
4842 | |||
4843 | ahd_validate_width(ahd, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN); | ||
4844 | ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX); | ||
4845 | ahd_validate_offset(ahd, /*tinfo limit*/NULL, period, | ||
4846 | &offset, width, ROLE_UNKNOWN); | ||
4847 | if (offset == 0 || period == 0) { | ||
4848 | period = 0; | ||
4849 | offset = 0; | ||
4850 | ppr_options = 0; | ||
4851 | } | 1937 | } |
4852 | /* Apply our filtered user settings. */ | 1938 | ahd_unlock(ahd, &s); |
4853 | curr->transport_version = trans_version; | ||
4854 | curr->protocol_version = prot_version; | ||
4855 | ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, /*paused*/FALSE); | ||
4856 | ahd_set_syncrate(ahd, devinfo, period, offset, ppr_options, | ||
4857 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
4858 | } | 1939 | } |
4859 | 1940 | ||
4860 | void | 1941 | void |
@@ -4882,12 +1963,6 @@ ahd_release_simq(struct ahd_softc *ahd) | |||
4882 | if (ahd->platform_data->qfrozen == 0) { | 1963 | if (ahd->platform_data->qfrozen == 0) { |
4883 | unblock_reqs = 1; | 1964 | unblock_reqs = 1; |
4884 | } | 1965 | } |
4885 | if (AHD_DV_SIMQ_FROZEN(ahd) | ||
4886 | && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) { | ||
4887 | ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE; | ||
4888 | up(&ahd->platform_data->dv_sem); | ||
4889 | } | ||
4890 | ahd_schedule_runq(ahd); | ||
4891 | ahd_unlock(ahd, &s); | 1966 | ahd_unlock(ahd, &s); |
4892 | /* | 1967 | /* |
4893 | * There is still a race here. The mid-layer | 1968 | * There is still a race here. The mid-layer |
@@ -4899,118 +1974,743 @@ ahd_release_simq(struct ahd_softc *ahd) | |||
4899 | scsi_unblock_requests(ahd->platform_data->host); | 1974 | scsi_unblock_requests(ahd->platform_data->host); |
4900 | } | 1975 | } |
4901 | 1976 | ||
4902 | static void | 1977 | static int |
4903 | ahd_linux_sem_timeout(u_long arg) | 1978 | ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) |
4904 | { | 1979 | { |
4905 | struct scb *scb; | 1980 | struct ahd_softc *ahd; |
4906 | struct ahd_softc *ahd; | 1981 | struct ahd_linux_device *dev; |
4907 | u_long s; | 1982 | struct scb *pending_scb; |
1983 | u_int saved_scbptr; | ||
1984 | u_int active_scbptr; | ||
1985 | u_int last_phase; | ||
1986 | u_int saved_scsiid; | ||
1987 | u_int cdb_byte; | ||
1988 | int retval; | ||
1989 | int was_paused; | ||
1990 | int paused; | ||
1991 | int wait; | ||
1992 | int disconnected; | ||
1993 | ahd_mode_state saved_modes; | ||
4908 | 1994 | ||
4909 | scb = (struct scb *)arg; | 1995 | pending_scb = NULL; |
4910 | ahd = scb->ahd_softc; | 1996 | paused = FALSE; |
4911 | ahd_lock(ahd, &s); | 1997 | wait = FALSE; |
4912 | if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { | 1998 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
4913 | scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; | 1999 | |
4914 | up(&ahd->platform_data->eh_sem); | 2000 | printf("%s:%d:%d:%d: Attempting to queue a%s message:", |
2001 | ahd_name(ahd), cmd->device->channel, | ||
2002 | cmd->device->id, cmd->device->lun, | ||
2003 | flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); | ||
2004 | |||
2005 | printf("CDB:"); | ||
2006 | for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) | ||
2007 | printf(" 0x%x", cmd->cmnd[cdb_byte]); | ||
2008 | printf("\n"); | ||
2009 | |||
2010 | spin_lock_irq(&ahd->platform_data->spin_lock); | ||
2011 | |||
2012 | /* | ||
2013 | * First determine if we currently own this command. | ||
2014 | * Start by searching the device queue. If not found | ||
2015 | * there, check the pending_scb list. If not found | ||
2016 | * at all, and the system wanted us to just abort the | ||
2017 | * command, return success. | ||
2018 | */ | ||
2019 | dev = scsi_transport_device_data(cmd->device); | ||
2020 | |||
2021 | if (dev == NULL) { | ||
2022 | /* | ||
2023 | * No target device for this command exists, | ||
2024 | * so we must not still own the command. | ||
2025 | */ | ||
2026 | printf("%s:%d:%d:%d: Is not an active device\n", | ||
2027 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
2028 | cmd->device->lun); | ||
2029 | retval = SUCCESS; | ||
2030 | goto no_cmd; | ||
4915 | } | 2031 | } |
4916 | ahd_unlock(ahd, &s); | 2032 | |
2033 | /* | ||
2034 | * See if we can find a matching cmd in the pending list. | ||
2035 | */ | ||
2036 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | ||
2037 | if (pending_scb->io_ctx == cmd) | ||
2038 | break; | ||
2039 | } | ||
2040 | |||
2041 | if (pending_scb == NULL && flag == SCB_DEVICE_RESET) { | ||
2042 | |||
2043 | /* Any SCB for this device will do for a target reset */ | ||
2044 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | ||
2045 | if (ahd_match_scb(ahd, pending_scb, cmd->device->id, | ||
2046 | cmd->device->channel + 'A', | ||
2047 | CAM_LUN_WILDCARD, | ||
2048 | SCB_LIST_NULL, ROLE_INITIATOR) == 0) | ||
2049 | break; | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | if (pending_scb == NULL) { | ||
2054 | printf("%s:%d:%d:%d: Command not found\n", | ||
2055 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
2056 | cmd->device->lun); | ||
2057 | goto no_cmd; | ||
2058 | } | ||
2059 | |||
2060 | if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { | ||
2061 | /* | ||
2062 | * We can't queue two recovery actions using the same SCB | ||
2063 | */ | ||
2064 | retval = FAILED; | ||
2065 | goto done; | ||
2066 | } | ||
2067 | |||
2068 | /* | ||
2069 | * Ensure that the card doesn't do anything | ||
2070 | * behind our back. Also make sure that we | ||
2071 | * didn't "just" miss an interrupt that would | ||
2072 | * affect this cmd. | ||
2073 | */ | ||
2074 | was_paused = ahd_is_paused(ahd); | ||
2075 | ahd_pause_and_flushwork(ahd); | ||
2076 | paused = TRUE; | ||
2077 | |||
2078 | if ((pending_scb->flags & SCB_ACTIVE) == 0) { | ||
2079 | printf("%s:%d:%d:%d: Command already completed\n", | ||
2080 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
2081 | cmd->device->lun); | ||
2082 | goto no_cmd; | ||
2083 | } | ||
2084 | |||
2085 | printf("%s: At time of recovery, card was %spaused\n", | ||
2086 | ahd_name(ahd), was_paused ? "" : "not "); | ||
2087 | ahd_dump_card_state(ahd); | ||
2088 | |||
2089 | disconnected = TRUE; | ||
2090 | if (flag == SCB_ABORT) { | ||
2091 | if (ahd_search_qinfifo(ahd, cmd->device->id, | ||
2092 | cmd->device->channel + 'A', | ||
2093 | cmd->device->lun, | ||
2094 | pending_scb->hscb->tag, | ||
2095 | ROLE_INITIATOR, CAM_REQ_ABORTED, | ||
2096 | SEARCH_COMPLETE) > 0) { | ||
2097 | printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", | ||
2098 | ahd_name(ahd), cmd->device->channel, | ||
2099 | cmd->device->id, cmd->device->lun); | ||
2100 | retval = SUCCESS; | ||
2101 | goto done; | ||
2102 | } | ||
2103 | } else if (ahd_search_qinfifo(ahd, cmd->device->id, | ||
2104 | cmd->device->channel + 'A', | ||
2105 | cmd->device->lun, pending_scb->hscb->tag, | ||
2106 | ROLE_INITIATOR, /*status*/0, | ||
2107 | SEARCH_COUNT) > 0) { | ||
2108 | disconnected = FALSE; | ||
2109 | } | ||
2110 | |||
2111 | saved_modes = ahd_save_modes(ahd); | ||
2112 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
2113 | last_phase = ahd_inb(ahd, LASTPHASE); | ||
2114 | saved_scbptr = ahd_get_scbptr(ahd); | ||
2115 | active_scbptr = saved_scbptr; | ||
2116 | if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { | ||
2117 | struct scb *bus_scb; | ||
2118 | |||
2119 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); | ||
2120 | if (bus_scb == pending_scb) | ||
2121 | disconnected = FALSE; | ||
2122 | else if (flag != SCB_ABORT | ||
2123 | && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid | ||
2124 | && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb)) | ||
2125 | disconnected = FALSE; | ||
2126 | } | ||
2127 | |||
2128 | /* | ||
2129 | * At this point, pending_scb is the scb associated with the | ||
2130 | * passed in command. That command is currently active on the | ||
2131 | * bus or is in the disconnected state. | ||
2132 | */ | ||
2133 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); | ||
2134 | if (last_phase != P_BUSFREE | ||
2135 | && (SCB_GET_TAG(pending_scb) == active_scbptr | ||
2136 | || (flag == SCB_DEVICE_RESET | ||
2137 | && SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) { | ||
2138 | |||
2139 | /* | ||
2140 | * We're active on the bus, so assert ATN | ||
2141 | * and hope that the target responds. | ||
2142 | */ | ||
2143 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); | ||
2144 | pending_scb->flags |= SCB_RECOVERY_SCB|flag; | ||
2145 | ahd_outb(ahd, MSG_OUT, HOST_MSG); | ||
2146 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); | ||
2147 | printf("%s:%d:%d:%d: Device is active, asserting ATN\n", | ||
2148 | ahd_name(ahd), cmd->device->channel, | ||
2149 | cmd->device->id, cmd->device->lun); | ||
2150 | wait = TRUE; | ||
2151 | } else if (disconnected) { | ||
2152 | |||
2153 | /* | ||
2154 | * Actually re-queue this SCB in an attempt | ||
2155 | * to select the device before it reconnects. | ||
2156 | */ | ||
2157 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; | ||
2158 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); | ||
2159 | pending_scb->hscb->cdb_len = 0; | ||
2160 | pending_scb->hscb->task_attribute = 0; | ||
2161 | pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; | ||
2162 | |||
2163 | if ((pending_scb->flags & SCB_PACKETIZED) != 0) { | ||
2164 | /* | ||
2165 | * Mark the SCB has having an outstanding | ||
2166 | * task management function. Should the command | ||
2167 | * complete normally before the task management | ||
2168 | * function can be sent, the host will be notified | ||
2169 | * to abort our requeued SCB. | ||
2170 | */ | ||
2171 | ahd_outb(ahd, SCB_TASK_MANAGEMENT, | ||
2172 | pending_scb->hscb->task_management); | ||
2173 | } else { | ||
2174 | /* | ||
2175 | * If non-packetized, set the MK_MESSAGE control | ||
2176 | * bit indicating that we desire to send a message. | ||
2177 | * We also set the disconnected flag since there is | ||
2178 | * no guarantee that our SCB control byte matches | ||
2179 | * the version on the card. We don't want the | ||
2180 | * sequencer to abort the command thinking an | ||
2181 | * unsolicited reselection occurred. | ||
2182 | */ | ||
2183 | pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED; | ||
2184 | |||
2185 | /* | ||
2186 | * The sequencer will never re-reference the | ||
2187 | * in-core SCB. To make sure we are notified | ||
2188 | * during reslection, set the MK_MESSAGE flag in | ||
2189 | * the card's copy of the SCB. | ||
2190 | */ | ||
2191 | ahd_outb(ahd, SCB_CONTROL, | ||
2192 | ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); | ||
2193 | } | ||
2194 | |||
2195 | /* | ||
2196 | * Clear out any entries in the QINFIFO first | ||
2197 | * so we are the next SCB for this target | ||
2198 | * to run. | ||
2199 | */ | ||
2200 | ahd_search_qinfifo(ahd, cmd->device->id, | ||
2201 | cmd->device->channel + 'A', cmd->device->lun, | ||
2202 | SCB_LIST_NULL, ROLE_INITIATOR, | ||
2203 | CAM_REQUEUE_REQ, SEARCH_COMPLETE); | ||
2204 | ahd_qinfifo_requeue_tail(ahd, pending_scb); | ||
2205 | ahd_set_scbptr(ahd, saved_scbptr); | ||
2206 | ahd_print_path(ahd, pending_scb); | ||
2207 | printf("Device is disconnected, re-queuing SCB\n"); | ||
2208 | wait = TRUE; | ||
2209 | } else { | ||
2210 | printf("%s:%d:%d:%d: Unable to deliver message\n", | ||
2211 | ahd_name(ahd), cmd->device->channel, | ||
2212 | cmd->device->id, cmd->device->lun); | ||
2213 | retval = FAILED; | ||
2214 | goto done; | ||
2215 | } | ||
2216 | |||
2217 | no_cmd: | ||
2218 | /* | ||
2219 | * Our assumption is that if we don't have the command, no | ||
2220 | * recovery action was required, so we return success. Again, | ||
2221 | * the semantics of the mid-layer recovery engine are not | ||
2222 | * well defined, so this may change in time. | ||
2223 | */ | ||
2224 | retval = SUCCESS; | ||
2225 | done: | ||
2226 | if (paused) | ||
2227 | ahd_unpause(ahd); | ||
2228 | if (wait) { | ||
2229 | struct timer_list timer; | ||
2230 | int ret; | ||
2231 | |||
2232 | ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM; | ||
2233 | spin_unlock_irq(&ahd->platform_data->spin_lock); | ||
2234 | init_timer(&timer); | ||
2235 | timer.data = (u_long)ahd; | ||
2236 | timer.expires = jiffies + (5 * HZ); | ||
2237 | timer.function = ahd_linux_sem_timeout; | ||
2238 | add_timer(&timer); | ||
2239 | printf("Recovery code sleeping\n"); | ||
2240 | down(&ahd->platform_data->eh_sem); | ||
2241 | printf("Recovery code awake\n"); | ||
2242 | ret = del_timer_sync(&timer); | ||
2243 | if (ret == 0) { | ||
2244 | printf("Timer Expired\n"); | ||
2245 | retval = FAILED; | ||
2246 | } | ||
2247 | spin_lock_irq(&ahd->platform_data->spin_lock); | ||
2248 | } | ||
2249 | spin_unlock_irq(&ahd->platform_data->spin_lock); | ||
2250 | return (retval); | ||
4917 | } | 2251 | } |
4918 | 2252 | ||
4919 | static void | 2253 | static void ahd_linux_set_width(struct scsi_target *starget, int width) |
4920 | ahd_linux_dev_timed_unfreeze(u_long arg) | ||
4921 | { | 2254 | { |
4922 | struct ahd_linux_device *dev; | 2255 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
4923 | struct ahd_softc *ahd; | 2256 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); |
4924 | u_long s; | 2257 | struct ahd_devinfo devinfo; |
2258 | unsigned long flags; | ||
4925 | 2259 | ||
4926 | dev = (struct ahd_linux_device *)arg; | 2260 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, |
4927 | ahd = dev->target->ahd; | 2261 | starget->channel + 'A', ROLE_INITIATOR); |
4928 | ahd_lock(ahd, &s); | 2262 | ahd_lock(ahd, &flags); |
4929 | dev->flags &= ~AHD_DEV_TIMER_ACTIVE; | 2263 | ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE); |
4930 | if (dev->qfrozen > 0) | 2264 | ahd_unlock(ahd, &flags); |
4931 | dev->qfrozen--; | ||
4932 | if (dev->qfrozen == 0 | ||
4933 | && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0) | ||
4934 | ahd_linux_run_device_queue(ahd, dev); | ||
4935 | if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 | ||
4936 | && dev->active == 0) | ||
4937 | ahd_linux_free_device(ahd, dev); | ||
4938 | ahd_unlock(ahd, &s); | ||
4939 | } | 2265 | } |
4940 | 2266 | ||
4941 | void | 2267 | static void ahd_linux_set_period(struct scsi_target *starget, int period) |
4942 | ahd_platform_dump_card_state(struct ahd_softc *ahd) | ||
4943 | { | 2268 | { |
4944 | struct ahd_linux_device *dev; | 2269 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
4945 | int target; | 2270 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); |
4946 | int maxtarget; | 2271 | struct ahd_tmode_tstate *tstate; |
4947 | int lun; | 2272 | struct ahd_initiator_tinfo *tinfo |
4948 | int i; | 2273 | = ahd_fetch_transinfo(ahd, |
4949 | 2274 | starget->channel + 'A', | |
4950 | maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7; | 2275 | shost->this_id, starget->id, &tstate); |
4951 | for (target = 0; target <=maxtarget; target++) { | 2276 | struct ahd_devinfo devinfo; |
4952 | 2277 | unsigned int ppr_options = tinfo->goal.ppr_options; | |
4953 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { | 2278 | unsigned int dt; |
4954 | struct ahd_cmd *acmd; | 2279 | unsigned long flags; |
4955 | 2280 | unsigned long offset = tinfo->goal.offset; | |
4956 | dev = ahd_linux_get_device(ahd, 0, target, | 2281 | |
4957 | lun, /*alloc*/FALSE); | 2282 | #ifdef AHD_DEBUG |
4958 | if (dev == NULL) | 2283 | if ((ahd_debug & AHD_SHOW_DV) != 0) |
4959 | continue; | 2284 | printf("%s: set period to %d\n", ahd_name(ahd), period); |
4960 | 2285 | #endif | |
4961 | printf("DevQ(%d:%d:%d): ", 0, target, lun); | 2286 | if (offset == 0) |
4962 | i = 0; | 2287 | offset = MAX_OFFSET; |
4963 | TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) { | 2288 | |
4964 | if (i++ > AHD_SCB_MAX) | 2289 | if (period < 8) |
4965 | break; | 2290 | period = 8; |
4966 | } | 2291 | if (period < 10) { |
4967 | printf("%d waiting\n", i); | 2292 | ppr_options |= MSG_EXT_PPR_DT_REQ; |
4968 | } | 2293 | if (period == 8) |
2294 | ppr_options |= MSG_EXT_PPR_IU_REQ; | ||
2295 | } | ||
2296 | |||
2297 | dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2298 | |||
2299 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2300 | starget->channel + 'A', ROLE_INITIATOR); | ||
2301 | |||
2302 | /* all PPR requests apart from QAS require wide transfers */ | ||
2303 | if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) { | ||
2304 | if (spi_width(starget) == 0) | ||
2305 | ppr_options &= MSG_EXT_PPR_QAS_REQ; | ||
4969 | } | 2306 | } |
2307 | |||
2308 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2309 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2310 | |||
2311 | ahd_lock(ahd, &flags); | ||
2312 | ahd_set_syncrate(ahd, &devinfo, period, offset, | ||
2313 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2314 | ahd_unlock(ahd, &flags); | ||
4970 | } | 2315 | } |
4971 | 2316 | ||
4972 | static int __init | 2317 | static void ahd_linux_set_offset(struct scsi_target *starget, int offset) |
4973 | ahd_linux_init(void) | ||
4974 | { | 2318 | { |
4975 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 2319 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
4976 | return ahd_linux_detect(&aic79xx_driver_template); | 2320 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); |
4977 | #else | 2321 | struct ahd_tmode_tstate *tstate; |
4978 | scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template); | 2322 | struct ahd_initiator_tinfo *tinfo |
4979 | if (aic79xx_driver_template.present == 0) { | 2323 | = ahd_fetch_transinfo(ahd, |
4980 | scsi_unregister_module(MODULE_SCSI_HA, | 2324 | starget->channel + 'A', |
4981 | &aic79xx_driver_template); | 2325 | shost->this_id, starget->id, &tstate); |
4982 | return (-ENODEV); | 2326 | struct ahd_devinfo devinfo; |
2327 | unsigned int ppr_options = 0; | ||
2328 | unsigned int period = 0; | ||
2329 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2330 | unsigned long flags; | ||
2331 | |||
2332 | #ifdef AHD_DEBUG | ||
2333 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2334 | printf("%s: set offset to %d\n", ahd_name(ahd), offset); | ||
2335 | #endif | ||
2336 | |||
2337 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2338 | starget->channel + 'A', ROLE_INITIATOR); | ||
2339 | if (offset != 0) { | ||
2340 | period = tinfo->goal.period; | ||
2341 | ppr_options = tinfo->goal.ppr_options; | ||
2342 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2343 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
4983 | } | 2344 | } |
4984 | 2345 | ||
4985 | return (0); | 2346 | ahd_lock(ahd, &flags); |
2347 | ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options, | ||
2348 | AHD_TRANS_GOAL, FALSE); | ||
2349 | ahd_unlock(ahd, &flags); | ||
2350 | } | ||
2351 | |||
2352 | static void ahd_linux_set_dt(struct scsi_target *starget, int dt) | ||
2353 | { | ||
2354 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2355 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2356 | struct ahd_tmode_tstate *tstate; | ||
2357 | struct ahd_initiator_tinfo *tinfo | ||
2358 | = ahd_fetch_transinfo(ahd, | ||
2359 | starget->channel + 'A', | ||
2360 | shost->this_id, starget->id, &tstate); | ||
2361 | struct ahd_devinfo devinfo; | ||
2362 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2363 | & ~MSG_EXT_PPR_DT_REQ; | ||
2364 | unsigned int period = tinfo->goal.period; | ||
2365 | unsigned int width = tinfo->goal.width; | ||
2366 | unsigned long flags; | ||
2367 | |||
2368 | #ifdef AHD_DEBUG | ||
2369 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2370 | printf("%s: %s DT\n", ahd_name(ahd), | ||
2371 | dt ? "enabling" : "disabling"); | ||
2372 | #endif | ||
2373 | if (dt) { | ||
2374 | ppr_options |= MSG_EXT_PPR_DT_REQ; | ||
2375 | if (!width) | ||
2376 | ahd_linux_set_width(starget, 1); | ||
2377 | } else { | ||
2378 | if (period <= 9) | ||
2379 | period = 10; /* If resetting DT, period must be >= 25ns */ | ||
2380 | /* IU is invalid without DT set */ | ||
2381 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | ||
2382 | } | ||
2383 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2384 | starget->channel + 'A', ROLE_INITIATOR); | ||
2385 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2386 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2387 | |||
2388 | ahd_lock(ahd, &flags); | ||
2389 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2390 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2391 | ahd_unlock(ahd, &flags); | ||
2392 | } | ||
2393 | |||
2394 | static void ahd_linux_set_qas(struct scsi_target *starget, int qas) | ||
2395 | { | ||
2396 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2397 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2398 | struct ahd_tmode_tstate *tstate; | ||
2399 | struct ahd_initiator_tinfo *tinfo | ||
2400 | = ahd_fetch_transinfo(ahd, | ||
2401 | starget->channel + 'A', | ||
2402 | shost->this_id, starget->id, &tstate); | ||
2403 | struct ahd_devinfo devinfo; | ||
2404 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2405 | & ~MSG_EXT_PPR_QAS_REQ; | ||
2406 | unsigned int period = tinfo->goal.period; | ||
2407 | unsigned int dt; | ||
2408 | unsigned long flags; | ||
2409 | |||
2410 | #ifdef AHD_DEBUG | ||
2411 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2412 | printf("%s: %s QAS\n", ahd_name(ahd), | ||
2413 | qas ? "enabling" : "disabling"); | ||
2414 | #endif | ||
2415 | |||
2416 | if (qas) { | ||
2417 | ppr_options |= MSG_EXT_PPR_QAS_REQ; | ||
2418 | } | ||
2419 | |||
2420 | dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2421 | |||
2422 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2423 | starget->channel + 'A', ROLE_INITIATOR); | ||
2424 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2425 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2426 | |||
2427 | ahd_lock(ahd, &flags); | ||
2428 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2429 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2430 | ahd_unlock(ahd, &flags); | ||
2431 | } | ||
2432 | |||
2433 | static void ahd_linux_set_iu(struct scsi_target *starget, int iu) | ||
2434 | { | ||
2435 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2436 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2437 | struct ahd_tmode_tstate *tstate; | ||
2438 | struct ahd_initiator_tinfo *tinfo | ||
2439 | = ahd_fetch_transinfo(ahd, | ||
2440 | starget->channel + 'A', | ||
2441 | shost->this_id, starget->id, &tstate); | ||
2442 | struct ahd_devinfo devinfo; | ||
2443 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2444 | & ~MSG_EXT_PPR_IU_REQ; | ||
2445 | unsigned int period = tinfo->goal.period; | ||
2446 | unsigned int dt; | ||
2447 | unsigned long flags; | ||
2448 | |||
2449 | #ifdef AHD_DEBUG | ||
2450 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2451 | printf("%s: %s IU\n", ahd_name(ahd), | ||
2452 | iu ? "enabling" : "disabling"); | ||
4986 | #endif | 2453 | #endif |
2454 | |||
2455 | if (iu) { | ||
2456 | ppr_options |= MSG_EXT_PPR_IU_REQ; | ||
2457 | ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */ | ||
2458 | } | ||
2459 | |||
2460 | dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2461 | |||
2462 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2463 | starget->channel + 'A', ROLE_INITIATOR); | ||
2464 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2465 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2466 | |||
2467 | ahd_lock(ahd, &flags); | ||
2468 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2469 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2470 | ahd_unlock(ahd, &flags); | ||
4987 | } | 2471 | } |
4988 | 2472 | ||
4989 | static void __exit | 2473 | static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) |
4990 | ahd_linux_exit(void) | ||
4991 | { | 2474 | { |
4992 | struct ahd_softc *ahd; | 2475 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
2476 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2477 | struct ahd_tmode_tstate *tstate; | ||
2478 | struct ahd_initiator_tinfo *tinfo | ||
2479 | = ahd_fetch_transinfo(ahd, | ||
2480 | starget->channel + 'A', | ||
2481 | shost->this_id, starget->id, &tstate); | ||
2482 | struct ahd_devinfo devinfo; | ||
2483 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2484 | & ~MSG_EXT_PPR_RD_STRM; | ||
2485 | unsigned int period = tinfo->goal.period; | ||
2486 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2487 | unsigned long flags; | ||
4993 | 2488 | ||
4994 | /* | 2489 | #ifdef AHD_DEBUG |
4995 | * Shutdown DV threads before going into the SCSI mid-layer. | 2490 | if ((ahd_debug & AHD_SHOW_DV) != 0) |
4996 | * This avoids situations where the mid-layer locks the entire | 2491 | printf("%s: %s Read Streaming\n", ahd_name(ahd), |
4997 | * kernel so that waiting for our DV threads to exit leads | 2492 | rdstrm ? "enabling" : "disabling"); |
4998 | * to deadlock. | 2493 | #endif |
4999 | */ | 2494 | |
5000 | TAILQ_FOREACH(ahd, &ahd_tailq, links) { | 2495 | if (rdstrm) |
2496 | ppr_options |= MSG_EXT_PPR_RD_STRM; | ||
2497 | |||
2498 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2499 | starget->channel + 'A', ROLE_INITIATOR); | ||
2500 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2501 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2502 | |||
2503 | ahd_lock(ahd, &flags); | ||
2504 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2505 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2506 | ahd_unlock(ahd, &flags); | ||
2507 | } | ||
2508 | |||
2509 | static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow) | ||
2510 | { | ||
2511 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2512 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2513 | struct ahd_tmode_tstate *tstate; | ||
2514 | struct ahd_initiator_tinfo *tinfo | ||
2515 | = ahd_fetch_transinfo(ahd, | ||
2516 | starget->channel + 'A', | ||
2517 | shost->this_id, starget->id, &tstate); | ||
2518 | struct ahd_devinfo devinfo; | ||
2519 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2520 | & ~MSG_EXT_PPR_WR_FLOW; | ||
2521 | unsigned int period = tinfo->goal.period; | ||
2522 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2523 | unsigned long flags; | ||
2524 | |||
2525 | #ifdef AHD_DEBUG | ||
2526 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2527 | printf("%s: %s Write Flow Control\n", ahd_name(ahd), | ||
2528 | wrflow ? "enabling" : "disabling"); | ||
2529 | #endif | ||
2530 | |||
2531 | if (wrflow) | ||
2532 | ppr_options |= MSG_EXT_PPR_WR_FLOW; | ||
2533 | |||
2534 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2535 | starget->channel + 'A', ROLE_INITIATOR); | ||
2536 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2537 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2538 | |||
2539 | ahd_lock(ahd, &flags); | ||
2540 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2541 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2542 | ahd_unlock(ahd, &flags); | ||
2543 | } | ||
2544 | |||
2545 | static void ahd_linux_set_rti(struct scsi_target *starget, int rti) | ||
2546 | { | ||
2547 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2548 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2549 | struct ahd_tmode_tstate *tstate; | ||
2550 | struct ahd_initiator_tinfo *tinfo | ||
2551 | = ahd_fetch_transinfo(ahd, | ||
2552 | starget->channel + 'A', | ||
2553 | shost->this_id, starget->id, &tstate); | ||
2554 | struct ahd_devinfo devinfo; | ||
2555 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2556 | & ~MSG_EXT_PPR_RTI; | ||
2557 | unsigned int period = tinfo->goal.period; | ||
2558 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2559 | unsigned long flags; | ||
5001 | 2560 | ||
5002 | ahd_linux_kill_dv_thread(ahd); | 2561 | if ((ahd->features & AHD_RTI) == 0) { |
2562 | #ifdef AHD_DEBUG | ||
2563 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2564 | printf("%s: RTI not available\n", ahd_name(ahd)); | ||
2565 | #endif | ||
2566 | return; | ||
5003 | } | 2567 | } |
5004 | 2568 | ||
5005 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 2569 | #ifdef AHD_DEBUG |
2570 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2571 | printf("%s: %s RTI\n", ahd_name(ahd), | ||
2572 | rti ? "enabling" : "disabling"); | ||
2573 | #endif | ||
2574 | |||
2575 | if (rti) | ||
2576 | ppr_options |= MSG_EXT_PPR_RTI; | ||
2577 | |||
2578 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2579 | starget->channel + 'A', ROLE_INITIATOR); | ||
2580 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2581 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2582 | |||
2583 | ahd_lock(ahd, &flags); | ||
2584 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2585 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2586 | ahd_unlock(ahd, &flags); | ||
2587 | } | ||
2588 | |||
2589 | static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) | ||
2590 | { | ||
2591 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2592 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2593 | struct ahd_tmode_tstate *tstate; | ||
2594 | struct ahd_initiator_tinfo *tinfo | ||
2595 | = ahd_fetch_transinfo(ahd, | ||
2596 | starget->channel + 'A', | ||
2597 | shost->this_id, starget->id, &tstate); | ||
2598 | struct ahd_devinfo devinfo; | ||
2599 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2600 | & ~MSG_EXT_PPR_PCOMP_EN; | ||
2601 | unsigned int period = tinfo->goal.period; | ||
2602 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2603 | unsigned long flags; | ||
2604 | |||
2605 | #ifdef AHD_DEBUG | ||
2606 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2607 | printf("%s: %s Precompensation\n", ahd_name(ahd), | ||
2608 | pcomp ? "Enable" : "Disable"); | ||
2609 | #endif | ||
2610 | |||
2611 | if (pcomp) | ||
2612 | ppr_options |= MSG_EXT_PPR_PCOMP_EN; | ||
2613 | |||
2614 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2615 | starget->channel + 'A', ROLE_INITIATOR); | ||
2616 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2617 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2618 | |||
2619 | ahd_lock(ahd, &flags); | ||
2620 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2621 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2622 | ahd_unlock(ahd, &flags); | ||
2623 | } | ||
2624 | |||
2625 | static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold) | ||
2626 | { | ||
2627 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2628 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2629 | struct ahd_tmode_tstate *tstate; | ||
2630 | struct ahd_initiator_tinfo *tinfo | ||
2631 | = ahd_fetch_transinfo(ahd, | ||
2632 | starget->channel + 'A', | ||
2633 | shost->this_id, starget->id, &tstate); | ||
2634 | struct ahd_devinfo devinfo; | ||
2635 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2636 | & ~MSG_EXT_PPR_HOLD_MCS; | ||
2637 | unsigned int period = tinfo->goal.period; | ||
2638 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2639 | unsigned long flags; | ||
2640 | |||
2641 | if (hold) | ||
2642 | ppr_options |= MSG_EXT_PPR_HOLD_MCS; | ||
2643 | |||
2644 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2645 | starget->channel + 'A', ROLE_INITIATOR); | ||
2646 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2647 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2648 | |||
2649 | ahd_lock(ahd, &flags); | ||
2650 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2651 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2652 | ahd_unlock(ahd, &flags); | ||
2653 | } | ||
2654 | |||
2655 | |||
2656 | |||
2657 | static struct spi_function_template ahd_linux_transport_functions = { | ||
2658 | .set_offset = ahd_linux_set_offset, | ||
2659 | .show_offset = 1, | ||
2660 | .set_period = ahd_linux_set_period, | ||
2661 | .show_period = 1, | ||
2662 | .set_width = ahd_linux_set_width, | ||
2663 | .show_width = 1, | ||
2664 | .set_dt = ahd_linux_set_dt, | ||
2665 | .show_dt = 1, | ||
2666 | .set_iu = ahd_linux_set_iu, | ||
2667 | .show_iu = 1, | ||
2668 | .set_qas = ahd_linux_set_qas, | ||
2669 | .show_qas = 1, | ||
2670 | .set_rd_strm = ahd_linux_set_rd_strm, | ||
2671 | .show_rd_strm = 1, | ||
2672 | .set_wr_flow = ahd_linux_set_wr_flow, | ||
2673 | .show_wr_flow = 1, | ||
2674 | .set_rti = ahd_linux_set_rti, | ||
2675 | .show_rti = 1, | ||
2676 | .set_pcomp_en = ahd_linux_set_pcomp_en, | ||
2677 | .show_pcomp_en = 1, | ||
2678 | .set_hold_mcs = ahd_linux_set_hold_mcs, | ||
2679 | .show_hold_mcs = 1, | ||
2680 | }; | ||
2681 | |||
2682 | static int __init | ||
2683 | ahd_linux_init(void) | ||
2684 | { | ||
2685 | int error = 0; | ||
2686 | |||
5006 | /* | 2687 | /* |
5007 | * In 2.4 we have to unregister from the PCI core _after_ | 2688 | * If we've been passed any parameters, process them now. |
5008 | * unregistering from the scsi midlayer to avoid dangling | ||
5009 | * references. | ||
5010 | */ | 2689 | */ |
5011 | scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template); | 2690 | if (aic79xx) |
5012 | #endif | 2691 | aic79xx_setup(aic79xx); |
2692 | |||
2693 | ahd_linux_transport_template = | ||
2694 | spi_attach_transport(&ahd_linux_transport_functions); | ||
2695 | if (!ahd_linux_transport_template) | ||
2696 | return -ENODEV; | ||
2697 | |||
2698 | scsi_transport_reserve_target(ahd_linux_transport_template, | ||
2699 | sizeof(struct ahd_linux_target)); | ||
2700 | scsi_transport_reserve_device(ahd_linux_transport_template, | ||
2701 | sizeof(struct ahd_linux_device)); | ||
2702 | |||
2703 | error = ahd_linux_pci_init(); | ||
2704 | if (error) | ||
2705 | spi_release_transport(ahd_linux_transport_template); | ||
2706 | return error; | ||
2707 | } | ||
2708 | |||
2709 | static void __exit | ||
2710 | ahd_linux_exit(void) | ||
2711 | { | ||
5013 | ahd_linux_pci_exit(); | 2712 | ahd_linux_pci_exit(); |
2713 | spi_release_transport(ahd_linux_transport_template); | ||
5014 | } | 2714 | } |
5015 | 2715 | ||
5016 | module_init(ahd_linux_init); | 2716 | module_init(ahd_linux_init); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 7823e52e99ab..052c6619accc 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #ifndef _AIC79XX_LINUX_H_ | 42 | #ifndef _AIC79XX_LINUX_H_ |
43 | #define _AIC79XX_LINUX_H_ | 43 | #define _AIC79XX_LINUX_H_ |
44 | 44 | ||
45 | #include <linux/config.h> | ||
45 | #include <linux/types.h> | 46 | #include <linux/types.h> |
46 | #include <linux/blkdev.h> | 47 | #include <linux/blkdev.h> |
47 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
@@ -49,18 +50,23 @@ | |||
49 | #include <linux/pci.h> | 50 | #include <linux/pci.h> |
50 | #include <linux/smp_lock.h> | 51 | #include <linux/smp_lock.h> |
51 | #include <linux/version.h> | 52 | #include <linux/version.h> |
53 | #include <linux/interrupt.h> | ||
52 | #include <linux/module.h> | 54 | #include <linux/module.h> |
55 | #include <linux/slab.h> | ||
53 | #include <asm/byteorder.h> | 56 | #include <asm/byteorder.h> |
54 | #include <asm/io.h> | 57 | #include <asm/io.h> |
55 | 58 | ||
56 | #include <linux/interrupt.h> /* For tasklet support. */ | 59 | #include <scsi/scsi.h> |
57 | #include <linux/config.h> | 60 | #include <scsi/scsi_cmnd.h> |
58 | #include <linux/slab.h> | 61 | #include <scsi/scsi_eh.h> |
62 | #include <scsi/scsi_device.h> | ||
63 | #include <scsi/scsi_host.h> | ||
64 | #include <scsi/scsi_tcq.h> | ||
65 | #include <scsi/scsi_transport.h> | ||
66 | #include <scsi/scsi_transport_spi.h> | ||
59 | 67 | ||
60 | /* Core SCSI definitions */ | 68 | /* Core SCSI definitions */ |
61 | #define AIC_LIB_PREFIX ahd | 69 | #define AIC_LIB_PREFIX ahd |
62 | #include "scsi.h" | ||
63 | #include <scsi/scsi_host.h> | ||
64 | 70 | ||
65 | /* Name space conflict with BSD queue macros */ | 71 | /* Name space conflict with BSD queue macros */ |
66 | #ifdef LIST_HEAD | 72 | #ifdef LIST_HEAD |
@@ -95,7 +101,7 @@ | |||
95 | /************************* Forward Declarations *******************************/ | 101 | /************************* Forward Declarations *******************************/ |
96 | struct ahd_softc; | 102 | struct ahd_softc; |
97 | typedef struct pci_dev *ahd_dev_softc_t; | 103 | typedef struct pci_dev *ahd_dev_softc_t; |
98 | typedef Scsi_Cmnd *ahd_io_ctx_t; | 104 | typedef struct scsi_cmnd *ahd_io_ctx_t; |
99 | 105 | ||
100 | /******************************* Byte Order ***********************************/ | 106 | /******************************* Byte Order ***********************************/ |
101 | #define ahd_htobe16(x) cpu_to_be16(x) | 107 | #define ahd_htobe16(x) cpu_to_be16(x) |
@@ -114,8 +120,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t; | |||
114 | 120 | ||
115 | /************************* Configuration Data *********************************/ | 121 | /************************* Configuration Data *********************************/ |
116 | extern uint32_t aic79xx_allow_memio; | 122 | extern uint32_t aic79xx_allow_memio; |
117 | extern int aic79xx_detect_complete; | 123 | extern struct scsi_host_template aic79xx_driver_template; |
118 | extern Scsi_Host_Template aic79xx_driver_template; | ||
119 | 124 | ||
120 | /***************************** Bus Space/DMA **********************************/ | 125 | /***************************** Bus Space/DMA **********************************/ |
121 | 126 | ||
@@ -145,11 +150,7 @@ struct ahd_linux_dma_tag | |||
145 | }; | 150 | }; |
146 | typedef struct ahd_linux_dma_tag* bus_dma_tag_t; | 151 | typedef struct ahd_linux_dma_tag* bus_dma_tag_t; |
147 | 152 | ||
148 | struct ahd_linux_dmamap | 153 | typedef dma_addr_t bus_dmamap_t; |
149 | { | ||
150 | dma_addr_t bus_addr; | ||
151 | }; | ||
152 | typedef struct ahd_linux_dmamap* bus_dmamap_t; | ||
153 | 154 | ||
154 | typedef int bus_dma_filter_t(void*, dma_addr_t); | 155 | typedef int bus_dma_filter_t(void*, dma_addr_t); |
155 | typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); | 156 | typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); |
@@ -226,12 +227,12 @@ typedef struct timer_list ahd_timer_t; | |||
226 | #define ahd_timer_init init_timer | 227 | #define ahd_timer_init init_timer |
227 | #define ahd_timer_stop del_timer_sync | 228 | #define ahd_timer_stop del_timer_sync |
228 | typedef void ahd_linux_callback_t (u_long); | 229 | typedef void ahd_linux_callback_t (u_long); |
229 | static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec, | 230 | static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, |
230 | ahd_callback_t *func, void *arg); | 231 | ahd_callback_t *func, void *arg); |
231 | static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); | 232 | static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); |
232 | 233 | ||
233 | static __inline void | 234 | static __inline void |
234 | ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg) | 235 | ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) |
235 | { | 236 | { |
236 | struct ahd_softc *ahd; | 237 | struct ahd_softc *ahd; |
237 | 238 | ||
@@ -252,43 +253,8 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec) | |||
252 | /***************************** SMP support ************************************/ | 253 | /***************************** SMP support ************************************/ |
253 | #include <linux/spinlock.h> | 254 | #include <linux/spinlock.h> |
254 | 255 | ||
255 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) | ||
256 | #define AHD_SCSI_HAS_HOST_LOCK 1 | ||
257 | #else | ||
258 | #define AHD_SCSI_HAS_HOST_LOCK 0 | ||
259 | #endif | ||
260 | |||
261 | #define AIC79XX_DRIVER_VERSION "1.3.11" | 256 | #define AIC79XX_DRIVER_VERSION "1.3.11" |
262 | 257 | ||
263 | /**************************** Front End Queues ********************************/ | ||
264 | /* | ||
265 | * Data structure used to cast the Linux struct scsi_cmnd to something | ||
266 | * that allows us to use the queue macros. The linux structure has | ||
267 | * plenty of space to hold the links fields as required by the queue | ||
268 | * macros, but the queue macors require them to have the correct type. | ||
269 | */ | ||
270 | struct ahd_cmd_internal { | ||
271 | /* Area owned by the Linux scsi layer. */ | ||
272 | uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; | ||
273 | union { | ||
274 | STAILQ_ENTRY(ahd_cmd) ste; | ||
275 | LIST_ENTRY(ahd_cmd) le; | ||
276 | TAILQ_ENTRY(ahd_cmd) tqe; | ||
277 | } links; | ||
278 | uint32_t end; | ||
279 | }; | ||
280 | |||
281 | struct ahd_cmd { | ||
282 | union { | ||
283 | struct ahd_cmd_internal icmd; | ||
284 | struct scsi_cmnd scsi_cmd; | ||
285 | } un; | ||
286 | }; | ||
287 | |||
288 | #define acmd_icmd(cmd) ((cmd)->un.icmd) | ||
289 | #define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) | ||
290 | #define acmd_links un.icmd.links | ||
291 | |||
292 | /*************************** Device Data Structures ***************************/ | 258 | /*************************** Device Data Structures ***************************/ |
293 | /* | 259 | /* |
294 | * A per probed device structure used to deal with some error recovery | 260 | * A per probed device structure used to deal with some error recovery |
@@ -297,22 +263,17 @@ struct ahd_cmd { | |||
297 | * after a successfully completed inquiry command to the target when | 263 | * after a successfully completed inquiry command to the target when |
298 | * that inquiry data indicates a lun is present. | 264 | * that inquiry data indicates a lun is present. |
299 | */ | 265 | */ |
300 | TAILQ_HEAD(ahd_busyq, ahd_cmd); | 266 | |
301 | typedef enum { | 267 | typedef enum { |
302 | AHD_DEV_UNCONFIGURED = 0x01, | ||
303 | AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ | 268 | AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ |
304 | AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ | ||
305 | AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ | ||
306 | AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ | 269 | AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ |
307 | AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ | 270 | AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ |
308 | AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ | 271 | AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ |
309 | AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ | ||
310 | } ahd_linux_dev_flags; | 272 | } ahd_linux_dev_flags; |
311 | 273 | ||
312 | struct ahd_linux_target; | 274 | struct ahd_linux_target; |
313 | struct ahd_linux_device { | 275 | struct ahd_linux_device { |
314 | TAILQ_ENTRY(ahd_linux_device) links; | 276 | TAILQ_ENTRY(ahd_linux_device) links; |
315 | struct ahd_busyq busyq; | ||
316 | 277 | ||
317 | /* | 278 | /* |
318 | * The number of transactions currently | 279 | * The number of transactions currently |
@@ -388,62 +349,12 @@ struct ahd_linux_device { | |||
388 | */ | 349 | */ |
389 | u_int commands_since_idle_or_otag; | 350 | u_int commands_since_idle_or_otag; |
390 | #define AHD_OTAG_THRESH 500 | 351 | #define AHD_OTAG_THRESH 500 |
391 | |||
392 | int lun; | ||
393 | Scsi_Device *scsi_device; | ||
394 | struct ahd_linux_target *target; | ||
395 | }; | 352 | }; |
396 | 353 | ||
397 | typedef enum { | ||
398 | AHD_DV_REQUIRED = 0x01, | ||
399 | AHD_INQ_VALID = 0x02, | ||
400 | AHD_BASIC_DV = 0x04, | ||
401 | AHD_ENHANCED_DV = 0x08 | ||
402 | } ahd_linux_targ_flags; | ||
403 | |||
404 | /* DV States */ | ||
405 | typedef enum { | ||
406 | AHD_DV_STATE_EXIT = 0, | ||
407 | AHD_DV_STATE_INQ_SHORT_ASYNC, | ||
408 | AHD_DV_STATE_INQ_ASYNC, | ||
409 | AHD_DV_STATE_INQ_ASYNC_VERIFY, | ||
410 | AHD_DV_STATE_TUR, | ||
411 | AHD_DV_STATE_REBD, | ||
412 | AHD_DV_STATE_INQ_VERIFY, | ||
413 | AHD_DV_STATE_WEB, | ||
414 | AHD_DV_STATE_REB, | ||
415 | AHD_DV_STATE_SU, | ||
416 | AHD_DV_STATE_BUSY | ||
417 | } ahd_dv_state; | ||
418 | |||
419 | struct ahd_linux_target { | 354 | struct ahd_linux_target { |
420 | struct ahd_linux_device *devices[AHD_NUM_LUNS]; | 355 | struct scsi_device *sdev[AHD_NUM_LUNS]; |
421 | int channel; | ||
422 | int target; | ||
423 | int refcount; | ||
424 | struct ahd_transinfo last_tinfo; | 356 | struct ahd_transinfo last_tinfo; |
425 | struct ahd_softc *ahd; | 357 | struct ahd_softc *ahd; |
426 | ahd_linux_targ_flags flags; | ||
427 | struct scsi_inquiry_data *inq_data; | ||
428 | /* | ||
429 | * The next "fallback" period to use for narrow/wide transfers. | ||
430 | */ | ||
431 | uint8_t dv_next_narrow_period; | ||
432 | uint8_t dv_next_wide_period; | ||
433 | uint8_t dv_max_width; | ||
434 | uint8_t dv_max_ppr_options; | ||
435 | uint8_t dv_last_ppr_options; | ||
436 | u_int dv_echo_size; | ||
437 | ahd_dv_state dv_state; | ||
438 | u_int dv_state_retry; | ||
439 | uint8_t *dv_buffer; | ||
440 | uint8_t *dv_buffer1; | ||
441 | |||
442 | /* | ||
443 | * Cumulative counter of errors. | ||
444 | */ | ||
445 | u_long errors_detected; | ||
446 | u_long cmds_since_error; | ||
447 | }; | 358 | }; |
448 | 359 | ||
449 | /********************* Definitions Required by the Core ***********************/ | 360 | /********************* Definitions Required by the Core ***********************/ |
@@ -453,32 +364,16 @@ struct ahd_linux_target { | |||
453 | * manner and are allocated below 4GB, the number of S/G segments is | 364 | * manner and are allocated below 4GB, the number of S/G segments is |
454 | * unrestricted. | 365 | * unrestricted. |
455 | */ | 366 | */ |
456 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
457 | /* | ||
458 | * We dynamically adjust the number of segments in pre-2.5 kernels to | ||
459 | * avoid fragmentation issues in the SCSI mid-layer's private memory | ||
460 | * allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details. | ||
461 | */ | ||
462 | extern u_int ahd_linux_nseg; | ||
463 | #define AHD_NSEG ahd_linux_nseg | ||
464 | #define AHD_LINUX_MIN_NSEG 64 | ||
465 | #else | ||
466 | #define AHD_NSEG 128 | 367 | #define AHD_NSEG 128 |
467 | #endif | ||
468 | 368 | ||
469 | /* | 369 | /* |
470 | * Per-SCB OSM storage. | 370 | * Per-SCB OSM storage. |
471 | */ | 371 | */ |
472 | typedef enum { | ||
473 | AHD_SCB_UP_EH_SEM = 0x1 | ||
474 | } ahd_linux_scb_flags; | ||
475 | |||
476 | struct scb_platform_data { | 372 | struct scb_platform_data { |
477 | struct ahd_linux_device *dev; | 373 | struct ahd_linux_device *dev; |
478 | dma_addr_t buf_busaddr; | 374 | dma_addr_t buf_busaddr; |
479 | uint32_t xfer_len; | 375 | uint32_t xfer_len; |
480 | uint32_t sense_resid; /* Auto-Sense residual */ | 376 | uint32_t sense_resid; /* Auto-Sense residual */ |
481 | ahd_linux_scb_flags flags; | ||
482 | }; | 377 | }; |
483 | 378 | ||
484 | /* | 379 | /* |
@@ -487,44 +382,23 @@ struct scb_platform_data { | |||
487 | * alignment restrictions of the various platforms supported by | 382 | * alignment restrictions of the various platforms supported by |
488 | * this driver. | 383 | * this driver. |
489 | */ | 384 | */ |
490 | typedef enum { | ||
491 | AHD_DV_WAIT_SIMQ_EMPTY = 0x01, | ||
492 | AHD_DV_WAIT_SIMQ_RELEASE = 0x02, | ||
493 | AHD_DV_ACTIVE = 0x04, | ||
494 | AHD_DV_SHUTDOWN = 0x08, | ||
495 | AHD_RUN_CMPLT_Q_TIMER = 0x10 | ||
496 | } ahd_linux_softc_flags; | ||
497 | |||
498 | TAILQ_HEAD(ahd_completeq, ahd_cmd); | ||
499 | |||
500 | struct ahd_platform_data { | 385 | struct ahd_platform_data { |
501 | /* | 386 | /* |
502 | * Fields accessed from interrupt context. | 387 | * Fields accessed from interrupt context. |
503 | */ | 388 | */ |
504 | struct ahd_linux_target *targets[AHD_NUM_TARGETS]; | 389 | struct scsi_target *starget[AHD_NUM_TARGETS]; |
505 | TAILQ_HEAD(, ahd_linux_device) device_runq; | ||
506 | struct ahd_completeq completeq; | ||
507 | 390 | ||
508 | spinlock_t spin_lock; | 391 | spinlock_t spin_lock; |
509 | struct tasklet_struct runq_tasklet; | ||
510 | u_int qfrozen; | 392 | u_int qfrozen; |
511 | pid_t dv_pid; | ||
512 | struct timer_list completeq_timer; | ||
513 | struct timer_list reset_timer; | 393 | struct timer_list reset_timer; |
514 | struct timer_list stats_timer; | ||
515 | struct semaphore eh_sem; | 394 | struct semaphore eh_sem; |
516 | struct semaphore dv_sem; | ||
517 | struct semaphore dv_cmd_sem; /* XXX This needs to be in | ||
518 | * the target struct | ||
519 | */ | ||
520 | struct scsi_device *dv_scsi_dev; | ||
521 | struct Scsi_Host *host; /* pointer to scsi host */ | 395 | struct Scsi_Host *host; /* pointer to scsi host */ |
522 | #define AHD_LINUX_NOIRQ ((uint32_t)~0) | 396 | #define AHD_LINUX_NOIRQ ((uint32_t)~0) |
523 | uint32_t irq; /* IRQ for this adapter */ | 397 | uint32_t irq; /* IRQ for this adapter */ |
524 | uint32_t bios_address; | 398 | uint32_t bios_address; |
525 | uint32_t mem_busaddr; /* Mem Base Addr */ | 399 | uint32_t mem_busaddr; /* Mem Base Addr */ |
526 | uint64_t hw_dma_mask; | 400 | #define AHD_SCB_UP_EH_SEM 0x1 |
527 | ahd_linux_softc_flags flags; | 401 | uint32_t flags; |
528 | }; | 402 | }; |
529 | 403 | ||
530 | /************************** OS Utility Wrappers *******************************/ | 404 | /************************** OS Utility Wrappers *******************************/ |
@@ -641,7 +515,7 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) | |||
641 | 515 | ||
642 | /**************************** Initialization **********************************/ | 516 | /**************************** Initialization **********************************/ |
643 | int ahd_linux_register_host(struct ahd_softc *, | 517 | int ahd_linux_register_host(struct ahd_softc *, |
644 | Scsi_Host_Template *); | 518 | struct scsi_host_template *); |
645 | 519 | ||
646 | uint64_t ahd_linux_get_memsize(void); | 520 | uint64_t ahd_linux_get_memsize(void); |
647 | 521 | ||
@@ -657,28 +531,6 @@ void ahd_format_transinfo(struct info_str *info, | |||
657 | struct ahd_transinfo *tinfo); | 531 | struct ahd_transinfo *tinfo); |
658 | 532 | ||
659 | /******************************** Locking *************************************/ | 533 | /******************************** Locking *************************************/ |
660 | /* Lock protecting internal data structures */ | ||
661 | static __inline void ahd_lockinit(struct ahd_softc *); | ||
662 | static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags); | ||
663 | static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags); | ||
664 | |||
665 | /* Lock acquisition and release of the above lock in midlayer entry points. */ | ||
666 | static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *, | ||
667 | unsigned long *flags); | ||
668 | static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *, | ||
669 | unsigned long *flags); | ||
670 | |||
671 | /* Lock held during command compeletion to the upper layer */ | ||
672 | static __inline void ahd_done_lockinit(struct ahd_softc *); | ||
673 | static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags); | ||
674 | static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags); | ||
675 | |||
676 | /* Lock held during ahd_list manipulation and ahd softc frees */ | ||
677 | extern spinlock_t ahd_list_spinlock; | ||
678 | static __inline void ahd_list_lockinit(void); | ||
679 | static __inline void ahd_list_lock(unsigned long *flags); | ||
680 | static __inline void ahd_list_unlock(unsigned long *flags); | ||
681 | |||
682 | static __inline void | 534 | static __inline void |
683 | ahd_lockinit(struct ahd_softc *ahd) | 535 | ahd_lockinit(struct ahd_softc *ahd) |
684 | { | 536 | { |
@@ -697,75 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) | |||
697 | spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); | 549 | spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); |
698 | } | 550 | } |
699 | 551 | ||
700 | static __inline void | ||
701 | ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags) | ||
702 | { | ||
703 | /* | ||
704 | * In 2.5.X and some 2.4.X versions, the midlayer takes our | ||
705 | * lock just before calling us, so we avoid locking again. | ||
706 | * For other kernel versions, the io_request_lock is taken | ||
707 | * just before our entry point is called. In this case, we | ||
708 | * trade the io_request_lock for our per-softc lock. | ||
709 | */ | ||
710 | #if AHD_SCSI_HAS_HOST_LOCK == 0 | ||
711 | spin_unlock(&io_request_lock); | ||
712 | spin_lock(&ahd->platform_data->spin_lock); | ||
713 | #endif | ||
714 | } | ||
715 | |||
716 | static __inline void | ||
717 | ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags) | ||
718 | { | ||
719 | #if AHD_SCSI_HAS_HOST_LOCK == 0 | ||
720 | spin_unlock(&ahd->platform_data->spin_lock); | ||
721 | spin_lock(&io_request_lock); | ||
722 | #endif | ||
723 | } | ||
724 | |||
725 | static __inline void | ||
726 | ahd_done_lockinit(struct ahd_softc *ahd) | ||
727 | { | ||
728 | /* | ||
729 | * In 2.5.X, our own lock is held during completions. | ||
730 | * In previous versions, the io_request_lock is used. | ||
731 | * In either case, we can't initialize this lock again. | ||
732 | */ | ||
733 | } | ||
734 | |||
735 | static __inline void | ||
736 | ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags) | ||
737 | { | ||
738 | #if AHD_SCSI_HAS_HOST_LOCK == 0 | ||
739 | spin_lock(&io_request_lock); | ||
740 | #endif | ||
741 | } | ||
742 | |||
743 | static __inline void | ||
744 | ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags) | ||
745 | { | ||
746 | #if AHD_SCSI_HAS_HOST_LOCK == 0 | ||
747 | spin_unlock(&io_request_lock); | ||
748 | #endif | ||
749 | } | ||
750 | |||
751 | static __inline void | ||
752 | ahd_list_lockinit(void) | ||
753 | { | ||
754 | spin_lock_init(&ahd_list_spinlock); | ||
755 | } | ||
756 | |||
757 | static __inline void | ||
758 | ahd_list_lock(unsigned long *flags) | ||
759 | { | ||
760 | spin_lock_irqsave(&ahd_list_spinlock, *flags); | ||
761 | } | ||
762 | |||
763 | static __inline void | ||
764 | ahd_list_unlock(unsigned long *flags) | ||
765 | { | ||
766 | spin_unlock_irqrestore(&ahd_list_spinlock, *flags); | ||
767 | } | ||
768 | |||
769 | /******************************* PCI Definitions ******************************/ | 552 | /******************************* PCI Definitions ******************************/ |
770 | /* | 553 | /* |
771 | * PCIM_xxx: mask to locate subfield in register | 554 | * PCIM_xxx: mask to locate subfield in register |
@@ -925,27 +708,17 @@ ahd_flush_device_writes(struct ahd_softc *ahd) | |||
925 | } | 708 | } |
926 | 709 | ||
927 | /**************************** Proc FS Support *********************************/ | 710 | /**************************** Proc FS Support *********************************/ |
928 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
929 | int ahd_linux_proc_info(char *, char **, off_t, int, int, int); | ||
930 | #else | ||
931 | int ahd_linux_proc_info(struct Scsi_Host *, char *, char **, | 711 | int ahd_linux_proc_info(struct Scsi_Host *, char *, char **, |
932 | off_t, int, int); | 712 | off_t, int, int); |
933 | #endif | ||
934 | |||
935 | /*************************** Domain Validation ********************************/ | ||
936 | #define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete) | ||
937 | #define AHD_DV_SIMQ_FROZEN(ahd) \ | ||
938 | ((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \ | ||
939 | && (ahd)->platform_data->qfrozen == 1) | ||
940 | 713 | ||
941 | /*********************** Transaction Access Wrappers **************************/ | 714 | /*********************** Transaction Access Wrappers **************************/ |
942 | static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); | 715 | static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); |
943 | static __inline void ahd_set_transaction_status(struct scb *, uint32_t); | 716 | static __inline void ahd_set_transaction_status(struct scb *, uint32_t); |
944 | static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); | 717 | static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); |
945 | static __inline void ahd_set_scsi_status(struct scb *, uint32_t); | 718 | static __inline void ahd_set_scsi_status(struct scb *, uint32_t); |
946 | static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd); | 719 | static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd); |
947 | static __inline uint32_t ahd_get_transaction_status(struct scb *); | 720 | static __inline uint32_t ahd_get_transaction_status(struct scb *); |
948 | static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd); | 721 | static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd); |
949 | static __inline uint32_t ahd_get_scsi_status(struct scb *); | 722 | static __inline uint32_t ahd_get_scsi_status(struct scb *); |
950 | static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); | 723 | static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); |
951 | static __inline u_long ahd_get_transfer_length(struct scb *); | 724 | static __inline u_long ahd_get_transfer_length(struct scb *); |
@@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd, | |||
964 | static __inline void ahd_freeze_scb(struct scb *scb); | 737 | static __inline void ahd_freeze_scb(struct scb *scb); |
965 | 738 | ||
966 | static __inline | 739 | static __inline |
967 | void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) | 740 | void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status) |
968 | { | 741 | { |
969 | cmd->result &= ~(CAM_STATUS_MASK << 16); | 742 | cmd->result &= ~(CAM_STATUS_MASK << 16); |
970 | cmd->result |= status << 16; | 743 | cmd->result |= status << 16; |
@@ -977,7 +750,7 @@ void ahd_set_transaction_status(struct scb *scb, uint32_t status) | |||
977 | } | 750 | } |
978 | 751 | ||
979 | static __inline | 752 | static __inline |
980 | void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) | 753 | void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status) |
981 | { | 754 | { |
982 | cmd->result &= ~0xFFFF; | 755 | cmd->result &= ~0xFFFF; |
983 | cmd->result |= status; | 756 | cmd->result |= status; |
@@ -990,7 +763,7 @@ void ahd_set_scsi_status(struct scb *scb, uint32_t status) | |||
990 | } | 763 | } |
991 | 764 | ||
992 | static __inline | 765 | static __inline |
993 | uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd) | 766 | uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd) |
994 | { | 767 | { |
995 | return ((cmd->result >> 16) & CAM_STATUS_MASK); | 768 | return ((cmd->result >> 16) & CAM_STATUS_MASK); |
996 | } | 769 | } |
@@ -1002,7 +775,7 @@ uint32_t ahd_get_transaction_status(struct scb *scb) | |||
1002 | } | 775 | } |
1003 | 776 | ||
1004 | static __inline | 777 | static __inline |
1005 | uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd) | 778 | uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd) |
1006 | { | 779 | { |
1007 | return (cmd->result & 0xFFFF); | 780 | return (cmd->result & 0xFFFF); |
1008 | } | 781 | } |
@@ -1117,7 +890,6 @@ void ahd_done(struct ahd_softc*, struct scb*); | |||
1117 | void ahd_send_async(struct ahd_softc *, char channel, | 890 | void ahd_send_async(struct ahd_softc *, char channel, |
1118 | u_int target, u_int lun, ac_code, void *); | 891 | u_int target, u_int lun, ac_code, void *); |
1119 | void ahd_print_path(struct ahd_softc *, struct scb *); | 892 | void ahd_print_path(struct ahd_softc *, struct scb *); |
1120 | void ahd_platform_dump_card_state(struct ahd_softc *ahd); | ||
1121 | 893 | ||
1122 | #ifdef CONFIG_PCI | 894 | #ifdef CONFIG_PCI |
1123 | #define AHD_PCI_CONFIG 1 | 895 | #define AHD_PCI_CONFIG 1 |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 91daf0c7fb10..390b53852d4b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c | |||
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = { | |||
92 | static void | 92 | static void |
93 | ahd_linux_pci_dev_remove(struct pci_dev *pdev) | 93 | ahd_linux_pci_dev_remove(struct pci_dev *pdev) |
94 | { | 94 | { |
95 | struct ahd_softc *ahd; | 95 | struct ahd_softc *ahd = pci_get_drvdata(pdev); |
96 | u_long l; | 96 | u_long s; |
97 | 97 | ||
98 | /* | 98 | ahd_lock(ahd, &s); |
99 | * We should be able to just perform | 99 | ahd_intr_enable(ahd, FALSE); |
100 | * the free directly, but check our | 100 | ahd_unlock(ahd, &s); |
101 | * list for extra sanity. | 101 | ahd_free(ahd); |
102 | */ | 102 | } |
103 | ahd_list_lock(&l); | 103 | |
104 | ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev)); | 104 | static void |
105 | if (ahd != NULL) { | 105 | ahd_linux_pci_inherit_flags(struct ahd_softc *ahd) |
106 | u_long s; | 106 | { |
107 | 107 | struct pci_dev *pdev = ahd->dev_softc, *master_pdev; | |
108 | TAILQ_REMOVE(&ahd_tailq, ahd, links); | 108 | unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); |
109 | ahd_list_unlock(&l); | 109 | |
110 | ahd_lock(ahd, &s); | 110 | master_pdev = pci_get_slot(pdev->bus, master_devfn); |
111 | ahd_intr_enable(ahd, FALSE); | 111 | if (master_pdev) { |
112 | ahd_unlock(ahd, &s); | 112 | struct ahd_softc *master = pci_get_drvdata(master_pdev); |
113 | ahd_free(ahd); | 113 | if (master) { |
114 | } else | 114 | ahd->flags &= ~AHD_BIOS_ENABLED; |
115 | ahd_list_unlock(&l); | 115 | ahd->flags |= master->flags & AHD_BIOS_ENABLED; |
116 | } else | ||
117 | printk(KERN_ERR "aic79xx: no multichannel peer found!\n"); | ||
118 | pci_dev_put(master_pdev); | ||
119 | } | ||
116 | } | 120 | } |
117 | 121 | ||
118 | static int | 122 | static int |
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
125 | char *name; | 129 | char *name; |
126 | int error; | 130 | int error; |
127 | 131 | ||
128 | /* | ||
129 | * Some BIOSen report the same device multiple times. | ||
130 | */ | ||
131 | TAILQ_FOREACH(ahd, &ahd_tailq, links) { | ||
132 | struct pci_dev *probed_pdev; | ||
133 | |||
134 | probed_pdev = ahd->dev_softc; | ||
135 | if (probed_pdev->bus->number == pdev->bus->number | ||
136 | && probed_pdev->devfn == pdev->devfn) | ||
137 | break; | ||
138 | } | ||
139 | if (ahd != NULL) { | ||
140 | /* Skip duplicate. */ | ||
141 | return (-ENODEV); | ||
142 | } | ||
143 | |||
144 | pci = pdev; | 132 | pci = pdev; |
145 | entry = ahd_find_pci_device(pci); | 133 | entry = ahd_find_pci_device(pci); |
146 | if (entry == NULL) | 134 | if (entry == NULL) |
@@ -177,15 +165,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
177 | if (memsize >= 0x8000000000ULL | 165 | if (memsize >= 0x8000000000ULL |
178 | && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { | 166 | && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { |
179 | ahd->flags |= AHD_64BIT_ADDRESSING; | 167 | ahd->flags |= AHD_64BIT_ADDRESSING; |
180 | ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK; | ||
181 | } else if (memsize > 0x80000000 | 168 | } else if (memsize > 0x80000000 |
182 | && pci_set_dma_mask(pdev, mask_39bit) == 0) { | 169 | && pci_set_dma_mask(pdev, mask_39bit) == 0) { |
183 | ahd->flags |= AHD_39BIT_ADDRESSING; | 170 | ahd->flags |= AHD_39BIT_ADDRESSING; |
184 | ahd->platform_data->hw_dma_mask = mask_39bit; | ||
185 | } | 171 | } |
186 | } else { | 172 | } else { |
187 | pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 173 | pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
188 | ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK; | ||
189 | } | 174 | } |
190 | ahd->dev_softc = pci; | 175 | ahd->dev_softc = pci; |
191 | error = ahd_pci_config(ahd, entry); | 176 | error = ahd_pci_config(ahd, entry); |
@@ -193,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
193 | ahd_free(ahd); | 178 | ahd_free(ahd); |
194 | return (-error); | 179 | return (-error); |
195 | } | 180 | } |
181 | |||
182 | /* | ||
183 | * Second Function PCI devices need to inherit some | ||
184 | * * settings from function 0. | ||
185 | */ | ||
186 | if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0) | ||
187 | ahd_linux_pci_inherit_flags(ahd); | ||
188 | |||
196 | pci_set_drvdata(pdev, ahd); | 189 | pci_set_drvdata(pdev, ahd); |
197 | if (aic79xx_detect_complete) { | 190 | |
198 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 191 | ahd_linux_register_host(ahd, &aic79xx_driver_template); |
199 | ahd_linux_register_host(ahd, &aic79xx_driver_template); | ||
200 | #else | ||
201 | printf("aic79xx: ignoring PCI device found after " | ||
202 | "initialization\n"); | ||
203 | return (-ENODEV); | ||
204 | #endif | ||
205 | } | ||
206 | return (0); | 192 | return (0); |
207 | } | 193 | } |
208 | 194 | ||
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 703f6e44889d..2131db60018a 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c | |||
@@ -283,7 +283,6 @@ int | |||
283 | ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) | 283 | ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) |
284 | { | 284 | { |
285 | struct scb_data *shared_scb_data; | 285 | struct scb_data *shared_scb_data; |
286 | u_long l; | ||
287 | u_int command; | 286 | u_int command; |
288 | uint32_t devconfig; | 287 | uint32_t devconfig; |
289 | uint16_t subvendor; | 288 | uint16_t subvendor; |
@@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) | |||
373 | * Allow interrupts now that we are completely setup. | 372 | * Allow interrupts now that we are completely setup. |
374 | */ | 373 | */ |
375 | error = ahd_pci_map_int(ahd); | 374 | error = ahd_pci_map_int(ahd); |
376 | if (error != 0) | 375 | if (!error) |
377 | return (error); | 376 | ahd->init_level++; |
378 | 377 | return error; | |
379 | ahd_list_lock(&l); | ||
380 | /* | ||
381 | * Link this softc in with all other ahd instances. | ||
382 | */ | ||
383 | ahd_softc_insert(ahd); | ||
384 | ahd_list_unlock(&l); | ||
385 | return (0); | ||
386 | } | 378 | } |
387 | 379 | ||
388 | /* | 380 | /* |
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index e01cd6175e34..32be1f55998c 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c | |||
@@ -49,7 +49,7 @@ static void ahd_dump_target_state(struct ahd_softc *ahd, | |||
49 | u_int our_id, char channel, | 49 | u_int our_id, char channel, |
50 | u_int target_id, u_int target_offset); | 50 | u_int target_id, u_int target_offset); |
51 | static void ahd_dump_device_state(struct info_str *info, | 51 | static void ahd_dump_device_state(struct info_str *info, |
52 | struct ahd_linux_device *dev); | 52 | struct scsi_device *sdev); |
53 | static int ahd_proc_write_seeprom(struct ahd_softc *ahd, | 53 | static int ahd_proc_write_seeprom(struct ahd_softc *ahd, |
54 | char *buffer, int length); | 54 | char *buffer, int length); |
55 | 55 | ||
@@ -167,6 +167,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
167 | u_int target_offset) | 167 | u_int target_offset) |
168 | { | 168 | { |
169 | struct ahd_linux_target *targ; | 169 | struct ahd_linux_target *targ; |
170 | struct scsi_target *starget; | ||
170 | struct ahd_initiator_tinfo *tinfo; | 171 | struct ahd_initiator_tinfo *tinfo; |
171 | struct ahd_tmode_tstate *tstate; | 172 | struct ahd_tmode_tstate *tstate; |
172 | int lun; | 173 | int lun; |
@@ -176,20 +177,20 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
176 | copy_info(info, "Target %d Negotiation Settings\n", target_id); | 177 | copy_info(info, "Target %d Negotiation Settings\n", target_id); |
177 | copy_info(info, "\tUser: "); | 178 | copy_info(info, "\tUser: "); |
178 | ahd_format_transinfo(info, &tinfo->user); | 179 | ahd_format_transinfo(info, &tinfo->user); |
179 | targ = ahd->platform_data->targets[target_offset]; | 180 | starget = ahd->platform_data->starget[target_offset]; |
180 | if (targ == NULL) | 181 | if (starget == NULL) |
181 | return; | 182 | return; |
183 | targ = scsi_transport_target_data(starget); | ||
182 | 184 | ||
183 | copy_info(info, "\tGoal: "); | 185 | copy_info(info, "\tGoal: "); |
184 | ahd_format_transinfo(info, &tinfo->goal); | 186 | ahd_format_transinfo(info, &tinfo->goal); |
185 | copy_info(info, "\tCurr: "); | 187 | copy_info(info, "\tCurr: "); |
186 | ahd_format_transinfo(info, &tinfo->curr); | 188 | ahd_format_transinfo(info, &tinfo->curr); |
187 | copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected); | ||
188 | 189 | ||
189 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { | 190 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { |
190 | struct ahd_linux_device *dev; | 191 | struct scsi_device *dev; |
191 | 192 | ||
192 | dev = targ->devices[lun]; | 193 | dev = targ->sdev[lun]; |
193 | 194 | ||
194 | if (dev == NULL) | 195 | if (dev == NULL) |
195 | continue; | 196 | continue; |
@@ -199,10 +200,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
199 | } | 200 | } |
200 | 201 | ||
201 | static void | 202 | static void |
202 | ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) | 203 | ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev) |
203 | { | 204 | { |
205 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); | ||
206 | |||
204 | copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", | 207 | copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", |
205 | dev->target->channel + 'A', dev->target->target, dev->lun); | 208 | sdev->sdev_target->channel + 'A', |
209 | sdev->sdev_target->id, sdev->lun); | ||
206 | 210 | ||
207 | copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); | 211 | copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); |
208 | copy_info(info, "\t\tCommands Active %d\n", dev->active); | 212 | copy_info(info, "\t\tCommands Active %d\n", dev->active); |
@@ -278,36 +282,16 @@ done: | |||
278 | * Return information to handle /proc support for the driver. | 282 | * Return information to handle /proc support for the driver. |
279 | */ | 283 | */ |
280 | int | 284 | int |
281 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
282 | ahd_linux_proc_info(char *buffer, char **start, off_t offset, | ||
283 | int length, int hostno, int inout) | ||
284 | #else | ||
285 | ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | 285 | ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, |
286 | off_t offset, int length, int inout) | 286 | off_t offset, int length, int inout) |
287 | #endif | ||
288 | { | 287 | { |
289 | struct ahd_softc *ahd; | 288 | struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; |
290 | struct info_str info; | 289 | struct info_str info; |
291 | char ahd_info[256]; | 290 | char ahd_info[256]; |
292 | u_long l; | ||
293 | u_int max_targ; | 291 | u_int max_targ; |
294 | u_int i; | 292 | u_int i; |
295 | int retval; | 293 | int retval; |
296 | 294 | ||
297 | retval = -EINVAL; | ||
298 | ahd_list_lock(&l); | ||
299 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
300 | TAILQ_FOREACH(ahd, &ahd_tailq, links) { | ||
301 | if (ahd->platform_data->host->host_no == hostno) | ||
302 | break; | ||
303 | } | ||
304 | #else | ||
305 | ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata); | ||
306 | #endif | ||
307 | |||
308 | if (ahd == NULL) | ||
309 | goto done; | ||
310 | |||
311 | /* Has data been written to the file? */ | 295 | /* Has data been written to the file? */ |
312 | if (inout == TRUE) { | 296 | if (inout == TRUE) { |
313 | retval = ahd_proc_write_seeprom(ahd, buffer, length); | 297 | retval = ahd_proc_write_seeprom(ahd, buffer, length); |
@@ -357,6 +341,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | |||
357 | } | 341 | } |
358 | retval = info.pos > info.offset ? info.pos - info.offset : 0; | 342 | retval = info.pos > info.offset ? info.pos - info.offset : 0; |
359 | done: | 343 | done: |
360 | ahd_list_unlock(&l); | ||
361 | return (retval); | 344 | return (retval); |
362 | } | 345 | } |
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 088cbc23743d..91d294c6334e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h | |||
@@ -37,7 +37,7 @@ | |||
37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
38 | * POSSIBILITY OF SUCH DAMAGES. | 38 | * POSSIBILITY OF SUCH DAMAGES. |
39 | * | 39 | * |
40 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $ | 40 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $ |
41 | * | 41 | * |
42 | * $FreeBSD$ | 42 | * $FreeBSD$ |
43 | */ | 43 | */ |
@@ -243,7 +243,7 @@ typedef enum { | |||
243 | */ | 243 | */ |
244 | AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, | 244 | AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, |
245 | AHC_AIC7860_FE = AHC_AIC7850_FE, | 245 | AHC_AIC7860_FE = AHC_AIC7850_FE, |
246 | AHC_AIC7870_FE = AHC_TARGETMODE, | 246 | AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE, |
247 | AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, | 247 | AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, |
248 | /* | 248 | /* |
249 | * Although we have space for both the initiator and | 249 | * Although we have space for both the initiator and |
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg index 810ec700d9fc..e196d83b93c7 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.reg +++ b/drivers/scsi/aic7xxx/aic7xxx.reg | |||
@@ -39,7 +39,7 @@ | |||
39 | * | 39 | * |
40 | * $FreeBSD$ | 40 | * $FreeBSD$ |
41 | */ | 41 | */ |
42 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $" | 42 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $" |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * This file is processed by the aic7xxx_asm utility for use in assembling | 45 | * This file is processed by the aic7xxx_asm utility for use in assembling |
@@ -1306,7 +1306,6 @@ scratch_ram { | |||
1306 | */ | 1306 | */ |
1307 | MWI_RESIDUAL { | 1307 | MWI_RESIDUAL { |
1308 | size 1 | 1308 | size 1 |
1309 | alias TARG_IMMEDIATE_SCB | ||
1310 | } | 1309 | } |
1311 | /* | 1310 | /* |
1312 | * SCBID of the next SCB to be started by the controller. | 1311 | * SCBID of the next SCB to be started by the controller. |
@@ -1461,6 +1460,7 @@ scratch_ram { | |||
1461 | */ | 1460 | */ |
1462 | LAST_MSG { | 1461 | LAST_MSG { |
1463 | size 1 | 1462 | size 1 |
1463 | alias TARG_IMMEDIATE_SCB | ||
1464 | } | 1464 | } |
1465 | 1465 | ||
1466 | /* | 1466 | /* |
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq index d84b741fbab5..15196390e28d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.seq +++ b/drivers/scsi/aic7xxx/aic7xxx.seq | |||
@@ -40,7 +40,7 @@ | |||
40 | * $FreeBSD$ | 40 | * $FreeBSD$ |
41 | */ | 41 | */ |
42 | 42 | ||
43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $" | 43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $" |
44 | PATCH_ARG_LIST = "struct ahc_softc *ahc" | 44 | PATCH_ARG_LIST = "struct ahc_softc *ahc" |
45 | PREFIX = "ahc_" | 45 | PREFIX = "ahc_" |
46 | 46 | ||
@@ -679,6 +679,7 @@ await_busfree: | |||
679 | clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ | 679 | clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ |
680 | } | 680 | } |
681 | and SXFRCTL0, ~SPIOEN; | 681 | and SXFRCTL0, ~SPIOEN; |
682 | mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; | ||
682 | test SSTAT1,REQINIT|BUSFREE jz .; | 683 | test SSTAT1,REQINIT|BUSFREE jz .; |
683 | test SSTAT1, BUSFREE jnz poll_for_work; | 684 | test SSTAT1, BUSFREE jnz poll_for_work; |
684 | mvi MISSED_BUSFREE call set_seqint; | 685 | mvi MISSED_BUSFREE call set_seqint; |
@@ -1097,7 +1098,7 @@ ultra2_dmahalt: | |||
1097 | test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; | 1098 | test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; |
1098 | if ((ahc->flags & AHC_TARGETROLE) != 0) { | 1099 | if ((ahc->flags & AHC_TARGETROLE) != 0) { |
1099 | test SSTAT0, TARGET jz dma_last_sg; | 1100 | test SSTAT0, TARGET jz dma_last_sg; |
1100 | if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) { | 1101 | if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) { |
1101 | test DMAPARAMS, DIRECTION jz dma_mid_sg; | 1102 | test DMAPARAMS, DIRECTION jz dma_mid_sg; |
1102 | } | 1103 | } |
1103 | } | 1104 | } |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c index 468d612a44f6..3cb07e114e89 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c +++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c | |||
@@ -28,9 +28,7 @@ | |||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | 29 | * SUCH DAMAGE. |
30 | * | 30 | * |
31 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $ | 31 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $ |
32 | * | ||
33 | * $FreeBSD$ | ||
34 | */ | 32 | */ |
35 | 33 | ||
36 | /* | 34 | /* |
@@ -64,7 +62,6 @@ | |||
64 | * is preceded by an initial zero (leading 0, followed by 16-bits, MSB | 62 | * is preceded by an initial zero (leading 0, followed by 16-bits, MSB |
65 | * first). The clock cycling from low to high initiates the next data | 63 | * first). The clock cycling from low to high initiates the next data |
66 | * bit to be sent from the chip. | 64 | * bit to be sent from the chip. |
67 | * | ||
68 | */ | 65 | */ |
69 | 66 | ||
70 | #ifdef __linux__ | 67 | #ifdef __linux__ |
@@ -81,14 +78,22 @@ | |||
81 | * Right now, we only have to read the SEEPROM. But we make it easier to | 78 | * Right now, we only have to read the SEEPROM. But we make it easier to |
82 | * add other 93Cx6 functions. | 79 | * add other 93Cx6 functions. |
83 | */ | 80 | */ |
84 | static struct seeprom_cmd { | 81 | struct seeprom_cmd { |
85 | uint8_t len; | 82 | uint8_t len; |
86 | uint8_t bits[9]; | 83 | uint8_t bits[11]; |
87 | } seeprom_read = {3, {1, 1, 0}}; | 84 | }; |
88 | 85 | ||
86 | /* Short opcodes for the c46 */ | ||
89 | static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; | 87 | static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; |
90 | static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; | 88 | static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; |
89 | |||
90 | /* Long opcodes for the C56/C66 */ | ||
91 | static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; | ||
92 | static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; | ||
93 | |||
94 | /* Common opcodes */ | ||
91 | static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; | 95 | static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; |
96 | static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}}; | ||
92 | 97 | ||
93 | /* | 98 | /* |
94 | * Wait for the SEERDY to go high; about 800 ns. | 99 | * Wait for the SEERDY to go high; about 800 ns. |
@@ -222,12 +227,25 @@ int | |||
222 | ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, | 227 | ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, |
223 | u_int start_addr, u_int count) | 228 | u_int start_addr, u_int count) |
224 | { | 229 | { |
230 | struct seeprom_cmd *ewen, *ewds; | ||
225 | uint16_t v; | 231 | uint16_t v; |
226 | uint8_t temp; | 232 | uint8_t temp; |
227 | int i, k; | 233 | int i, k; |
228 | 234 | ||
229 | /* Place the chip into write-enable mode */ | 235 | /* Place the chip into write-enable mode */ |
230 | send_seeprom_cmd(sd, &seeprom_ewen); | 236 | if (sd->sd_chip == C46) { |
237 | ewen = &seeprom_ewen; | ||
238 | ewds = &seeprom_ewds; | ||
239 | } else if (sd->sd_chip == C56_66) { | ||
240 | ewen = &seeprom_long_ewen; | ||
241 | ewds = &seeprom_long_ewds; | ||
242 | } else { | ||
243 | printf("ahc_write_seeprom: unsupported seeprom type %d\n", | ||
244 | sd->sd_chip); | ||
245 | return (0); | ||
246 | } | ||
247 | |||
248 | send_seeprom_cmd(sd, ewen); | ||
231 | reset_seeprom(sd); | 249 | reset_seeprom(sd); |
232 | 250 | ||
233 | /* Write all requested data out to the seeprom. */ | 251 | /* Write all requested data out to the seeprom. */ |
@@ -277,7 +295,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, | |||
277 | } | 295 | } |
278 | 296 | ||
279 | /* Put the chip back into write-protect mode */ | 297 | /* Put the chip back into write-protect mode */ |
280 | send_seeprom_cmd(sd, &seeprom_ewds); | 298 | send_seeprom_cmd(sd, ewds); |
281 | reset_seeprom(sd); | 299 | reset_seeprom(sd); |
282 | 300 | ||
283 | return (1); | 301 | return (1); |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 7bc01e41bcce..58ac46103eb6 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c | |||
@@ -37,9 +37,7 @@ | |||
37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
38 | * POSSIBILITY OF SUCH DAMAGES. | 38 | * POSSIBILITY OF SUCH DAMAGES. |
39 | * | 39 | * |
40 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $ | 40 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $ |
41 | * | ||
42 | * $FreeBSD$ | ||
43 | */ | 41 | */ |
44 | 42 | ||
45 | #ifdef __linux__ | 43 | #ifdef __linux__ |
@@ -287,10 +285,19 @@ ahc_restart(struct ahc_softc *ahc) | |||
287 | ahc_outb(ahc, SEQ_FLAGS2, | 285 | ahc_outb(ahc, SEQ_FLAGS2, |
288 | ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA); | 286 | ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA); |
289 | } | 287 | } |
288 | |||
289 | /* | ||
290 | * Clear any pending sequencer interrupt. It is no | ||
291 | * longer relevant since we're resetting the Program | ||
292 | * Counter. | ||
293 | */ | ||
294 | ahc_outb(ahc, CLRINT, CLRSEQINT); | ||
295 | |||
290 | ahc_outb(ahc, MWI_RESIDUAL, 0); | 296 | ahc_outb(ahc, MWI_RESIDUAL, 0); |
291 | ahc_outb(ahc, SEQCTL, ahc->seqctl); | 297 | ahc_outb(ahc, SEQCTL, ahc->seqctl); |
292 | ahc_outb(ahc, SEQADDR0, 0); | 298 | ahc_outb(ahc, SEQADDR0, 0); |
293 | ahc_outb(ahc, SEQADDR1, 0); | 299 | ahc_outb(ahc, SEQADDR1, 0); |
300 | |||
294 | ahc_unpause(ahc); | 301 | ahc_unpause(ahc); |
295 | } | 302 | } |
296 | 303 | ||
@@ -1174,19 +1181,20 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) | |||
1174 | scb_index); | 1181 | scb_index); |
1175 | } | 1182 | } |
1176 | #endif | 1183 | #endif |
1177 | /* | ||
1178 | * Force a renegotiation with this target just in | ||
1179 | * case the cable was pulled and will later be | ||
1180 | * re-attached. The target may forget its negotiation | ||
1181 | * settings with us should it attempt to reselect | ||
1182 | * during the interruption. The target will not issue | ||
1183 | * a unit attention in this case, so we must always | ||
1184 | * renegotiate. | ||
1185 | */ | ||
1186 | ahc_scb_devinfo(ahc, &devinfo, scb); | 1184 | ahc_scb_devinfo(ahc, &devinfo, scb); |
1187 | ahc_force_renegotiation(ahc, &devinfo); | ||
1188 | ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); | 1185 | ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); |
1189 | ahc_freeze_devq(ahc, scb); | 1186 | ahc_freeze_devq(ahc, scb); |
1187 | |||
1188 | /* | ||
1189 | * Cancel any pending transactions on the device | ||
1190 | * now that it seems to be missing. This will | ||
1191 | * also revert us to async/narrow transfers until | ||
1192 | * we can renegotiate with the device. | ||
1193 | */ | ||
1194 | ahc_handle_devreset(ahc, &devinfo, | ||
1195 | CAM_SEL_TIMEOUT, | ||
1196 | "Selection Timeout", | ||
1197 | /*verbose_level*/1); | ||
1190 | } | 1198 | } |
1191 | ahc_outb(ahc, CLRINT, CLRSCSIINT); | 1199 | ahc_outb(ahc, CLRINT, CLRSCSIINT); |
1192 | ahc_restart(ahc); | 1200 | ahc_restart(ahc); |
@@ -3763,8 +3771,9 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, | |||
3763 | /*period*/0, /*offset*/0, /*ppr_options*/0, | 3771 | /*period*/0, /*offset*/0, /*ppr_options*/0, |
3764 | AHC_TRANS_CUR, /*paused*/TRUE); | 3772 | AHC_TRANS_CUR, /*paused*/TRUE); |
3765 | 3773 | ||
3766 | ahc_send_async(ahc, devinfo->channel, devinfo->target, | 3774 | if (status != CAM_SEL_TIMEOUT) |
3767 | CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); | 3775 | ahc_send_async(ahc, devinfo->channel, devinfo->target, |
3776 | CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); | ||
3768 | 3777 | ||
3769 | if (message != NULL | 3778 | if (message != NULL |
3770 | && (verbose_level <= bootverbose)) | 3779 | && (verbose_level <= bootverbose)) |
@@ -4003,14 +4012,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit) | |||
4003 | * to disturb the integrity of the bus. | 4012 | * to disturb the integrity of the bus. |
4004 | */ | 4013 | */ |
4005 | ahc_pause(ahc); | 4014 | ahc_pause(ahc); |
4006 | if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) { | ||
4007 | /* | ||
4008 | * The chip has not been initialized since | ||
4009 | * PCI/EISA/VLB bus reset. Don't trust | ||
4010 | * "left over BIOS data". | ||
4011 | */ | ||
4012 | ahc->flags |= AHC_NO_BIOS_INIT; | ||
4013 | } | ||
4014 | sxfrctl1_b = 0; | 4015 | sxfrctl1_b = 0; |
4015 | if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { | 4016 | if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { |
4016 | u_int sblkctl; | 4017 | u_int sblkctl; |
@@ -5036,14 +5037,23 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) | |||
5036 | ahc->flags |= AHC_ALL_INTERRUPTS; | 5037 | ahc->flags |= AHC_ALL_INTERRUPTS; |
5037 | paused = FALSE; | 5038 | paused = FALSE; |
5038 | do { | 5039 | do { |
5039 | if (paused) | 5040 | if (paused) { |
5040 | ahc_unpause(ahc); | 5041 | ahc_unpause(ahc); |
5042 | /* | ||
5043 | * Give the sequencer some time to service | ||
5044 | * any active selections. | ||
5045 | */ | ||
5046 | ahc_delay(500); | ||
5047 | } | ||
5041 | ahc_intr(ahc); | 5048 | ahc_intr(ahc); |
5042 | ahc_pause(ahc); | 5049 | ahc_pause(ahc); |
5043 | paused = TRUE; | 5050 | paused = TRUE; |
5044 | ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO); | 5051 | ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO); |
5045 | ahc_clear_critical_section(ahc); | ||
5046 | intstat = ahc_inb(ahc, INTSTAT); | 5052 | intstat = ahc_inb(ahc, INTSTAT); |
5053 | if ((intstat & INT_PEND) == 0) { | ||
5054 | ahc_clear_critical_section(ahc); | ||
5055 | intstat = ahc_inb(ahc, INTSTAT); | ||
5056 | } | ||
5047 | } while (--maxloops | 5057 | } while (--maxloops |
5048 | && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) | 5058 | && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) |
5049 | && ((intstat & INT_PEND) != 0 | 5059 | && ((intstat & INT_PEND) != 0 |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 687f19e9cf03..54173887e160 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -635,6 +635,8 @@ ahc_linux_slave_alloc(struct scsi_device *sdev) | |||
635 | 635 | ||
636 | targ->sdev[sdev->lun] = sdev; | 636 | targ->sdev[sdev->lun] = sdev; |
637 | 637 | ||
638 | spi_period(starget) = 0; | ||
639 | |||
638 | return 0; | 640 | return 0; |
639 | } | 641 | } |
640 | 642 | ||
@@ -1612,9 +1614,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel, | |||
1612 | if (channel == 'B') | 1614 | if (channel == 'B') |
1613 | target_offset += 8; | 1615 | target_offset += 8; |
1614 | starget = ahc->platform_data->starget[target_offset]; | 1616 | starget = ahc->platform_data->starget[target_offset]; |
1615 | targ = scsi_transport_target_data(starget); | 1617 | if (starget == NULL) |
1616 | if (targ == NULL) | ||
1617 | break; | 1618 | break; |
1619 | targ = scsi_transport_target_data(starget); | ||
1618 | 1620 | ||
1619 | target_ppr_options = | 1621 | target_ppr_options = |
1620 | (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) | 1622 | (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) |
@@ -2329,8 +2331,6 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) | |||
2329 | { | 2331 | { |
2330 | } | 2332 | } |
2331 | 2333 | ||
2332 | static void ahc_linux_exit(void); | ||
2333 | |||
2334 | static void ahc_linux_set_width(struct scsi_target *starget, int width) | 2334 | static void ahc_linux_set_width(struct scsi_target *starget, int width) |
2335 | { | 2335 | { |
2336 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 2336 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 0e47ac217549..c52996269240 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h | |||
@@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec) | |||
265 | /***************************** SMP support ************************************/ | 265 | /***************************** SMP support ************************************/ |
266 | #include <linux/spinlock.h> | 266 | #include <linux/spinlock.h> |
267 | 267 | ||
268 | #define AIC7XXX_DRIVER_VERSION "6.2.36" | 268 | #define AIC7XXX_DRIVER_VERSION "7.0" |
269 | 269 | ||
270 | /*************************** Device Data Structures ***************************/ | 270 | /*************************** Device Data Structures ***************************/ |
271 | /* | 271 | /* |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 9d318ce2c993..0d44a6907dd2 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | |||
@@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev) | |||
149 | ahc_free(ahc); | 149 | ahc_free(ahc); |
150 | } | 150 | } |
151 | 151 | ||
152 | static void | ||
153 | ahc_linux_pci_inherit_flags(struct ahc_softc *ahc) | ||
154 | { | ||
155 | struct pci_dev *pdev = ahc->dev_softc, *master_pdev; | ||
156 | unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); | ||
157 | |||
158 | master_pdev = pci_get_slot(pdev->bus, master_devfn); | ||
159 | if (master_pdev) { | ||
160 | struct ahc_softc *master = pci_get_drvdata(master_pdev); | ||
161 | if (master) { | ||
162 | ahc->flags &= ~AHC_BIOS_ENABLED; | ||
163 | ahc->flags |= master->flags & AHC_BIOS_ENABLED; | ||
164 | |||
165 | ahc->flags &= ~AHC_PRIMARY_CHANNEL; | ||
166 | ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL; | ||
167 | } else | ||
168 | printk(KERN_ERR "aic7xxx: no multichannel peer found!\n"); | ||
169 | pci_dev_put(master_pdev); | ||
170 | } | ||
171 | } | ||
172 | |||
152 | static int | 173 | static int |
153 | ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 174 | ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
154 | { | 175 | { |
@@ -203,6 +224,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
203 | ahc_free(ahc); | 224 | ahc_free(ahc); |
204 | return (-error); | 225 | return (-error); |
205 | } | 226 | } |
227 | |||
228 | /* | ||
229 | * Second Function PCI devices need to inherit some | ||
230 | * settings from function 0. | ||
231 | */ | ||
232 | if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0) | ||
233 | ahc_linux_pci_inherit_flags(ahc); | ||
234 | |||
206 | pci_set_drvdata(pdev, ahc); | 235 | pci_set_drvdata(pdev, ahc); |
207 | ahc_linux_register_host(ahc, &aic7xxx_driver_template); | 236 | ahc_linux_register_host(ahc, &aic7xxx_driver_template); |
208 | return (0); | 237 | return (0); |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped index 7c1390ed1179..2ce1febca207 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped +++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped | |||
@@ -2,8 +2,8 @@ | |||
2 | * DO NOT EDIT - This file is automatically generated | 2 | * DO NOT EDIT - This file is automatically generated |
3 | * from the following source files: | 3 | * from the following source files: |
4 | * | 4 | * |
5 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ | 5 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ |
6 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ | 6 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ |
7 | */ | 7 | */ |
8 | typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); | 8 | typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); |
9 | typedef struct ahc_reg_parse_entry { | 9 | typedef struct ahc_reg_parse_entry { |
@@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print; | |||
1298 | #define CMDSIZE_TABLE_TAIL 0x34 | 1298 | #define CMDSIZE_TABLE_TAIL 0x34 |
1299 | 1299 | ||
1300 | #define MWI_RESIDUAL 0x38 | 1300 | #define MWI_RESIDUAL 0x38 |
1301 | #define TARG_IMMEDIATE_SCB 0x38 | ||
1302 | 1301 | ||
1303 | #define NEXT_QUEUED_SCB 0x39 | 1302 | #define NEXT_QUEUED_SCB 0x39 |
1304 | 1303 | ||
@@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print; | |||
1380 | #define RETURN_2 0x52 | 1379 | #define RETURN_2 0x52 |
1381 | 1380 | ||
1382 | #define LAST_MSG 0x53 | 1381 | #define LAST_MSG 0x53 |
1382 | #define TARG_IMMEDIATE_SCB 0x53 | ||
1383 | 1383 | ||
1384 | #define SCSISEQ_TEMPLATE 0x54 | 1384 | #define SCSISEQ_TEMPLATE 0x54 |
1385 | #define ENSELO 0x40 | 1385 | #define ENSELO 0x40 |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped index 9c713775d44a..88bfd767c51c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped +++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped | |||
@@ -2,8 +2,8 @@ | |||
2 | * DO NOT EDIT - This file is automatically generated | 2 | * DO NOT EDIT - This file is automatically generated |
3 | * from the following source files: | 3 | * from the following source files: |
4 | * | 4 | * |
5 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ | 5 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ |
6 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ | 6 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "aic7xxx_osm.h" | 9 | #include "aic7xxx_osm.h" |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped index cf411368a871..4cee08521e75 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped | |||
@@ -2,13 +2,13 @@ | |||
2 | * DO NOT EDIT - This file is automatically generated | 2 | * DO NOT EDIT - This file is automatically generated |
3 | * from the following source files: | 3 | * from the following source files: |
4 | * | 4 | * |
5 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ | 5 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ |
6 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ | 6 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ |
7 | */ | 7 | */ |
8 | static uint8_t seqprog[] = { | 8 | static uint8_t seqprog[] = { |
9 | 0xb2, 0x00, 0x00, 0x08, | 9 | 0xb2, 0x00, 0x00, 0x08, |
10 | 0xf7, 0x11, 0x22, 0x08, | 10 | 0xf7, 0x11, 0x22, 0x08, |
11 | 0x00, 0x65, 0xec, 0x59, | 11 | 0x00, 0x65, 0xee, 0x59, |
12 | 0xf7, 0x01, 0x02, 0x08, | 12 | 0xf7, 0x01, 0x02, 0x08, |
13 | 0xff, 0x6a, 0x24, 0x08, | 13 | 0xff, 0x6a, 0x24, 0x08, |
14 | 0x40, 0x00, 0x40, 0x68, | 14 | 0x40, 0x00, 0x40, 0x68, |
@@ -21,15 +21,15 @@ static uint8_t seqprog[] = { | |||
21 | 0x01, 0x4d, 0xc8, 0x30, | 21 | 0x01, 0x4d, 0xc8, 0x30, |
22 | 0x00, 0x4c, 0x12, 0x70, | 22 | 0x00, 0x4c, 0x12, 0x70, |
23 | 0x01, 0x39, 0xa2, 0x30, | 23 | 0x01, 0x39, 0xa2, 0x30, |
24 | 0x00, 0x6a, 0xc0, 0x5e, | 24 | 0x00, 0x6a, 0xc2, 0x5e, |
25 | 0x01, 0x51, 0x20, 0x31, | 25 | 0x01, 0x51, 0x20, 0x31, |
26 | 0x01, 0x57, 0xae, 0x00, | 26 | 0x01, 0x57, 0xae, 0x00, |
27 | 0x0d, 0x6a, 0x76, 0x00, | 27 | 0x0d, 0x6a, 0x76, 0x00, |
28 | 0x00, 0x51, 0x12, 0x5e, | 28 | 0x00, 0x51, 0x14, 0x5e, |
29 | 0x01, 0x51, 0xc8, 0x30, | 29 | 0x01, 0x51, 0xc8, 0x30, |
30 | 0x00, 0x39, 0xc8, 0x60, | 30 | 0x00, 0x39, 0xc8, 0x60, |
31 | 0x00, 0xbb, 0x30, 0x70, | 31 | 0x00, 0xbb, 0x30, 0x70, |
32 | 0xc1, 0x6a, 0xd8, 0x5e, | 32 | 0xc1, 0x6a, 0xda, 0x5e, |
33 | 0x01, 0xbf, 0x72, 0x30, | 33 | 0x01, 0xbf, 0x72, 0x30, |
34 | 0x01, 0x40, 0x7e, 0x31, | 34 | 0x01, 0x40, 0x7e, 0x31, |
35 | 0x01, 0x90, 0x80, 0x30, | 35 | 0x01, 0x90, 0x80, 0x30, |
@@ -49,10 +49,10 @@ static uint8_t seqprog[] = { | |||
49 | 0x08, 0x6a, 0x78, 0x00, | 49 | 0x08, 0x6a, 0x78, 0x00, |
50 | 0x01, 0x50, 0xc8, 0x30, | 50 | 0x01, 0x50, 0xc8, 0x30, |
51 | 0xe0, 0x6a, 0xcc, 0x00, | 51 | 0xe0, 0x6a, 0xcc, 0x00, |
52 | 0x48, 0x6a, 0xfc, 0x5d, | 52 | 0x48, 0x6a, 0xfe, 0x5d, |
53 | 0x01, 0x6a, 0xdc, 0x01, | 53 | 0x01, 0x6a, 0xdc, 0x01, |
54 | 0x88, 0x6a, 0xcc, 0x00, | 54 | 0x88, 0x6a, 0xcc, 0x00, |
55 | 0x48, 0x6a, 0xfc, 0x5d, | 55 | 0x48, 0x6a, 0xfe, 0x5d, |
56 | 0x01, 0x6a, 0x26, 0x01, | 56 | 0x01, 0x6a, 0x26, 0x01, |
57 | 0xf0, 0x19, 0x7a, 0x08, | 57 | 0xf0, 0x19, 0x7a, 0x08, |
58 | 0x0f, 0x18, 0xc8, 0x08, | 58 | 0x0f, 0x18, 0xc8, 0x08, |
@@ -93,7 +93,7 @@ static uint8_t seqprog[] = { | |||
93 | 0x00, 0x65, 0x20, 0x41, | 93 | 0x00, 0x65, 0x20, 0x41, |
94 | 0x02, 0x57, 0xae, 0x00, | 94 | 0x02, 0x57, 0xae, 0x00, |
95 | 0x00, 0x65, 0x9e, 0x40, | 95 | 0x00, 0x65, 0x9e, 0x40, |
96 | 0x61, 0x6a, 0xd8, 0x5e, | 96 | 0x61, 0x6a, 0xda, 0x5e, |
97 | 0x08, 0x51, 0x20, 0x71, | 97 | 0x08, 0x51, 0x20, 0x71, |
98 | 0x02, 0x0b, 0xb2, 0x78, | 98 | 0x02, 0x0b, 0xb2, 0x78, |
99 | 0x00, 0x65, 0xae, 0x40, | 99 | 0x00, 0x65, 0xae, 0x40, |
@@ -106,7 +106,7 @@ static uint8_t seqprog[] = { | |||
106 | 0x80, 0x3d, 0x7a, 0x00, | 106 | 0x80, 0x3d, 0x7a, 0x00, |
107 | 0x20, 0x6a, 0x16, 0x00, | 107 | 0x20, 0x6a, 0x16, 0x00, |
108 | 0x00, 0x65, 0xcc, 0x41, | 108 | 0x00, 0x65, 0xcc, 0x41, |
109 | 0x00, 0x65, 0xb2, 0x5e, | 109 | 0x00, 0x65, 0xb4, 0x5e, |
110 | 0x00, 0x65, 0x12, 0x40, | 110 | 0x00, 0x65, 0x12, 0x40, |
111 | 0x20, 0x11, 0xd2, 0x68, | 111 | 0x20, 0x11, 0xd2, 0x68, |
112 | 0x20, 0x6a, 0x18, 0x00, | 112 | 0x20, 0x6a, 0x18, 0x00, |
@@ -140,27 +140,27 @@ static uint8_t seqprog[] = { | |||
140 | 0x80, 0x0b, 0xc4, 0x79, | 140 | 0x80, 0x0b, 0xc4, 0x79, |
141 | 0x12, 0x01, 0x02, 0x00, | 141 | 0x12, 0x01, 0x02, 0x00, |
142 | 0x01, 0xab, 0xac, 0x30, | 142 | 0x01, 0xab, 0xac, 0x30, |
143 | 0xe4, 0x6a, 0x6e, 0x5d, | 143 | 0xe4, 0x6a, 0x70, 0x5d, |
144 | 0x40, 0x6a, 0x16, 0x00, | 144 | 0x40, 0x6a, 0x16, 0x00, |
145 | 0x80, 0x3e, 0x84, 0x5d, | 145 | 0x80, 0x3e, 0x86, 0x5d, |
146 | 0x20, 0xb8, 0x18, 0x79, | 146 | 0x20, 0xb8, 0x18, 0x79, |
147 | 0x20, 0x6a, 0x84, 0x5d, | 147 | 0x20, 0x6a, 0x86, 0x5d, |
148 | 0x00, 0xab, 0x84, 0x5d, | 148 | 0x00, 0xab, 0x86, 0x5d, |
149 | 0x01, 0xa9, 0x78, 0x30, | 149 | 0x01, 0xa9, 0x78, 0x30, |
150 | 0x10, 0xb8, 0x20, 0x79, | 150 | 0x10, 0xb8, 0x20, 0x79, |
151 | 0xe4, 0x6a, 0x6e, 0x5d, | 151 | 0xe4, 0x6a, 0x70, 0x5d, |
152 | 0x00, 0x65, 0xae, 0x40, | 152 | 0x00, 0x65, 0xae, 0x40, |
153 | 0x10, 0x03, 0x3c, 0x69, | 153 | 0x10, 0x03, 0x3c, 0x69, |
154 | 0x08, 0x3c, 0x5a, 0x69, | 154 | 0x08, 0x3c, 0x5a, 0x69, |
155 | 0x04, 0x3c, 0x92, 0x69, | 155 | 0x04, 0x3c, 0x92, 0x69, |
156 | 0x02, 0x3c, 0x98, 0x69, | 156 | 0x02, 0x3c, 0x98, 0x69, |
157 | 0x01, 0x3c, 0x44, 0x79, | 157 | 0x01, 0x3c, 0x44, 0x79, |
158 | 0xff, 0x6a, 0x70, 0x00, | 158 | 0xff, 0x6a, 0xa6, 0x00, |
159 | 0x00, 0x65, 0xa4, 0x59, | 159 | 0x00, 0x65, 0xa4, 0x59, |
160 | 0x00, 0x6a, 0xc0, 0x5e, | 160 | 0x00, 0x6a, 0xc2, 0x5e, |
161 | 0xff, 0x38, 0x30, 0x71, | 161 | 0xff, 0x53, 0x30, 0x71, |
162 | 0x0d, 0x6a, 0x76, 0x00, | 162 | 0x0d, 0x6a, 0x76, 0x00, |
163 | 0x00, 0x38, 0x12, 0x5e, | 163 | 0x00, 0x53, 0x14, 0x5e, |
164 | 0x00, 0x65, 0xea, 0x58, | 164 | 0x00, 0x65, 0xea, 0x58, |
165 | 0x12, 0x01, 0x02, 0x00, | 165 | 0x12, 0x01, 0x02, 0x00, |
166 | 0x00, 0x65, 0x18, 0x41, | 166 | 0x00, 0x65, 0x18, 0x41, |
@@ -168,10 +168,10 @@ static uint8_t seqprog[] = { | |||
168 | 0x00, 0x65, 0xf2, 0x58, | 168 | 0x00, 0x65, 0xf2, 0x58, |
169 | 0xfd, 0x57, 0xae, 0x08, | 169 | 0xfd, 0x57, 0xae, 0x08, |
170 | 0x00, 0x65, 0xae, 0x40, | 170 | 0x00, 0x65, 0xae, 0x40, |
171 | 0xe4, 0x6a, 0x6e, 0x5d, | 171 | 0xe4, 0x6a, 0x70, 0x5d, |
172 | 0x20, 0x3c, 0x4a, 0x79, | 172 | 0x20, 0x3c, 0x4a, 0x79, |
173 | 0x02, 0x6a, 0x84, 0x5d, | 173 | 0x02, 0x6a, 0x86, 0x5d, |
174 | 0x04, 0x6a, 0x84, 0x5d, | 174 | 0x04, 0x6a, 0x86, 0x5d, |
175 | 0x01, 0x03, 0x4c, 0x69, | 175 | 0x01, 0x03, 0x4c, 0x69, |
176 | 0xf7, 0x11, 0x22, 0x08, | 176 | 0xf7, 0x11, 0x22, 0x08, |
177 | 0xff, 0x6a, 0x24, 0x08, | 177 | 0xff, 0x6a, 0x24, 0x08, |
@@ -182,13 +182,13 @@ static uint8_t seqprog[] = { | |||
182 | 0x80, 0x86, 0xc8, 0x08, | 182 | 0x80, 0x86, 0xc8, 0x08, |
183 | 0x01, 0x4f, 0xc8, 0x30, | 183 | 0x01, 0x4f, 0xc8, 0x30, |
184 | 0x00, 0x50, 0x6c, 0x61, | 184 | 0x00, 0x50, 0x6c, 0x61, |
185 | 0xc4, 0x6a, 0x6e, 0x5d, | 185 | 0xc4, 0x6a, 0x70, 0x5d, |
186 | 0x40, 0x3c, 0x68, 0x79, | 186 | 0x40, 0x3c, 0x68, 0x79, |
187 | 0x28, 0x6a, 0x84, 0x5d, | 187 | 0x28, 0x6a, 0x86, 0x5d, |
188 | 0x00, 0x65, 0x4c, 0x41, | 188 | 0x00, 0x65, 0x4c, 0x41, |
189 | 0x08, 0x6a, 0x84, 0x5d, | 189 | 0x08, 0x6a, 0x86, 0x5d, |
190 | 0x00, 0x65, 0x4c, 0x41, | 190 | 0x00, 0x65, 0x4c, 0x41, |
191 | 0x84, 0x6a, 0x6e, 0x5d, | 191 | 0x84, 0x6a, 0x70, 0x5d, |
192 | 0x00, 0x65, 0xf2, 0x58, | 192 | 0x00, 0x65, 0xf2, 0x58, |
193 | 0x01, 0x66, 0xc8, 0x30, | 193 | 0x01, 0x66, 0xc8, 0x30, |
194 | 0x01, 0x64, 0xd8, 0x31, | 194 | 0x01, 0x64, 0xd8, 0x31, |
@@ -208,16 +208,16 @@ static uint8_t seqprog[] = { | |||
208 | 0xf7, 0x3c, 0x78, 0x08, | 208 | 0xf7, 0x3c, 0x78, 0x08, |
209 | 0x00, 0x65, 0x20, 0x41, | 209 | 0x00, 0x65, 0x20, 0x41, |
210 | 0x40, 0xaa, 0x7e, 0x10, | 210 | 0x40, 0xaa, 0x7e, 0x10, |
211 | 0x04, 0xaa, 0x6e, 0x5d, | 211 | 0x04, 0xaa, 0x70, 0x5d, |
212 | 0x00, 0x65, 0x56, 0x42, | 212 | 0x00, 0x65, 0x58, 0x42, |
213 | 0xc4, 0x6a, 0x6e, 0x5d, | 213 | 0xc4, 0x6a, 0x70, 0x5d, |
214 | 0xc0, 0x6a, 0x7e, 0x00, | 214 | 0xc0, 0x6a, 0x7e, 0x00, |
215 | 0x00, 0xa8, 0x84, 0x5d, | 215 | 0x00, 0xa8, 0x86, 0x5d, |
216 | 0xe4, 0x6a, 0x06, 0x00, | 216 | 0xe4, 0x6a, 0x06, 0x00, |
217 | 0x00, 0x6a, 0x84, 0x5d, | 217 | 0x00, 0x6a, 0x86, 0x5d, |
218 | 0x00, 0x65, 0x4c, 0x41, | 218 | 0x00, 0x65, 0x4c, 0x41, |
219 | 0x10, 0x3c, 0xa8, 0x69, | 219 | 0x10, 0x3c, 0xa8, 0x69, |
220 | 0x00, 0xbb, 0x8a, 0x44, | 220 | 0x00, 0xbb, 0x8c, 0x44, |
221 | 0x18, 0x6a, 0xda, 0x01, | 221 | 0x18, 0x6a, 0xda, 0x01, |
222 | 0x01, 0x69, 0xd8, 0x31, | 222 | 0x01, 0x69, 0xd8, 0x31, |
223 | 0x1c, 0x6a, 0xd0, 0x01, | 223 | 0x1c, 0x6a, 0xd0, 0x01, |
@@ -227,31 +227,32 @@ static uint8_t seqprog[] = { | |||
227 | 0x01, 0x93, 0x26, 0x01, | 227 | 0x01, 0x93, 0x26, 0x01, |
228 | 0x03, 0x6a, 0x2a, 0x01, | 228 | 0x03, 0x6a, 0x2a, 0x01, |
229 | 0x01, 0x69, 0x32, 0x31, | 229 | 0x01, 0x69, 0x32, 0x31, |
230 | 0x1c, 0x6a, 0xe0, 0x5d, | 230 | 0x1c, 0x6a, 0xe2, 0x5d, |
231 | 0x0a, 0x93, 0x26, 0x01, | 231 | 0x0a, 0x93, 0x26, 0x01, |
232 | 0x00, 0x65, 0xa8, 0x5e, | 232 | 0x00, 0x65, 0xaa, 0x5e, |
233 | 0x01, 0x50, 0xa0, 0x18, | 233 | 0x01, 0x50, 0xa0, 0x18, |
234 | 0x02, 0x6a, 0x22, 0x05, | 234 | 0x02, 0x6a, 0x22, 0x05, |
235 | 0x1a, 0x01, 0x02, 0x00, | 235 | 0x1a, 0x01, 0x02, 0x00, |
236 | 0x80, 0x6a, 0x74, 0x00, | 236 | 0x80, 0x6a, 0x74, 0x00, |
237 | 0x40, 0x6a, 0x78, 0x00, | 237 | 0x40, 0x6a, 0x78, 0x00, |
238 | 0x40, 0x6a, 0x16, 0x00, | 238 | 0x40, 0x6a, 0x16, 0x00, |
239 | 0x00, 0x65, 0xd8, 0x5d, | 239 | 0x00, 0x65, 0xda, 0x5d, |
240 | 0x01, 0x3f, 0xc8, 0x30, | 240 | 0x01, 0x3f, 0xc8, 0x30, |
241 | 0xbf, 0x64, 0x56, 0x7a, | 241 | 0xbf, 0x64, 0x58, 0x7a, |
242 | 0x80, 0x64, 0x9e, 0x73, | 242 | 0x80, 0x64, 0xa0, 0x73, |
243 | 0xa0, 0x64, 0x00, 0x74, | 243 | 0xa0, 0x64, 0x02, 0x74, |
244 | 0xc0, 0x64, 0xf4, 0x73, | 244 | 0xc0, 0x64, 0xf6, 0x73, |
245 | 0xe0, 0x64, 0x30, 0x74, | 245 | 0xe0, 0x64, 0x32, 0x74, |
246 | 0x01, 0x6a, 0xd8, 0x5e, | 246 | 0x01, 0x6a, 0xda, 0x5e, |
247 | 0x00, 0x65, 0xcc, 0x41, | 247 | 0x00, 0x65, 0xcc, 0x41, |
248 | 0xf7, 0x11, 0x22, 0x08, | 248 | 0xf7, 0x11, 0x22, 0x08, |
249 | 0x01, 0x06, 0xd4, 0x30, | 249 | 0x01, 0x06, 0xd4, 0x30, |
250 | 0xff, 0x6a, 0x24, 0x08, | 250 | 0xff, 0x6a, 0x24, 0x08, |
251 | 0xf7, 0x01, 0x02, 0x08, | 251 | 0xf7, 0x01, 0x02, 0x08, |
252 | 0x09, 0x0c, 0xe6, 0x79, | 252 | 0xc0, 0x6a, 0x78, 0x00, |
253 | 0x09, 0x0c, 0xe8, 0x79, | ||
253 | 0x08, 0x0c, 0x04, 0x68, | 254 | 0x08, 0x0c, 0x04, 0x68, |
254 | 0xb1, 0x6a, 0xd8, 0x5e, | 255 | 0xb1, 0x6a, 0xda, 0x5e, |
255 | 0xff, 0x6a, 0x26, 0x09, | 256 | 0xff, 0x6a, 0x26, 0x09, |
256 | 0x12, 0x01, 0x02, 0x00, | 257 | 0x12, 0x01, 0x02, 0x00, |
257 | 0x02, 0x6a, 0x08, 0x30, | 258 | 0x02, 0x6a, 0x08, 0x30, |
@@ -264,29 +265,29 @@ static uint8_t seqprog[] = { | |||
264 | 0x00, 0xa5, 0x4a, 0x21, | 265 | 0x00, 0xa5, 0x4a, 0x21, |
265 | 0x00, 0xa6, 0x4c, 0x21, | 266 | 0x00, 0xa6, 0x4c, 0x21, |
266 | 0x00, 0xa7, 0x4e, 0x25, | 267 | 0x00, 0xa7, 0x4e, 0x25, |
267 | 0x08, 0xeb, 0xdc, 0x7e, | 268 | 0x08, 0xeb, 0xde, 0x7e, |
268 | 0x80, 0xeb, 0x06, 0x7a, | 269 | 0x80, 0xeb, 0x08, 0x7a, |
269 | 0xff, 0x6a, 0xd6, 0x09, | 270 | 0xff, 0x6a, 0xd6, 0x09, |
270 | 0x08, 0xeb, 0x0a, 0x6a, | 271 | 0x08, 0xeb, 0x0c, 0x6a, |
271 | 0xff, 0x6a, 0xd4, 0x0c, | 272 | 0xff, 0x6a, 0xd4, 0x0c, |
272 | 0x80, 0xa3, 0xdc, 0x6e, | 273 | 0x80, 0xa3, 0xde, 0x6e, |
273 | 0x88, 0xeb, 0x20, 0x72, | 274 | 0x88, 0xeb, 0x22, 0x72, |
274 | 0x08, 0xeb, 0xdc, 0x6e, | 275 | 0x08, 0xeb, 0xde, 0x6e, |
275 | 0x04, 0xea, 0x24, 0xe2, | 276 | 0x04, 0xea, 0x26, 0xe2, |
276 | 0x08, 0xee, 0xdc, 0x6e, | 277 | 0x08, 0xee, 0xde, 0x6e, |
277 | 0x04, 0x6a, 0xd0, 0x81, | 278 | 0x04, 0x6a, 0xd0, 0x81, |
278 | 0x05, 0xa4, 0xc0, 0x89, | 279 | 0x05, 0xa4, 0xc0, 0x89, |
279 | 0x03, 0xa5, 0xc2, 0x31, | 280 | 0x03, 0xa5, 0xc2, 0x31, |
280 | 0x09, 0x6a, 0xd6, 0x05, | 281 | 0x09, 0x6a, 0xd6, 0x05, |
281 | 0x00, 0x65, 0x08, 0x5a, | 282 | 0x00, 0x65, 0x0a, 0x5a, |
282 | 0x06, 0xa4, 0xd4, 0x89, | 283 | 0x06, 0xa4, 0xd4, 0x89, |
283 | 0x80, 0x94, 0xdc, 0x7e, | 284 | 0x80, 0x94, 0xde, 0x7e, |
284 | 0x07, 0xe9, 0x10, 0x31, | 285 | 0x07, 0xe9, 0x10, 0x31, |
285 | 0x01, 0xe9, 0x46, 0x31, | 286 | 0x01, 0xe9, 0x46, 0x31, |
286 | 0x00, 0xa3, 0xba, 0x5e, | 287 | 0x00, 0xa3, 0xbc, 0x5e, |
287 | 0x00, 0x65, 0xfa, 0x59, | 288 | 0x00, 0x65, 0xfc, 0x59, |
288 | 0x01, 0xa4, 0xca, 0x30, | 289 | 0x01, 0xa4, 0xca, 0x30, |
289 | 0x80, 0xa3, 0x34, 0x7a, | 290 | 0x80, 0xa3, 0x36, 0x7a, |
290 | 0x02, 0x65, 0xca, 0x00, | 291 | 0x02, 0x65, 0xca, 0x00, |
291 | 0x01, 0x65, 0xf8, 0x31, | 292 | 0x01, 0x65, 0xf8, 0x31, |
292 | 0x80, 0x93, 0x26, 0x01, | 293 | 0x80, 0x93, 0x26, 0x01, |
@@ -294,162 +295,162 @@ static uint8_t seqprog[] = { | |||
294 | 0x01, 0x8c, 0xc8, 0x30, | 295 | 0x01, 0x8c, 0xc8, 0x30, |
295 | 0x00, 0x88, 0xc8, 0x18, | 296 | 0x00, 0x88, 0xc8, 0x18, |
296 | 0x02, 0x64, 0xc8, 0x88, | 297 | 0x02, 0x64, 0xc8, 0x88, |
297 | 0xff, 0x64, 0xdc, 0x7e, | 298 | 0xff, 0x64, 0xde, 0x7e, |
298 | 0xff, 0x8d, 0x4a, 0x6a, | 299 | 0xff, 0x8d, 0x4c, 0x6a, |
299 | 0xff, 0x8e, 0x4a, 0x6a, | 300 | 0xff, 0x8e, 0x4c, 0x6a, |
300 | 0x03, 0x8c, 0xd4, 0x98, | 301 | 0x03, 0x8c, 0xd4, 0x98, |
301 | 0x00, 0x65, 0xdc, 0x56, | 302 | 0x00, 0x65, 0xde, 0x56, |
302 | 0x01, 0x64, 0x70, 0x30, | 303 | 0x01, 0x64, 0x70, 0x30, |
303 | 0xff, 0x64, 0xc8, 0x10, | 304 | 0xff, 0x64, 0xc8, 0x10, |
304 | 0x01, 0x64, 0xc8, 0x18, | 305 | 0x01, 0x64, 0xc8, 0x18, |
305 | 0x00, 0x8c, 0x18, 0x19, | 306 | 0x00, 0x8c, 0x18, 0x19, |
306 | 0xff, 0x8d, 0x1a, 0x21, | 307 | 0xff, 0x8d, 0x1a, 0x21, |
307 | 0xff, 0x8e, 0x1c, 0x25, | 308 | 0xff, 0x8e, 0x1c, 0x25, |
308 | 0xc0, 0x3c, 0x5a, 0x7a, | 309 | 0xc0, 0x3c, 0x5c, 0x7a, |
309 | 0x21, 0x6a, 0xd8, 0x5e, | 310 | 0x21, 0x6a, 0xda, 0x5e, |
310 | 0xa8, 0x6a, 0x76, 0x00, | 311 | 0xa8, 0x6a, 0x76, 0x00, |
311 | 0x79, 0x6a, 0x76, 0x00, | 312 | 0x79, 0x6a, 0x76, 0x00, |
312 | 0x40, 0x3f, 0x62, 0x6a, | 313 | 0x40, 0x3f, 0x64, 0x6a, |
313 | 0x04, 0x3b, 0x76, 0x00, | 314 | 0x04, 0x3b, 0x76, 0x00, |
314 | 0x04, 0x6a, 0xd4, 0x81, | 315 | 0x04, 0x6a, 0xd4, 0x81, |
315 | 0x20, 0x3c, 0x6a, 0x7a, | 316 | 0x20, 0x3c, 0x6c, 0x7a, |
316 | 0x51, 0x6a, 0xd8, 0x5e, | 317 | 0x51, 0x6a, 0xda, 0x5e, |
317 | 0x00, 0x65, 0x82, 0x42, | 318 | 0x00, 0x65, 0x84, 0x42, |
318 | 0x20, 0x3c, 0x78, 0x00, | 319 | 0x20, 0x3c, 0x78, 0x00, |
319 | 0x00, 0xb3, 0xba, 0x5e, | 320 | 0x00, 0xb3, 0xbc, 0x5e, |
320 | 0x07, 0xac, 0x10, 0x31, | 321 | 0x07, 0xac, 0x10, 0x31, |
321 | 0x05, 0xb3, 0x46, 0x31, | 322 | 0x05, 0xb3, 0x46, 0x31, |
322 | 0x88, 0x6a, 0xcc, 0x00, | 323 | 0x88, 0x6a, 0xcc, 0x00, |
323 | 0xac, 0x6a, 0xee, 0x5d, | 324 | 0xac, 0x6a, 0xf0, 0x5d, |
324 | 0xa3, 0x6a, 0xcc, 0x00, | 325 | 0xa3, 0x6a, 0xcc, 0x00, |
325 | 0xb3, 0x6a, 0xf2, 0x5d, | 326 | 0xb3, 0x6a, 0xf4, 0x5d, |
326 | 0x00, 0x65, 0x3a, 0x5a, | 327 | 0x00, 0x65, 0x3c, 0x5a, |
327 | 0xfd, 0xa4, 0x48, 0x09, | 328 | 0xfd, 0xa4, 0x48, 0x09, |
328 | 0x03, 0x8c, 0x10, 0x30, | 329 | 0x03, 0x8c, 0x10, 0x30, |
329 | 0x00, 0x65, 0xe6, 0x5d, | 330 | 0x00, 0x65, 0xe8, 0x5d, |
330 | 0x01, 0xa4, 0x94, 0x7a, | 331 | 0x01, 0xa4, 0x96, 0x7a, |
331 | 0x04, 0x3b, 0x76, 0x08, | 332 | 0x04, 0x3b, 0x76, 0x08, |
332 | 0x01, 0x3b, 0x26, 0x31, | 333 | 0x01, 0x3b, 0x26, 0x31, |
333 | 0x80, 0x02, 0x04, 0x00, | 334 | 0x80, 0x02, 0x04, 0x00, |
334 | 0x10, 0x0c, 0x8a, 0x7a, | 335 | 0x10, 0x0c, 0x8c, 0x7a, |
335 | 0x03, 0x9e, 0x8c, 0x6a, | 336 | 0x03, 0x9e, 0x8e, 0x6a, |
336 | 0x7f, 0x02, 0x04, 0x08, | 337 | 0x7f, 0x02, 0x04, 0x08, |
337 | 0x91, 0x6a, 0xd8, 0x5e, | 338 | 0x91, 0x6a, 0xda, 0x5e, |
338 | 0x00, 0x65, 0xcc, 0x41, | 339 | 0x00, 0x65, 0xcc, 0x41, |
339 | 0x01, 0xa4, 0xca, 0x30, | 340 | 0x01, 0xa4, 0xca, 0x30, |
340 | 0x80, 0xa3, 0x9a, 0x7a, | 341 | 0x80, 0xa3, 0x9c, 0x7a, |
341 | 0x02, 0x65, 0xca, 0x00, | 342 | 0x02, 0x65, 0xca, 0x00, |
342 | 0x01, 0x65, 0xf8, 0x31, | 343 | 0x01, 0x65, 0xf8, 0x31, |
343 | 0x01, 0x3b, 0x26, 0x31, | 344 | 0x01, 0x3b, 0x26, 0x31, |
344 | 0x00, 0x65, 0x0e, 0x5a, | 345 | 0x00, 0x65, 0x10, 0x5a, |
345 | 0x01, 0xfc, 0xa8, 0x6a, | 346 | 0x01, 0xfc, 0xaa, 0x6a, |
346 | 0x80, 0x0b, 0x9e, 0x6a, | 347 | 0x80, 0x0b, 0xa0, 0x6a, |
347 | 0x10, 0x0c, 0x9e, 0x7a, | 348 | 0x10, 0x0c, 0xa0, 0x7a, |
348 | 0x20, 0x93, 0x9e, 0x6a, | 349 | 0x20, 0x93, 0xa0, 0x6a, |
349 | 0x02, 0x93, 0x26, 0x01, | 350 | 0x02, 0x93, 0x26, 0x01, |
350 | 0x02, 0xfc, 0xb2, 0x7a, | 351 | 0x02, 0xfc, 0xb4, 0x7a, |
351 | 0x40, 0x0d, 0xc6, 0x6a, | 352 | 0x40, 0x0d, 0xc8, 0x6a, |
352 | 0x01, 0xa4, 0x48, 0x01, | 353 | 0x01, 0xa4, 0x48, 0x01, |
353 | 0x00, 0x65, 0xc6, 0x42, | 354 | 0x00, 0x65, 0xc8, 0x42, |
354 | 0x40, 0x0d, 0xb8, 0x6a, | 355 | 0x40, 0x0d, 0xba, 0x6a, |
355 | 0x00, 0x65, 0x0e, 0x5a, | 356 | 0x00, 0x65, 0x10, 0x5a, |
356 | 0x00, 0x65, 0xaa, 0x42, | 357 | 0x00, 0x65, 0xac, 0x42, |
357 | 0x80, 0xfc, 0xc2, 0x7a, | 358 | 0x80, 0xfc, 0xc4, 0x7a, |
358 | 0x80, 0xa4, 0xc2, 0x6a, | 359 | 0x80, 0xa4, 0xc4, 0x6a, |
359 | 0xff, 0xa5, 0x4a, 0x19, | 360 | 0xff, 0xa5, 0x4a, 0x19, |
360 | 0xff, 0xa6, 0x4c, 0x21, | 361 | 0xff, 0xa6, 0x4c, 0x21, |
361 | 0xff, 0xa7, 0x4e, 0x21, | 362 | 0xff, 0xa7, 0x4e, 0x21, |
362 | 0xf8, 0xfc, 0x48, 0x09, | 363 | 0xf8, 0xfc, 0x48, 0x09, |
363 | 0x7f, 0xa3, 0x46, 0x09, | 364 | 0x7f, 0xa3, 0x46, 0x09, |
364 | 0x04, 0x3b, 0xe2, 0x6a, | 365 | 0x04, 0x3b, 0xe4, 0x6a, |
365 | 0x02, 0x93, 0x26, 0x01, | 366 | 0x02, 0x93, 0x26, 0x01, |
366 | 0x01, 0x94, 0xc8, 0x7a, | 367 | 0x01, 0x94, 0xca, 0x7a, |
367 | 0x01, 0x94, 0xc8, 0x7a, | 368 | 0x01, 0x94, 0xca, 0x7a, |
368 | 0x01, 0x94, 0xc8, 0x7a, | 369 | 0x01, 0x94, 0xca, 0x7a, |
369 | 0x01, 0x94, 0xc8, 0x7a, | 370 | 0x01, 0x94, 0xca, 0x7a, |
370 | 0x01, 0x94, 0xc8, 0x7a, | 371 | 0x01, 0x94, 0xca, 0x7a, |
371 | 0x01, 0xa4, 0xe0, 0x7a, | 372 | 0x01, 0xa4, 0xe2, 0x7a, |
372 | 0x01, 0xfc, 0xd6, 0x7a, | 373 | 0x01, 0xfc, 0xd8, 0x7a, |
373 | 0x01, 0x94, 0xe2, 0x6a, | 374 | 0x01, 0x94, 0xe4, 0x6a, |
374 | 0x01, 0x94, 0xe2, 0x6a, | 375 | 0x01, 0x94, 0xe4, 0x6a, |
375 | 0x01, 0x94, 0xe2, 0x6a, | 376 | 0x01, 0x94, 0xe4, 0x6a, |
376 | 0x00, 0x65, 0x82, 0x42, | 377 | 0x00, 0x65, 0x84, 0x42, |
377 | 0x01, 0x94, 0xe0, 0x7a, | 378 | 0x01, 0x94, 0xe2, 0x7a, |
378 | 0x10, 0x94, 0xe2, 0x6a, | 379 | 0x10, 0x94, 0xe4, 0x6a, |
379 | 0xd7, 0x93, 0x26, 0x09, | 380 | 0xd7, 0x93, 0x26, 0x09, |
380 | 0x28, 0x93, 0xe6, 0x6a, | 381 | 0x28, 0x93, 0xe8, 0x6a, |
381 | 0x01, 0x85, 0x0a, 0x01, | 382 | 0x01, 0x85, 0x0a, 0x01, |
382 | 0x02, 0xfc, 0xee, 0x6a, | 383 | 0x02, 0xfc, 0xf0, 0x6a, |
383 | 0x01, 0x14, 0x46, 0x31, | 384 | 0x01, 0x14, 0x46, 0x31, |
384 | 0xff, 0x6a, 0x10, 0x09, | 385 | 0xff, 0x6a, 0x10, 0x09, |
385 | 0xfe, 0x85, 0x0a, 0x09, | 386 | 0xfe, 0x85, 0x0a, 0x09, |
386 | 0xff, 0x38, 0xfc, 0x6a, | 387 | 0xff, 0x38, 0xfe, 0x6a, |
387 | 0x80, 0xa3, 0xfc, 0x7a, | 388 | 0x80, 0xa3, 0xfe, 0x7a, |
388 | 0x80, 0x0b, 0xfa, 0x7a, | 389 | 0x80, 0x0b, 0xfc, 0x7a, |
389 | 0x04, 0x3b, 0xfc, 0x7a, | 390 | 0x04, 0x3b, 0xfe, 0x7a, |
390 | 0xbf, 0x3b, 0x76, 0x08, | 391 | 0xbf, 0x3b, 0x76, 0x08, |
391 | 0x01, 0x3b, 0x26, 0x31, | 392 | 0x01, 0x3b, 0x26, 0x31, |
392 | 0x00, 0x65, 0x0e, 0x5a, | 393 | 0x00, 0x65, 0x10, 0x5a, |
393 | 0x01, 0x0b, 0x0a, 0x6b, | 394 | 0x01, 0x0b, 0x0c, 0x6b, |
394 | 0x10, 0x0c, 0xfe, 0x7a, | 395 | 0x10, 0x0c, 0x00, 0x7b, |
395 | 0x04, 0x93, 0x08, 0x6b, | 396 | 0x04, 0x93, 0x0a, 0x6b, |
396 | 0x01, 0x94, 0x06, 0x7b, | 397 | 0x01, 0x94, 0x08, 0x7b, |
397 | 0x10, 0x94, 0x08, 0x6b, | 398 | 0x10, 0x94, 0x0a, 0x6b, |
398 | 0xc7, 0x93, 0x26, 0x09, | 399 | 0xc7, 0x93, 0x26, 0x09, |
399 | 0x01, 0x99, 0xd4, 0x30, | 400 | 0x01, 0x99, 0xd4, 0x30, |
400 | 0x38, 0x93, 0x0c, 0x6b, | 401 | 0x38, 0x93, 0x0e, 0x6b, |
401 | 0xff, 0x08, 0x5a, 0x6b, | 402 | 0xff, 0x08, 0x5c, 0x6b, |
402 | 0xff, 0x09, 0x5a, 0x6b, | 403 | 0xff, 0x09, 0x5c, 0x6b, |
403 | 0xff, 0x0a, 0x5a, 0x6b, | 404 | 0xff, 0x0a, 0x5c, 0x6b, |
404 | 0xff, 0x38, 0x28, 0x7b, | 405 | 0xff, 0x38, 0x2a, 0x7b, |
405 | 0x04, 0x14, 0x10, 0x31, | 406 | 0x04, 0x14, 0x10, 0x31, |
406 | 0x01, 0x38, 0x18, 0x31, | 407 | 0x01, 0x38, 0x18, 0x31, |
407 | 0x02, 0x6a, 0x1a, 0x31, | 408 | 0x02, 0x6a, 0x1a, 0x31, |
408 | 0x88, 0x6a, 0xcc, 0x00, | 409 | 0x88, 0x6a, 0xcc, 0x00, |
409 | 0x14, 0x6a, 0xf4, 0x5d, | 410 | 0x14, 0x6a, 0xf6, 0x5d, |
410 | 0x00, 0x38, 0xe0, 0x5d, | 411 | 0x00, 0x38, 0xe2, 0x5d, |
411 | 0xff, 0x6a, 0x70, 0x08, | 412 | 0xff, 0x6a, 0x70, 0x08, |
412 | 0x00, 0x65, 0x54, 0x43, | 413 | 0x00, 0x65, 0x56, 0x43, |
413 | 0x80, 0xa3, 0x2e, 0x7b, | 414 | 0x80, 0xa3, 0x30, 0x7b, |
414 | 0x01, 0xa4, 0x48, 0x01, | 415 | 0x01, 0xa4, 0x48, 0x01, |
415 | 0x00, 0x65, 0x5a, 0x43, | 416 | 0x00, 0x65, 0x5c, 0x43, |
416 | 0x08, 0xeb, 0x34, 0x7b, | 417 | 0x08, 0xeb, 0x36, 0x7b, |
417 | 0x00, 0x65, 0x0e, 0x5a, | 418 | 0x00, 0x65, 0x10, 0x5a, |
418 | 0x08, 0xeb, 0x30, 0x6b, | 419 | 0x08, 0xeb, 0x32, 0x6b, |
419 | 0x07, 0xe9, 0x10, 0x31, | 420 | 0x07, 0xe9, 0x10, 0x31, |
420 | 0x01, 0xe9, 0xca, 0x30, | 421 | 0x01, 0xe9, 0xca, 0x30, |
421 | 0x01, 0x65, 0x46, 0x31, | 422 | 0x01, 0x65, 0x46, 0x31, |
422 | 0x00, 0x6a, 0xba, 0x5e, | 423 | 0x00, 0x6a, 0xbc, 0x5e, |
423 | 0x88, 0x6a, 0xcc, 0x00, | 424 | 0x88, 0x6a, 0xcc, 0x00, |
424 | 0xa4, 0x6a, 0xf4, 0x5d, | 425 | 0xa4, 0x6a, 0xf6, 0x5d, |
425 | 0x08, 0x6a, 0xe0, 0x5d, | 426 | 0x08, 0x6a, 0xe2, 0x5d, |
426 | 0x0d, 0x93, 0x26, 0x01, | 427 | 0x0d, 0x93, 0x26, 0x01, |
427 | 0x00, 0x65, 0xa8, 0x5e, | 428 | 0x00, 0x65, 0xaa, 0x5e, |
428 | 0x88, 0x6a, 0xcc, 0x00, | 429 | 0x88, 0x6a, 0xcc, 0x00, |
429 | 0x00, 0x65, 0x8a, 0x5e, | 430 | 0x00, 0x65, 0x8c, 0x5e, |
430 | 0x01, 0x99, 0x46, 0x31, | 431 | 0x01, 0x99, 0x46, 0x31, |
431 | 0x00, 0xa3, 0xba, 0x5e, | 432 | 0x00, 0xa3, 0xbc, 0x5e, |
432 | 0x01, 0x88, 0x10, 0x31, | 433 | 0x01, 0x88, 0x10, 0x31, |
433 | 0x00, 0x65, 0x3a, 0x5a, | 434 | 0x00, 0x65, 0x3c, 0x5a, |
434 | 0x00, 0x65, 0xfa, 0x59, | 435 | 0x00, 0x65, 0xfc, 0x59, |
435 | 0x03, 0x8c, 0x10, 0x30, | 436 | 0x03, 0x8c, 0x10, 0x30, |
436 | 0x00, 0x65, 0xe6, 0x5d, | 437 | 0x00, 0x65, 0xe8, 0x5d, |
437 | 0x80, 0x0b, 0x82, 0x6a, | 438 | 0x80, 0x0b, 0x84, 0x6a, |
438 | 0x80, 0x0b, 0x62, 0x6b, | 439 | 0x80, 0x0b, 0x64, 0x6b, |
439 | 0x01, 0x0c, 0x5c, 0x7b, | 440 | 0x01, 0x0c, 0x5e, 0x7b, |
440 | 0x10, 0x0c, 0x82, 0x7a, | 441 | 0x10, 0x0c, 0x84, 0x7a, |
441 | 0x03, 0x9e, 0x82, 0x6a, | 442 | 0x03, 0x9e, 0x84, 0x6a, |
442 | 0x00, 0x65, 0x04, 0x5a, | 443 | 0x00, 0x65, 0x06, 0x5a, |
443 | 0x00, 0x6a, 0xba, 0x5e, | 444 | 0x00, 0x6a, 0xbc, 0x5e, |
444 | 0x01, 0xa4, 0x82, 0x6b, | 445 | 0x01, 0xa4, 0x84, 0x6b, |
445 | 0xff, 0x38, 0x78, 0x7b, | 446 | 0xff, 0x38, 0x7a, 0x7b, |
446 | 0x01, 0x38, 0xc8, 0x30, | 447 | 0x01, 0x38, 0xc8, 0x30, |
447 | 0x00, 0x08, 0x40, 0x19, | 448 | 0x00, 0x08, 0x40, 0x19, |
448 | 0xff, 0x6a, 0xc8, 0x08, | 449 | 0xff, 0x6a, 0xc8, 0x08, |
449 | 0x00, 0x09, 0x42, 0x21, | 450 | 0x00, 0x09, 0x42, 0x21, |
450 | 0x00, 0x0a, 0x44, 0x21, | 451 | 0x00, 0x0a, 0x44, 0x21, |
451 | 0xff, 0x6a, 0x70, 0x08, | 452 | 0xff, 0x6a, 0x70, 0x08, |
452 | 0x00, 0x65, 0x7a, 0x43, | 453 | 0x00, 0x65, 0x7c, 0x43, |
453 | 0x03, 0x08, 0x40, 0x31, | 454 | 0x03, 0x08, 0x40, 0x31, |
454 | 0x03, 0x08, 0x40, 0x31, | 455 | 0x03, 0x08, 0x40, 0x31, |
455 | 0x01, 0x08, 0x40, 0x31, | 456 | 0x01, 0x08, 0x40, 0x31, |
@@ -461,16 +462,16 @@ static uint8_t seqprog[] = { | |||
461 | 0x04, 0x3c, 0xcc, 0x79, | 462 | 0x04, 0x3c, 0xcc, 0x79, |
462 | 0xfb, 0x3c, 0x78, 0x08, | 463 | 0xfb, 0x3c, 0x78, 0x08, |
463 | 0x04, 0x93, 0x20, 0x79, | 464 | 0x04, 0x93, 0x20, 0x79, |
464 | 0x01, 0x0c, 0x8e, 0x6b, | 465 | 0x01, 0x0c, 0x90, 0x6b, |
465 | 0x80, 0xba, 0x20, 0x79, | 466 | 0x80, 0xba, 0x20, 0x79, |
466 | 0x80, 0x04, 0x20, 0x79, | 467 | 0x80, 0x04, 0x20, 0x79, |
467 | 0xe4, 0x6a, 0x6e, 0x5d, | 468 | 0xe4, 0x6a, 0x70, 0x5d, |
468 | 0x23, 0x6a, 0x84, 0x5d, | 469 | 0x23, 0x6a, 0x86, 0x5d, |
469 | 0x01, 0x6a, 0x84, 0x5d, | 470 | 0x01, 0x6a, 0x86, 0x5d, |
470 | 0x00, 0x65, 0x20, 0x41, | 471 | 0x00, 0x65, 0x20, 0x41, |
471 | 0x00, 0x65, 0xcc, 0x41, | 472 | 0x00, 0x65, 0xcc, 0x41, |
472 | 0x80, 0x3c, 0xa2, 0x7b, | 473 | 0x80, 0x3c, 0xa4, 0x7b, |
473 | 0x21, 0x6a, 0xd8, 0x5e, | 474 | 0x21, 0x6a, 0xda, 0x5e, |
474 | 0x01, 0xbc, 0x18, 0x31, | 475 | 0x01, 0xbc, 0x18, 0x31, |
475 | 0x02, 0x6a, 0x1a, 0x31, | 476 | 0x02, 0x6a, 0x1a, 0x31, |
476 | 0x02, 0x6a, 0xf8, 0x01, | 477 | 0x02, 0x6a, 0xf8, 0x01, |
@@ -480,16 +481,16 @@ static uint8_t seqprog[] = { | |||
480 | 0xff, 0x6a, 0x12, 0x08, | 481 | 0xff, 0x6a, 0x12, 0x08, |
481 | 0xff, 0x6a, 0x14, 0x08, | 482 | 0xff, 0x6a, 0x14, 0x08, |
482 | 0xf3, 0xbc, 0xd4, 0x18, | 483 | 0xf3, 0xbc, 0xd4, 0x18, |
483 | 0xa0, 0x6a, 0xc8, 0x53, | 484 | 0xa0, 0x6a, 0xca, 0x53, |
484 | 0x04, 0xa0, 0x10, 0x31, | 485 | 0x04, 0xa0, 0x10, 0x31, |
485 | 0xac, 0x6a, 0x26, 0x01, | 486 | 0xac, 0x6a, 0x26, 0x01, |
486 | 0x04, 0xa0, 0x10, 0x31, | 487 | 0x04, 0xa0, 0x10, 0x31, |
487 | 0x03, 0x08, 0x18, 0x31, | 488 | 0x03, 0x08, 0x18, 0x31, |
488 | 0x88, 0x6a, 0xcc, 0x00, | 489 | 0x88, 0x6a, 0xcc, 0x00, |
489 | 0xa0, 0x6a, 0xf4, 0x5d, | 490 | 0xa0, 0x6a, 0xf6, 0x5d, |
490 | 0x00, 0xbc, 0xe0, 0x5d, | 491 | 0x00, 0xbc, 0xe2, 0x5d, |
491 | 0x3d, 0x6a, 0x26, 0x01, | 492 | 0x3d, 0x6a, 0x26, 0x01, |
492 | 0x00, 0x65, 0xe0, 0x43, | 493 | 0x00, 0x65, 0xe2, 0x43, |
493 | 0xff, 0x6a, 0x10, 0x09, | 494 | 0xff, 0x6a, 0x10, 0x09, |
494 | 0xa4, 0x6a, 0x26, 0x01, | 495 | 0xa4, 0x6a, 0x26, 0x01, |
495 | 0x0c, 0xa0, 0x32, 0x31, | 496 | 0x0c, 0xa0, 0x32, 0x31, |
@@ -499,128 +500,128 @@ static uint8_t seqprog[] = { | |||
499 | 0x36, 0x6a, 0x26, 0x01, | 500 | 0x36, 0x6a, 0x26, 0x01, |
500 | 0x02, 0x93, 0x26, 0x01, | 501 | 0x02, 0x93, 0x26, 0x01, |
501 | 0x35, 0x6a, 0x26, 0x01, | 502 | 0x35, 0x6a, 0x26, 0x01, |
502 | 0x00, 0x65, 0x9c, 0x5e, | 503 | 0x00, 0x65, 0x9e, 0x5e, |
503 | 0x00, 0x65, 0x9c, 0x5e, | 504 | 0x00, 0x65, 0x9e, 0x5e, |
504 | 0x02, 0x93, 0x26, 0x01, | 505 | 0x02, 0x93, 0x26, 0x01, |
505 | 0xbf, 0x3c, 0x78, 0x08, | 506 | 0xbf, 0x3c, 0x78, 0x08, |
506 | 0x04, 0x0b, 0xe6, 0x6b, | 507 | 0x04, 0x0b, 0xe8, 0x6b, |
507 | 0x10, 0x0c, 0xe2, 0x7b, | 508 | 0x10, 0x0c, 0xe4, 0x7b, |
508 | 0x01, 0x03, 0xe6, 0x6b, | 509 | 0x01, 0x03, 0xe8, 0x6b, |
509 | 0x20, 0x93, 0xe8, 0x6b, | 510 | 0x20, 0x93, 0xea, 0x6b, |
510 | 0x04, 0x0b, 0xee, 0x6b, | 511 | 0x04, 0x0b, 0xf0, 0x6b, |
511 | 0x40, 0x3c, 0x78, 0x00, | 512 | 0x40, 0x3c, 0x78, 0x00, |
512 | 0xc7, 0x93, 0x26, 0x09, | 513 | 0xc7, 0x93, 0x26, 0x09, |
513 | 0x38, 0x93, 0xf0, 0x6b, | 514 | 0x38, 0x93, 0xf2, 0x6b, |
514 | 0x00, 0x65, 0xcc, 0x41, | 515 | 0x00, 0x65, 0xcc, 0x41, |
515 | 0x80, 0x3c, 0x56, 0x6c, | 516 | 0x80, 0x3c, 0x58, 0x6c, |
516 | 0x01, 0x06, 0x50, 0x31, | 517 | 0x01, 0x06, 0x50, 0x31, |
517 | 0x80, 0xb8, 0x70, 0x01, | 518 | 0x80, 0xb8, 0x70, 0x01, |
518 | 0x00, 0x65, 0xcc, 0x41, | 519 | 0x00, 0x65, 0xcc, 0x41, |
519 | 0x10, 0x3f, 0x06, 0x00, | 520 | 0x10, 0x3f, 0x06, 0x00, |
520 | 0x10, 0x6a, 0x06, 0x00, | 521 | 0x10, 0x6a, 0x06, 0x00, |
521 | 0x01, 0x3a, 0xca, 0x30, | 522 | 0x01, 0x3a, 0xca, 0x30, |
522 | 0x80, 0x65, 0x1c, 0x64, | 523 | 0x80, 0x65, 0x1e, 0x64, |
523 | 0x10, 0xb8, 0x40, 0x6c, | 524 | 0x10, 0xb8, 0x42, 0x6c, |
524 | 0xc0, 0x3e, 0xca, 0x00, | 525 | 0xc0, 0x3e, 0xca, 0x00, |
525 | 0x40, 0xb8, 0x0c, 0x6c, | 526 | 0x40, 0xb8, 0x0e, 0x6c, |
526 | 0xbf, 0x65, 0xca, 0x08, | 527 | 0xbf, 0x65, 0xca, 0x08, |
527 | 0x20, 0xb8, 0x20, 0x7c, | 528 | 0x20, 0xb8, 0x22, 0x7c, |
528 | 0x01, 0x65, 0x0c, 0x30, | 529 | 0x01, 0x65, 0x0c, 0x30, |
529 | 0x00, 0x65, 0xd8, 0x5d, | 530 | 0x00, 0x65, 0xda, 0x5d, |
530 | 0xa0, 0x3f, 0x28, 0x64, | 531 | 0xa0, 0x3f, 0x2a, 0x64, |
531 | 0x23, 0xb8, 0x0c, 0x08, | 532 | 0x23, 0xb8, 0x0c, 0x08, |
532 | 0x00, 0x65, 0xd8, 0x5d, | 533 | 0x00, 0x65, 0xda, 0x5d, |
533 | 0xa0, 0x3f, 0x28, 0x64, | 534 | 0xa0, 0x3f, 0x2a, 0x64, |
534 | 0x00, 0xbb, 0x20, 0x44, | 535 | 0x00, 0xbb, 0x22, 0x44, |
535 | 0xff, 0x65, 0x20, 0x64, | 536 | 0xff, 0x65, 0x22, 0x64, |
536 | 0x00, 0x65, 0x40, 0x44, | 537 | 0x00, 0x65, 0x42, 0x44, |
537 | 0x40, 0x6a, 0x18, 0x00, | 538 | 0x40, 0x6a, 0x18, 0x00, |
538 | 0x01, 0x65, 0x0c, 0x30, | 539 | 0x01, 0x65, 0x0c, 0x30, |
539 | 0x00, 0x65, 0xd8, 0x5d, | 540 | 0x00, 0x65, 0xda, 0x5d, |
540 | 0xa0, 0x3f, 0xfc, 0x73, | 541 | 0xa0, 0x3f, 0xfe, 0x73, |
541 | 0x40, 0x6a, 0x18, 0x00, | 542 | 0x40, 0x6a, 0x18, 0x00, |
542 | 0x01, 0x3a, 0xa6, 0x30, | 543 | 0x01, 0x3a, 0xa6, 0x30, |
543 | 0x08, 0x6a, 0x74, 0x00, | 544 | 0x08, 0x6a, 0x74, 0x00, |
544 | 0x00, 0x65, 0xcc, 0x41, | 545 | 0x00, 0x65, 0xcc, 0x41, |
545 | 0x64, 0x6a, 0x68, 0x5d, | 546 | 0x64, 0x6a, 0x6a, 0x5d, |
546 | 0x80, 0x64, 0xd8, 0x6c, | 547 | 0x80, 0x64, 0xda, 0x6c, |
547 | 0x04, 0x64, 0x9a, 0x74, | 548 | 0x04, 0x64, 0x9c, 0x74, |
548 | 0x02, 0x64, 0xaa, 0x74, | 549 | 0x02, 0x64, 0xac, 0x74, |
549 | 0x00, 0x6a, 0x60, 0x74, | 550 | 0x00, 0x6a, 0x62, 0x74, |
550 | 0x03, 0x64, 0xc8, 0x74, | 551 | 0x03, 0x64, 0xca, 0x74, |
551 | 0x23, 0x64, 0x48, 0x74, | 552 | 0x23, 0x64, 0x4a, 0x74, |
552 | 0x08, 0x64, 0x5c, 0x74, | 553 | 0x08, 0x64, 0x5e, 0x74, |
553 | 0x61, 0x6a, 0xd8, 0x5e, | 554 | 0x61, 0x6a, 0xda, 0x5e, |
554 | 0x00, 0x65, 0xd8, 0x5d, | 555 | 0x00, 0x65, 0xda, 0x5d, |
555 | 0x08, 0x51, 0xce, 0x71, | 556 | 0x08, 0x51, 0xce, 0x71, |
556 | 0x00, 0x65, 0x40, 0x44, | 557 | 0x00, 0x65, 0x42, 0x44, |
557 | 0x80, 0x04, 0x5a, 0x7c, | 558 | 0x80, 0x04, 0x5c, 0x7c, |
558 | 0x51, 0x6a, 0x5e, 0x5d, | 559 | 0x51, 0x6a, 0x60, 0x5d, |
559 | 0x01, 0x51, 0x5a, 0x64, | 560 | 0x01, 0x51, 0x5c, 0x64, |
560 | 0x01, 0xa4, 0x52, 0x7c, | 561 | 0x01, 0xa4, 0x54, 0x7c, |
561 | 0x80, 0xba, 0x5c, 0x6c, | 562 | 0x80, 0xba, 0x5e, 0x6c, |
562 | 0x41, 0x6a, 0xd8, 0x5e, | 563 | 0x41, 0x6a, 0xda, 0x5e, |
563 | 0x00, 0x65, 0x5c, 0x44, | 564 | 0x00, 0x65, 0x5e, 0x44, |
564 | 0x21, 0x6a, 0xd8, 0x5e, | 565 | 0x21, 0x6a, 0xda, 0x5e, |
565 | 0x00, 0x65, 0x5c, 0x44, | 566 | 0x00, 0x65, 0x5e, 0x44, |
566 | 0x07, 0x6a, 0x54, 0x5d, | 567 | 0x07, 0x6a, 0x56, 0x5d, |
567 | 0x01, 0x06, 0xd4, 0x30, | 568 | 0x01, 0x06, 0xd4, 0x30, |
568 | 0x00, 0x65, 0xcc, 0x41, | 569 | 0x00, 0x65, 0xcc, 0x41, |
569 | 0x80, 0xb8, 0x56, 0x7c, | 570 | 0x80, 0xb8, 0x58, 0x7c, |
570 | 0xc0, 0x3c, 0x6a, 0x7c, | 571 | 0xc0, 0x3c, 0x6c, 0x7c, |
571 | 0x80, 0x3c, 0x56, 0x6c, | 572 | 0x80, 0x3c, 0x58, 0x6c, |
572 | 0xff, 0xa8, 0x6a, 0x6c, | 573 | 0xff, 0xa8, 0x6c, 0x6c, |
573 | 0x40, 0x3c, 0x56, 0x6c, | 574 | 0x40, 0x3c, 0x58, 0x6c, |
574 | 0x10, 0xb8, 0x6e, 0x7c, | 575 | 0x10, 0xb8, 0x70, 0x7c, |
575 | 0xa1, 0x6a, 0xd8, 0x5e, | 576 | 0xa1, 0x6a, 0xda, 0x5e, |
576 | 0x01, 0xb4, 0x74, 0x6c, | 577 | 0x01, 0xb4, 0x76, 0x6c, |
577 | 0x02, 0xb4, 0x76, 0x6c, | 578 | 0x02, 0xb4, 0x78, 0x6c, |
578 | 0x01, 0xa4, 0x76, 0x7c, | 579 | 0x01, 0xa4, 0x78, 0x7c, |
579 | 0xff, 0xa8, 0x86, 0x7c, | 580 | 0xff, 0xa8, 0x88, 0x7c, |
580 | 0x04, 0xb4, 0x68, 0x01, | 581 | 0x04, 0xb4, 0x68, 0x01, |
581 | 0x01, 0x6a, 0x76, 0x00, | 582 | 0x01, 0x6a, 0x76, 0x00, |
582 | 0x00, 0xbb, 0x12, 0x5e, | 583 | 0x00, 0xbb, 0x14, 0x5e, |
583 | 0xff, 0xa8, 0x86, 0x7c, | 584 | 0xff, 0xa8, 0x88, 0x7c, |
584 | 0x71, 0x6a, 0xd8, 0x5e, | 585 | 0x71, 0x6a, 0xda, 0x5e, |
585 | 0x40, 0x51, 0x86, 0x64, | 586 | 0x40, 0x51, 0x88, 0x64, |
586 | 0x00, 0x65, 0xb2, 0x5e, | 587 | 0x00, 0x65, 0xb4, 0x5e, |
587 | 0x00, 0x65, 0xde, 0x41, | 588 | 0x00, 0x65, 0xde, 0x41, |
588 | 0x00, 0xbb, 0x8a, 0x5c, | 589 | 0x00, 0xbb, 0x8c, 0x5c, |
589 | 0x00, 0x65, 0xde, 0x41, | 590 | 0x00, 0x65, 0xde, 0x41, |
590 | 0x00, 0x65, 0xb2, 0x5e, | 591 | 0x00, 0x65, 0xb4, 0x5e, |
591 | 0x01, 0x65, 0xa2, 0x30, | 592 | 0x01, 0x65, 0xa2, 0x30, |
592 | 0x01, 0xf8, 0xc8, 0x30, | 593 | 0x01, 0xf8, 0xc8, 0x30, |
593 | 0x01, 0x4e, 0xc8, 0x30, | 594 | 0x01, 0x4e, 0xc8, 0x30, |
594 | 0x00, 0x6a, 0xb6, 0xdd, | 595 | 0x00, 0x6a, 0xb8, 0xdd, |
595 | 0x00, 0x51, 0xc8, 0x5d, | 596 | 0x00, 0x51, 0xca, 0x5d, |
596 | 0x01, 0x4e, 0x9c, 0x18, | 597 | 0x01, 0x4e, 0x9c, 0x18, |
597 | 0x02, 0x6a, 0x22, 0x05, | 598 | 0x02, 0x6a, 0x22, 0x05, |
598 | 0xc0, 0x3c, 0x56, 0x6c, | 599 | 0xc0, 0x3c, 0x58, 0x6c, |
599 | 0x04, 0xb8, 0x70, 0x01, | 600 | 0x04, 0xb8, 0x70, 0x01, |
600 | 0x00, 0x65, 0xd4, 0x5e, | 601 | 0x00, 0x65, 0xd6, 0x5e, |
601 | 0x20, 0xb8, 0xde, 0x69, | 602 | 0x20, 0xb8, 0xde, 0x69, |
602 | 0x01, 0xbb, 0xa2, 0x30, | 603 | 0x01, 0xbb, 0xa2, 0x30, |
603 | 0x3f, 0xba, 0x7c, 0x08, | 604 | 0x3f, 0xba, 0x7c, 0x08, |
604 | 0x00, 0xb9, 0xce, 0x5c, | 605 | 0x00, 0xb9, 0xd0, 0x5c, |
605 | 0x00, 0x65, 0xde, 0x41, | 606 | 0x00, 0x65, 0xde, 0x41, |
606 | 0x01, 0x06, 0xd4, 0x30, | 607 | 0x01, 0x06, 0xd4, 0x30, |
607 | 0x20, 0x3c, 0xcc, 0x79, | 608 | 0x20, 0x3c, 0xcc, 0x79, |
608 | 0x20, 0x3c, 0x5c, 0x7c, | 609 | 0x20, 0x3c, 0x5e, 0x7c, |
609 | 0x01, 0xa4, 0xb8, 0x7c, | 610 | 0x01, 0xa4, 0xba, 0x7c, |
610 | 0x01, 0xb4, 0x68, 0x01, | 611 | 0x01, 0xb4, 0x68, 0x01, |
611 | 0x00, 0x65, 0xcc, 0x41, | 612 | 0x00, 0x65, 0xcc, 0x41, |
612 | 0x00, 0x65, 0x5c, 0x44, | 613 | 0x00, 0x65, 0x5e, 0x44, |
613 | 0x04, 0x14, 0x58, 0x31, | 614 | 0x04, 0x14, 0x58, 0x31, |
614 | 0x01, 0x06, 0xd4, 0x30, | 615 | 0x01, 0x06, 0xd4, 0x30, |
615 | 0x08, 0xa0, 0x60, 0x31, | 616 | 0x08, 0xa0, 0x60, 0x31, |
616 | 0xac, 0x6a, 0xcc, 0x00, | 617 | 0xac, 0x6a, 0xcc, 0x00, |
617 | 0x14, 0x6a, 0xf4, 0x5d, | 618 | 0x14, 0x6a, 0xf6, 0x5d, |
618 | 0x01, 0x06, 0xd4, 0x30, | 619 | 0x01, 0x06, 0xd4, 0x30, |
619 | 0xa0, 0x6a, 0xec, 0x5d, | 620 | 0xa0, 0x6a, 0xee, 0x5d, |
620 | 0x00, 0x65, 0xcc, 0x41, | 621 | 0x00, 0x65, 0xcc, 0x41, |
621 | 0xdf, 0x3c, 0x78, 0x08, | 622 | 0xdf, 0x3c, 0x78, 0x08, |
622 | 0x12, 0x01, 0x02, 0x00, | 623 | 0x12, 0x01, 0x02, 0x00, |
623 | 0x00, 0x65, 0x5c, 0x44, | 624 | 0x00, 0x65, 0x5e, 0x44, |
624 | 0x4c, 0x65, 0xcc, 0x28, | 625 | 0x4c, 0x65, 0xcc, 0x28, |
625 | 0x01, 0x3e, 0x20, 0x31, | 626 | 0x01, 0x3e, 0x20, 0x31, |
626 | 0xd0, 0x66, 0xcc, 0x18, | 627 | 0xd0, 0x66, 0xcc, 0x18, |
@@ -631,102 +632,102 @@ static uint8_t seqprog[] = { | |||
631 | 0xd0, 0x65, 0xca, 0x18, | 632 | 0xd0, 0x65, 0xca, 0x18, |
632 | 0x01, 0x3e, 0x20, 0x31, | 633 | 0x01, 0x3e, 0x20, 0x31, |
633 | 0x30, 0x65, 0xd4, 0x18, | 634 | 0x30, 0x65, 0xd4, 0x18, |
634 | 0x00, 0x65, 0xe6, 0x4c, | 635 | 0x00, 0x65, 0xe8, 0x4c, |
635 | 0xe1, 0x6a, 0x22, 0x01, | 636 | 0xe1, 0x6a, 0x22, 0x01, |
636 | 0xff, 0x6a, 0xd4, 0x08, | 637 | 0xff, 0x6a, 0xd4, 0x08, |
637 | 0x20, 0x65, 0xd4, 0x18, | 638 | 0x20, 0x65, 0xd4, 0x18, |
638 | 0x00, 0x65, 0xee, 0x54, | 639 | 0x00, 0x65, 0xf0, 0x54, |
639 | 0xe1, 0x6a, 0x22, 0x01, | 640 | 0xe1, 0x6a, 0x22, 0x01, |
640 | 0xff, 0x6a, 0xd4, 0x08, | 641 | 0xff, 0x6a, 0xd4, 0x08, |
641 | 0x20, 0x65, 0xca, 0x18, | 642 | 0x20, 0x65, 0xca, 0x18, |
642 | 0xe0, 0x65, 0xd4, 0x18, | 643 | 0xe0, 0x65, 0xd4, 0x18, |
643 | 0x00, 0x65, 0xf8, 0x4c, | 644 | 0x00, 0x65, 0xfa, 0x4c, |
644 | 0xe1, 0x6a, 0x22, 0x01, | 645 | 0xe1, 0x6a, 0x22, 0x01, |
645 | 0xff, 0x6a, 0xd4, 0x08, | 646 | 0xff, 0x6a, 0xd4, 0x08, |
646 | 0xd0, 0x65, 0xd4, 0x18, | 647 | 0xd0, 0x65, 0xd4, 0x18, |
647 | 0x00, 0x65, 0x00, 0x55, | 648 | 0x00, 0x65, 0x02, 0x55, |
648 | 0xe1, 0x6a, 0x22, 0x01, | 649 | 0xe1, 0x6a, 0x22, 0x01, |
649 | 0xff, 0x6a, 0xd4, 0x08, | 650 | 0xff, 0x6a, 0xd4, 0x08, |
650 | 0x01, 0x6c, 0xa2, 0x30, | 651 | 0x01, 0x6c, 0xa2, 0x30, |
651 | 0xff, 0x51, 0x12, 0x75, | 652 | 0xff, 0x51, 0x14, 0x75, |
652 | 0x00, 0x51, 0x8e, 0x5d, | 653 | 0x00, 0x51, 0x90, 0x5d, |
653 | 0x01, 0x51, 0x20, 0x31, | 654 | 0x01, 0x51, 0x20, 0x31, |
654 | 0x00, 0x65, 0x34, 0x45, | 655 | 0x00, 0x65, 0x36, 0x45, |
655 | 0x3f, 0xba, 0xc8, 0x08, | 656 | 0x3f, 0xba, 0xc8, 0x08, |
656 | 0x00, 0x3e, 0x34, 0x75, | 657 | 0x00, 0x3e, 0x36, 0x75, |
657 | 0x00, 0x65, 0xb0, 0x5e, | 658 | 0x00, 0x65, 0xb2, 0x5e, |
658 | 0x80, 0x3c, 0x78, 0x00, | 659 | 0x80, 0x3c, 0x78, 0x00, |
659 | 0x01, 0x06, 0xd4, 0x30, | 660 | 0x01, 0x06, 0xd4, 0x30, |
660 | 0x00, 0x65, 0xd8, 0x5d, | 661 | 0x00, 0x65, 0xda, 0x5d, |
661 | 0x01, 0x3c, 0x78, 0x00, | 662 | 0x01, 0x3c, 0x78, 0x00, |
662 | 0xe0, 0x3f, 0x50, 0x65, | 663 | 0xe0, 0x3f, 0x52, 0x65, |
663 | 0x02, 0x3c, 0x78, 0x00, | 664 | 0x02, 0x3c, 0x78, 0x00, |
664 | 0x20, 0x12, 0x50, 0x65, | 665 | 0x20, 0x12, 0x52, 0x65, |
665 | 0x51, 0x6a, 0x5e, 0x5d, | 666 | 0x51, 0x6a, 0x60, 0x5d, |
666 | 0x00, 0x51, 0x8e, 0x5d, | 667 | 0x00, 0x51, 0x90, 0x5d, |
667 | 0x51, 0x6a, 0x5e, 0x5d, | 668 | 0x51, 0x6a, 0x60, 0x5d, |
668 | 0x01, 0x51, 0x20, 0x31, | 669 | 0x01, 0x51, 0x20, 0x31, |
669 | 0x04, 0x3c, 0x78, 0x00, | 670 | 0x04, 0x3c, 0x78, 0x00, |
670 | 0x01, 0xb9, 0xc8, 0x30, | 671 | 0x01, 0xb9, 0xc8, 0x30, |
671 | 0x00, 0x3d, 0x4e, 0x65, | 672 | 0x00, 0x3d, 0x50, 0x65, |
672 | 0x08, 0x3c, 0x78, 0x00, | 673 | 0x08, 0x3c, 0x78, 0x00, |
673 | 0x3f, 0xba, 0xc8, 0x08, | 674 | 0x3f, 0xba, 0xc8, 0x08, |
674 | 0x00, 0x3e, 0x4e, 0x65, | 675 | 0x00, 0x3e, 0x50, 0x65, |
675 | 0x10, 0x3c, 0x78, 0x00, | 676 | 0x10, 0x3c, 0x78, 0x00, |
676 | 0x04, 0xb8, 0x4e, 0x7d, | 677 | 0x04, 0xb8, 0x50, 0x7d, |
677 | 0xfb, 0xb8, 0x70, 0x09, | 678 | 0xfb, 0xb8, 0x70, 0x09, |
678 | 0x20, 0xb8, 0x44, 0x6d, | 679 | 0x20, 0xb8, 0x46, 0x6d, |
679 | 0x01, 0x90, 0xc8, 0x30, | 680 | 0x01, 0x90, 0xc8, 0x30, |
680 | 0xff, 0x6a, 0xa2, 0x00, | 681 | 0xff, 0x6a, 0xa2, 0x00, |
681 | 0x00, 0x3d, 0xce, 0x5c, | 682 | 0x00, 0x3d, 0xd0, 0x5c, |
682 | 0x01, 0x64, 0x20, 0x31, | 683 | 0x01, 0x64, 0x20, 0x31, |
683 | 0xff, 0x6a, 0x78, 0x08, | 684 | 0xff, 0x6a, 0x78, 0x08, |
684 | 0x00, 0x65, 0xea, 0x58, | 685 | 0x00, 0x65, 0xea, 0x58, |
685 | 0x10, 0xb8, 0x5c, 0x7c, | 686 | 0x10, 0xb8, 0x5e, 0x7c, |
686 | 0xff, 0x6a, 0x54, 0x5d, | 687 | 0xff, 0x6a, 0x56, 0x5d, |
687 | 0x00, 0x65, 0x5c, 0x44, | 688 | 0x00, 0x65, 0x5e, 0x44, |
688 | 0x00, 0x65, 0xb0, 0x5e, | 689 | 0x00, 0x65, 0xb2, 0x5e, |
689 | 0x31, 0x6a, 0xd8, 0x5e, | 690 | 0x31, 0x6a, 0xda, 0x5e, |
690 | 0x00, 0x65, 0x5c, 0x44, | 691 | 0x00, 0x65, 0x5e, 0x44, |
691 | 0x10, 0x3f, 0x06, 0x00, | 692 | 0x10, 0x3f, 0x06, 0x00, |
692 | 0x10, 0x6a, 0x06, 0x00, | 693 | 0x10, 0x6a, 0x06, 0x00, |
693 | 0x01, 0x65, 0x74, 0x34, | 694 | 0x01, 0x65, 0x74, 0x34, |
694 | 0x81, 0x6a, 0xd8, 0x5e, | 695 | 0x81, 0x6a, 0xda, 0x5e, |
695 | 0x00, 0x65, 0x60, 0x45, | 696 | 0x00, 0x65, 0x62, 0x45, |
696 | 0x01, 0x06, 0xd4, 0x30, | 697 | 0x01, 0x06, 0xd4, 0x30, |
697 | 0x01, 0x0c, 0x60, 0x7d, | 698 | 0x01, 0x0c, 0x62, 0x7d, |
698 | 0x04, 0x0c, 0x5a, 0x6d, | 699 | 0x04, 0x0c, 0x5c, 0x6d, |
699 | 0xe0, 0x03, 0x7e, 0x08, | 700 | 0xe0, 0x03, 0x7e, 0x08, |
700 | 0xe0, 0x3f, 0xcc, 0x61, | 701 | 0xe0, 0x3f, 0xcc, 0x61, |
701 | 0x01, 0x65, 0xcc, 0x30, | 702 | 0x01, 0x65, 0xcc, 0x30, |
702 | 0x01, 0x12, 0xda, 0x34, | 703 | 0x01, 0x12, 0xda, 0x34, |
703 | 0x01, 0x06, 0xd4, 0x34, | 704 | 0x01, 0x06, 0xd4, 0x34, |
704 | 0x01, 0x03, 0x6e, 0x6d, | 705 | 0x01, 0x03, 0x70, 0x6d, |
705 | 0x40, 0x03, 0xcc, 0x08, | 706 | 0x40, 0x03, 0xcc, 0x08, |
706 | 0x01, 0x65, 0x06, 0x30, | 707 | 0x01, 0x65, 0x06, 0x30, |
707 | 0x40, 0x65, 0xc8, 0x08, | 708 | 0x40, 0x65, 0xc8, 0x08, |
708 | 0x00, 0x66, 0x7c, 0x75, | 709 | 0x00, 0x66, 0x7e, 0x75, |
709 | 0x40, 0x65, 0x7c, 0x7d, | 710 | 0x40, 0x65, 0x7e, 0x7d, |
710 | 0x00, 0x65, 0x7c, 0x5d, | 711 | 0x00, 0x65, 0x7e, 0x5d, |
711 | 0xff, 0x6a, 0xd4, 0x08, | 712 | 0xff, 0x6a, 0xd4, 0x08, |
712 | 0xff, 0x6a, 0xd4, 0x08, | 713 | 0xff, 0x6a, 0xd4, 0x08, |
713 | 0xff, 0x6a, 0xd4, 0x08, | 714 | 0xff, 0x6a, 0xd4, 0x08, |
714 | 0xff, 0x6a, 0xd4, 0x0c, | 715 | 0xff, 0x6a, 0xd4, 0x0c, |
715 | 0x08, 0x01, 0x02, 0x00, | 716 | 0x08, 0x01, 0x02, 0x00, |
716 | 0x02, 0x0b, 0x86, 0x7d, | 717 | 0x02, 0x0b, 0x88, 0x7d, |
717 | 0x01, 0x65, 0x0c, 0x30, | 718 | 0x01, 0x65, 0x0c, 0x30, |
718 | 0x02, 0x0b, 0x8a, 0x7d, | 719 | 0x02, 0x0b, 0x8c, 0x7d, |
719 | 0xf7, 0x01, 0x02, 0x0c, | 720 | 0xf7, 0x01, 0x02, 0x0c, |
720 | 0x01, 0x65, 0xc8, 0x30, | 721 | 0x01, 0x65, 0xc8, 0x30, |
721 | 0xff, 0x41, 0xae, 0x75, | 722 | 0xff, 0x41, 0xb0, 0x75, |
722 | 0x01, 0x41, 0x20, 0x31, | 723 | 0x01, 0x41, 0x20, 0x31, |
723 | 0xff, 0x6a, 0xa4, 0x00, | 724 | 0xff, 0x6a, 0xa4, 0x00, |
724 | 0x00, 0x65, 0x9e, 0x45, | 725 | 0x00, 0x65, 0xa0, 0x45, |
725 | 0xff, 0xbf, 0xae, 0x75, | 726 | 0xff, 0xbf, 0xb0, 0x75, |
726 | 0x01, 0x90, 0xa4, 0x30, | 727 | 0x01, 0x90, 0xa4, 0x30, |
727 | 0x01, 0xbf, 0x20, 0x31, | 728 | 0x01, 0xbf, 0x20, 0x31, |
728 | 0x00, 0xbb, 0x98, 0x65, | 729 | 0x00, 0xbb, 0x9a, 0x65, |
729 | 0xff, 0x52, 0xac, 0x75, | 730 | 0xff, 0x52, 0xae, 0x75, |
730 | 0x01, 0xbf, 0xcc, 0x30, | 731 | 0x01, 0xbf, 0xcc, 0x30, |
731 | 0x01, 0x90, 0xca, 0x30, | 732 | 0x01, 0x90, 0xca, 0x30, |
732 | 0x01, 0x52, 0x20, 0x31, | 733 | 0x01, 0x52, 0x20, 0x31, |
@@ -734,28 +735,28 @@ static uint8_t seqprog[] = { | |||
734 | 0x01, 0x65, 0x20, 0x35, | 735 | 0x01, 0x65, 0x20, 0x35, |
735 | 0x01, 0xbf, 0x82, 0x34, | 736 | 0x01, 0xbf, 0x82, 0x34, |
736 | 0x01, 0x64, 0xa2, 0x30, | 737 | 0x01, 0x64, 0xa2, 0x30, |
737 | 0x00, 0x6a, 0xc0, 0x5e, | 738 | 0x00, 0x6a, 0xc2, 0x5e, |
738 | 0x0d, 0x6a, 0x76, 0x00, | 739 | 0x0d, 0x6a, 0x76, 0x00, |
739 | 0x00, 0x51, 0x12, 0x46, | 740 | 0x00, 0x51, 0x14, 0x46, |
740 | 0x01, 0x65, 0xa4, 0x30, | 741 | 0x01, 0x65, 0xa4, 0x30, |
741 | 0xe0, 0x6a, 0xcc, 0x00, | 742 | 0xe0, 0x6a, 0xcc, 0x00, |
742 | 0x48, 0x6a, 0x06, 0x5e, | 743 | 0x48, 0x6a, 0x08, 0x5e, |
743 | 0x01, 0x6a, 0xd0, 0x01, | 744 | 0x01, 0x6a, 0xd0, 0x01, |
744 | 0x01, 0x6a, 0xdc, 0x05, | 745 | 0x01, 0x6a, 0xdc, 0x05, |
745 | 0x88, 0x6a, 0xcc, 0x00, | 746 | 0x88, 0x6a, 0xcc, 0x00, |
746 | 0x48, 0x6a, 0x06, 0x5e, | 747 | 0x48, 0x6a, 0x08, 0x5e, |
747 | 0x01, 0x6a, 0xe0, 0x5d, | 748 | 0x01, 0x6a, 0xe2, 0x5d, |
748 | 0x01, 0x6a, 0x26, 0x05, | 749 | 0x01, 0x6a, 0x26, 0x05, |
749 | 0x01, 0x65, 0xd8, 0x31, | 750 | 0x01, 0x65, 0xd8, 0x31, |
750 | 0x09, 0xee, 0xdc, 0x01, | 751 | 0x09, 0xee, 0xdc, 0x01, |
751 | 0x80, 0xee, 0xcc, 0x7d, | 752 | 0x80, 0xee, 0xce, 0x7d, |
752 | 0xff, 0x6a, 0xdc, 0x0d, | 753 | 0xff, 0x6a, 0xdc, 0x0d, |
753 | 0x01, 0x65, 0x32, 0x31, | 754 | 0x01, 0x65, 0x32, 0x31, |
754 | 0x0a, 0x93, 0x26, 0x01, | 755 | 0x0a, 0x93, 0x26, 0x01, |
755 | 0x00, 0x65, 0xa8, 0x46, | 756 | 0x00, 0x65, 0xaa, 0x46, |
756 | 0x81, 0x6a, 0xd8, 0x5e, | 757 | 0x81, 0x6a, 0xda, 0x5e, |
757 | 0x01, 0x0c, 0xd8, 0x7d, | 758 | 0x01, 0x0c, 0xda, 0x7d, |
758 | 0x04, 0x0c, 0xd6, 0x6d, | 759 | 0x04, 0x0c, 0xd8, 0x6d, |
759 | 0xe0, 0x03, 0x06, 0x08, | 760 | 0xe0, 0x03, 0x06, 0x08, |
760 | 0xe0, 0x03, 0x7e, 0x0c, | 761 | 0xe0, 0x03, 0x7e, 0x0c, |
761 | 0x01, 0x65, 0x18, 0x31, | 762 | 0x01, 0x65, 0x18, 0x31, |
@@ -774,7 +775,7 @@ static uint8_t seqprog[] = { | |||
774 | 0x01, 0x6c, 0xda, 0x34, | 775 | 0x01, 0x6c, 0xda, 0x34, |
775 | 0x3d, 0x64, 0xa4, 0x28, | 776 | 0x3d, 0x64, 0xa4, 0x28, |
776 | 0x55, 0x64, 0xc8, 0x28, | 777 | 0x55, 0x64, 0xc8, 0x28, |
777 | 0x00, 0x65, 0x06, 0x46, | 778 | 0x00, 0x65, 0x08, 0x46, |
778 | 0x2e, 0x64, 0xa4, 0x28, | 779 | 0x2e, 0x64, 0xa4, 0x28, |
779 | 0x66, 0x64, 0xc8, 0x28, | 780 | 0x66, 0x64, 0xc8, 0x28, |
780 | 0x00, 0x6c, 0xda, 0x18, | 781 | 0x00, 0x6c, 0xda, 0x18, |
@@ -785,63 +786,63 @@ static uint8_t seqprog[] = { | |||
785 | 0x00, 0x6c, 0xda, 0x24, | 786 | 0x00, 0x6c, 0xda, 0x24, |
786 | 0x01, 0x65, 0xc8, 0x30, | 787 | 0x01, 0x65, 0xc8, 0x30, |
787 | 0xe0, 0x6a, 0xcc, 0x00, | 788 | 0xe0, 0x6a, 0xcc, 0x00, |
788 | 0x44, 0x6a, 0x02, 0x5e, | 789 | 0x44, 0x6a, 0x04, 0x5e, |
789 | 0x01, 0x90, 0xe2, 0x31, | 790 | 0x01, 0x90, 0xe2, 0x31, |
790 | 0x04, 0x3b, 0x26, 0x7e, | 791 | 0x04, 0x3b, 0x28, 0x7e, |
791 | 0x30, 0x6a, 0xd0, 0x01, | 792 | 0x30, 0x6a, 0xd0, 0x01, |
792 | 0x20, 0x6a, 0xd0, 0x01, | 793 | 0x20, 0x6a, 0xd0, 0x01, |
793 | 0x1d, 0x6a, 0xdc, 0x01, | 794 | 0x1d, 0x6a, 0xdc, 0x01, |
794 | 0xdc, 0xee, 0x22, 0x66, | 795 | 0xdc, 0xee, 0x24, 0x66, |
795 | 0x00, 0x65, 0x3e, 0x46, | 796 | 0x00, 0x65, 0x40, 0x46, |
796 | 0x20, 0x6a, 0xd0, 0x01, | 797 | 0x20, 0x6a, 0xd0, 0x01, |
797 | 0x01, 0x6a, 0xdc, 0x01, | 798 | 0x01, 0x6a, 0xdc, 0x01, |
798 | 0x20, 0xa0, 0xd8, 0x31, | 799 | 0x20, 0xa0, 0xd8, 0x31, |
799 | 0x09, 0xee, 0xdc, 0x01, | 800 | 0x09, 0xee, 0xdc, 0x01, |
800 | 0x80, 0xee, 0x2e, 0x7e, | 801 | 0x80, 0xee, 0x30, 0x7e, |
801 | 0x11, 0x6a, 0xdc, 0x01, | 802 | 0x11, 0x6a, 0xdc, 0x01, |
802 | 0x50, 0xee, 0x32, 0x66, | 803 | 0x50, 0xee, 0x34, 0x66, |
803 | 0x20, 0x6a, 0xd0, 0x01, | 804 | 0x20, 0x6a, 0xd0, 0x01, |
804 | 0x09, 0x6a, 0xdc, 0x01, | 805 | 0x09, 0x6a, 0xdc, 0x01, |
805 | 0x88, 0xee, 0x38, 0x66, | 806 | 0x88, 0xee, 0x3a, 0x66, |
806 | 0x19, 0x6a, 0xdc, 0x01, | 807 | 0x19, 0x6a, 0xdc, 0x01, |
807 | 0xd8, 0xee, 0x3c, 0x66, | 808 | 0xd8, 0xee, 0x3e, 0x66, |
808 | 0xff, 0x6a, 0xdc, 0x09, | 809 | 0xff, 0x6a, 0xdc, 0x09, |
809 | 0x18, 0xee, 0x40, 0x6e, | 810 | 0x18, 0xee, 0x42, 0x6e, |
810 | 0xff, 0x6a, 0xd4, 0x0c, | 811 | 0xff, 0x6a, 0xd4, 0x0c, |
811 | 0x88, 0x6a, 0xcc, 0x00, | 812 | 0x88, 0x6a, 0xcc, 0x00, |
812 | 0x44, 0x6a, 0x02, 0x5e, | 813 | 0x44, 0x6a, 0x04, 0x5e, |
813 | 0x20, 0x6a, 0xe0, 0x5d, | 814 | 0x20, 0x6a, 0xe2, 0x5d, |
814 | 0x01, 0x3b, 0x26, 0x31, | 815 | 0x01, 0x3b, 0x26, 0x31, |
815 | 0x04, 0x3b, 0x5a, 0x6e, | 816 | 0x04, 0x3b, 0x5c, 0x6e, |
816 | 0xa0, 0x6a, 0xca, 0x00, | 817 | 0xa0, 0x6a, 0xca, 0x00, |
817 | 0x20, 0x65, 0xc8, 0x18, | 818 | 0x20, 0x65, 0xc8, 0x18, |
818 | 0x00, 0x65, 0x98, 0x5e, | 819 | 0x00, 0x65, 0x9a, 0x5e, |
819 | 0x00, 0x65, 0x52, 0x66, | 820 | 0x00, 0x65, 0x54, 0x66, |
820 | 0x0a, 0x93, 0x26, 0x01, | 821 | 0x0a, 0x93, 0x26, 0x01, |
821 | 0x00, 0x65, 0xa8, 0x46, | 822 | 0x00, 0x65, 0xaa, 0x46, |
822 | 0xa0, 0x6a, 0xcc, 0x00, | 823 | 0xa0, 0x6a, 0xcc, 0x00, |
823 | 0xff, 0x6a, 0xc8, 0x08, | 824 | 0xff, 0x6a, 0xc8, 0x08, |
824 | 0x20, 0x94, 0x5e, 0x6e, | 825 | 0x20, 0x94, 0x60, 0x6e, |
825 | 0x10, 0x94, 0x60, 0x6e, | 826 | 0x10, 0x94, 0x62, 0x6e, |
826 | 0x08, 0x94, 0x7a, 0x6e, | 827 | 0x08, 0x94, 0x7c, 0x6e, |
827 | 0x08, 0x94, 0x7a, 0x6e, | 828 | 0x08, 0x94, 0x7c, 0x6e, |
828 | 0x08, 0x94, 0x7a, 0x6e, | 829 | 0x08, 0x94, 0x7c, 0x6e, |
829 | 0xff, 0x8c, 0xc8, 0x10, | 830 | 0xff, 0x8c, 0xc8, 0x10, |
830 | 0xc1, 0x64, 0xc8, 0x18, | 831 | 0xc1, 0x64, 0xc8, 0x18, |
831 | 0xf8, 0x64, 0xc8, 0x08, | 832 | 0xf8, 0x64, 0xc8, 0x08, |
832 | 0x01, 0x99, 0xda, 0x30, | 833 | 0x01, 0x99, 0xda, 0x30, |
833 | 0x00, 0x66, 0x6e, 0x66, | 834 | 0x00, 0x66, 0x70, 0x66, |
834 | 0xc0, 0x66, 0xaa, 0x76, | 835 | 0xc0, 0x66, 0xac, 0x76, |
835 | 0x60, 0x66, 0xc8, 0x18, | 836 | 0x60, 0x66, 0xc8, 0x18, |
836 | 0x3d, 0x64, 0xc8, 0x28, | 837 | 0x3d, 0x64, 0xc8, 0x28, |
837 | 0x00, 0x65, 0x5e, 0x46, | 838 | 0x00, 0x65, 0x60, 0x46, |
838 | 0xf7, 0x93, 0x26, 0x09, | 839 | 0xf7, 0x93, 0x26, 0x09, |
839 | 0x08, 0x93, 0x7c, 0x6e, | 840 | 0x08, 0x93, 0x7e, 0x6e, |
840 | 0x00, 0x62, 0xc4, 0x18, | 841 | 0x00, 0x62, 0xc4, 0x18, |
841 | 0x00, 0x65, 0xa8, 0x5e, | 842 | 0x00, 0x65, 0xaa, 0x5e, |
842 | 0x00, 0x65, 0x88, 0x5e, | 843 | 0x00, 0x65, 0x8a, 0x5e, |
843 | 0x00, 0x65, 0x88, 0x5e, | 844 | 0x00, 0x65, 0x8a, 0x5e, |
844 | 0x00, 0x65, 0x88, 0x5e, | 845 | 0x00, 0x65, 0x8a, 0x5e, |
845 | 0x01, 0x99, 0xda, 0x30, | 846 | 0x01, 0x99, 0xda, 0x30, |
846 | 0x01, 0x99, 0xda, 0x30, | 847 | 0x01, 0x99, 0xda, 0x30, |
847 | 0x01, 0x99, 0xda, 0x30, | 848 | 0x01, 0x99, 0xda, 0x30, |
@@ -858,11 +859,11 @@ static uint8_t seqprog[] = { | |||
858 | 0x01, 0x6c, 0x32, 0x31, | 859 | 0x01, 0x6c, 0x32, 0x31, |
859 | 0x01, 0x6c, 0x32, 0x31, | 860 | 0x01, 0x6c, 0x32, 0x31, |
860 | 0x01, 0x6c, 0x32, 0x35, | 861 | 0x01, 0x6c, 0x32, 0x35, |
861 | 0x08, 0x94, 0xa8, 0x7e, | 862 | 0x08, 0x94, 0xaa, 0x7e, |
862 | 0xf7, 0x93, 0x26, 0x09, | 863 | 0xf7, 0x93, 0x26, 0x09, |
863 | 0x08, 0x93, 0xac, 0x6e, | 864 | 0x08, 0x93, 0xae, 0x6e, |
864 | 0xff, 0x6a, 0xd4, 0x0c, | 865 | 0xff, 0x6a, 0xd4, 0x0c, |
865 | 0x04, 0xb8, 0xd4, 0x6e, | 866 | 0x04, 0xb8, 0xd6, 0x6e, |
866 | 0x01, 0x42, 0x7e, 0x31, | 867 | 0x01, 0x42, 0x7e, 0x31, |
867 | 0xff, 0x6a, 0x76, 0x01, | 868 | 0xff, 0x6a, 0x76, 0x01, |
868 | 0x01, 0x90, 0x84, 0x34, | 869 | 0x01, 0x90, 0x84, 0x34, |
@@ -870,14 +871,14 @@ static uint8_t seqprog[] = { | |||
870 | 0x01, 0x85, 0x0a, 0x01, | 871 | 0x01, 0x85, 0x0a, 0x01, |
871 | 0x7f, 0x65, 0x10, 0x09, | 872 | 0x7f, 0x65, 0x10, 0x09, |
872 | 0xfe, 0x85, 0x0a, 0x0d, | 873 | 0xfe, 0x85, 0x0a, 0x0d, |
873 | 0xff, 0x42, 0xd0, 0x66, | 874 | 0xff, 0x42, 0xd2, 0x66, |
874 | 0xff, 0x41, 0xc8, 0x66, | 875 | 0xff, 0x41, 0xca, 0x66, |
875 | 0xd1, 0x6a, 0xd8, 0x5e, | 876 | 0xd1, 0x6a, 0xda, 0x5e, |
876 | 0xff, 0x6a, 0xca, 0x04, | 877 | 0xff, 0x6a, 0xca, 0x04, |
877 | 0x01, 0x41, 0x20, 0x31, | 878 | 0x01, 0x41, 0x20, 0x31, |
878 | 0x01, 0xbf, 0x82, 0x30, | 879 | 0x01, 0xbf, 0x82, 0x30, |
879 | 0x01, 0x6a, 0x76, 0x00, | 880 | 0x01, 0x6a, 0x76, 0x00, |
880 | 0x00, 0xbb, 0x12, 0x46, | 881 | 0x00, 0xbb, 0x14, 0x46, |
881 | 0x01, 0x42, 0x20, 0x31, | 882 | 0x01, 0x42, 0x20, 0x31, |
882 | 0x01, 0xbf, 0x84, 0x34, | 883 | 0x01, 0xbf, 0x84, 0x34, |
883 | 0x01, 0x41, 0x7e, 0x31, | 884 | 0x01, 0x41, 0x7e, 0x31, |
@@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func; | |||
941 | static int | 942 | static int |
942 | ahc_patch17_func(struct ahc_softc *ahc) | 943 | ahc_patch17_func(struct ahc_softc *ahc) |
943 | { | 944 | { |
944 | return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0); | 945 | return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0); |
945 | } | 946 | } |
946 | 947 | ||
947 | static ahc_patch_func_t ahc_patch16_func; | 948 | static ahc_patch_func_t ahc_patch16_func; |
@@ -1142,152 +1143,152 @@ static struct patch { | |||
1142 | { ahc_patch0_func, 196, 1, 1 }, | 1143 | { ahc_patch0_func, 196, 1, 1 }, |
1143 | { ahc_patch9_func, 212, 6, 2 }, | 1144 | { ahc_patch9_func, 212, 6, 2 }, |
1144 | { ahc_patch0_func, 218, 6, 1 }, | 1145 | { ahc_patch0_func, 218, 6, 1 }, |
1145 | { ahc_patch8_func, 226, 20, 2 }, | 1146 | { ahc_patch8_func, 226, 21, 2 }, |
1146 | { ahc_patch1_func, 241, 1, 1 }, | 1147 | { ahc_patch1_func, 241, 1, 1 }, |
1147 | { ahc_patch1_func, 248, 1, 2 }, | 1148 | { ahc_patch1_func, 249, 1, 2 }, |
1148 | { ahc_patch0_func, 249, 2, 2 }, | 1149 | { ahc_patch0_func, 250, 2, 2 }, |
1149 | { ahc_patch11_func, 250, 1, 1 }, | 1150 | { ahc_patch11_func, 251, 1, 1 }, |
1150 | { ahc_patch9_func, 258, 27, 3 }, | 1151 | { ahc_patch9_func, 259, 27, 3 }, |
1151 | { ahc_patch1_func, 274, 10, 2 }, | 1152 | { ahc_patch1_func, 275, 10, 2 }, |
1152 | { ahc_patch13_func, 277, 1, 1 }, | 1153 | { ahc_patch13_func, 278, 1, 1 }, |
1153 | { ahc_patch14_func, 285, 14, 1 }, | 1154 | { ahc_patch14_func, 286, 14, 1 }, |
1154 | { ahc_patch1_func, 301, 1, 2 }, | 1155 | { ahc_patch1_func, 302, 1, 2 }, |
1155 | { ahc_patch0_func, 302, 1, 1 }, | 1156 | { ahc_patch0_func, 303, 1, 1 }, |
1156 | { ahc_patch9_func, 305, 1, 1 }, | 1157 | { ahc_patch9_func, 306, 1, 1 }, |
1157 | { ahc_patch13_func, 310, 1, 1 }, | 1158 | { ahc_patch13_func, 311, 1, 1 }, |
1158 | { ahc_patch9_func, 311, 2, 2 }, | 1159 | { ahc_patch9_func, 312, 2, 2 }, |
1159 | { ahc_patch0_func, 313, 4, 1 }, | 1160 | { ahc_patch0_func, 314, 4, 1 }, |
1160 | { ahc_patch14_func, 317, 1, 1 }, | 1161 | { ahc_patch14_func, 318, 1, 1 }, |
1161 | { ahc_patch15_func, 319, 2, 3 }, | 1162 | { ahc_patch15_func, 320, 2, 3 }, |
1162 | { ahc_patch9_func, 319, 1, 2 }, | 1163 | { ahc_patch9_func, 320, 1, 2 }, |
1163 | { ahc_patch0_func, 320, 1, 1 }, | 1164 | { ahc_patch0_func, 321, 1, 1 }, |
1164 | { ahc_patch6_func, 325, 1, 2 }, | 1165 | { ahc_patch6_func, 326, 1, 2 }, |
1165 | { ahc_patch0_func, 326, 1, 1 }, | 1166 | { ahc_patch0_func, 327, 1, 1 }, |
1166 | { ahc_patch1_func, 330, 47, 11 }, | 1167 | { ahc_patch1_func, 331, 47, 11 }, |
1167 | { ahc_patch6_func, 337, 2, 4 }, | 1168 | { ahc_patch6_func, 338, 2, 4 }, |
1168 | { ahc_patch7_func, 337, 1, 1 }, | 1169 | { ahc_patch7_func, 338, 1, 1 }, |
1169 | { ahc_patch8_func, 338, 1, 1 }, | 1170 | { ahc_patch8_func, 339, 1, 1 }, |
1170 | { ahc_patch0_func, 339, 1, 1 }, | 1171 | { ahc_patch0_func, 340, 1, 1 }, |
1171 | { ahc_patch16_func, 340, 1, 1 }, | 1172 | { ahc_patch16_func, 341, 1, 1 }, |
1172 | { ahc_patch6_func, 356, 6, 3 }, | 1173 | { ahc_patch6_func, 357, 6, 3 }, |
1173 | { ahc_patch16_func, 356, 5, 1 }, | 1174 | { ahc_patch16_func, 357, 5, 1 }, |
1174 | { ahc_patch0_func, 362, 7, 1 }, | 1175 | { ahc_patch0_func, 363, 7, 1 }, |
1175 | { ahc_patch13_func, 372, 5, 1 }, | 1176 | { ahc_patch13_func, 373, 5, 1 }, |
1176 | { ahc_patch0_func, 377, 52, 17 }, | 1177 | { ahc_patch0_func, 378, 52, 17 }, |
1177 | { ahc_patch14_func, 377, 1, 1 }, | 1178 | { ahc_patch14_func, 378, 1, 1 }, |
1178 | { ahc_patch7_func, 379, 2, 2 }, | 1179 | { ahc_patch7_func, 380, 2, 2 }, |
1179 | { ahc_patch17_func, 380, 1, 1 }, | 1180 | { ahc_patch17_func, 381, 1, 1 }, |
1180 | { ahc_patch9_func, 383, 1, 1 }, | 1181 | { ahc_patch9_func, 384, 1, 1 }, |
1181 | { ahc_patch18_func, 390, 1, 1 }, | 1182 | { ahc_patch18_func, 391, 1, 1 }, |
1182 | { ahc_patch14_func, 395, 9, 3 }, | 1183 | { ahc_patch14_func, 396, 9, 3 }, |
1183 | { ahc_patch9_func, 396, 3, 2 }, | 1184 | { ahc_patch9_func, 397, 3, 2 }, |
1184 | { ahc_patch0_func, 399, 3, 1 }, | 1185 | { ahc_patch0_func, 400, 3, 1 }, |
1185 | { ahc_patch9_func, 407, 6, 2 }, | 1186 | { ahc_patch9_func, 408, 6, 2 }, |
1186 | { ahc_patch0_func, 413, 9, 2 }, | 1187 | { ahc_patch0_func, 414, 9, 2 }, |
1187 | { ahc_patch13_func, 413, 1, 1 }, | 1188 | { ahc_patch13_func, 414, 1, 1 }, |
1188 | { ahc_patch13_func, 422, 2, 1 }, | 1189 | { ahc_patch13_func, 423, 2, 1 }, |
1189 | { ahc_patch14_func, 424, 1, 1 }, | 1190 | { ahc_patch14_func, 425, 1, 1 }, |
1190 | { ahc_patch9_func, 426, 1, 2 }, | 1191 | { ahc_patch9_func, 427, 1, 2 }, |
1191 | { ahc_patch0_func, 427, 1, 1 }, | 1192 | { ahc_patch0_func, 428, 1, 1 }, |
1192 | { ahc_patch7_func, 428, 1, 1 }, | ||
1193 | { ahc_patch7_func, 429, 1, 1 }, | 1193 | { ahc_patch7_func, 429, 1, 1 }, |
1194 | { ahc_patch8_func, 430, 3, 3 }, | 1194 | { ahc_patch7_func, 430, 1, 1 }, |
1195 | { ahc_patch6_func, 431, 1, 2 }, | 1195 | { ahc_patch8_func, 431, 3, 3 }, |
1196 | { ahc_patch0_func, 432, 1, 1 }, | 1196 | { ahc_patch6_func, 432, 1, 2 }, |
1197 | { ahc_patch9_func, 433, 1, 1 }, | 1197 | { ahc_patch0_func, 433, 1, 1 }, |
1198 | { ahc_patch15_func, 434, 1, 2 }, | 1198 | { ahc_patch9_func, 434, 1, 1 }, |
1199 | { ahc_patch13_func, 434, 1, 1 }, | 1199 | { ahc_patch15_func, 435, 1, 2 }, |
1200 | { ahc_patch14_func, 436, 9, 4 }, | 1200 | { ahc_patch13_func, 435, 1, 1 }, |
1201 | { ahc_patch9_func, 436, 1, 1 }, | 1201 | { ahc_patch14_func, 437, 9, 4 }, |
1202 | { ahc_patch9_func, 443, 2, 1 }, | 1202 | { ahc_patch9_func, 437, 1, 1 }, |
1203 | { ahc_patch0_func, 445, 4, 3 }, | 1203 | { ahc_patch9_func, 444, 2, 1 }, |
1204 | { ahc_patch9_func, 445, 1, 2 }, | 1204 | { ahc_patch0_func, 446, 4, 3 }, |
1205 | { ahc_patch0_func, 446, 3, 1 }, | 1205 | { ahc_patch9_func, 446, 1, 2 }, |
1206 | { ahc_patch1_func, 450, 2, 1 }, | 1206 | { ahc_patch0_func, 447, 3, 1 }, |
1207 | { ahc_patch7_func, 452, 10, 2 }, | 1207 | { ahc_patch1_func, 451, 2, 1 }, |
1208 | { ahc_patch0_func, 462, 1, 1 }, | 1208 | { ahc_patch7_func, 453, 10, 2 }, |
1209 | { ahc_patch8_func, 463, 118, 22 }, | 1209 | { ahc_patch0_func, 463, 1, 1 }, |
1210 | { ahc_patch1_func, 465, 3, 2 }, | 1210 | { ahc_patch8_func, 464, 118, 22 }, |
1211 | { ahc_patch0_func, 468, 5, 3 }, | 1211 | { ahc_patch1_func, 466, 3, 2 }, |
1212 | { ahc_patch9_func, 468, 2, 2 }, | 1212 | { ahc_patch0_func, 469, 5, 3 }, |
1213 | { ahc_patch0_func, 470, 3, 1 }, | 1213 | { ahc_patch9_func, 469, 2, 2 }, |
1214 | { ahc_patch1_func, 475, 2, 2 }, | 1214 | { ahc_patch0_func, 471, 3, 1 }, |
1215 | { ahc_patch0_func, 477, 6, 3 }, | 1215 | { ahc_patch1_func, 476, 2, 2 }, |
1216 | { ahc_patch9_func, 477, 2, 2 }, | 1216 | { ahc_patch0_func, 478, 6, 3 }, |
1217 | { ahc_patch0_func, 479, 3, 1 }, | 1217 | { ahc_patch9_func, 478, 2, 2 }, |
1218 | { ahc_patch1_func, 485, 2, 2 }, | 1218 | { ahc_patch0_func, 480, 3, 1 }, |
1219 | { ahc_patch0_func, 487, 9, 7 }, | 1219 | { ahc_patch1_func, 486, 2, 2 }, |
1220 | { ahc_patch9_func, 487, 5, 6 }, | 1220 | { ahc_patch0_func, 488, 9, 7 }, |
1221 | { ahc_patch19_func, 487, 1, 2 }, | 1221 | { ahc_patch9_func, 488, 5, 6 }, |
1222 | { ahc_patch0_func, 488, 1, 1 }, | 1222 | { ahc_patch19_func, 488, 1, 2 }, |
1223 | { ahc_patch19_func, 490, 1, 2 }, | 1223 | { ahc_patch0_func, 489, 1, 1 }, |
1224 | { ahc_patch0_func, 491, 1, 1 }, | 1224 | { ahc_patch19_func, 491, 1, 2 }, |
1225 | { ahc_patch0_func, 492, 4, 1 }, | 1225 | { ahc_patch0_func, 492, 1, 1 }, |
1226 | { ahc_patch6_func, 497, 3, 2 }, | 1226 | { ahc_patch0_func, 493, 4, 1 }, |
1227 | { ahc_patch0_func, 500, 1, 1 }, | 1227 | { ahc_patch6_func, 498, 3, 2 }, |
1228 | { ahc_patch6_func, 510, 1, 2 }, | 1228 | { ahc_patch0_func, 501, 1, 1 }, |
1229 | { ahc_patch0_func, 511, 1, 1 }, | 1229 | { ahc_patch6_func, 511, 1, 2 }, |
1230 | { ahc_patch20_func, 548, 7, 1 }, | 1230 | { ahc_patch0_func, 512, 1, 1 }, |
1231 | { ahc_patch3_func, 583, 1, 2 }, | 1231 | { ahc_patch20_func, 549, 7, 1 }, |
1232 | { ahc_patch0_func, 584, 1, 1 }, | 1232 | { ahc_patch3_func, 584, 1, 2 }, |
1233 | { ahc_patch21_func, 587, 1, 1 }, | 1233 | { ahc_patch0_func, 585, 1, 1 }, |
1234 | { ahc_patch8_func, 589, 106, 33 }, | 1234 | { ahc_patch21_func, 588, 1, 1 }, |
1235 | { ahc_patch4_func, 591, 1, 1 }, | 1235 | { ahc_patch8_func, 590, 106, 33 }, |
1236 | { ahc_patch1_func, 597, 2, 2 }, | 1236 | { ahc_patch4_func, 592, 1, 1 }, |
1237 | { ahc_patch0_func, 599, 1, 1 }, | 1237 | { ahc_patch1_func, 598, 2, 2 }, |
1238 | { ahc_patch1_func, 602, 1, 2 }, | 1238 | { ahc_patch0_func, 600, 1, 1 }, |
1239 | { ahc_patch0_func, 603, 1, 1 }, | 1239 | { ahc_patch1_func, 603, 1, 2 }, |
1240 | { ahc_patch9_func, 604, 3, 3 }, | 1240 | { ahc_patch0_func, 604, 1, 1 }, |
1241 | { ahc_patch15_func, 605, 1, 1 }, | 1241 | { ahc_patch9_func, 605, 3, 3 }, |
1242 | { ahc_patch0_func, 607, 4, 1 }, | 1242 | { ahc_patch15_func, 606, 1, 1 }, |
1243 | { ahc_patch19_func, 616, 2, 2 }, | 1243 | { ahc_patch0_func, 608, 4, 1 }, |
1244 | { ahc_patch0_func, 618, 1, 1 }, | 1244 | { ahc_patch19_func, 617, 2, 2 }, |
1245 | { ahc_patch19_func, 622, 10, 3 }, | 1245 | { ahc_patch0_func, 619, 1, 1 }, |
1246 | { ahc_patch5_func, 624, 8, 1 }, | 1246 | { ahc_patch19_func, 623, 10, 3 }, |
1247 | { ahc_patch0_func, 632, 9, 2 }, | 1247 | { ahc_patch5_func, 625, 8, 1 }, |
1248 | { ahc_patch5_func, 633, 8, 1 }, | 1248 | { ahc_patch0_func, 633, 9, 2 }, |
1249 | { ahc_patch4_func, 643, 1, 2 }, | 1249 | { ahc_patch5_func, 634, 8, 1 }, |
1250 | { ahc_patch0_func, 644, 1, 1 }, | 1250 | { ahc_patch4_func, 644, 1, 2 }, |
1251 | { ahc_patch19_func, 645, 1, 2 }, | 1251 | { ahc_patch0_func, 645, 1, 1 }, |
1252 | { ahc_patch0_func, 646, 3, 2 }, | 1252 | { ahc_patch19_func, 646, 1, 2 }, |
1253 | { ahc_patch4_func, 648, 1, 1 }, | 1253 | { ahc_patch0_func, 647, 3, 2 }, |
1254 | { ahc_patch5_func, 649, 1, 1 }, | 1254 | { ahc_patch4_func, 649, 1, 1 }, |
1255 | { ahc_patch5_func, 652, 1, 1 }, | 1255 | { ahc_patch5_func, 650, 1, 1 }, |
1256 | { ahc_patch5_func, 654, 1, 1 }, | 1256 | { ahc_patch5_func, 653, 1, 1 }, |
1257 | { ahc_patch4_func, 656, 2, 2 }, | 1257 | { ahc_patch5_func, 655, 1, 1 }, |
1258 | { ahc_patch0_func, 658, 2, 1 }, | 1258 | { ahc_patch4_func, 657, 2, 2 }, |
1259 | { ahc_patch5_func, 660, 1, 1 }, | 1259 | { ahc_patch0_func, 659, 2, 1 }, |
1260 | { ahc_patch5_func, 663, 1, 1 }, | 1260 | { ahc_patch5_func, 661, 1, 1 }, |
1261 | { ahc_patch5_func, 666, 1, 1 }, | 1261 | { ahc_patch5_func, 664, 1, 1 }, |
1262 | { ahc_patch19_func, 670, 1, 1 }, | 1262 | { ahc_patch5_func, 667, 1, 1 }, |
1263 | { ahc_patch19_func, 673, 1, 1 }, | 1263 | { ahc_patch19_func, 671, 1, 1 }, |
1264 | { ahc_patch4_func, 679, 1, 1 }, | 1264 | { ahc_patch19_func, 674, 1, 1 }, |
1265 | { ahc_patch6_func, 682, 1, 2 }, | 1265 | { ahc_patch4_func, 680, 1, 1 }, |
1266 | { ahc_patch0_func, 683, 1, 1 }, | 1266 | { ahc_patch6_func, 683, 1, 2 }, |
1267 | { ahc_patch7_func, 695, 16, 1 }, | 1267 | { ahc_patch0_func, 684, 1, 1 }, |
1268 | { ahc_patch4_func, 711, 20, 1 }, | 1268 | { ahc_patch7_func, 696, 16, 1 }, |
1269 | { ahc_patch9_func, 732, 4, 2 }, | 1269 | { ahc_patch4_func, 712, 20, 1 }, |
1270 | { ahc_patch0_func, 736, 4, 1 }, | 1270 | { ahc_patch9_func, 733, 4, 2 }, |
1271 | { ahc_patch9_func, 740, 4, 2 }, | 1271 | { ahc_patch0_func, 737, 4, 1 }, |
1272 | { ahc_patch0_func, 744, 3, 1 }, | 1272 | { ahc_patch9_func, 741, 4, 2 }, |
1273 | { ahc_patch6_func, 750, 1, 1 }, | 1273 | { ahc_patch0_func, 745, 3, 1 }, |
1274 | { ahc_patch22_func, 752, 14, 1 }, | 1274 | { ahc_patch6_func, 751, 1, 1 }, |
1275 | { ahc_patch7_func, 766, 3, 1 }, | 1275 | { ahc_patch22_func, 753, 14, 1 }, |
1276 | { ahc_patch9_func, 778, 24, 8 }, | 1276 | { ahc_patch7_func, 767, 3, 1 }, |
1277 | { ahc_patch19_func, 782, 1, 2 }, | 1277 | { ahc_patch9_func, 779, 24, 8 }, |
1278 | { ahc_patch0_func, 783, 1, 1 }, | 1278 | { ahc_patch19_func, 783, 1, 2 }, |
1279 | { ahc_patch15_func, 788, 4, 2 }, | 1279 | { ahc_patch0_func, 784, 1, 1 }, |
1280 | { ahc_patch0_func, 792, 7, 3 }, | 1280 | { ahc_patch15_func, 789, 4, 2 }, |
1281 | { ahc_patch23_func, 792, 5, 2 }, | 1281 | { ahc_patch0_func, 793, 7, 3 }, |
1282 | { ahc_patch0_func, 797, 2, 1 }, | 1282 | { ahc_patch23_func, 793, 5, 2 }, |
1283 | { ahc_patch0_func, 802, 42, 3 }, | 1283 | { ahc_patch0_func, 798, 2, 1 }, |
1284 | { ahc_patch18_func, 814, 18, 2 }, | 1284 | { ahc_patch0_func, 803, 42, 3 }, |
1285 | { ahc_patch0_func, 832, 1, 1 }, | 1285 | { ahc_patch18_func, 815, 18, 2 }, |
1286 | { ahc_patch4_func, 856, 1, 1 }, | 1286 | { ahc_patch0_func, 833, 1, 1 }, |
1287 | { ahc_patch4_func, 857, 3, 2 }, | 1287 | { ahc_patch4_func, 857, 1, 1 }, |
1288 | { ahc_patch0_func, 860, 1, 1 }, | 1288 | { ahc_patch4_func, 858, 3, 2 }, |
1289 | { ahc_patch13_func, 861, 3, 1 }, | 1289 | { ahc_patch0_func, 861, 1, 1 }, |
1290 | { ahc_patch4_func, 864, 12, 1 } | 1290 | { ahc_patch13_func, 862, 3, 1 }, |
1291 | { ahc_patch4_func, 865, 12, 1 } | ||
1291 | }; | 1292 | }; |
1292 | 1293 | ||
1293 | static struct cs { | 1294 | static struct cs { |
@@ -1296,11 +1297,11 @@ static struct cs { | |||
1296 | } critical_sections[] = { | 1297 | } critical_sections[] = { |
1297 | { 11, 18 }, | 1298 | { 11, 18 }, |
1298 | { 21, 30 }, | 1299 | { 21, 30 }, |
1299 | { 711, 727 }, | 1300 | { 712, 728 }, |
1300 | { 857, 860 }, | 1301 | { 858, 861 }, |
1301 | { 864, 870 }, | 1302 | { 865, 871 }, |
1302 | { 872, 874 }, | 1303 | { 873, 875 }, |
1303 | { 874, 876 } | 1304 | { 875, 877 } |
1304 | }; | 1305 | }; |
1305 | 1306 | ||
1306 | static const int num_critical_sections = sizeof(critical_sections) | 1307 | static const int num_critical_sections = sizeof(critical_sections) |
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c index 7c5a6db0e672..4d44a9211185 100644 --- a/drivers/scsi/aic7xxx/aiclib.c +++ b/drivers/scsi/aic7xxx/aiclib.c | |||
@@ -30,1162 +30,8 @@ | |||
30 | * $Id$ | 30 | * $Id$ |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/blkdev.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/version.h> | ||
36 | |||
37 | /* Core SCSI definitions */ | ||
38 | #include <scsi/scsi_host.h> | ||
39 | #include "aiclib.h" | 33 | #include "aiclib.h" |
40 | #include "cam.h" | ||
41 | |||
42 | #ifndef FALSE | ||
43 | #define FALSE 0 | ||
44 | #endif /* FALSE */ | ||
45 | #ifndef TRUE | ||
46 | #define TRUE 1 | ||
47 | #endif /* TRUE */ | ||
48 | #ifndef ERESTART | ||
49 | #define ERESTART -1 /* restart syscall */ | ||
50 | #endif | ||
51 | #ifndef EJUSTRETURN | ||
52 | #define EJUSTRETURN -2 /* don't modify regs, just return */ | ||
53 | #endif | ||
54 | |||
55 | static int ascentrycomp(const void *key, const void *member); | ||
56 | static int senseentrycomp(const void *key, const void *member); | ||
57 | static void fetchtableentries(int sense_key, int asc, int ascq, | ||
58 | struct scsi_inquiry_data *, | ||
59 | const struct sense_key_table_entry **, | ||
60 | const struct asc_table_entry **); | ||
61 | static void * scsibsearch(const void *key, const void *base, size_t nmemb, | ||
62 | size_t size, | ||
63 | int (*compar)(const void *, const void *)); | ||
64 | typedef int (cam_quirkmatch_t)(caddr_t, caddr_t); | ||
65 | static int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, | ||
66 | int str_len); | ||
67 | static caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, | ||
68 | int num_entries, int entry_size, | ||
69 | cam_quirkmatch_t *comp_func); | ||
70 | |||
71 | #define SCSI_NO_SENSE_STRINGS 1 | ||
72 | #if !defined(SCSI_NO_SENSE_STRINGS) | ||
73 | #define SST(asc, ascq, action, desc) \ | ||
74 | asc, ascq, action, desc | ||
75 | #else | ||
76 | static const char empty_string[] = ""; | ||
77 | |||
78 | #define SST(asc, ascq, action, desc) \ | ||
79 | asc, ascq, action, empty_string | ||
80 | #endif | ||
81 | |||
82 | static const struct sense_key_table_entry sense_key_table[] = | ||
83 | { | ||
84 | { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" }, | ||
85 | { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" }, | ||
86 | { | ||
87 | SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY, | ||
88 | "NOT READY" | ||
89 | }, | ||
90 | { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" }, | ||
91 | { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" }, | ||
92 | { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" }, | ||
93 | { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" }, | ||
94 | { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" }, | ||
95 | { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" }, | ||
96 | { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" }, | ||
97 | { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" }, | ||
98 | { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" }, | ||
99 | { SSD_KEY_EQUAL, SS_NOP, "EQUAL" }, | ||
100 | { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" }, | ||
101 | { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" }, | ||
102 | { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" } | ||
103 | }; | ||
104 | |||
105 | static const int sense_key_table_size = | ||
106 | sizeof(sense_key_table)/sizeof(sense_key_table[0]); | ||
107 | |||
108 | static struct asc_table_entry quantum_fireball_entries[] = { | ||
109 | {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO, | ||
110 | "Logical unit not ready, initializing cmd. required")} | ||
111 | }; | ||
112 | |||
113 | static struct asc_table_entry sony_mo_entries[] = { | ||
114 | {SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO, | ||
115 | "Logical unit not ready, cause not reportable")} | ||
116 | }; | ||
117 | |||
118 | static struct scsi_sense_quirk_entry sense_quirk_table[] = { | ||
119 | { | ||
120 | /* | ||
121 | * The Quantum Fireball ST and SE like to return 0x04 0x0b when | ||
122 | * they really should return 0x04 0x02. 0x04,0x0b isn't | ||
123 | * defined in any SCSI spec, and it isn't mentioned in the | ||
124 | * hardware manual for these drives. | ||
125 | */ | ||
126 | {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"}, | ||
127 | /*num_sense_keys*/0, | ||
128 | sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry), | ||
129 | /*sense key entries*/NULL, | ||
130 | quantum_fireball_entries | ||
131 | }, | ||
132 | { | ||
133 | /* | ||
134 | * This Sony MO drive likes to return 0x04, 0x00 when it | ||
135 | * isn't spun up. | ||
136 | */ | ||
137 | {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"}, | ||
138 | /*num_sense_keys*/0, | ||
139 | sizeof(sony_mo_entries)/sizeof(struct asc_table_entry), | ||
140 | /*sense key entries*/NULL, | ||
141 | sony_mo_entries | ||
142 | } | ||
143 | }; | ||
144 | |||
145 | static const int sense_quirk_table_size = | ||
146 | sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]); | ||
147 | |||
148 | static struct asc_table_entry asc_table[] = { | ||
149 | /* | ||
150 | * From File: ASC-NUM.TXT | ||
151 | * SCSI ASC/ASCQ Assignments | ||
152 | * Numeric Sorted Listing | ||
153 | * as of 5/12/97 | ||
154 | * | ||
155 | * D - DIRECT ACCESS DEVICE (SBC) device column key | ||
156 | * .T - SEQUENTIAL ACCESS DEVICE (SSC) ------------------- | ||
157 | * . L - PRINTER DEVICE (SSC) blank = reserved | ||
158 | * . P - PROCESSOR DEVICE (SPC) not blank = allowed | ||
159 | * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC) | ||
160 | * . . R - CD DEVICE (MMC) | ||
161 | * . . S - SCANNER DEVICE (SGC) | ||
162 | * . . .O - OPTICAL MEMORY DEVICE (SBC) | ||
163 | * . . . M - MEDIA CHANGER DEVICE (SMC) | ||
164 | * . . . C - COMMUNICATION DEVICE (SSC) | ||
165 | * . . . .A - STORAGE ARRAY DEVICE (SCC) | ||
166 | * . . . . E - ENCLOSURE SERVICES DEVICE (SES) | ||
167 | * DTLPWRSOMCAE ASC ASCQ Action Description | ||
168 | * ------------ ---- ---- ------ -----------------------------------*/ | ||
169 | /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP, | ||
170 | "No additional sense information") }, | ||
171 | /* T S */{SST(0x00, 0x01, SS_RDEF, | ||
172 | "Filemark detected") }, | ||
173 | /* T S */{SST(0x00, 0x02, SS_RDEF, | ||
174 | "End-of-partition/medium detected") }, | ||
175 | /* T */{SST(0x00, 0x03, SS_RDEF, | ||
176 | "Setmark detected") }, | ||
177 | /* T S */{SST(0x00, 0x04, SS_RDEF, | ||
178 | "Beginning-of-partition/medium detected") }, | ||
179 | /* T S */{SST(0x00, 0x05, SS_RDEF, | ||
180 | "End-of-data detected") }, | ||
181 | /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF, | ||
182 | "I/O process terminated") }, | ||
183 | /* R */{SST(0x00, 0x11, SS_FATAL|EBUSY, | ||
184 | "Audio play operation in progress") }, | ||
185 | /* R */{SST(0x00, 0x12, SS_NOP, | ||
186 | "Audio play operation paused") }, | ||
187 | /* R */{SST(0x00, 0x13, SS_NOP, | ||
188 | "Audio play operation successfully completed") }, | ||
189 | /* R */{SST(0x00, 0x14, SS_RDEF, | ||
190 | "Audio play operation stopped due to error") }, | ||
191 | /* R */{SST(0x00, 0x15, SS_NOP, | ||
192 | "No current audio status to return") }, | ||
193 | /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY, | ||
194 | "Operation in progress") }, | ||
195 | /* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF, | ||
196 | "Cleaning requested") }, | ||
197 | /* D W O */{SST(0x01, 0x00, SS_RDEF, | ||
198 | "No index/sector signal") }, | ||
199 | /* D WR OM */{SST(0x02, 0x00, SS_RDEF, | ||
200 | "No seek complete") }, | ||
201 | /* DTL W SO */{SST(0x03, 0x00, SS_RDEF, | ||
202 | "Peripheral device write fault") }, | ||
203 | /* T */{SST(0x03, 0x01, SS_RDEF, | ||
204 | "No write current") }, | ||
205 | /* T */{SST(0x03, 0x02, SS_RDEF, | ||
206 | "Excessive write errors") }, | ||
207 | /* DTLPWRSOMCAE */{SST(0x04, 0x00, | ||
208 | SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO, | ||
209 | "Logical unit not ready, cause not reportable") }, | ||
210 | /* DTLPWRSOMCAE */{SST(0x04, 0x01, | ||
211 | SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY, | ||
212 | "Logical unit is in process of becoming ready") }, | ||
213 | /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO, | ||
214 | "Logical unit not ready, initializing cmd. required") }, | ||
215 | /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO, | ||
216 | "Logical unit not ready, manual intervention required")}, | ||
217 | /* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY, | ||
218 | "Logical unit not ready, format in progress") }, | ||
219 | /* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY, | ||
220 | "Logical unit not ready, rebuild in progress") }, | ||
221 | /* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY, | ||
222 | "Logical unit not ready, recalculation in progress") }, | ||
223 | /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY, | ||
224 | "Logical unit not ready, operation in progress") }, | ||
225 | /* R */{SST(0x04, 0x08, SS_FATAL|EBUSY, | ||
226 | "Logical unit not ready, long write in progress") }, | ||
227 | /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF, | ||
228 | "Logical unit does not respond to selection") }, | ||
229 | /* D WR OM */{SST(0x06, 0x00, SS_RDEF, | ||
230 | "No reference position found") }, | ||
231 | /* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF, | ||
232 | "Multiple peripheral devices selected") }, | ||
233 | /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF, | ||
234 | "Logical unit communication failure") }, | ||
235 | /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF, | ||
236 | "Logical unit communication time-out") }, | ||
237 | /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF, | ||
238 | "Logical unit communication parity error") }, | ||
239 | /* DT R OM */{SST(0x08, 0x03, SS_RDEF, | ||
240 | "Logical unit communication crc error (ultra-dma/32)")}, | ||
241 | /* DT WR O */{SST(0x09, 0x00, SS_RDEF, | ||
242 | "Track following error") }, | ||
243 | /* WR O */{SST(0x09, 0x01, SS_RDEF, | ||
244 | "Tracking servo failure") }, | ||
245 | /* WR O */{SST(0x09, 0x02, SS_RDEF, | ||
246 | "Focus servo failure") }, | ||
247 | /* WR O */{SST(0x09, 0x03, SS_RDEF, | ||
248 | "Spindle servo failure") }, | ||
249 | /* DT WR O */{SST(0x09, 0x04, SS_RDEF, | ||
250 | "Head select fault") }, | ||
251 | /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC, | ||
252 | "Error log overflow") }, | ||
253 | /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF, | ||
254 | "Warning") }, | ||
255 | /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF, | ||
256 | "Specified temperature exceeded") }, | ||
257 | /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF, | ||
258 | "Enclosure degraded") }, | ||
259 | /* T RS */{SST(0x0C, 0x00, SS_RDEF, | ||
260 | "Write error") }, | ||
261 | /* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE, | ||
262 | "Write error - recovered with auto reallocation") }, | ||
263 | /* D W O */{SST(0x0C, 0x02, SS_RDEF, | ||
264 | "Write error - auto reallocation failed") }, | ||
265 | /* D W O */{SST(0x0C, 0x03, SS_RDEF, | ||
266 | "Write error - recommend reassignment") }, | ||
267 | /* DT W O */{SST(0x0C, 0x04, SS_RDEF, | ||
268 | "Compression check miscompare error") }, | ||
269 | /* DT W O */{SST(0x0C, 0x05, SS_RDEF, | ||
270 | "Data expansion occurred during compression") }, | ||
271 | /* DT W O */{SST(0x0C, 0x06, SS_RDEF, | ||
272 | "Block not compressible") }, | ||
273 | /* R */{SST(0x0C, 0x07, SS_RDEF, | ||
274 | "Write error - recovery needed") }, | ||
275 | /* R */{SST(0x0C, 0x08, SS_RDEF, | ||
276 | "Write error - recovery failed") }, | ||
277 | /* R */{SST(0x0C, 0x09, SS_RDEF, | ||
278 | "Write error - loss of streaming") }, | ||
279 | /* R */{SST(0x0C, 0x0A, SS_RDEF, | ||
280 | "Write error - padding blocks added") }, | ||
281 | /* D W O */{SST(0x10, 0x00, SS_RDEF, | ||
282 | "ID CRC or ECC error") }, | ||
283 | /* DT WRSO */{SST(0x11, 0x00, SS_RDEF, | ||
284 | "Unrecovered read error") }, | ||
285 | /* DT W SO */{SST(0x11, 0x01, SS_RDEF, | ||
286 | "Read retries exhausted") }, | ||
287 | /* DT W SO */{SST(0x11, 0x02, SS_RDEF, | ||
288 | "Error too long to correct") }, | ||
289 | /* DT W SO */{SST(0x11, 0x03, SS_RDEF, | ||
290 | "Multiple read errors") }, | ||
291 | /* D W O */{SST(0x11, 0x04, SS_RDEF, | ||
292 | "Unrecovered read error - auto reallocate failed") }, | ||
293 | /* WR O */{SST(0x11, 0x05, SS_RDEF, | ||
294 | "L-EC uncorrectable error") }, | ||
295 | /* WR O */{SST(0x11, 0x06, SS_RDEF, | ||
296 | "CIRC unrecovered error") }, | ||
297 | /* W O */{SST(0x11, 0x07, SS_RDEF, | ||
298 | "Data re-synchronization error") }, | ||
299 | /* T */{SST(0x11, 0x08, SS_RDEF, | ||
300 | "Incomplete block read") }, | ||
301 | /* T */{SST(0x11, 0x09, SS_RDEF, | ||
302 | "No gap found") }, | ||
303 | /* DT O */{SST(0x11, 0x0A, SS_RDEF, | ||
304 | "Miscorrected error") }, | ||
305 | /* D W O */{SST(0x11, 0x0B, SS_RDEF, | ||
306 | "Unrecovered read error - recommend reassignment") }, | ||
307 | /* D W O */{SST(0x11, 0x0C, SS_RDEF, | ||
308 | "Unrecovered read error - recommend rewrite the data")}, | ||
309 | /* DT WR O */{SST(0x11, 0x0D, SS_RDEF, | ||
310 | "De-compression CRC error") }, | ||
311 | /* DT WR O */{SST(0x11, 0x0E, SS_RDEF, | ||
312 | "Cannot decompress using declared algorithm") }, | ||
313 | /* R */{SST(0x11, 0x0F, SS_RDEF, | ||
314 | "Error reading UPC/EAN number") }, | ||
315 | /* R */{SST(0x11, 0x10, SS_RDEF, | ||
316 | "Error reading ISRC number") }, | ||
317 | /* R */{SST(0x11, 0x11, SS_RDEF, | ||
318 | "Read error - loss of streaming") }, | ||
319 | /* D W O */{SST(0x12, 0x00, SS_RDEF, | ||
320 | "Address mark not found for id field") }, | ||
321 | /* D W O */{SST(0x13, 0x00, SS_RDEF, | ||
322 | "Address mark not found for data field") }, | ||
323 | /* DTL WRSO */{SST(0x14, 0x00, SS_RDEF, | ||
324 | "Recorded entity not found") }, | ||
325 | /* DT WR O */{SST(0x14, 0x01, SS_RDEF, | ||
326 | "Record not found") }, | ||
327 | /* T */{SST(0x14, 0x02, SS_RDEF, | ||
328 | "Filemark or setmark not found") }, | ||
329 | /* T */{SST(0x14, 0x03, SS_RDEF, | ||
330 | "End-of-data not found") }, | ||
331 | /* T */{SST(0x14, 0x04, SS_RDEF, | ||
332 | "Block sequence error") }, | ||
333 | /* DT W O */{SST(0x14, 0x05, SS_RDEF, | ||
334 | "Record not found - recommend reassignment") }, | ||
335 | /* DT W O */{SST(0x14, 0x06, SS_RDEF, | ||
336 | "Record not found - data auto-reallocated") }, | ||
337 | /* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF, | ||
338 | "Random positioning error") }, | ||
339 | /* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF, | ||
340 | "Mechanical positioning error") }, | ||
341 | /* DT WR O */{SST(0x15, 0x02, SS_RDEF, | ||
342 | "Positioning error detected by read of medium") }, | ||
343 | /* D W O */{SST(0x16, 0x00, SS_RDEF, | ||
344 | "Data synchronization mark error") }, | ||
345 | /* D W O */{SST(0x16, 0x01, SS_RDEF, | ||
346 | "Data sync error - data rewritten") }, | ||
347 | /* D W O */{SST(0x16, 0x02, SS_RDEF, | ||
348 | "Data sync error - recommend rewrite") }, | ||
349 | /* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE, | ||
350 | "Data sync error - data auto-reallocated") }, | ||
351 | /* D W O */{SST(0x16, 0x04, SS_RDEF, | ||
352 | "Data sync error - recommend reassignment") }, | ||
353 | /* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE, | ||
354 | "Recovered data with no error correction applied") }, | ||
355 | /* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE, | ||
356 | "Recovered data with retries") }, | ||
357 | /* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE, | ||
358 | "Recovered data with positive head offset") }, | ||
359 | /* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE, | ||
360 | "Recovered data with negative head offset") }, | ||
361 | /* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE, | ||
362 | "Recovered data with retries and/or CIRC applied") }, | ||
363 | /* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE, | ||
364 | "Recovered data using previous sector id") }, | ||
365 | /* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE, | ||
366 | "Recovered data without ECC - data auto-reallocated") }, | ||
367 | /* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE, | ||
368 | "Recovered data without ECC - recommend reassignment")}, | ||
369 | /* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE, | ||
370 | "Recovered data without ECC - recommend rewrite") }, | ||
371 | /* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE, | ||
372 | "Recovered data without ECC - data rewritten") }, | ||
373 | /* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE, | ||
374 | "Recovered data with error correction applied") }, | ||
375 | /* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE, | ||
376 | "Recovered data with error corr. & retries applied") }, | ||
377 | /* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE, | ||
378 | "Recovered data - data auto-reallocated") }, | ||
379 | /* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE, | ||
380 | "Recovered data with CIRC") }, | ||
381 | /* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE, | ||
382 | "Recovered data with L-EC") }, | ||
383 | /* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE, | ||
384 | "Recovered data - recommend reassignment") }, | ||
385 | /* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE, | ||
386 | "Recovered data - recommend rewrite") }, | ||
387 | /* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE, | ||
388 | "Recovered data with ECC - data rewritten") }, | ||
389 | /* D O */{SST(0x19, 0x00, SS_RDEF, | ||
390 | "Defect list error") }, | ||
391 | /* D O */{SST(0x19, 0x01, SS_RDEF, | ||
392 | "Defect list not available") }, | ||
393 | /* D O */{SST(0x19, 0x02, SS_RDEF, | ||
394 | "Defect list error in primary list") }, | ||
395 | /* D O */{SST(0x19, 0x03, SS_RDEF, | ||
396 | "Defect list error in grown list") }, | ||
397 | /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF, | ||
398 | "Parameter list length error") }, | ||
399 | /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF, | ||
400 | "Synchronous data transfer error") }, | ||
401 | /* D O */{SST(0x1C, 0x00, SS_RDEF, | ||
402 | "Defect list not found") }, | ||
403 | /* D O */{SST(0x1C, 0x01, SS_RDEF, | ||
404 | "Primary defect list not found") }, | ||
405 | /* D O */{SST(0x1C, 0x02, SS_RDEF, | ||
406 | "Grown defect list not found") }, | ||
407 | /* D W O */{SST(0x1D, 0x00, SS_FATAL, | ||
408 | "Miscompare during verify operation" )}, | ||
409 | /* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE, | ||
410 | "Recovered id with ecc correction") }, | ||
411 | /* D O */{SST(0x1F, 0x00, SS_RDEF, | ||
412 | "Partial defect list transfer") }, | ||
413 | /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL, | ||
414 | "Invalid command operation code") }, | ||
415 | /* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL, | ||
416 | "Logical block address out of range" )}, | ||
417 | /* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL, | ||
418 | "Invalid element address") }, | ||
419 | /* D */{SST(0x22, 0x00, SS_FATAL|EINVAL, | ||
420 | "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */ | ||
421 | /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL, | ||
422 | "Invalid field in CDB") }, | ||
423 | /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO, | ||
424 | "Logical unit not supported") }, | ||
425 | /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL, | ||
426 | "Invalid field in parameter list") }, | ||
427 | /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL, | ||
428 | "Parameter not supported") }, | ||
429 | /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL, | ||
430 | "Parameter value invalid") }, | ||
431 | /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL, | ||
432 | "Threshold parameters not supported") }, | ||
433 | /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL, | ||
434 | "Invalid release of active persistent reservation") }, | ||
435 | /* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES, | ||
436 | "Write protected") }, | ||
437 | /* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES, | ||
438 | "Hardware write protected") }, | ||
439 | /* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES, | ||
440 | "Logical unit software write protected") }, | ||
441 | /* T */{SST(0x27, 0x03, SS_FATAL|EACCES, | ||
442 | "Associated write protect") }, | ||
443 | /* T */{SST(0x27, 0x04, SS_FATAL|EACCES, | ||
444 | "Persistent write protect") }, | ||
445 | /* T */{SST(0x27, 0x05, SS_FATAL|EACCES, | ||
446 | "Permanent write protect") }, | ||
447 | /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_RDEF, | ||
448 | "Not ready to ready change, medium may have changed") }, | ||
449 | /* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO, | ||
450 | "Import or export element accessed") }, | ||
451 | /* | ||
452 | * XXX JGibbs - All of these should use the same errno, but I don't think | ||
453 | * ENXIO is the correct choice. Should we borrow from the networking | ||
454 | * errnos? ECONNRESET anyone? | ||
455 | */ | ||
456 | /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_RDEF, | ||
457 | "Power on, reset, or bus device reset occurred") }, | ||
458 | /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF, | ||
459 | "Power on occurred") }, | ||
460 | /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF, | ||
461 | "Scsi bus reset occurred") }, | ||
462 | /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF, | ||
463 | "Bus device reset function occurred") }, | ||
464 | /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF, | ||
465 | "Device internal reset") }, | ||
466 | /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF, | ||
467 | "Transceiver mode changed to single-ended") }, | ||
468 | /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF, | ||
469 | "Transceiver mode changed to LVD") }, | ||
470 | /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF, | ||
471 | "Parameters changed") }, | ||
472 | /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF, | ||
473 | "Mode parameters changed") }, | ||
474 | /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF, | ||
475 | "Log parameters changed") }, | ||
476 | /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF, | ||
477 | "Reservations preempted") }, | ||
478 | /* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF, | ||
479 | "Copy cannot execute since host cannot disconnect") }, | ||
480 | /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF, | ||
481 | "Command sequence error") }, | ||
482 | /* S */{SST(0x2C, 0x01, SS_RDEF, | ||
483 | "Too many windows specified") }, | ||
484 | /* S */{SST(0x2C, 0x02, SS_RDEF, | ||
485 | "Invalid combination of windows specified") }, | ||
486 | /* R */{SST(0x2C, 0x03, SS_RDEF, | ||
487 | "Current program area is not empty") }, | ||
488 | /* R */{SST(0x2C, 0x04, SS_RDEF, | ||
489 | "Current program area is empty") }, | ||
490 | /* T */{SST(0x2D, 0x00, SS_RDEF, | ||
491 | "Overwrite error on update in place") }, | ||
492 | /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF, | ||
493 | "Commands cleared by another initiator") }, | ||
494 | /* DT WR OM */{SST(0x30, 0x00, SS_RDEF, | ||
495 | "Incompatible medium installed") }, | ||
496 | /* DT WR O */{SST(0x30, 0x01, SS_RDEF, | ||
497 | "Cannot read medium - unknown format") }, | ||
498 | /* DT WR O */{SST(0x30, 0x02, SS_RDEF, | ||
499 | "Cannot read medium - incompatible format") }, | ||
500 | /* DT */{SST(0x30, 0x03, SS_RDEF, | ||
501 | "Cleaning cartridge installed") }, | ||
502 | /* DT WR O */{SST(0x30, 0x04, SS_RDEF, | ||
503 | "Cannot write medium - unknown format") }, | ||
504 | /* DT WR O */{SST(0x30, 0x05, SS_RDEF, | ||
505 | "Cannot write medium - incompatible format") }, | ||
506 | /* DT W O */{SST(0x30, 0x06, SS_RDEF, | ||
507 | "Cannot format medium - incompatible medium") }, | ||
508 | /* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF, | ||
509 | "Cleaning failure") }, | ||
510 | /* R */{SST(0x30, 0x08, SS_RDEF, | ||
511 | "Cannot write - application code mismatch") }, | ||
512 | /* R */{SST(0x30, 0x09, SS_RDEF, | ||
513 | "Current session not fixated for append") }, | ||
514 | /* DT WR O */{SST(0x31, 0x00, SS_RDEF, | ||
515 | "Medium format corrupted") }, | ||
516 | /* D L R O */{SST(0x31, 0x01, SS_RDEF, | ||
517 | "Format command failed") }, | ||
518 | /* D W O */{SST(0x32, 0x00, SS_RDEF, | ||
519 | "No defect spare location available") }, | ||
520 | /* D W O */{SST(0x32, 0x01, SS_RDEF, | ||
521 | "Defect list update failure") }, | ||
522 | /* T */{SST(0x33, 0x00, SS_RDEF, | ||
523 | "Tape length error") }, | ||
524 | /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF, | ||
525 | "Enclosure failure") }, | ||
526 | /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF, | ||
527 | "Enclosure services failure") }, | ||
528 | /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF, | ||
529 | "Unsupported enclosure function") }, | ||
530 | /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF, | ||
531 | "Enclosure services unavailable") }, | ||
532 | /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF, | ||
533 | "Enclosure services transfer failure") }, | ||
534 | /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF, | ||
535 | "Enclosure services transfer refused") }, | ||
536 | /* L */{SST(0x36, 0x00, SS_RDEF, | ||
537 | "Ribbon, ink, or toner failure") }, | ||
538 | /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF, | ||
539 | "Rounded parameter") }, | ||
540 | /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF, | ||
541 | "Saving parameters not supported") }, | ||
542 | /* DTL WRSOM */{SST(0x3A, 0x00, SS_NOP, | ||
543 | "Medium not present") }, | ||
544 | /* DT WR OM */{SST(0x3A, 0x01, SS_NOP, | ||
545 | "Medium not present - tray closed") }, | ||
546 | /* DT WR OM */{SST(0x3A, 0x01, SS_NOP, | ||
547 | "Medium not present - tray open") }, | ||
548 | /* DT WR OM */{SST(0x3A, 0x03, SS_NOP, | ||
549 | "Medium not present - Loadable") }, | ||
550 | /* DT WR OM */{SST(0x3A, 0x04, SS_NOP, | ||
551 | "Medium not present - medium auxiliary " | ||
552 | "memory accessible") }, | ||
553 | /* DT WR OM */{SST(0x3A, 0xFF, SS_NOP, NULL) },/* Range 0x05->0xFF */ | ||
554 | /* TL */{SST(0x3B, 0x00, SS_RDEF, | ||
555 | "Sequential positioning error") }, | ||
556 | /* T */{SST(0x3B, 0x01, SS_RDEF, | ||
557 | "Tape position error at beginning-of-medium") }, | ||
558 | /* T */{SST(0x3B, 0x02, SS_RDEF, | ||
559 | "Tape position error at end-of-medium") }, | ||
560 | /* L */{SST(0x3B, 0x03, SS_RDEF, | ||
561 | "Tape or electronic vertical forms unit not ready") }, | ||
562 | /* L */{SST(0x3B, 0x04, SS_RDEF, | ||
563 | "Slew failure") }, | ||
564 | /* L */{SST(0x3B, 0x05, SS_RDEF, | ||
565 | "Paper jam") }, | ||
566 | /* L */{SST(0x3B, 0x06, SS_RDEF, | ||
567 | "Failed to sense top-of-form") }, | ||
568 | /* L */{SST(0x3B, 0x07, SS_RDEF, | ||
569 | "Failed to sense bottom-of-form") }, | ||
570 | /* T */{SST(0x3B, 0x08, SS_RDEF, | ||
571 | "Reposition error") }, | ||
572 | /* S */{SST(0x3B, 0x09, SS_RDEF, | ||
573 | "Read past end of medium") }, | ||
574 | /* S */{SST(0x3B, 0x0A, SS_RDEF, | ||
575 | "Read past beginning of medium") }, | ||
576 | /* S */{SST(0x3B, 0x0B, SS_RDEF, | ||
577 | "Position past end of medium") }, | ||
578 | /* T S */{SST(0x3B, 0x0C, SS_RDEF, | ||
579 | "Position past beginning of medium") }, | ||
580 | /* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC, | ||
581 | "Medium destination element full") }, | ||
582 | /* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF, | ||
583 | "Medium source element empty") }, | ||
584 | /* R */{SST(0x3B, 0x0F, SS_RDEF, | ||
585 | "End of medium reached") }, | ||
586 | /* DT WR OM */{SST(0x3B, 0x11, SS_RDEF, | ||
587 | "Medium magazine not accessible") }, | ||
588 | /* DT WR OM */{SST(0x3B, 0x12, SS_RDEF, | ||
589 | "Medium magazine removed") }, | ||
590 | /* DT WR OM */{SST(0x3B, 0x13, SS_RDEF, | ||
591 | "Medium magazine inserted") }, | ||
592 | /* DT WR OM */{SST(0x3B, 0x14, SS_RDEF, | ||
593 | "Medium magazine locked") }, | ||
594 | /* DT WR OM */{SST(0x3B, 0x15, SS_RDEF, | ||
595 | "Medium magazine unlocked") }, | ||
596 | /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF, | ||
597 | "Invalid bits in identify message") }, | ||
598 | /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF, | ||
599 | "Logical unit has not self-configured yet") }, | ||
600 | /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF, | ||
601 | "Logical unit failure") }, | ||
602 | /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF, | ||
603 | "Timeout on logical unit") }, | ||
604 | /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF, | ||
605 | "Target operating conditions have changed") }, | ||
606 | /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF, | ||
607 | "Microcode has been changed") }, | ||
608 | /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF, | ||
609 | "Changed operating definition") }, | ||
610 | /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_INQ_REFRESH|SSQ_DECREMENT_COUNT, | ||
611 | "Inquiry data has changed") }, | ||
612 | /* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF, | ||
613 | "Component device attached") }, | ||
614 | /* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF, | ||
615 | "Device identifier changed") }, | ||
616 | /* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF, | ||
617 | "Redundancy group created or modified") }, | ||
618 | /* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF, | ||
619 | "Redundancy group deleted") }, | ||
620 | /* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF, | ||
621 | "Spare created or modified") }, | ||
622 | /* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF, | ||
623 | "Spare deleted") }, | ||
624 | /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF, | ||
625 | "Volume set created or modified") }, | ||
626 | /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF, | ||
627 | "Volume set deleted") }, | ||
628 | /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF, | ||
629 | "Volume set deassigned") }, | ||
630 | /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF, | ||
631 | "Volume set reassigned") }, | ||
632 | /* DTLPWRSOMCAE */{SST(0x3F, 0x0E, SS_RDEF, | ||
633 | "Reported luns data has changed") }, | ||
634 | /* DTLPWRSOMCAE */{SST(0x3F, 0x0F, SS_RETRY|SSQ_DECREMENT_COUNT | ||
635 | | SSQ_DELAY_RANDOM|EBUSY, | ||
636 | "Echo buffer overwritten") }, | ||
637 | /* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF, "Medium Loadable") }, | ||
638 | /* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF, | ||
639 | "Medium auxiliary memory accessible") }, | ||
640 | /* D */{SST(0x40, 0x00, SS_RDEF, | ||
641 | "Ram failure") }, /* deprecated - use 40 NN instead */ | ||
642 | /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF, | ||
643 | "Diagnostic failure: ASCQ = Component ID") }, | ||
644 | /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE, | ||
645 | NULL) },/* Range 0x80->0xFF */ | ||
646 | /* D */{SST(0x41, 0x00, SS_RDEF, | ||
647 | "Data path failure") }, /* deprecated - use 40 NN instead */ | ||
648 | /* D */{SST(0x42, 0x00, SS_RDEF, | ||
649 | "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */ | ||
650 | /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF, | ||
651 | "Message error") }, | ||
652 | /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF, | ||
653 | "Internal target failure") }, | ||
654 | /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF, | ||
655 | "Select or reselect failure") }, | ||
656 | /* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF, | ||
657 | "Unsuccessful soft reset") }, | ||
658 | /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF|SSQ_FALLBACK, | ||
659 | "SCSI parity error") }, | ||
660 | /* DTLPWRSOMCAE */{SST(0x47, 0x01, SS_RDEF|SSQ_FALLBACK, | ||
661 | "Data Phase CRC error detected") }, | ||
662 | /* DTLPWRSOMCAE */{SST(0x47, 0x02, SS_RDEF|SSQ_FALLBACK, | ||
663 | "SCSI parity error detected during ST data phase") }, | ||
664 | /* DTLPWRSOMCAE */{SST(0x47, 0x03, SS_RDEF|SSQ_FALLBACK, | ||
665 | "Information Unit iuCRC error") }, | ||
666 | /* DTLPWRSOMCAE */{SST(0x47, 0x04, SS_RDEF|SSQ_FALLBACK, | ||
667 | "Asynchronous information protection error detected") }, | ||
668 | /* DTLPWRSOMCAE */{SST(0x47, 0x05, SS_RDEF|SSQ_FALLBACK, | ||
669 | "Protocol server CRC error") }, | ||
670 | /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF|SSQ_FALLBACK, | ||
671 | "Initiator detected error message received") }, | ||
672 | /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF, | ||
673 | "Invalid message error") }, | ||
674 | /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF, | ||
675 | "Command phase error") }, | ||
676 | /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF, | ||
677 | "Data phase error") }, | ||
678 | /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF, | ||
679 | "Logical unit failed self-configuration") }, | ||
680 | /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF, | ||
681 | "Tagged overlapped commands: ASCQ = Queue tag ID") }, | ||
682 | /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE, | ||
683 | NULL)}, /* Range 0x00->0xFF */ | ||
684 | /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF, | ||
685 | "Overlapped commands attempted") }, | ||
686 | /* T */{SST(0x50, 0x00, SS_RDEF, | ||
687 | "Write append error") }, | ||
688 | /* T */{SST(0x50, 0x01, SS_RDEF, | ||
689 | "Write append position error") }, | ||
690 | /* T */{SST(0x50, 0x02, SS_RDEF, | ||
691 | "Position error related to timing") }, | ||
692 | /* T O */{SST(0x51, 0x00, SS_RDEF, | ||
693 | "Erase failure") }, | ||
694 | /* T */{SST(0x52, 0x00, SS_RDEF, | ||
695 | "Cartridge fault") }, | ||
696 | /* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF, | ||
697 | "Media load or eject failed") }, | ||
698 | /* T */{SST(0x53, 0x01, SS_RDEF, | ||
699 | "Unload tape failure") }, | ||
700 | /* DT WR OM */{SST(0x53, 0x02, SS_RDEF, | ||
701 | "Medium removal prevented") }, | ||
702 | /* P */{SST(0x54, 0x00, SS_RDEF, | ||
703 | "Scsi to host system interface failure") }, | ||
704 | /* P */{SST(0x55, 0x00, SS_RDEF, | ||
705 | "System resource failure") }, | ||
706 | /* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC, | ||
707 | "System buffer full") }, | ||
708 | /* R */{SST(0x57, 0x00, SS_RDEF, | ||
709 | "Unable to recover table-of-contents") }, | ||
710 | /* O */{SST(0x58, 0x00, SS_RDEF, | ||
711 | "Generation does not exist") }, | ||
712 | /* O */{SST(0x59, 0x00, SS_RDEF, | ||
713 | "Updated block read") }, | ||
714 | /* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF, | ||
715 | "Operator request or state change input") }, | ||
716 | /* DT WR OM */{SST(0x5A, 0x01, SS_RDEF, | ||
717 | "Operator medium removal request") }, | ||
718 | /* DT W O */{SST(0x5A, 0x02, SS_RDEF, | ||
719 | "Operator selected write protect") }, | ||
720 | /* DT W O */{SST(0x5A, 0x03, SS_RDEF, | ||
721 | "Operator selected write permit") }, | ||
722 | /* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF, | ||
723 | "Log exception") }, | ||
724 | /* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF, | ||
725 | "Threshold condition met") }, | ||
726 | /* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF, | ||
727 | "Log counter at maximum") }, | ||
728 | /* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF, | ||
729 | "Log list codes exhausted") }, | ||
730 | /* D O */{SST(0x5C, 0x00, SS_RDEF, | ||
731 | "RPL status change") }, | ||
732 | /* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE, | ||
733 | "Spindles synchronized") }, | ||
734 | /* D O */{SST(0x5C, 0x02, SS_RDEF, | ||
735 | "Spindles not synchronized") }, | ||
736 | /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF, | ||
737 | "Failure prediction threshold exceeded") }, | ||
738 | /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF, | ||
739 | "Failure prediction threshold exceeded (false)") }, | ||
740 | /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF, | ||
741 | "Low power condition on") }, | ||
742 | /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF, | ||
743 | "Idle condition activated by timer") }, | ||
744 | /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF, | ||
745 | "Standby condition activated by timer") }, | ||
746 | /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF, | ||
747 | "Idle condition activated by command") }, | ||
748 | /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF, | ||
749 | "Standby condition activated by command") }, | ||
750 | /* S */{SST(0x60, 0x00, SS_RDEF, | ||
751 | "Lamp failure") }, | ||
752 | /* S */{SST(0x61, 0x00, SS_RDEF, | ||
753 | "Video acquisition error") }, | ||
754 | /* S */{SST(0x61, 0x01, SS_RDEF, | ||
755 | "Unable to acquire video") }, | ||
756 | /* S */{SST(0x61, 0x02, SS_RDEF, | ||
757 | "Out of focus") }, | ||
758 | /* S */{SST(0x62, 0x00, SS_RDEF, | ||
759 | "Scan head positioning error") }, | ||
760 | /* R */{SST(0x63, 0x00, SS_RDEF, | ||
761 | "End of user area encountered on this track") }, | ||
762 | /* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC, | ||
763 | "Packet does not fit in available space") }, | ||
764 | /* R */{SST(0x64, 0x00, SS_RDEF, | ||
765 | "Illegal mode for this track") }, | ||
766 | /* R */{SST(0x64, 0x01, SS_RDEF, | ||
767 | "Invalid packet size") }, | ||
768 | /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF, | ||
769 | "Voltage fault") }, | ||
770 | /* S */{SST(0x66, 0x00, SS_RDEF, | ||
771 | "Automatic document feeder cover up") }, | ||
772 | /* S */{SST(0x66, 0x01, SS_RDEF, | ||
773 | "Automatic document feeder lift up") }, | ||
774 | /* S */{SST(0x66, 0x02, SS_RDEF, | ||
775 | "Document jam in automatic document feeder") }, | ||
776 | /* S */{SST(0x66, 0x03, SS_RDEF, | ||
777 | "Document miss feed automatic in document feeder") }, | ||
778 | /* A */{SST(0x67, 0x00, SS_RDEF, | ||
779 | "Configuration failure") }, | ||
780 | /* A */{SST(0x67, 0x01, SS_RDEF, | ||
781 | "Configuration of incapable logical units failed") }, | ||
782 | /* A */{SST(0x67, 0x02, SS_RDEF, | ||
783 | "Add logical unit failed") }, | ||
784 | /* A */{SST(0x67, 0x03, SS_RDEF, | ||
785 | "Modification of logical unit failed") }, | ||
786 | /* A */{SST(0x67, 0x04, SS_RDEF, | ||
787 | "Exchange of logical unit failed") }, | ||
788 | /* A */{SST(0x67, 0x05, SS_RDEF, | ||
789 | "Remove of logical unit failed") }, | ||
790 | /* A */{SST(0x67, 0x06, SS_RDEF, | ||
791 | "Attachment of logical unit failed") }, | ||
792 | /* A */{SST(0x67, 0x07, SS_RDEF, | ||
793 | "Creation of logical unit failed") }, | ||
794 | /* A */{SST(0x68, 0x00, SS_RDEF, | ||
795 | "Logical unit not configured") }, | ||
796 | /* A */{SST(0x69, 0x00, SS_RDEF, | ||
797 | "Data loss on logical unit") }, | ||
798 | /* A */{SST(0x69, 0x01, SS_RDEF, | ||
799 | "Multiple logical unit failures") }, | ||
800 | /* A */{SST(0x69, 0x02, SS_RDEF, | ||
801 | "Parity/data mismatch") }, | ||
802 | /* A */{SST(0x6A, 0x00, SS_RDEF, | ||
803 | "Informational, refer to log") }, | ||
804 | /* A */{SST(0x6B, 0x00, SS_RDEF, | ||
805 | "State change has occurred") }, | ||
806 | /* A */{SST(0x6B, 0x01, SS_RDEF, | ||
807 | "Redundancy level got better") }, | ||
808 | /* A */{SST(0x6B, 0x02, SS_RDEF, | ||
809 | "Redundancy level got worse") }, | ||
810 | /* A */{SST(0x6C, 0x00, SS_RDEF, | ||
811 | "Rebuild failure occurred") }, | ||
812 | /* A */{SST(0x6D, 0x00, SS_RDEF, | ||
813 | "Recalculate failure occurred") }, | ||
814 | /* A */{SST(0x6E, 0x00, SS_RDEF, | ||
815 | "Command to logical unit failed") }, | ||
816 | /* T */{SST(0x70, 0x00, SS_RDEF, | ||
817 | "Decompression exception short: ASCQ = Algorithm ID") }, | ||
818 | /* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE, | ||
819 | NULL) }, /* Range 0x00 -> 0xFF */ | ||
820 | /* T */{SST(0x71, 0x00, SS_RDEF, | ||
821 | "Decompression exception long: ASCQ = Algorithm ID") }, | ||
822 | /* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE, | ||
823 | NULL) }, /* Range 0x00 -> 0xFF */ | ||
824 | /* R */{SST(0x72, 0x00, SS_RDEF, | ||
825 | "Session fixation error") }, | ||
826 | /* R */{SST(0x72, 0x01, SS_RDEF, | ||
827 | "Session fixation error writing lead-in") }, | ||
828 | /* R */{SST(0x72, 0x02, SS_RDEF, | ||
829 | "Session fixation error writing lead-out") }, | ||
830 | /* R */{SST(0x72, 0x03, SS_RDEF, | ||
831 | "Session fixation error - incomplete track in session") }, | ||
832 | /* R */{SST(0x72, 0x04, SS_RDEF, | ||
833 | "Empty or partially written reserved track") }, | ||
834 | /* R */{SST(0x73, 0x00, SS_RDEF, | ||
835 | "CD control error") }, | ||
836 | /* R */{SST(0x73, 0x01, SS_RDEF, | ||
837 | "Power calibration area almost full") }, | ||
838 | /* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC, | ||
839 | "Power calibration area is full") }, | ||
840 | /* R */{SST(0x73, 0x03, SS_RDEF, | ||
841 | "Power calibration area error") }, | ||
842 | /* R */{SST(0x73, 0x04, SS_RDEF, | ||
843 | "Program memory area update failure") }, | ||
844 | /* R */{SST(0x73, 0x05, SS_RDEF, | ||
845 | "program memory area is full") } | ||
846 | }; | ||
847 | |||
848 | static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]); | ||
849 | |||
850 | struct asc_key | ||
851 | { | ||
852 | int asc; | ||
853 | int ascq; | ||
854 | }; | ||
855 | |||
856 | static int | ||
857 | ascentrycomp(const void *key, const void *member) | ||
858 | { | ||
859 | int asc; | ||
860 | int ascq; | ||
861 | const struct asc_table_entry *table_entry; | ||
862 | |||
863 | asc = ((const struct asc_key *)key)->asc; | ||
864 | ascq = ((const struct asc_key *)key)->ascq; | ||
865 | table_entry = (const struct asc_table_entry *)member; | ||
866 | |||
867 | if (asc >= table_entry->asc) { | ||
868 | |||
869 | if (asc > table_entry->asc) | ||
870 | return (1); | ||
871 | |||
872 | if (ascq <= table_entry->ascq) { | ||
873 | /* Check for ranges */ | ||
874 | if (ascq == table_entry->ascq | ||
875 | || ((table_entry->action & SSQ_RANGE) != 0 | ||
876 | && ascq >= (table_entry - 1)->ascq)) | ||
877 | return (0); | ||
878 | return (-1); | ||
879 | } | ||
880 | return (1); | ||
881 | } | ||
882 | return (-1); | ||
883 | } | ||
884 | |||
885 | static int | ||
886 | senseentrycomp(const void *key, const void *member) | ||
887 | { | ||
888 | int sense_key; | ||
889 | const struct sense_key_table_entry *table_entry; | ||
890 | |||
891 | sense_key = *((const int *)key); | ||
892 | table_entry = (const struct sense_key_table_entry *)member; | ||
893 | |||
894 | if (sense_key >= table_entry->sense_key) { | ||
895 | if (sense_key == table_entry->sense_key) | ||
896 | return (0); | ||
897 | return (1); | ||
898 | } | ||
899 | return (-1); | ||
900 | } | ||
901 | |||
902 | static void | ||
903 | fetchtableentries(int sense_key, int asc, int ascq, | ||
904 | struct scsi_inquiry_data *inq_data, | ||
905 | const struct sense_key_table_entry **sense_entry, | ||
906 | const struct asc_table_entry **asc_entry) | ||
907 | { | ||
908 | void *match; | ||
909 | const struct asc_table_entry *asc_tables[2]; | ||
910 | const struct sense_key_table_entry *sense_tables[2]; | ||
911 | struct asc_key asc_ascq; | ||
912 | size_t asc_tables_size[2]; | ||
913 | size_t sense_tables_size[2]; | ||
914 | int num_asc_tables; | ||
915 | int num_sense_tables; | ||
916 | int i; | ||
917 | |||
918 | /* Default to failure */ | ||
919 | *sense_entry = NULL; | ||
920 | *asc_entry = NULL; | ||
921 | match = NULL; | ||
922 | if (inq_data != NULL) | ||
923 | match = cam_quirkmatch((void *)inq_data, | ||
924 | (void *)sense_quirk_table, | ||
925 | sense_quirk_table_size, | ||
926 | sizeof(*sense_quirk_table), | ||
927 | aic_inquiry_match); | ||
928 | |||
929 | if (match != NULL) { | ||
930 | struct scsi_sense_quirk_entry *quirk; | ||
931 | |||
932 | quirk = (struct scsi_sense_quirk_entry *)match; | ||
933 | asc_tables[0] = quirk->asc_info; | ||
934 | asc_tables_size[0] = quirk->num_ascs; | ||
935 | asc_tables[1] = asc_table; | ||
936 | asc_tables_size[1] = asc_table_size; | ||
937 | num_asc_tables = 2; | ||
938 | sense_tables[0] = quirk->sense_key_info; | ||
939 | sense_tables_size[0] = quirk->num_sense_keys; | ||
940 | sense_tables[1] = sense_key_table; | ||
941 | sense_tables_size[1] = sense_key_table_size; | ||
942 | num_sense_tables = 2; | ||
943 | } else { | ||
944 | asc_tables[0] = asc_table; | ||
945 | asc_tables_size[0] = asc_table_size; | ||
946 | num_asc_tables = 1; | ||
947 | sense_tables[0] = sense_key_table; | ||
948 | sense_tables_size[0] = sense_key_table_size; | ||
949 | num_sense_tables = 1; | ||
950 | } | ||
951 | |||
952 | asc_ascq.asc = asc; | ||
953 | asc_ascq.ascq = ascq; | ||
954 | for (i = 0; i < num_asc_tables; i++) { | ||
955 | void *found_entry; | ||
956 | |||
957 | found_entry = scsibsearch(&asc_ascq, asc_tables[i], | ||
958 | asc_tables_size[i], | ||
959 | sizeof(**asc_tables), | ||
960 | ascentrycomp); | ||
961 | |||
962 | if (found_entry) { | ||
963 | *asc_entry = (struct asc_table_entry *)found_entry; | ||
964 | break; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | for (i = 0; i < num_sense_tables; i++) { | ||
969 | void *found_entry; | ||
970 | |||
971 | found_entry = scsibsearch(&sense_key, sense_tables[i], | ||
972 | sense_tables_size[i], | ||
973 | sizeof(**sense_tables), | ||
974 | senseentrycomp); | ||
975 | |||
976 | if (found_entry) { | ||
977 | *sense_entry = | ||
978 | (struct sense_key_table_entry *)found_entry; | ||
979 | break; | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | |||
984 | static void * | ||
985 | scsibsearch(const void *key, const void *base, size_t nmemb, size_t size, | ||
986 | int (*compar)(const void *, const void *)) | ||
987 | { | ||
988 | const void *entry; | ||
989 | u_int l; | ||
990 | u_int u; | ||
991 | u_int m; | ||
992 | |||
993 | l = -1; | ||
994 | u = nmemb; | ||
995 | while (l + 1 != u) { | ||
996 | m = (l + u) / 2; | ||
997 | entry = base + m * size; | ||
998 | if (compar(key, entry) > 0) | ||
999 | l = m; | ||
1000 | else | ||
1001 | u = m; | ||
1002 | } | ||
1003 | |||
1004 | entry = base + u * size; | ||
1005 | if (u == nmemb | ||
1006 | || compar(key, entry) != 0) | ||
1007 | return (NULL); | ||
1008 | 34 | ||
1009 | return ((void *)entry); | ||
1010 | } | ||
1011 | |||
1012 | /* | ||
1013 | * Compare string with pattern, returning 0 on match. | ||
1014 | * Short pattern matches trailing blanks in name, | ||
1015 | * wildcard '*' in pattern matches rest of name, | ||
1016 | * wildcard '?' matches a single non-space character. | ||
1017 | */ | ||
1018 | static int | ||
1019 | cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len) | ||
1020 | { | ||
1021 | |||
1022 | while (*pattern != '\0'&& str_len > 0) { | ||
1023 | |||
1024 | if (*pattern == '*') { | ||
1025 | return (0); | ||
1026 | } | ||
1027 | if ((*pattern != *str) | ||
1028 | && (*pattern != '?' || *str == ' ')) { | ||
1029 | return (1); | ||
1030 | } | ||
1031 | pattern++; | ||
1032 | str++; | ||
1033 | str_len--; | ||
1034 | } | ||
1035 | while (str_len > 0 && *str++ == ' ') | ||
1036 | str_len--; | ||
1037 | |||
1038 | return (str_len); | ||
1039 | } | ||
1040 | |||
1041 | static caddr_t | ||
1042 | cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries, | ||
1043 | int entry_size, cam_quirkmatch_t *comp_func) | ||
1044 | { | ||
1045 | for (; num_entries > 0; num_entries--, quirk_table += entry_size) { | ||
1046 | if ((*comp_func)(target, quirk_table) == 0) | ||
1047 | return (quirk_table); | ||
1048 | } | ||
1049 | return (NULL); | ||
1050 | } | ||
1051 | |||
1052 | void | ||
1053 | aic_sense_desc(int sense_key, int asc, int ascq, | ||
1054 | struct scsi_inquiry_data *inq_data, | ||
1055 | const char **sense_key_desc, const char **asc_desc) | ||
1056 | { | ||
1057 | const struct asc_table_entry *asc_entry; | ||
1058 | const struct sense_key_table_entry *sense_entry; | ||
1059 | |||
1060 | fetchtableentries(sense_key, asc, ascq, | ||
1061 | inq_data, | ||
1062 | &sense_entry, | ||
1063 | &asc_entry); | ||
1064 | |||
1065 | *sense_key_desc = sense_entry->desc; | ||
1066 | |||
1067 | if (asc_entry != NULL) | ||
1068 | *asc_desc = asc_entry->desc; | ||
1069 | else if (asc >= 0x80 && asc <= 0xff) | ||
1070 | *asc_desc = "Vendor Specific ASC"; | ||
1071 | else if (ascq >= 0x80 && ascq <= 0xff) | ||
1072 | *asc_desc = "Vendor Specific ASCQ"; | ||
1073 | else | ||
1074 | *asc_desc = "Reserved ASC/ASCQ pair"; | ||
1075 | } | ||
1076 | |||
1077 | /* | ||
1078 | * Given sense and device type information, return the appropriate action. | ||
1079 | * If we do not understand the specific error as identified by the ASC/ASCQ | ||
1080 | * pair, fall back on the more generic actions derived from the sense key. | ||
1081 | */ | ||
1082 | aic_sense_action | ||
1083 | aic_sense_error_action(struct scsi_sense_data *sense_data, | ||
1084 | struct scsi_inquiry_data *inq_data, uint32_t sense_flags) | ||
1085 | { | ||
1086 | const struct asc_table_entry *asc_entry; | ||
1087 | const struct sense_key_table_entry *sense_entry; | ||
1088 | int error_code, sense_key, asc, ascq; | ||
1089 | aic_sense_action action; | ||
1090 | |||
1091 | scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq); | ||
1092 | |||
1093 | if (error_code == SSD_DEFERRED_ERROR) { | ||
1094 | /* | ||
1095 | * XXX dufault@FreeBSD.org | ||
1096 | * This error doesn't relate to the command associated | ||
1097 | * with this request sense. A deferred error is an error | ||
1098 | * for a command that has already returned GOOD status | ||
1099 | * (see SCSI2 8.2.14.2). | ||
1100 | * | ||
1101 | * By my reading of that section, it looks like the current | ||
1102 | * command has been cancelled, we should now clean things up | ||
1103 | * (hopefully recovering any lost data) and then retry the | ||
1104 | * current command. There are two easy choices, both wrong: | ||
1105 | * | ||
1106 | * 1. Drop through (like we had been doing), thus treating | ||
1107 | * this as if the error were for the current command and | ||
1108 | * return and stop the current command. | ||
1109 | * | ||
1110 | * 2. Issue a retry (like I made it do) thus hopefully | ||
1111 | * recovering the current transfer, and ignoring the | ||
1112 | * fact that we've dropped a command. | ||
1113 | * | ||
1114 | * These should probably be handled in a device specific | ||
1115 | * sense handler or punted back up to a user mode daemon | ||
1116 | */ | ||
1117 | action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE; | ||
1118 | } else { | ||
1119 | fetchtableentries(sense_key, asc, ascq, | ||
1120 | inq_data, | ||
1121 | &sense_entry, | ||
1122 | &asc_entry); | ||
1123 | |||
1124 | /* | ||
1125 | * Override the 'No additional Sense' entry (0,0) | ||
1126 | * with the error action of the sense key. | ||
1127 | */ | ||
1128 | if (asc_entry != NULL | ||
1129 | && (asc != 0 || ascq != 0)) | ||
1130 | action = asc_entry->action; | ||
1131 | else | ||
1132 | action = sense_entry->action; | ||
1133 | |||
1134 | if (sense_key == SSD_KEY_RECOVERED_ERROR) { | ||
1135 | /* | ||
1136 | * The action succeeded but the device wants | ||
1137 | * the user to know that some recovery action | ||
1138 | * was required. | ||
1139 | */ | ||
1140 | action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK); | ||
1141 | action |= SS_NOP|SSQ_PRINT_SENSE; | ||
1142 | } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) { | ||
1143 | if ((sense_flags & SF_QUIET_IR) != 0) | ||
1144 | action &= ~SSQ_PRINT_SENSE; | ||
1145 | } else if (sense_key == SSD_KEY_UNIT_ATTENTION) { | ||
1146 | if ((sense_flags & SF_RETRY_UA) != 0 | ||
1147 | && (action & SS_MASK) == SS_FAIL) { | ||
1148 | action &= ~(SS_MASK|SSQ_MASK); | ||
1149 | action |= SS_RETRY|SSQ_DECREMENT_COUNT| | ||
1150 | SSQ_PRINT_SENSE; | ||
1151 | } | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | if ((sense_flags & SF_PRINT_ALWAYS) != 0) | ||
1156 | action |= SSQ_PRINT_SENSE; | ||
1157 | else if ((sense_flags & SF_NO_PRINT) != 0) | ||
1158 | action &= ~SSQ_PRINT_SENSE; | ||
1159 | |||
1160 | return (action); | ||
1161 | } | ||
1162 | |||
1163 | /* | ||
1164 | * Try make as good a match as possible with | ||
1165 | * available sub drivers | ||
1166 | */ | ||
1167 | int | ||
1168 | aic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) | ||
1169 | { | ||
1170 | struct scsi_inquiry_pattern *entry; | ||
1171 | struct scsi_inquiry_data *inq; | ||
1172 | |||
1173 | entry = (struct scsi_inquiry_pattern *)table_entry; | ||
1174 | inq = (struct scsi_inquiry_data *)inqbuffer; | ||
1175 | |||
1176 | if (((SID_TYPE(inq) == entry->type) | ||
1177 | || (entry->type == T_ANY)) | ||
1178 | && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE | ||
1179 | : entry->media_type & SIP_MEDIA_FIXED) | ||
1180 | && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) | ||
1181 | && (cam_strmatch(inq->product, entry->product, | ||
1182 | sizeof(inq->product)) == 0) | ||
1183 | && (cam_strmatch(inq->revision, entry->revision, | ||
1184 | sizeof(inq->revision)) == 0)) { | ||
1185 | return (0); | ||
1186 | } | ||
1187 | return (-1); | ||
1188 | } | ||
1189 | 35 | ||
1190 | /* | 36 | /* |
1191 | * Table of syncrates that don't follow the "divisible by 4" | 37 | * Table of syncrates that don't follow the "divisible by 4" |
@@ -1229,108 +75,6 @@ aic_calc_syncsrate(u_int period_factor) | |||
1229 | return (10000000 / (period_factor * 4 * 10)); | 75 | return (10000000 / (period_factor * 4 * 10)); |
1230 | } | 76 | } |
1231 | 77 | ||
1232 | /* | ||
1233 | * Return speed in KB/s. | ||
1234 | */ | ||
1235 | u_int | ||
1236 | aic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate) | ||
1237 | { | ||
1238 | u_int freq; | ||
1239 | |||
1240 | if (offset != 0 && period < min_rate) | ||
1241 | freq = aic_calc_syncsrate(period); | ||
1242 | else | ||
1243 | /* Roughly 3.3MB/s for async */ | ||
1244 | freq = 3300; | ||
1245 | freq <<= width; | ||
1246 | return (freq); | ||
1247 | } | ||
1248 | |||
1249 | uint32_t | ||
1250 | aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data, | ||
1251 | cam_status status, u_int scsi_status) | ||
1252 | { | ||
1253 | aic_sense_action err_action; | ||
1254 | int sense; | ||
1255 | |||
1256 | sense = (cmd->result >> 24) == DRIVER_SENSE; | ||
1257 | |||
1258 | switch (status) { | ||
1259 | case CAM_REQ_CMP: | ||
1260 | err_action = SS_NOP; | ||
1261 | break; | ||
1262 | case CAM_AUTOSENSE_FAIL: | ||
1263 | case CAM_SCSI_STATUS_ERROR: | ||
1264 | |||
1265 | switch (scsi_status) { | ||
1266 | case SCSI_STATUS_OK: | ||
1267 | case SCSI_STATUS_COND_MET: | ||
1268 | case SCSI_STATUS_INTERMED: | ||
1269 | case SCSI_STATUS_INTERMED_COND_MET: | ||
1270 | err_action = SS_NOP; | ||
1271 | break; | ||
1272 | case SCSI_STATUS_CMD_TERMINATED: | ||
1273 | case SCSI_STATUS_CHECK_COND: | ||
1274 | if (sense != 0) { | ||
1275 | struct scsi_sense_data *sense; | ||
1276 | |||
1277 | sense = (struct scsi_sense_data *) | ||
1278 | &cmd->sense_buffer; | ||
1279 | err_action = | ||
1280 | aic_sense_error_action(sense, inq_data, 0); | ||
1281 | |||
1282 | } else { | ||
1283 | err_action = SS_RETRY|SSQ_FALLBACK | ||
1284 | | SSQ_DECREMENT_COUNT|EIO; | ||
1285 | } | ||
1286 | break; | ||
1287 | case SCSI_STATUS_QUEUE_FULL: | ||
1288 | case SCSI_STATUS_BUSY: | ||
1289 | err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY | ||
1290 | | SSQ_DECREMENT_COUNT|EBUSY; | ||
1291 | break; | ||
1292 | case SCSI_STATUS_RESERV_CONFLICT: | ||
1293 | default: | ||
1294 | err_action = SS_FAIL|EBUSY; | ||
1295 | break; | ||
1296 | } | ||
1297 | break; | ||
1298 | case CAM_CMD_TIMEOUT: | ||
1299 | case CAM_REQ_CMP_ERR: | ||
1300 | case CAM_UNEXP_BUSFREE: | ||
1301 | case CAM_UNCOR_PARITY: | ||
1302 | case CAM_DATA_RUN_ERR: | ||
1303 | err_action = SS_RETRY|SSQ_FALLBACK|EIO; | ||
1304 | break; | ||
1305 | case CAM_UA_ABORT: | ||
1306 | case CAM_UA_TERMIO: | ||
1307 | case CAM_MSG_REJECT_REC: | ||
1308 | case CAM_SEL_TIMEOUT: | ||
1309 | err_action = SS_FAIL|EIO; | ||
1310 | break; | ||
1311 | case CAM_REQ_INVALID: | ||
1312 | case CAM_PATH_INVALID: | ||
1313 | case CAM_DEV_NOT_THERE: | ||
1314 | case CAM_NO_HBA: | ||
1315 | case CAM_PROVIDE_FAIL: | ||
1316 | case CAM_REQ_TOO_BIG: | ||
1317 | case CAM_RESRC_UNAVAIL: | ||
1318 | case CAM_BUSY: | ||
1319 | default: | ||
1320 | /* panic?? These should never occur in our application. */ | ||
1321 | err_action = SS_FAIL|EIO; | ||
1322 | break; | ||
1323 | case CAM_SCSI_BUS_RESET: | ||
1324 | case CAM_BDR_SENT: | ||
1325 | case CAM_REQUEUE_REQ: | ||
1326 | /* Unconditional requeue */ | ||
1327 | err_action = SS_RETRY; | ||
1328 | break; | ||
1329 | } | ||
1330 | |||
1331 | return (err_action); | ||
1332 | } | ||
1333 | |||
1334 | char * | 78 | char * |
1335 | aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | 79 | aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, |
1336 | aic_option_callback_t *callback, u_long callback_arg) | 80 | aic_option_callback_t *callback, u_long callback_arg) |
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h index bfe6f954d3c4..e7d94cbaf2a8 100644 --- a/drivers/scsi/aic7xxx/aiclib.h +++ b/drivers/scsi/aic7xxx/aiclib.h | |||
@@ -57,121 +57,6 @@ | |||
57 | #ifndef _AICLIB_H | 57 | #ifndef _AICLIB_H |
58 | #define _AICLIB_H | 58 | #define _AICLIB_H |
59 | 59 | ||
60 | /* | ||
61 | * Linux Interrupt Support. | ||
62 | */ | ||
63 | #ifndef IRQ_RETVAL | ||
64 | typedef void irqreturn_t; | ||
65 | #define IRQ_RETVAL(x) | ||
66 | #endif | ||
67 | |||
68 | /* | ||
69 | * SCSI command format | ||
70 | */ | ||
71 | |||
72 | /* | ||
73 | * Define dome bits that are in ALL (or a lot of) scsi commands | ||
74 | */ | ||
75 | #define SCSI_CTL_LINK 0x01 | ||
76 | #define SCSI_CTL_FLAG 0x02 | ||
77 | #define SCSI_CTL_VENDOR 0xC0 | ||
78 | #define SCSI_CMD_LUN 0xA0 /* these two should not be needed */ | ||
79 | #define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */ | ||
80 | |||
81 | #define SCSI_MAX_CDBLEN 16 /* | ||
82 | * 16 byte commands are in the | ||
83 | * SCSI-3 spec | ||
84 | */ | ||
85 | /* 6byte CDBs special case 0 length to be 256 */ | ||
86 | #define SCSI_CDB6_LEN(len) ((len) == 0 ? 256 : len) | ||
87 | |||
88 | /* | ||
89 | * This type defines actions to be taken when a particular sense code is | ||
90 | * received. Right now, these flags are only defined to take up 16 bits, | ||
91 | * but can be expanded in the future if necessary. | ||
92 | */ | ||
93 | typedef enum { | ||
94 | SS_NOP = 0x000000, /* Do nothing */ | ||
95 | SS_RETRY = 0x010000, /* Retry the command */ | ||
96 | SS_FAIL = 0x020000, /* Bail out */ | ||
97 | SS_START = 0x030000, /* Send a Start Unit command to the device, | ||
98 | * then retry the original command. | ||
99 | */ | ||
100 | SS_TUR = 0x040000, /* Send a Test Unit Ready command to the | ||
101 | * device, then retry the original command. | ||
102 | */ | ||
103 | SS_REQSENSE = 0x050000, /* Send a RequestSense command to the | ||
104 | * device, then retry the original command. | ||
105 | */ | ||
106 | SS_INQ_REFRESH = 0x060000, | ||
107 | SS_MASK = 0xff0000 | ||
108 | } aic_sense_action; | ||
109 | |||
110 | typedef enum { | ||
111 | SSQ_NONE = 0x0000, | ||
112 | SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */ | ||
113 | SSQ_MANY = 0x0200, /* send lots of recovery commands */ | ||
114 | SSQ_RANGE = 0x0400, /* | ||
115 | * This table entry represents the | ||
116 | * end of a range of ASCQs that | ||
117 | * have identical error actions | ||
118 | * and text. | ||
119 | */ | ||
120 | SSQ_PRINT_SENSE = 0x0800, | ||
121 | SSQ_DELAY = 0x1000, /* Delay before retry. */ | ||
122 | SSQ_DELAY_RANDOM = 0x2000, /* Randomized delay before retry. */ | ||
123 | SSQ_FALLBACK = 0x4000, /* Do a speed fallback to recover */ | ||
124 | SSQ_MASK = 0xff00 | ||
125 | } aic_sense_action_qualifier; | ||
126 | |||
127 | /* Mask for error status values */ | ||
128 | #define SS_ERRMASK 0xff | ||
129 | |||
130 | /* The default, retyable, error action */ | ||
131 | #define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO | ||
132 | |||
133 | /* The retyable, error action, with table specified error code */ | ||
134 | #define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE | ||
135 | |||
136 | /* Fatal error action, with table specified error code */ | ||
137 | #define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE | ||
138 | |||
139 | struct scsi_generic | ||
140 | { | ||
141 | uint8_t opcode; | ||
142 | uint8_t bytes[11]; | ||
143 | }; | ||
144 | |||
145 | struct scsi_request_sense | ||
146 | { | ||
147 | uint8_t opcode; | ||
148 | uint8_t byte2; | ||
149 | uint8_t unused[2]; | ||
150 | uint8_t length; | ||
151 | uint8_t control; | ||
152 | }; | ||
153 | |||
154 | struct scsi_test_unit_ready | ||
155 | { | ||
156 | uint8_t opcode; | ||
157 | uint8_t byte2; | ||
158 | uint8_t unused[3]; | ||
159 | uint8_t control; | ||
160 | }; | ||
161 | |||
162 | struct scsi_send_diag | ||
163 | { | ||
164 | uint8_t opcode; | ||
165 | uint8_t byte2; | ||
166 | #define SSD_UOL 0x01 | ||
167 | #define SSD_DOL 0x02 | ||
168 | #define SSD_SELFTEST 0x04 | ||
169 | #define SSD_PF 0x10 | ||
170 | uint8_t unused[1]; | ||
171 | uint8_t paramlen[2]; | ||
172 | uint8_t control; | ||
173 | }; | ||
174 | |||
175 | struct scsi_sense | 60 | struct scsi_sense |
176 | { | 61 | { |
177 | uint8_t opcode; | 62 | uint8_t opcode; |
@@ -181,537 +66,12 @@ struct scsi_sense | |||
181 | uint8_t control; | 66 | uint8_t control; |
182 | }; | 67 | }; |
183 | 68 | ||
184 | struct scsi_inquiry | ||
185 | { | ||
186 | uint8_t opcode; | ||
187 | uint8_t byte2; | ||
188 | #define SI_EVPD 0x01 | ||
189 | uint8_t page_code; | ||
190 | uint8_t reserved; | ||
191 | uint8_t length; | ||
192 | uint8_t control; | ||
193 | }; | ||
194 | |||
195 | struct scsi_mode_sense_6 | ||
196 | { | ||
197 | uint8_t opcode; | ||
198 | uint8_t byte2; | ||
199 | #define SMS_DBD 0x08 | ||
200 | uint8_t page; | ||
201 | #define SMS_PAGE_CODE 0x3F | ||
202 | #define SMS_VENDOR_SPECIFIC_PAGE 0x00 | ||
203 | #define SMS_DISCONNECT_RECONNECT_PAGE 0x02 | ||
204 | #define SMS_PERIPHERAL_DEVICE_PAGE 0x09 | ||
205 | #define SMS_CONTROL_MODE_PAGE 0x0A | ||
206 | #define SMS_ALL_PAGES_PAGE 0x3F | ||
207 | #define SMS_PAGE_CTRL_MASK 0xC0 | ||
208 | #define SMS_PAGE_CTRL_CURRENT 0x00 | ||
209 | #define SMS_PAGE_CTRL_CHANGEABLE 0x40 | ||
210 | #define SMS_PAGE_CTRL_DEFAULT 0x80 | ||
211 | #define SMS_PAGE_CTRL_SAVED 0xC0 | ||
212 | uint8_t unused; | ||
213 | uint8_t length; | ||
214 | uint8_t control; | ||
215 | }; | ||
216 | |||
217 | struct scsi_mode_sense_10 | ||
218 | { | ||
219 | uint8_t opcode; | ||
220 | uint8_t byte2; /* same bits as small version */ | ||
221 | uint8_t page; /* same bits as small version */ | ||
222 | uint8_t unused[4]; | ||
223 | uint8_t length[2]; | ||
224 | uint8_t control; | ||
225 | }; | ||
226 | |||
227 | struct scsi_mode_select_6 | ||
228 | { | ||
229 | uint8_t opcode; | ||
230 | uint8_t byte2; | ||
231 | #define SMS_SP 0x01 | ||
232 | #define SMS_PF 0x10 | ||
233 | uint8_t unused[2]; | ||
234 | uint8_t length; | ||
235 | uint8_t control; | ||
236 | }; | ||
237 | |||
238 | struct scsi_mode_select_10 | ||
239 | { | ||
240 | uint8_t opcode; | ||
241 | uint8_t byte2; /* same bits as small version */ | ||
242 | uint8_t unused[5]; | ||
243 | uint8_t length[2]; | ||
244 | uint8_t control; | ||
245 | }; | ||
246 | |||
247 | /* | ||
248 | * When sending a mode select to a tape drive, the medium type must be 0. | ||
249 | */ | ||
250 | struct scsi_mode_hdr_6 | ||
251 | { | ||
252 | uint8_t datalen; | ||
253 | uint8_t medium_type; | ||
254 | uint8_t dev_specific; | ||
255 | uint8_t block_descr_len; | ||
256 | }; | ||
257 | |||
258 | struct scsi_mode_hdr_10 | ||
259 | { | ||
260 | uint8_t datalen[2]; | ||
261 | uint8_t medium_type; | ||
262 | uint8_t dev_specific; | ||
263 | uint8_t reserved[2]; | ||
264 | uint8_t block_descr_len[2]; | ||
265 | }; | ||
266 | |||
267 | struct scsi_mode_block_descr | ||
268 | { | ||
269 | uint8_t density_code; | ||
270 | uint8_t num_blocks[3]; | ||
271 | uint8_t reserved; | ||
272 | uint8_t block_len[3]; | ||
273 | }; | ||
274 | |||
275 | struct scsi_log_sense | ||
276 | { | ||
277 | uint8_t opcode; | ||
278 | uint8_t byte2; | ||
279 | #define SLS_SP 0x01 | ||
280 | #define SLS_PPC 0x02 | ||
281 | uint8_t page; | ||
282 | #define SLS_PAGE_CODE 0x3F | ||
283 | #define SLS_ALL_PAGES_PAGE 0x00 | ||
284 | #define SLS_OVERRUN_PAGE 0x01 | ||
285 | #define SLS_ERROR_WRITE_PAGE 0x02 | ||
286 | #define SLS_ERROR_READ_PAGE 0x03 | ||
287 | #define SLS_ERROR_READREVERSE_PAGE 0x04 | ||
288 | #define SLS_ERROR_VERIFY_PAGE 0x05 | ||
289 | #define SLS_ERROR_NONMEDIUM_PAGE 0x06 | ||
290 | #define SLS_ERROR_LASTN_PAGE 0x07 | ||
291 | #define SLS_PAGE_CTRL_MASK 0xC0 | ||
292 | #define SLS_PAGE_CTRL_THRESHOLD 0x00 | ||
293 | #define SLS_PAGE_CTRL_CUMULATIVE 0x40 | ||
294 | #define SLS_PAGE_CTRL_THRESH_DEFAULT 0x80 | ||
295 | #define SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0 | ||
296 | uint8_t reserved[2]; | ||
297 | uint8_t paramptr[2]; | ||
298 | uint8_t length[2]; | ||
299 | uint8_t control; | ||
300 | }; | ||
301 | |||
302 | struct scsi_log_select | ||
303 | { | ||
304 | uint8_t opcode; | ||
305 | uint8_t byte2; | ||
306 | /* SLS_SP 0x01 */ | ||
307 | #define SLS_PCR 0x02 | ||
308 | uint8_t page; | ||
309 | /* SLS_PAGE_CTRL_MASK 0xC0 */ | ||
310 | /* SLS_PAGE_CTRL_THRESHOLD 0x00 */ | ||
311 | /* SLS_PAGE_CTRL_CUMULATIVE 0x40 */ | ||
312 | /* SLS_PAGE_CTRL_THRESH_DEFAULT 0x80 */ | ||
313 | /* SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0 */ | ||
314 | uint8_t reserved[4]; | ||
315 | uint8_t length[2]; | ||
316 | uint8_t control; | ||
317 | }; | ||
318 | |||
319 | struct scsi_log_header | ||
320 | { | ||
321 | uint8_t page; | ||
322 | uint8_t reserved; | ||
323 | uint8_t datalen[2]; | ||
324 | }; | ||
325 | |||
326 | struct scsi_log_param_header { | ||
327 | uint8_t param_code[2]; | ||
328 | uint8_t param_control; | ||
329 | #define SLP_LP 0x01 | ||
330 | #define SLP_LBIN 0x02 | ||
331 | #define SLP_TMC_MASK 0x0C | ||
332 | #define SLP_TMC_ALWAYS 0x00 | ||
333 | #define SLP_TMC_EQUAL 0x04 | ||
334 | #define SLP_TMC_NOTEQUAL 0x08 | ||
335 | #define SLP_TMC_GREATER 0x0C | ||
336 | #define SLP_ETC 0x10 | ||
337 | #define SLP_TSD 0x20 | ||
338 | #define SLP_DS 0x40 | ||
339 | #define SLP_DU 0x80 | ||
340 | uint8_t param_len; | ||
341 | }; | ||
342 | |||
343 | struct scsi_control_page { | ||
344 | uint8_t page_code; | ||
345 | uint8_t page_length; | ||
346 | uint8_t rlec; | ||
347 | #define SCB_RLEC 0x01 /*Report Log Exception Cond*/ | ||
348 | uint8_t queue_flags; | ||
349 | #define SCP_QUEUE_ALG_MASK 0xF0 | ||
350 | #define SCP_QUEUE_ALG_RESTRICTED 0x00 | ||
351 | #define SCP_QUEUE_ALG_UNRESTRICTED 0x10 | ||
352 | #define SCP_QUEUE_ERR 0x02 /*Queued I/O aborted for CACs*/ | ||
353 | #define SCP_QUEUE_DQUE 0x01 /*Queued I/O disabled*/ | ||
354 | uint8_t eca_and_aen; | ||
355 | #define SCP_EECA 0x80 /*Enable Extended CA*/ | ||
356 | #define SCP_RAENP 0x04 /*Ready AEN Permission*/ | ||
357 | #define SCP_UAAENP 0x02 /*UA AEN Permission*/ | ||
358 | #define SCP_EAENP 0x01 /*Error AEN Permission*/ | ||
359 | uint8_t reserved; | ||
360 | uint8_t aen_holdoff_period[2]; | ||
361 | }; | ||
362 | |||
363 | struct scsi_reserve | ||
364 | { | ||
365 | uint8_t opcode; | ||
366 | uint8_t byte2; | ||
367 | uint8_t unused[2]; | ||
368 | uint8_t length; | ||
369 | uint8_t control; | ||
370 | }; | ||
371 | |||
372 | struct scsi_release | ||
373 | { | ||
374 | uint8_t opcode; | ||
375 | uint8_t byte2; | ||
376 | uint8_t unused[2]; | ||
377 | uint8_t length; | ||
378 | uint8_t control; | ||
379 | }; | ||
380 | |||
381 | struct scsi_prevent | ||
382 | { | ||
383 | uint8_t opcode; | ||
384 | uint8_t byte2; | ||
385 | uint8_t unused[2]; | ||
386 | uint8_t how; | ||
387 | uint8_t control; | ||
388 | }; | ||
389 | #define PR_PREVENT 0x01 | ||
390 | #define PR_ALLOW 0x00 | ||
391 | |||
392 | struct scsi_sync_cache | ||
393 | { | ||
394 | uint8_t opcode; | ||
395 | uint8_t byte2; | ||
396 | uint8_t begin_lba[4]; | ||
397 | uint8_t reserved; | ||
398 | uint8_t lb_count[2]; | ||
399 | uint8_t control; | ||
400 | }; | ||
401 | |||
402 | |||
403 | struct scsi_changedef | ||
404 | { | ||
405 | uint8_t opcode; | ||
406 | uint8_t byte2; | ||
407 | uint8_t unused1; | ||
408 | uint8_t how; | ||
409 | uint8_t unused[4]; | ||
410 | uint8_t datalen; | ||
411 | uint8_t control; | ||
412 | }; | ||
413 | |||
414 | struct scsi_read_buffer | ||
415 | { | ||
416 | uint8_t opcode; | ||
417 | uint8_t byte2; | ||
418 | #define RWB_MODE 0x07 | ||
419 | #define RWB_MODE_HDR_DATA 0x00 | ||
420 | #define RWB_MODE_DATA 0x02 | ||
421 | #define RWB_MODE_DOWNLOAD 0x04 | ||
422 | #define RWB_MODE_DOWNLOAD_SAVE 0x05 | ||
423 | uint8_t buffer_id; | ||
424 | uint8_t offset[3]; | ||
425 | uint8_t length[3]; | ||
426 | uint8_t control; | ||
427 | }; | ||
428 | |||
429 | struct scsi_write_buffer | ||
430 | { | ||
431 | uint8_t opcode; | ||
432 | uint8_t byte2; | ||
433 | uint8_t buffer_id; | ||
434 | uint8_t offset[3]; | ||
435 | uint8_t length[3]; | ||
436 | uint8_t control; | ||
437 | }; | ||
438 | |||
439 | struct scsi_rw_6 | ||
440 | { | ||
441 | uint8_t opcode; | ||
442 | uint8_t addr[3]; | ||
443 | /* only 5 bits are valid in the MSB address byte */ | ||
444 | #define SRW_TOPADDR 0x1F | ||
445 | uint8_t length; | ||
446 | uint8_t control; | ||
447 | }; | ||
448 | |||
449 | struct scsi_rw_10 | ||
450 | { | ||
451 | uint8_t opcode; | ||
452 | #define SRW10_RELADDR 0x01 | ||
453 | #define SRW10_FUA 0x08 | ||
454 | #define SRW10_DPO 0x10 | ||
455 | uint8_t byte2; | ||
456 | uint8_t addr[4]; | ||
457 | uint8_t reserved; | ||
458 | uint8_t length[2]; | ||
459 | uint8_t control; | ||
460 | }; | ||
461 | |||
462 | struct scsi_rw_12 | ||
463 | { | ||
464 | uint8_t opcode; | ||
465 | #define SRW12_RELADDR 0x01 | ||
466 | #define SRW12_FUA 0x08 | ||
467 | #define SRW12_DPO 0x10 | ||
468 | uint8_t byte2; | ||
469 | uint8_t addr[4]; | ||
470 | uint8_t length[4]; | ||
471 | uint8_t reserved; | ||
472 | uint8_t control; | ||
473 | }; | ||
474 | |||
475 | struct scsi_start_stop_unit | ||
476 | { | ||
477 | uint8_t opcode; | ||
478 | uint8_t byte2; | ||
479 | #define SSS_IMMED 0x01 | ||
480 | uint8_t reserved[2]; | ||
481 | uint8_t how; | ||
482 | #define SSS_START 0x01 | ||
483 | #define SSS_LOEJ 0x02 | ||
484 | uint8_t control; | ||
485 | }; | ||
486 | |||
487 | #define SC_SCSI_1 0x01 | ||
488 | #define SC_SCSI_2 0x03 | ||
489 | |||
490 | /* | ||
491 | * Opcodes | ||
492 | */ | ||
493 | |||
494 | #define TEST_UNIT_READY 0x00 | ||
495 | #define REQUEST_SENSE 0x03 | ||
496 | #define READ_6 0x08 | ||
497 | #define WRITE_6 0x0a | ||
498 | #define INQUIRY 0x12 | ||
499 | #define MODE_SELECT_6 0x15 | ||
500 | #define MODE_SENSE_6 0x1a | ||
501 | #define START_STOP_UNIT 0x1b | ||
502 | #define START_STOP 0x1b | ||
503 | #define RESERVE 0x16 | ||
504 | #define RELEASE 0x17 | ||
505 | #define RECEIVE_DIAGNOSTIC 0x1c | ||
506 | #define SEND_DIAGNOSTIC 0x1d | ||
507 | #define PREVENT_ALLOW 0x1e | ||
508 | #define READ_CAPACITY 0x25 | ||
509 | #define READ_10 0x28 | ||
510 | #define WRITE_10 0x2a | ||
511 | #define POSITION_TO_ELEMENT 0x2b | ||
512 | #define SYNCHRONIZE_CACHE 0x35 | ||
513 | #define WRITE_BUFFER 0x3b | ||
514 | #define READ_BUFFER 0x3c | ||
515 | #define CHANGE_DEFINITION 0x40 | ||
516 | #define LOG_SELECT 0x4c | ||
517 | #define LOG_SENSE 0x4d | ||
518 | #ifdef XXXCAM | ||
519 | #define MODE_SENSE_10 0x5A | ||
520 | #endif | ||
521 | #define MODE_SELECT_10 0x55 | ||
522 | #define MOVE_MEDIUM 0xa5 | ||
523 | #define READ_12 0xa8 | ||
524 | #define WRITE_12 0xaa | ||
525 | #define READ_ELEMENT_STATUS 0xb8 | ||
526 | |||
527 | |||
528 | /* | ||
529 | * Device Types | ||
530 | */ | ||
531 | #define T_DIRECT 0x00 | ||
532 | #define T_SEQUENTIAL 0x01 | ||
533 | #define T_PRINTER 0x02 | ||
534 | #define T_PROCESSOR 0x03 | ||
535 | #define T_WORM 0x04 | ||
536 | #define T_CDROM 0x05 | ||
537 | #define T_SCANNER 0x06 | ||
538 | #define T_OPTICAL 0x07 | ||
539 | #define T_CHANGER 0x08 | ||
540 | #define T_COMM 0x09 | ||
541 | #define T_ASC0 0x0a | ||
542 | #define T_ASC1 0x0b | ||
543 | #define T_STORARRAY 0x0c | ||
544 | #define T_ENCLOSURE 0x0d | ||
545 | #define T_RBC 0x0e | ||
546 | #define T_OCRW 0x0f | ||
547 | #define T_NODEVICE 0x1F | ||
548 | #define T_ANY 0xFF /* Used in Quirk table matches */ | ||
549 | |||
550 | #define T_REMOV 1 | ||
551 | #define T_FIXED 0 | ||
552 | |||
553 | /* | ||
554 | * This length is the initial inquiry length used by the probe code, as | ||
555 | * well as the legnth necessary for aic_print_inquiry() to function | ||
556 | * correctly. If either use requires a different length in the future, | ||
557 | * the two values should be de-coupled. | ||
558 | */ | ||
559 | #define SHORT_INQUIRY_LENGTH 36 | ||
560 | |||
561 | struct scsi_inquiry_data | ||
562 | { | ||
563 | uint8_t device; | ||
564 | #define SID_TYPE(inq_data) ((inq_data)->device & 0x1f) | ||
565 | #define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5) | ||
566 | #define SID_QUAL_LU_CONNECTED 0x00 /* | ||
567 | * The specified peripheral device | ||
568 | * type is currently connected to | ||
569 | * logical unit. If the target cannot | ||
570 | * determine whether or not a physical | ||
571 | * device is currently connected, it | ||
572 | * shall also use this peripheral | ||
573 | * qualifier when returning the INQUIRY | ||
574 | * data. This peripheral qualifier | ||
575 | * does not mean that the device is | ||
576 | * ready for access by the initiator. | ||
577 | */ | ||
578 | #define SID_QUAL_LU_OFFLINE 0x01 /* | ||
579 | * The target is capable of supporting | ||
580 | * the specified peripheral device type | ||
581 | * on this logical unit; however, the | ||
582 | * physical device is not currently | ||
583 | * connected to this logical unit. | ||
584 | */ | ||
585 | #define SID_QUAL_RSVD 0x02 | ||
586 | #define SID_QUAL_BAD_LU 0x03 /* | ||
587 | * The target is not capable of | ||
588 | * supporting a physical device on | ||
589 | * this logical unit. For this | ||
590 | * peripheral qualifier the peripheral | ||
591 | * device type shall be set to 1Fh to | ||
592 | * provide compatibility with previous | ||
593 | * versions of SCSI. All other | ||
594 | * peripheral device type values are | ||
595 | * reserved for this peripheral | ||
596 | * qualifier. | ||
597 | */ | ||
598 | #define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0) | ||
599 | uint8_t dev_qual2; | ||
600 | #define SID_QUAL2 0x7F | ||
601 | #define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0) | ||
602 | uint8_t version; | ||
603 | #define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07) | ||
604 | #define SCSI_REV_0 0 | 69 | #define SCSI_REV_0 0 |
605 | #define SCSI_REV_CCS 1 | 70 | #define SCSI_REV_CCS 1 |
606 | #define SCSI_REV_2 2 | 71 | #define SCSI_REV_2 2 |
607 | #define SCSI_REV_SPC 3 | 72 | #define SCSI_REV_SPC 3 |
608 | #define SCSI_REV_SPC2 4 | 73 | #define SCSI_REV_SPC2 4 |
609 | 74 | ||
610 | #define SID_ECMA 0x38 | ||
611 | #define SID_ISO 0xC0 | ||
612 | uint8_t response_format; | ||
613 | #define SID_AENC 0x80 | ||
614 | #define SID_TrmIOP 0x40 | ||
615 | uint8_t additional_length; | ||
616 | uint8_t reserved[2]; | ||
617 | uint8_t flags; | ||
618 | #define SID_SftRe 0x01 | ||
619 | #define SID_CmdQue 0x02 | ||
620 | #define SID_Linked 0x08 | ||
621 | #define SID_Sync 0x10 | ||
622 | #define SID_WBus16 0x20 | ||
623 | #define SID_WBus32 0x40 | ||
624 | #define SID_RelAdr 0x80 | ||
625 | #define SID_VENDOR_SIZE 8 | ||
626 | char vendor[SID_VENDOR_SIZE]; | ||
627 | #define SID_PRODUCT_SIZE 16 | ||
628 | char product[SID_PRODUCT_SIZE]; | ||
629 | #define SID_REVISION_SIZE 4 | ||
630 | char revision[SID_REVISION_SIZE]; | ||
631 | /* | ||
632 | * The following fields were taken from SCSI Primary Commands - 2 | ||
633 | * (SPC-2) Revision 14, Dated 11 November 1999 | ||
634 | */ | ||
635 | #define SID_VENDOR_SPECIFIC_0_SIZE 20 | ||
636 | uint8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE]; | ||
637 | /* | ||
638 | * An extension of SCSI Parallel Specific Values | ||
639 | */ | ||
640 | #define SID_SPI_IUS 0x01 | ||
641 | #define SID_SPI_QAS 0x02 | ||
642 | #define SID_SPI_CLOCK_ST 0x00 | ||
643 | #define SID_SPI_CLOCK_DT 0x04 | ||
644 | #define SID_SPI_CLOCK_DT_ST 0x0C | ||
645 | #define SID_SPI_MASK 0x0F | ||
646 | uint8_t spi3data; | ||
647 | uint8_t reserved2; | ||
648 | /* | ||
649 | * Version Descriptors, stored 2 byte values. | ||
650 | */ | ||
651 | uint8_t version1[2]; | ||
652 | uint8_t version2[2]; | ||
653 | uint8_t version3[2]; | ||
654 | uint8_t version4[2]; | ||
655 | uint8_t version5[2]; | ||
656 | uint8_t version6[2]; | ||
657 | uint8_t version7[2]; | ||
658 | uint8_t version8[2]; | ||
659 | |||
660 | uint8_t reserved3[22]; | ||
661 | |||
662 | #define SID_VENDOR_SPECIFIC_1_SIZE 160 | ||
663 | uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE]; | ||
664 | }; | ||
665 | |||
666 | struct scsi_vpd_unit_serial_number | ||
667 | { | ||
668 | uint8_t device; | ||
669 | uint8_t page_code; | ||
670 | #define SVPD_UNIT_SERIAL_NUMBER 0x80 | ||
671 | uint8_t reserved; | ||
672 | uint8_t length; /* serial number length */ | ||
673 | #define SVPD_SERIAL_NUM_SIZE 251 | ||
674 | uint8_t serial_num[SVPD_SERIAL_NUM_SIZE]; | ||
675 | }; | ||
676 | |||
677 | struct scsi_read_capacity | ||
678 | { | ||
679 | uint8_t opcode; | ||
680 | uint8_t byte2; | ||
681 | uint8_t addr[4]; | ||
682 | uint8_t unused[3]; | ||
683 | uint8_t control; | ||
684 | }; | ||
685 | |||
686 | struct scsi_read_capacity_data | ||
687 | { | ||
688 | uint8_t addr[4]; | ||
689 | uint8_t length[4]; | ||
690 | }; | ||
691 | |||
692 | struct scsi_report_luns | ||
693 | { | ||
694 | uint8_t opcode; | ||
695 | uint8_t byte2; | ||
696 | uint8_t unused[3]; | ||
697 | uint8_t addr[4]; | ||
698 | uint8_t control; | ||
699 | }; | ||
700 | |||
701 | struct scsi_report_luns_data { | ||
702 | uint8_t length[4]; /* length of LUN inventory, in bytes */ | ||
703 | uint8_t reserved[4]; /* unused */ | ||
704 | /* | ||
705 | * LUN inventory- we only support the type zero form for now. | ||
706 | */ | ||
707 | struct { | ||
708 | uint8_t lundata[8]; | ||
709 | } luns[1]; | ||
710 | }; | ||
711 | #define RPL_LUNDATA_ATYP_MASK 0xc0 /* MBZ for type 0 lun */ | ||
712 | #define RPL_LUNDATA_T0LUN 1 /* @ lundata[1] */ | ||
713 | |||
714 | |||
715 | struct scsi_sense_data | 75 | struct scsi_sense_data |
716 | { | 76 | { |
717 | uint8_t error_code; | 77 | uint8_t error_code; |
@@ -757,41 +117,6 @@ struct scsi_sense_data | |||
757 | #define SSD_FULL_SIZE sizeof(struct scsi_sense_data) | 117 | #define SSD_FULL_SIZE sizeof(struct scsi_sense_data) |
758 | }; | 118 | }; |
759 | 119 | ||
760 | struct scsi_mode_header_6 | ||
761 | { | ||
762 | uint8_t data_length; /* Sense data length */ | ||
763 | uint8_t medium_type; | ||
764 | uint8_t dev_spec; | ||
765 | uint8_t blk_desc_len; | ||
766 | }; | ||
767 | |||
768 | struct scsi_mode_header_10 | ||
769 | { | ||
770 | uint8_t data_length[2];/* Sense data length */ | ||
771 | uint8_t medium_type; | ||
772 | uint8_t dev_spec; | ||
773 | uint8_t unused[2]; | ||
774 | uint8_t blk_desc_len[2]; | ||
775 | }; | ||
776 | |||
777 | struct scsi_mode_page_header | ||
778 | { | ||
779 | uint8_t page_code; | ||
780 | uint8_t page_length; | ||
781 | }; | ||
782 | |||
783 | struct scsi_mode_blk_desc | ||
784 | { | ||
785 | uint8_t density; | ||
786 | uint8_t nblocks[3]; | ||
787 | uint8_t reserved; | ||
788 | uint8_t blklen[3]; | ||
789 | }; | ||
790 | |||
791 | #define SCSI_DEFAULT_DENSITY 0x00 /* use 'default' density */ | ||
792 | #define SCSI_SAME_DENSITY 0x7f /* use 'same' density- >= SCSI-2 only */ | ||
793 | |||
794 | |||
795 | /* | 120 | /* |
796 | * Status Byte | 121 | * Status Byte |
797 | */ | 122 | */ |
@@ -807,76 +132,7 @@ struct scsi_mode_blk_desc | |||
807 | #define SCSI_STATUS_ACA_ACTIVE 0x30 | 132 | #define SCSI_STATUS_ACA_ACTIVE 0x30 |
808 | #define SCSI_STATUS_TASK_ABORTED 0x40 | 133 | #define SCSI_STATUS_TASK_ABORTED 0x40 |
809 | 134 | ||
810 | struct scsi_inquiry_pattern { | ||
811 | uint8_t type; | ||
812 | uint8_t media_type; | ||
813 | #define SIP_MEDIA_REMOVABLE 0x01 | ||
814 | #define SIP_MEDIA_FIXED 0x02 | ||
815 | const char *vendor; | ||
816 | const char *product; | ||
817 | const char *revision; | ||
818 | }; | ||
819 | |||
820 | struct scsi_static_inquiry_pattern { | ||
821 | uint8_t type; | ||
822 | uint8_t media_type; | ||
823 | char vendor[SID_VENDOR_SIZE+1]; | ||
824 | char product[SID_PRODUCT_SIZE+1]; | ||
825 | char revision[SID_REVISION_SIZE+1]; | ||
826 | }; | ||
827 | |||
828 | struct scsi_sense_quirk_entry { | ||
829 | struct scsi_inquiry_pattern inq_pat; | ||
830 | int num_sense_keys; | ||
831 | int num_ascs; | ||
832 | struct sense_key_table_entry *sense_key_info; | ||
833 | struct asc_table_entry *asc_info; | ||
834 | }; | ||
835 | |||
836 | struct sense_key_table_entry { | ||
837 | uint8_t sense_key; | ||
838 | uint32_t action; | ||
839 | const char *desc; | ||
840 | }; | ||
841 | |||
842 | struct asc_table_entry { | ||
843 | uint8_t asc; | ||
844 | uint8_t ascq; | ||
845 | uint32_t action; | ||
846 | const char *desc; | ||
847 | }; | ||
848 | |||
849 | struct op_table_entry { | ||
850 | uint8_t opcode; | ||
851 | uint16_t opmask; | ||
852 | const char *desc; | ||
853 | }; | ||
854 | |||
855 | struct scsi_op_quirk_entry { | ||
856 | struct scsi_inquiry_pattern inq_pat; | ||
857 | int num_ops; | ||
858 | struct op_table_entry *op_table; | ||
859 | }; | ||
860 | |||
861 | typedef enum { | ||
862 | SSS_FLAG_NONE = 0x00, | ||
863 | SSS_FLAG_PRINT_COMMAND = 0x01 | ||
864 | } scsi_sense_string_flags; | ||
865 | |||
866 | extern const char *scsi_sense_key_text[]; | ||
867 | |||
868 | /************************* Large Disk Handling ********************************/ | 135 | /************************* Large Disk Handling ********************************/ |
869 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
870 | static __inline int aic_sector_div(u_long capacity, int heads, int sectors); | ||
871 | |||
872 | static __inline int | ||
873 | aic_sector_div(u_long capacity, int heads, int sectors) | ||
874 | { | ||
875 | return (capacity / (heads * sectors)); | ||
876 | } | ||
877 | #else | ||
878 | static __inline int aic_sector_div(sector_t capacity, int heads, int sectors); | ||
879 | |||
880 | static __inline int | 136 | static __inline int |
881 | aic_sector_div(sector_t capacity, int heads, int sectors) | 137 | aic_sector_div(sector_t capacity, int heads, int sectors) |
882 | { | 138 | { |
@@ -884,7 +140,6 @@ aic_sector_div(sector_t capacity, int heads, int sectors) | |||
884 | sector_div(capacity, (heads * sectors)); | 140 | sector_div(capacity, (heads * sectors)); |
885 | return (int)capacity; | 141 | return (int)capacity; |
886 | } | 142 | } |
887 | #endif | ||
888 | 143 | ||
889 | /**************************** Module Library Hack *****************************/ | 144 | /**************************** Module Library Hack *****************************/ |
890 | /* | 145 | /* |
@@ -899,138 +154,15 @@ aic_sector_div(sector_t capacity, int heads, int sectors) | |||
899 | #define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) | 154 | #define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) |
900 | #define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) | 155 | #define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) |
901 | 156 | ||
902 | #define aic_sense_desc AIC_LIB_ENTRY(_sense_desc) | ||
903 | #define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action) | ||
904 | #define aic_error_action AIC_LIB_ENTRY(_error_action) | ||
905 | #define aic_op_desc AIC_LIB_ENTRY(_op_desc) | ||
906 | #define aic_cdb_string AIC_LIB_ENTRY(_cdb_string) | ||
907 | #define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry) | ||
908 | #define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) | 157 | #define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) |
909 | #define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam) | ||
910 | #define aic_calc_speed AIC_LIB_ENTRY(_calc_speed) | ||
911 | #define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match) | ||
912 | #define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match) | ||
913 | #define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option) | ||
914 | |||
915 | /******************************************************************************/ | ||
916 | |||
917 | void aic_sense_desc(int /*sense_key*/, int /*asc*/, | ||
918 | int /*ascq*/, struct scsi_inquiry_data*, | ||
919 | const char** /*sense_key_desc*/, | ||
920 | const char** /*asc_desc*/); | ||
921 | aic_sense_action aic_sense_error_action(struct scsi_sense_data*, | ||
922 | struct scsi_inquiry_data*, | ||
923 | uint32_t /*sense_flags*/); | ||
924 | uint32_t aic_error_action(struct scsi_cmnd *, | ||
925 | struct scsi_inquiry_data *, | ||
926 | cam_status, u_int); | ||
927 | |||
928 | #define SF_RETRY_UA 0x01 | ||
929 | #define SF_NO_PRINT 0x02 | ||
930 | #define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */ | ||
931 | #define SF_PRINT_ALWAYS 0x08 | ||
932 | |||
933 | |||
934 | const char * aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*); | ||
935 | char * aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/, | ||
936 | size_t /*len*/); | ||
937 | void aic_print_inquiry(struct scsi_inquiry_data*); | ||
938 | 158 | ||
939 | u_int aic_calc_syncsrate(u_int /*period_factor*/); | 159 | u_int aic_calc_syncsrate(u_int /*period_factor*/); |
940 | u_int aic_calc_syncparam(u_int /*period*/); | ||
941 | u_int aic_calc_speed(u_int width, u_int period, u_int offset, | ||
942 | u_int min_rate); | ||
943 | |||
944 | int aic_inquiry_match(caddr_t /*inqbuffer*/, | ||
945 | caddr_t /*table_entry*/); | ||
946 | int aic_static_inquiry_match(caddr_t /*inqbuffer*/, | ||
947 | caddr_t /*table_entry*/); | ||
948 | 160 | ||
949 | typedef void aic_option_callback_t(u_long, int, int, int32_t); | 161 | typedef void aic_option_callback_t(u_long, int, int, int32_t); |
950 | char * aic_parse_brace_option(char *opt_name, char *opt_arg, | 162 | char * aic_parse_brace_option(char *opt_name, char *opt_arg, |
951 | char *end, int depth, | 163 | char *end, int depth, |
952 | aic_option_callback_t *, u_long); | 164 | aic_option_callback_t *, u_long); |
953 | 165 | ||
954 | static __inline void scsi_extract_sense(struct scsi_sense_data *sense, | ||
955 | int *error_code, int *sense_key, | ||
956 | int *asc, int *ascq); | ||
957 | static __inline void scsi_ulto2b(uint32_t val, uint8_t *bytes); | ||
958 | static __inline void scsi_ulto3b(uint32_t val, uint8_t *bytes); | ||
959 | static __inline void scsi_ulto4b(uint32_t val, uint8_t *bytes); | ||
960 | static __inline uint32_t scsi_2btoul(uint8_t *bytes); | ||
961 | static __inline uint32_t scsi_3btoul(uint8_t *bytes); | ||
962 | static __inline int32_t scsi_3btol(uint8_t *bytes); | ||
963 | static __inline uint32_t scsi_4btoul(uint8_t *bytes); | ||
964 | |||
965 | static __inline void scsi_extract_sense(struct scsi_sense_data *sense, | ||
966 | int *error_code, int *sense_key, | ||
967 | int *asc, int *ascq) | ||
968 | { | ||
969 | *error_code = sense->error_code & SSD_ERRCODE; | ||
970 | *sense_key = sense->flags & SSD_KEY; | ||
971 | *asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; | ||
972 | *ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; | ||
973 | } | ||
974 | |||
975 | static __inline void | ||
976 | scsi_ulto2b(uint32_t val, uint8_t *bytes) | ||
977 | { | ||
978 | |||
979 | bytes[0] = (val >> 8) & 0xff; | ||
980 | bytes[1] = val & 0xff; | ||
981 | } | ||
982 | |||
983 | static __inline void | ||
984 | scsi_ulto3b(uint32_t val, uint8_t *bytes) | ||
985 | { | ||
986 | |||
987 | bytes[0] = (val >> 16) & 0xff; | ||
988 | bytes[1] = (val >> 8) & 0xff; | ||
989 | bytes[2] = val & 0xff; | ||
990 | } | ||
991 | |||
992 | static __inline void | ||
993 | scsi_ulto4b(uint32_t val, uint8_t *bytes) | ||
994 | { | ||
995 | |||
996 | bytes[0] = (val >> 24) & 0xff; | ||
997 | bytes[1] = (val >> 16) & 0xff; | ||
998 | bytes[2] = (val >> 8) & 0xff; | ||
999 | bytes[3] = val & 0xff; | ||
1000 | } | ||
1001 | |||
1002 | static __inline uint32_t | ||
1003 | scsi_2btoul(uint8_t *bytes) | ||
1004 | { | ||
1005 | uint32_t rv; | ||
1006 | |||
1007 | rv = (bytes[0] << 8) | | ||
1008 | bytes[1]; | ||
1009 | return (rv); | ||
1010 | } | ||
1011 | |||
1012 | static __inline uint32_t | ||
1013 | scsi_3btoul(uint8_t *bytes) | ||
1014 | { | ||
1015 | uint32_t rv; | ||
1016 | |||
1017 | rv = (bytes[0] << 16) | | ||
1018 | (bytes[1] << 8) | | ||
1019 | bytes[2]; | ||
1020 | return (rv); | ||
1021 | } | ||
1022 | |||
1023 | static __inline int32_t | ||
1024 | scsi_3btol(uint8_t *bytes) | ||
1025 | { | ||
1026 | uint32_t rc = scsi_3btoul(bytes); | ||
1027 | |||
1028 | if (rc & 0x00800000) | ||
1029 | rc |= 0xff000000; | ||
1030 | |||
1031 | return (int32_t) rc; | ||
1032 | } | ||
1033 | |||
1034 | static __inline uint32_t | 166 | static __inline uint32_t |
1035 | scsi_4btoul(uint8_t *bytes) | 167 | scsi_4btoul(uint8_t *bytes) |
1036 | { | 168 | { |
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 3900e28ac7d6..53b395534313 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
22 | #include <linux/completion.h> | 22 | #include <linux/completion.h> |
23 | #include <linux/devfs_fs_kernel.h> | ||
24 | #include <linux/ioctl32.h> | 23 | #include <linux/ioctl32.h> |
25 | #include <linux/compat.h> | 24 | #include <linux/compat.h> |
26 | #include <linux/chio.h> /* here are all the ioctls */ | 25 | #include <linux/chio.h> /* here are all the ioctls */ |
@@ -940,8 +939,6 @@ static int ch_probe(struct device *dev) | |||
940 | if (init) | 939 | if (init) |
941 | ch_init_elem(ch); | 940 | ch_init_elem(ch); |
942 | 941 | ||
943 | devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor), | ||
944 | S_IFCHR | S_IRUGO | S_IWUGO, ch->name); | ||
945 | class_device_create(ch_sysfs_class, | 942 | class_device_create(ch_sysfs_class, |
946 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor), | 943 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor), |
947 | dev, "s%s", ch->name); | 944 | dev, "s%s", ch->name); |
@@ -974,7 +971,6 @@ static int ch_remove(struct device *dev) | |||
974 | 971 | ||
975 | class_device_destroy(ch_sysfs_class, | 972 | class_device_destroy(ch_sysfs_class, |
976 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor)); | 973 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor)); |
977 | devfs_remove(ch->name); | ||
978 | kfree(ch->dt); | 974 | kfree(ch->dt); |
979 | kfree(ch); | 975 | kfree(ch); |
980 | ch_devcount--; | 976 | ch_devcount--; |
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index ec161733a82b..0d58d3538bdf 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <scsi/scsi_host.h> | 17 | #include <scsi/scsi_host.h> |
18 | #include <scsi/scsi_request.h> | 18 | #include <scsi/scsi_request.h> |
19 | #include <scsi/scsi_eh.h> | 19 | #include <scsi/scsi_eh.h> |
20 | #include <scsi/scsi_dbg.h> | ||
20 | 21 | ||
21 | 22 | ||
22 | 23 | ||
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 5feb886c3392..8640ad1c17e2 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -52,21 +52,80 @@ static struct class shost_class = { | |||
52 | }; | 52 | }; |
53 | 53 | ||
54 | /** | 54 | /** |
55 | * scsi_host_cancel - cancel outstanding IO to this host | 55 | * scsi_host_set_state - Take the given host through the host |
56 | * @shost: pointer to struct Scsi_Host | 56 | * state model. |
57 | * recovery: recovery requested to run. | 57 | * @shost: scsi host to change the state of. |
58 | * @state: state to change to. | ||
59 | * | ||
60 | * Returns zero if unsuccessful or an error if the requested | ||
61 | * transition is illegal. | ||
58 | **/ | 62 | **/ |
59 | static void scsi_host_cancel(struct Scsi_Host *shost, int recovery) | 63 | int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) |
60 | { | 64 | { |
61 | struct scsi_device *sdev; | 65 | enum scsi_host_state oldstate = shost->shost_state; |
66 | |||
67 | if (state == oldstate) | ||
68 | return 0; | ||
69 | |||
70 | switch (state) { | ||
71 | case SHOST_CREATED: | ||
72 | /* There are no legal states that come back to | ||
73 | * created. This is the manually initialised start | ||
74 | * state */ | ||
75 | goto illegal; | ||
76 | |||
77 | case SHOST_RUNNING: | ||
78 | switch (oldstate) { | ||
79 | case SHOST_CREATED: | ||
80 | case SHOST_RECOVERY: | ||
81 | break; | ||
82 | default: | ||
83 | goto illegal; | ||
84 | } | ||
85 | break; | ||
86 | |||
87 | case SHOST_RECOVERY: | ||
88 | switch (oldstate) { | ||
89 | case SHOST_RUNNING: | ||
90 | break; | ||
91 | default: | ||
92 | goto illegal; | ||
93 | } | ||
94 | break; | ||
95 | |||
96 | case SHOST_CANCEL: | ||
97 | switch (oldstate) { | ||
98 | case SHOST_CREATED: | ||
99 | case SHOST_RUNNING: | ||
100 | break; | ||
101 | default: | ||
102 | goto illegal; | ||
103 | } | ||
104 | break; | ||
105 | |||
106 | case SHOST_DEL: | ||
107 | switch (oldstate) { | ||
108 | case SHOST_CANCEL: | ||
109 | break; | ||
110 | default: | ||
111 | goto illegal; | ||
112 | } | ||
113 | break; | ||
62 | 114 | ||
63 | set_bit(SHOST_CANCEL, &shost->shost_state); | ||
64 | shost_for_each_device(sdev, shost) { | ||
65 | scsi_device_cancel(sdev, recovery); | ||
66 | } | 115 | } |
67 | wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY, | 116 | shost->shost_state = state; |
68 | &shost->shost_state))); | 117 | return 0; |
118 | |||
119 | illegal: | ||
120 | SCSI_LOG_ERROR_RECOVERY(1, | ||
121 | dev_printk(KERN_ERR, &shost->shost_gendev, | ||
122 | "Illegal host state transition" | ||
123 | "%s->%s\n", | ||
124 | scsi_host_state_name(oldstate), | ||
125 | scsi_host_state_name(state))); | ||
126 | return -EINVAL; | ||
69 | } | 127 | } |
128 | EXPORT_SYMBOL(scsi_host_set_state); | ||
70 | 129 | ||
71 | /** | 130 | /** |
72 | * scsi_remove_host - remove a scsi host | 131 | * scsi_remove_host - remove a scsi host |
@@ -74,11 +133,13 @@ static void scsi_host_cancel(struct Scsi_Host *shost, int recovery) | |||
74 | **/ | 133 | **/ |
75 | void scsi_remove_host(struct Scsi_Host *shost) | 134 | void scsi_remove_host(struct Scsi_Host *shost) |
76 | { | 135 | { |
136 | down(&shost->scan_mutex); | ||
137 | scsi_host_set_state(shost, SHOST_CANCEL); | ||
138 | up(&shost->scan_mutex); | ||
77 | scsi_forget_host(shost); | 139 | scsi_forget_host(shost); |
78 | scsi_host_cancel(shost, 0); | ||
79 | scsi_proc_host_rm(shost); | 140 | scsi_proc_host_rm(shost); |
80 | 141 | ||
81 | set_bit(SHOST_DEL, &shost->shost_state); | 142 | scsi_host_set_state(shost, SHOST_DEL); |
82 | 143 | ||
83 | transport_unregister_device(&shost->shost_gendev); | 144 | transport_unregister_device(&shost->shost_gendev); |
84 | class_device_unregister(&shost->shost_classdev); | 145 | class_device_unregister(&shost->shost_classdev); |
@@ -115,7 +176,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) | |||
115 | if (error) | 176 | if (error) |
116 | goto out; | 177 | goto out; |
117 | 178 | ||
118 | set_bit(SHOST_ADD, &shost->shost_state); | 179 | scsi_host_set_state(shost, SHOST_RUNNING); |
119 | get_device(shost->shost_gendev.parent); | 180 | get_device(shost->shost_gendev.parent); |
120 | 181 | ||
121 | error = class_device_add(&shost->shost_classdev); | 182 | error = class_device_add(&shost->shost_classdev); |
@@ -226,6 +287,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
226 | 287 | ||
227 | spin_lock_init(&shost->default_lock); | 288 | spin_lock_init(&shost->default_lock); |
228 | scsi_assign_lock(shost, &shost->default_lock); | 289 | scsi_assign_lock(shost, &shost->default_lock); |
290 | shost->shost_state = SHOST_CREATED; | ||
229 | INIT_LIST_HEAD(&shost->__devices); | 291 | INIT_LIST_HEAD(&shost->__devices); |
230 | INIT_LIST_HEAD(&shost->__targets); | 292 | INIT_LIST_HEAD(&shost->__targets); |
231 | INIT_LIST_HEAD(&shost->eh_cmd_q); | 293 | INIT_LIST_HEAD(&shost->eh_cmd_q); |
@@ -382,7 +444,7 @@ EXPORT_SYMBOL(scsi_host_lookup); | |||
382 | **/ | 444 | **/ |
383 | struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) | 445 | struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) |
384 | { | 446 | { |
385 | if (test_bit(SHOST_DEL, &shost->shost_state) || | 447 | if ((shost->shost_state == SHOST_DEL) || |
386 | !get_device(&shost->shost_gendev)) | 448 | !get_device(&shost->shost_gendev)) |
387 | return NULL; | 449 | return NULL; |
388 | return shost; | 450 | return shost; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index fe09d145542a..e3e6752c4104 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -594,7 +594,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
594 | init_event_struct(evt_struct, | 594 | init_event_struct(evt_struct, |
595 | handle_cmd_rsp, | 595 | handle_cmd_rsp, |
596 | VIOSRP_SRP_FORMAT, | 596 | VIOSRP_SRP_FORMAT, |
597 | cmnd->timeout); | 597 | cmnd->timeout_per_command/HZ); |
598 | 598 | ||
599 | evt_struct->cmnd = cmnd; | 599 | evt_struct->cmnd = cmnd; |
600 | evt_struct->cmnd_done = done; | 600 | evt_struct->cmnd_done = done; |
@@ -826,11 +826,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
826 | struct srp_event_struct *tmp_evt, *found_evt; | 826 | struct srp_event_struct *tmp_evt, *found_evt; |
827 | union viosrp_iu srp_rsp; | 827 | union viosrp_iu srp_rsp; |
828 | int rsp_rc; | 828 | int rsp_rc; |
829 | unsigned long flags; | ||
829 | u16 lun = lun_from_dev(cmd->device); | 830 | u16 lun = lun_from_dev(cmd->device); |
830 | 831 | ||
831 | /* First, find this command in our sent list so we can figure | 832 | /* First, find this command in our sent list so we can figure |
832 | * out the correct tag | 833 | * out the correct tag |
833 | */ | 834 | */ |
835 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
834 | found_evt = NULL; | 836 | found_evt = NULL; |
835 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | 837 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { |
836 | if (tmp_evt->cmnd == cmd) { | 838 | if (tmp_evt->cmnd == cmd) { |
@@ -839,11 +841,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
839 | } | 841 | } |
840 | } | 842 | } |
841 | 843 | ||
842 | if (!found_evt) | 844 | if (!found_evt) { |
845 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
843 | return FAILED; | 846 | return FAILED; |
847 | } | ||
844 | 848 | ||
845 | evt = get_event_struct(&hostdata->pool); | 849 | evt = get_event_struct(&hostdata->pool); |
846 | if (evt == NULL) { | 850 | if (evt == NULL) { |
851 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
847 | printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n"); | 852 | printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n"); |
848 | return FAILED; | 853 | return FAILED; |
849 | } | 854 | } |
@@ -867,7 +872,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
867 | 872 | ||
868 | evt->sync_srp = &srp_rsp; | 873 | evt->sync_srp = &srp_rsp; |
869 | init_completion(&evt->comp); | 874 | init_completion(&evt->comp); |
870 | if (ibmvscsi_send_srp_event(evt, hostdata) != 0) { | 875 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata); |
876 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
877 | if (rsp_rc != 0) { | ||
871 | printk(KERN_ERR "ibmvscsi: failed to send abort() event\n"); | 878 | printk(KERN_ERR "ibmvscsi: failed to send abort() event\n"); |
872 | return FAILED; | 879 | return FAILED; |
873 | } | 880 | } |
@@ -901,6 +908,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
901 | * The event is no longer in our list. Make sure it didn't | 908 | * The event is no longer in our list. Make sure it didn't |
902 | * complete while we were aborting | 909 | * complete while we were aborting |
903 | */ | 910 | */ |
911 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
904 | found_evt = NULL; | 912 | found_evt = NULL; |
905 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | 913 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { |
906 | if (tmp_evt->cmnd == cmd) { | 914 | if (tmp_evt->cmnd == cmd) { |
@@ -910,6 +918,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
910 | } | 918 | } |
911 | 919 | ||
912 | if (found_evt == NULL) { | 920 | if (found_evt == NULL) { |
921 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
913 | printk(KERN_INFO | 922 | printk(KERN_INFO |
914 | "ibmvscsi: aborted task tag 0x%lx completed\n", | 923 | "ibmvscsi: aborted task tag 0x%lx completed\n", |
915 | tsk_mgmt->managed_task_tag); | 924 | tsk_mgmt->managed_task_tag); |
@@ -924,6 +933,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
924 | list_del(&found_evt->list); | 933 | list_del(&found_evt->list); |
925 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev); | 934 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev); |
926 | free_event_struct(&found_evt->hostdata->pool, found_evt); | 935 | free_event_struct(&found_evt->hostdata->pool, found_evt); |
936 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
927 | atomic_inc(&hostdata->request_limit); | 937 | atomic_inc(&hostdata->request_limit); |
928 | return SUCCESS; | 938 | return SUCCESS; |
929 | } | 939 | } |
@@ -943,10 +953,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
943 | struct srp_event_struct *tmp_evt, *pos; | 953 | struct srp_event_struct *tmp_evt, *pos; |
944 | union viosrp_iu srp_rsp; | 954 | union viosrp_iu srp_rsp; |
945 | int rsp_rc; | 955 | int rsp_rc; |
956 | unsigned long flags; | ||
946 | u16 lun = lun_from_dev(cmd->device); | 957 | u16 lun = lun_from_dev(cmd->device); |
947 | 958 | ||
959 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
948 | evt = get_event_struct(&hostdata->pool); | 960 | evt = get_event_struct(&hostdata->pool); |
949 | if (evt == NULL) { | 961 | if (evt == NULL) { |
962 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
950 | printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n"); | 963 | printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n"); |
951 | return FAILED; | 964 | return FAILED; |
952 | } | 965 | } |
@@ -969,7 +982,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
969 | 982 | ||
970 | evt->sync_srp = &srp_rsp; | 983 | evt->sync_srp = &srp_rsp; |
971 | init_completion(&evt->comp); | 984 | init_completion(&evt->comp); |
972 | if (ibmvscsi_send_srp_event(evt, hostdata) != 0) { | 985 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata); |
986 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
987 | if (rsp_rc != 0) { | ||
973 | printk(KERN_ERR "ibmvscsi: failed to send reset event\n"); | 988 | printk(KERN_ERR "ibmvscsi: failed to send reset event\n"); |
974 | return FAILED; | 989 | return FAILED; |
975 | } | 990 | } |
@@ -1002,6 +1017,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1002 | /* We need to find all commands for this LUN that have not yet been | 1017 | /* We need to find all commands for this LUN that have not yet been |
1003 | * responded to, and fail them with DID_RESET | 1018 | * responded to, and fail them with DID_RESET |
1004 | */ | 1019 | */ |
1020 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
1005 | list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { | 1021 | list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { |
1006 | if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { | 1022 | if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { |
1007 | if (tmp_evt->cmnd) | 1023 | if (tmp_evt->cmnd) |
@@ -1017,6 +1033,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1017 | tmp_evt->done(tmp_evt); | 1033 | tmp_evt->done(tmp_evt); |
1018 | } | 1034 | } |
1019 | } | 1035 | } |
1036 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1020 | return SUCCESS; | 1037 | return SUCCESS; |
1021 | } | 1038 | } |
1022 | 1039 | ||
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3bb82aae432e..adb95674823f 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -342,9 +342,6 @@ struct lpfc_hba { | |||
342 | #define VPD_MASK 0xf /* mask for any vpd data */ | 342 | #define VPD_MASK 0xf /* mask for any vpd data */ |
343 | 343 | ||
344 | struct timer_list els_tmofunc; | 344 | struct timer_list els_tmofunc; |
345 | |||
346 | void *link_stats; | ||
347 | |||
348 | /* | 345 | /* |
349 | * stat counters | 346 | * stat counters |
350 | */ | 347 | */ |
@@ -370,6 +367,8 @@ struct lpfc_hba { | |||
370 | struct list_head freebufList; | 367 | struct list_head freebufList; |
371 | struct list_head ctrspbuflist; | 368 | struct list_head ctrspbuflist; |
372 | struct list_head rnidrspbuflist; | 369 | struct list_head rnidrspbuflist; |
370 | |||
371 | struct fc_host_statistics link_stats; | ||
373 | }; | 372 | }; |
374 | 373 | ||
375 | 374 | ||
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 3cea92883019..0e089a42c03a 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | 25 | ||
26 | #include <scsi/scsi.h> | ||
26 | #include <scsi/scsi_device.h> | 27 | #include <scsi/scsi_device.h> |
27 | #include <scsi/scsi_host.h> | 28 | #include <scsi/scsi_host.h> |
28 | #include <scsi/scsi_tcq.h> | 29 | #include <scsi/scsi_tcq.h> |
@@ -988,8 +989,7 @@ lpfc_get_stats(struct Scsi_Host *shost) | |||
988 | { | 989 | { |
989 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; | 990 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; |
990 | struct lpfc_sli *psli = &phba->sli; | 991 | struct lpfc_sli *psli = &phba->sli; |
991 | struct fc_host_statistics *hs = | 992 | struct fc_host_statistics *hs = &phba->link_stats; |
992 | (struct fc_host_statistics *)phba->link_stats; | ||
993 | LPFC_MBOXQ_t *pmboxq; | 993 | LPFC_MBOXQ_t *pmboxq; |
994 | MAILBOX_t *pmb; | 994 | MAILBOX_t *pmb; |
995 | int rc=0; | 995 | int rc=0; |
@@ -1020,6 +1020,8 @@ lpfc_get_stats(struct Scsi_Host *shost) | |||
1020 | return NULL; | 1020 | return NULL; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | memset(hs, 0, sizeof (struct fc_host_statistics)); | ||
1024 | |||
1023 | hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt; | 1025 | hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt; |
1024 | hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256); | 1026 | hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256); |
1025 | hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt; | 1027 | hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt; |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 78adee4699af..1280f0e54636 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -27,8 +27,10 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/utsname.h> | 28 | #include <linux/utsname.h> |
29 | 29 | ||
30 | #include <scsi/scsi.h> | ||
30 | #include <scsi/scsi_device.h> | 31 | #include <scsi/scsi_device.h> |
31 | #include <scsi/scsi_host.h> | 32 | #include <scsi/scsi_host.h> |
33 | #include <scsi/scsi_transport_fc.h> | ||
32 | 34 | ||
33 | #include "lpfc_hw.h" | 35 | #include "lpfc_hw.h" |
34 | #include "lpfc_sli.h" | 36 | #include "lpfc_sli.h" |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 2b1c9572dae7..63caf7fe9725 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | 25 | ||
26 | #include <scsi/scsi.h> | ||
26 | #include <scsi/scsi_device.h> | 27 | #include <scsi/scsi_device.h> |
27 | #include <scsi/scsi_host.h> | 28 | #include <scsi/scsi_host.h> |
28 | #include <scsi/scsi_transport_fc.h> | 29 | #include <scsi/scsi_transport_fc.h> |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 233901e9dfde..0a8269d6b130 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | 26 | ||
27 | #include <scsi/scsi.h> | ||
27 | #include <scsi/scsi_device.h> | 28 | #include <scsi/scsi_device.h> |
28 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
29 | #include <scsi/scsi_transport_fc.h> | 30 | #include <scsi/scsi_transport_fc.h> |
@@ -1135,6 +1136,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | |||
1135 | switch(list) { | 1136 | switch(list) { |
1136 | case NLP_NO_LIST: /* No list, just remove it */ | 1137 | case NLP_NO_LIST: /* No list, just remove it */ |
1137 | lpfc_nlp_remove(phba, nlp); | 1138 | lpfc_nlp_remove(phba, nlp); |
1139 | /* as node removed - stop further transport calls */ | ||
1140 | rport_del = none; | ||
1138 | break; | 1141 | break; |
1139 | case NLP_UNUSED_LIST: | 1142 | case NLP_UNUSED_LIST: |
1140 | spin_lock_irq(phba->host->host_lock); | 1143 | spin_lock_irq(phba->host->host_lock); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 34d416d2b007..6f3cb59bf9e0 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | 30 | ||
31 | #include <scsi/scsi.h> | ||
31 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
32 | #include <scsi/scsi_host.h> | 33 | #include <scsi/scsi_host.h> |
33 | #include <scsi/scsi_transport_fc.h> | 34 | #include <scsi/scsi_transport_fc.h> |
@@ -1339,14 +1340,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1339 | if (pci_request_regions(pdev, LPFC_DRIVER_NAME)) | 1340 | if (pci_request_regions(pdev, LPFC_DRIVER_NAME)) |
1340 | goto out_disable_device; | 1341 | goto out_disable_device; |
1341 | 1342 | ||
1342 | host = scsi_host_alloc(&lpfc_template, | 1343 | host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba)); |
1343 | sizeof (struct lpfc_hba) + sizeof (unsigned long)); | ||
1344 | if (!host) | 1344 | if (!host) |
1345 | goto out_release_regions; | 1345 | goto out_release_regions; |
1346 | 1346 | ||
1347 | phba = (struct lpfc_hba*)host->hostdata; | 1347 | phba = (struct lpfc_hba*)host->hostdata; |
1348 | memset(phba, 0, sizeof (struct lpfc_hba)); | 1348 | memset(phba, 0, sizeof (struct lpfc_hba)); |
1349 | phba->link_stats = (void *)&phba[1]; | ||
1350 | phba->host = host; | 1349 | phba->host = host; |
1351 | 1350 | ||
1352 | phba->fc_flag |= FC_LOADING; | 1351 | phba->fc_flag |= FC_LOADING; |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index c27cf94795db..73eb89f91593 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -23,6 +23,11 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | 25 | ||
26 | #include <scsi/scsi_device.h> | ||
27 | #include <scsi/scsi_transport_fc.h> | ||
28 | |||
29 | #include <scsi/scsi.h> | ||
30 | |||
26 | #include "lpfc_hw.h" | 31 | #include "lpfc_hw.h" |
27 | #include "lpfc_sli.h" | 32 | #include "lpfc_sli.h" |
28 | #include "lpfc_disc.h" | 33 | #include "lpfc_disc.h" |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index a5cfb6421fa9..0aba13ceaacf 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -23,6 +23,11 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | 25 | ||
26 | #include <scsi/scsi_device.h> | ||
27 | #include <scsi/scsi_transport_fc.h> | ||
28 | |||
29 | #include <scsi/scsi.h> | ||
30 | |||
26 | #include "lpfc_hw.h" | 31 | #include "lpfc_hw.h" |
27 | #include "lpfc_sli.h" | 32 | #include "lpfc_sli.h" |
28 | #include "lpfc_disc.h" | 33 | #include "lpfc_disc.h" |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 45dc0210fc49..9b35eaac781d 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | 25 | ||
26 | #include <scsi/scsi.h> | ||
26 | #include <scsi/scsi_device.h> | 27 | #include <scsi/scsi_device.h> |
27 | #include <scsi/scsi_host.h> | 28 | #include <scsi/scsi_host.h> |
28 | #include <scsi/scsi_transport_fc.h> | 29 | #include <scsi/scsi_transport_fc.h> |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 17e4974d4445..b5ad1871d34b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -40,11 +40,6 @@ | |||
40 | #define LPFC_RESET_WAIT 2 | 40 | #define LPFC_RESET_WAIT 2 |
41 | #define LPFC_ABORT_WAIT 2 | 41 | #define LPFC_ABORT_WAIT 2 |
42 | 42 | ||
43 | static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun) | ||
44 | { | ||
45 | fcmd->fcpLunLsl = 0; | ||
46 | fcmd->fcpLunMsl = swab16((uint16_t)lun); | ||
47 | } | ||
48 | 43 | ||
49 | /* | 44 | /* |
50 | * This routine allocates a scsi buffer, which contains all the necessary | 45 | * This routine allocates a scsi buffer, which contains all the necessary |
@@ -238,6 +233,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd) | |||
238 | bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen; | 233 | bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen; |
239 | if (datadir == DMA_TO_DEVICE) | 234 | if (datadir == DMA_TO_DEVICE) |
240 | bpl->tus.f.bdeFlags = 0; | 235 | bpl->tus.f.bdeFlags = 0; |
236 | else | ||
237 | bpl->tus.f.bdeFlags = BUFF_USE_RCV; | ||
241 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 238 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
242 | num_bde = 1; | 239 | num_bde = 1; |
243 | bpl++; | 240 | bpl++; |
@@ -245,8 +242,11 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd) | |||
245 | 242 | ||
246 | /* | 243 | /* |
247 | * Finish initializing those IOCB fields that are dependent on the | 244 | * Finish initializing those IOCB fields that are dependent on the |
248 | * scsi_cmnd request_buffer | 245 | * scsi_cmnd request_buffer. Note that the bdeSize is explicitly |
246 | * reinitialized since all iocb memory resources are used many times | ||
247 | * for transmit, receive, and continuation bpl's. | ||
249 | */ | 248 | */ |
249 | iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); | ||
250 | iocb_cmd->un.fcpi64.bdl.bdeSize += | 250 | iocb_cmd->un.fcpi64.bdl.bdeSize += |
251 | (num_bde * sizeof (struct ulp_bde64)); | 251 | (num_bde * sizeof (struct ulp_bde64)); |
252 | iocb_cmd->ulpBdeCount = 1; | 252 | iocb_cmd->ulpBdeCount = 1; |
@@ -445,8 +445,11 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd, | |||
445 | int datadir = scsi_cmnd->sc_data_direction; | 445 | int datadir = scsi_cmnd->sc_data_direction; |
446 | 446 | ||
447 | lpfc_cmd->fcp_rsp->rspSnsLen = 0; | 447 | lpfc_cmd->fcp_rsp->rspSnsLen = 0; |
448 | /* clear task management bits */ | ||
449 | lpfc_cmd->fcp_cmnd->fcpCntl2 = 0; | ||
448 | 450 | ||
449 | lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun); | 451 | int_to_scsilun(lpfc_cmd->pCmd->device->lun, |
452 | &lpfc_cmd->fcp_cmnd->fcp_lun); | ||
450 | 453 | ||
451 | memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16); | 454 | memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16); |
452 | 455 | ||
@@ -545,7 +548,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba, | |||
545 | piocb = &piocbq->iocb; | 548 | piocb = &piocbq->iocb; |
546 | 549 | ||
547 | fcp_cmnd = lpfc_cmd->fcp_cmnd; | 550 | fcp_cmnd = lpfc_cmd->fcp_cmnd; |
548 | lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun); | 551 | int_to_scsilun(lpfc_cmd->pCmd->device->lun, |
552 | &lpfc_cmd->fcp_cmnd->fcp_lun); | ||
549 | fcp_cmnd->fcpCntl2 = task_mgmt_cmd; | 553 | fcp_cmnd->fcpCntl2 = task_mgmt_cmd; |
550 | 554 | ||
551 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; | 555 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; |
@@ -746,6 +750,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
746 | cmnd->result = ScsiResult(DID_NO_CONNECT, 0); | 750 | cmnd->result = ScsiResult(DID_NO_CONNECT, 0); |
747 | goto out_fail_command; | 751 | goto out_fail_command; |
748 | } | 752 | } |
753 | else if (ndlp->nlp_state == NLP_STE_NPR_NODE) { | ||
754 | cmnd->result = ScsiResult(DID_BUS_BUSY, 0); | ||
755 | goto out_fail_command; | ||
756 | } | ||
749 | /* | 757 | /* |
750 | * The device is most likely recovered and the driver | 758 | * The device is most likely recovered and the driver |
751 | * needs a bit more time to finish. Ask the midlayer | 759 | * needs a bit more time to finish. Ask the midlayer |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index 0fd9ba14e1b5..acd64c49e849 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h | |||
@@ -78,18 +78,7 @@ struct fcp_rsp { | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | struct fcp_cmnd { | 80 | struct fcp_cmnd { |
81 | uint32_t fcpLunMsl; /* most significant lun word (32 bits) */ | 81 | struct scsi_lun fcp_lun; |
82 | uint32_t fcpLunLsl; /* least significant lun word (32 bits) */ | ||
83 | /* # of bits to shift lun id to end up in right | ||
84 | * payload word, little endian = 8, big = 16. | ||
85 | */ | ||
86 | #ifdef __BIG_ENDIAN | ||
87 | #define FC_LUN_SHIFT 16 | ||
88 | #define FC_ADDR_MODE_SHIFT 24 | ||
89 | #else /* __LITTLE_ENDIAN */ | ||
90 | #define FC_LUN_SHIFT 8 | ||
91 | #define FC_ADDR_MODE_SHIFT 0 | ||
92 | #endif | ||
93 | 82 | ||
94 | uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */ | 83 | uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */ |
95 | uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */ | 84 | uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1775508ed276..e74e224fd77c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -24,9 +24,11 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | 26 | ||
27 | #include <scsi/scsi.h> | ||
27 | #include <scsi/scsi_cmnd.h> | 28 | #include <scsi/scsi_cmnd.h> |
28 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
29 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
31 | #include <scsi/scsi_transport_fc.h> | ||
30 | 32 | ||
31 | #include "lpfc_hw.h" | 33 | #include "lpfc_hw.h" |
32 | #include "lpfc_sli.h" | 34 | #include "lpfc_sli.h" |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 47dea48ee0ec..7e6747b06f90 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "8.0.29" | 21 | #define LPFC_DRIVER_VERSION "8.0.30" |
22 | 22 | ||
23 | #define LPFC_DRIVER_NAME "lpfc" | 23 | #define LPFC_DRIVER_NAME "lpfc" |
24 | 24 | ||
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index b993652bfa25..637fb6565d28 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
@@ -996,7 +996,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action) | |||
996 | break; | 996 | break; |
997 | 997 | ||
998 | case ABORT_DEVICE: | 998 | case ABORT_DEVICE: |
999 | ha->flags.in_reset = 1; | ||
1000 | if (qla1280_verbose) | 999 | if (qla1280_verbose) |
1001 | printk(KERN_INFO | 1000 | printk(KERN_INFO |
1002 | "scsi(%ld:%d:%d:%d): Queueing abort device " | 1001 | "scsi(%ld:%d:%d:%d): Queueing abort device " |
@@ -1010,7 +1009,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action) | |||
1010 | printk(KERN_INFO | 1009 | printk(KERN_INFO |
1011 | "scsi(%ld:%d:%d:%d): Queueing device reset " | 1010 | "scsi(%ld:%d:%d:%d): Queueing device reset " |
1012 | "command.\n", ha->host_no, bus, target, lun); | 1011 | "command.\n", ha->host_no, bus, target, lun); |
1013 | ha->flags.in_reset = 1; | ||
1014 | if (qla1280_device_reset(ha, bus, target) == 0) | 1012 | if (qla1280_device_reset(ha, bus, target) == 0) |
1015 | result = SUCCESS; | 1013 | result = SUCCESS; |
1016 | break; | 1014 | break; |
@@ -1019,7 +1017,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action) | |||
1019 | if (qla1280_verbose) | 1017 | if (qla1280_verbose) |
1020 | printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS " | 1018 | printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS " |
1021 | "DEVICE RESET\n", ha->host_no, bus); | 1019 | "DEVICE RESET\n", ha->host_no, bus); |
1022 | ha->flags.in_reset = 1; | ||
1023 | if (qla1280_bus_reset(ha, bus == 0)) | 1020 | if (qla1280_bus_reset(ha, bus == 0)) |
1024 | result = SUCCESS; | 1021 | result = SUCCESS; |
1025 | 1022 | ||
@@ -1047,7 +1044,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action) | |||
1047 | 1044 | ||
1048 | if (!list_empty(&ha->done_q)) | 1045 | if (!list_empty(&ha->done_q)) |
1049 | qla1280_done(ha); | 1046 | qla1280_done(ha); |
1050 | ha->flags.in_reset = 0; | ||
1051 | 1047 | ||
1052 | /* If we didn't manage to issue the action, or we have no | 1048 | /* If we didn't manage to issue the action, or we have no |
1053 | * command to wait for, exit here */ | 1049 | * command to wait for, exit here */ |
@@ -1269,6 +1265,22 @@ qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[]) | |||
1269 | return qla1280_biosparam(disk->device, NULL, disk->capacity, geom); | 1265 | return qla1280_biosparam(disk->device, NULL, disk->capacity, geom); |
1270 | } | 1266 | } |
1271 | #endif | 1267 | #endif |
1268 | |||
1269 | /* disable risc and host interrupts */ | ||
1270 | static inline void | ||
1271 | qla1280_disable_intrs(struct scsi_qla_host *ha) | ||
1272 | { | ||
1273 | WRT_REG_WORD(&ha->iobase->ictrl, 0); | ||
1274 | RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */ | ||
1275 | } | ||
1276 | |||
1277 | /* enable risc and host interrupts */ | ||
1278 | static inline void | ||
1279 | qla1280_enable_intrs(struct scsi_qla_host *ha) | ||
1280 | { | ||
1281 | WRT_REG_WORD(&ha->iobase->ictrl, (ISP_EN_INT | ISP_EN_RISC)); | ||
1282 | RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */ | ||
1283 | } | ||
1272 | 1284 | ||
1273 | /************************************************************************** | 1285 | /************************************************************************** |
1274 | * qla1280_intr_handler | 1286 | * qla1280_intr_handler |
@@ -1290,7 +1302,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
1290 | ha->isr_count++; | 1302 | ha->isr_count++; |
1291 | reg = ha->iobase; | 1303 | reg = ha->iobase; |
1292 | 1304 | ||
1293 | WRT_REG_WORD(®->ictrl, 0); /* disable our interrupt. */ | 1305 | qla1280_disable_intrs(ha); |
1294 | 1306 | ||
1295 | data = qla1280_debounce_register(®->istatus); | 1307 | data = qla1280_debounce_register(®->istatus); |
1296 | /* Check for pending interrupts. */ | 1308 | /* Check for pending interrupts. */ |
@@ -1303,8 +1315,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
1303 | 1315 | ||
1304 | spin_unlock(HOST_LOCK); | 1316 | spin_unlock(HOST_LOCK); |
1305 | 1317 | ||
1306 | /* enable our interrupt. */ | 1318 | qla1280_enable_intrs(ha); |
1307 | WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); | ||
1308 | 1319 | ||
1309 | LEAVE_INTR("qla1280_intr_handler"); | 1320 | LEAVE_INTR("qla1280_intr_handler"); |
1310 | return IRQ_RETVAL(handled); | 1321 | return IRQ_RETVAL(handled); |
@@ -1317,7 +1328,7 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) | |||
1317 | uint8_t mr; | 1328 | uint8_t mr; |
1318 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | 1329 | uint16_t mb[MAILBOX_REGISTER_COUNT]; |
1319 | struct nvram *nv; | 1330 | struct nvram *nv; |
1320 | int status; | 1331 | int status, lun; |
1321 | 1332 | ||
1322 | nv = &ha->nvram; | 1333 | nv = &ha->nvram; |
1323 | 1334 | ||
@@ -1325,24 +1336,38 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) | |||
1325 | 1336 | ||
1326 | /* Set Target Parameters. */ | 1337 | /* Set Target Parameters. */ |
1327 | mb[0] = MBC_SET_TARGET_PARAMETERS; | 1338 | mb[0] = MBC_SET_TARGET_PARAMETERS; |
1328 | mb[1] = (uint16_t) (bus ? target | BIT_7 : target); | 1339 | mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8); |
1329 | mb[1] <<= 8; | 1340 | mb[2] = nv->bus[bus].target[target].parameter.renegotiate_on_error << 8; |
1330 | 1341 | mb[2] |= nv->bus[bus].target[target].parameter.stop_queue_on_check << 9; | |
1331 | mb[2] = (nv->bus[bus].target[target].parameter.c << 8); | 1342 | mb[2] |= nv->bus[bus].target[target].parameter.auto_request_sense << 10; |
1343 | mb[2] |= nv->bus[bus].target[target].parameter.tag_queuing << 11; | ||
1344 | mb[2] |= nv->bus[bus].target[target].parameter.enable_sync << 12; | ||
1345 | mb[2] |= nv->bus[bus].target[target].parameter.enable_wide << 13; | ||
1346 | mb[2] |= nv->bus[bus].target[target].parameter.parity_checking << 14; | ||
1347 | mb[2] |= nv->bus[bus].target[target].parameter.disconnect_allowed << 15; | ||
1332 | 1348 | ||
1333 | if (IS_ISP1x160(ha)) { | 1349 | if (IS_ISP1x160(ha)) { |
1334 | mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; | 1350 | mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; |
1335 | mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) | | 1351 | mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8); |
1336 | nv->bus[bus].target[target].sync_period; | ||
1337 | mb[6] = (nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) | | 1352 | mb[6] = (nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) | |
1338 | nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; | 1353 | nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; |
1339 | mr |= BIT_6; | 1354 | mr |= BIT_6; |
1340 | } else { | 1355 | } else { |
1341 | mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) | | 1356 | mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8); |
1342 | nv->bus[bus].target[target].sync_period; | ||
1343 | } | 1357 | } |
1358 | mb[3] |= nv->bus[bus].target[target].sync_period; | ||
1344 | 1359 | ||
1345 | status = qla1280_mailbox_command(ha, mr, &mb[0]); | 1360 | status = qla1280_mailbox_command(ha, mr, mb); |
1361 | |||
1362 | /* Set Device Queue Parameters. */ | ||
1363 | for (lun = 0; lun < MAX_LUNS; lun++) { | ||
1364 | mb[0] = MBC_SET_DEVICE_QUEUE; | ||
1365 | mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8); | ||
1366 | mb[1] |= lun; | ||
1367 | mb[2] = nv->bus[bus].max_queue_depth; | ||
1368 | mb[3] = nv->bus[bus].target[target].execution_throttle; | ||
1369 | status |= qla1280_mailbox_command(ha, 0x0f, mb); | ||
1370 | } | ||
1346 | 1371 | ||
1347 | if (status) | 1372 | if (status) |
1348 | printk(KERN_WARNING "scsi(%ld:%i:%i): " | 1373 | printk(KERN_WARNING "scsi(%ld:%i:%i): " |
@@ -1389,19 +1414,19 @@ qla1280_slave_configure(struct scsi_device *device) | |||
1389 | } | 1414 | } |
1390 | 1415 | ||
1391 | #if LINUX_VERSION_CODE > 0x020500 | 1416 | #if LINUX_VERSION_CODE > 0x020500 |
1392 | nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr; | 1417 | nv->bus[bus].target[target].parameter.enable_sync = device->sdtr; |
1393 | nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr; | 1418 | nv->bus[bus].target[target].parameter.enable_wide = device->wdtr; |
1394 | nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr; | 1419 | nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr; |
1395 | #endif | 1420 | #endif |
1396 | 1421 | ||
1397 | if (driver_setup.no_sync || | 1422 | if (driver_setup.no_sync || |
1398 | (driver_setup.sync_mask && | 1423 | (driver_setup.sync_mask && |
1399 | (~driver_setup.sync_mask & (1 << target)))) | 1424 | (~driver_setup.sync_mask & (1 << target)))) |
1400 | nv->bus[bus].target[target].parameter.f.enable_sync = 0; | 1425 | nv->bus[bus].target[target].parameter.enable_sync = 0; |
1401 | if (driver_setup.no_wide || | 1426 | if (driver_setup.no_wide || |
1402 | (driver_setup.wide_mask && | 1427 | (driver_setup.wide_mask && |
1403 | (~driver_setup.wide_mask & (1 << target)))) | 1428 | (~driver_setup.wide_mask & (1 << target)))) |
1404 | nv->bus[bus].target[target].parameter.f.enable_wide = 0; | 1429 | nv->bus[bus].target[target].parameter.enable_wide = 0; |
1405 | if (IS_ISP1x160(ha)) { | 1430 | if (IS_ISP1x160(ha)) { |
1406 | if (driver_setup.no_ppr || | 1431 | if (driver_setup.no_ppr || |
1407 | (driver_setup.ppr_mask && | 1432 | (driver_setup.ppr_mask && |
@@ -1410,7 +1435,7 @@ qla1280_slave_configure(struct scsi_device *device) | |||
1410 | } | 1435 | } |
1411 | 1436 | ||
1412 | spin_lock_irqsave(HOST_LOCK, flags); | 1437 | spin_lock_irqsave(HOST_LOCK, flags); |
1413 | if (nv->bus[bus].target[target].parameter.f.enable_sync) | 1438 | if (nv->bus[bus].target[target].parameter.enable_sync) |
1414 | status = qla1280_set_target_parameters(ha, bus, target); | 1439 | status = qla1280_set_target_parameters(ha, bus, target); |
1415 | qla1280_get_target_parameters(ha, device); | 1440 | qla1280_get_target_parameters(ha, device); |
1416 | spin_unlock_irqrestore(HOST_LOCK, flags); | 1441 | spin_unlock_irqrestore(HOST_LOCK, flags); |
@@ -1448,7 +1473,6 @@ qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q) | |||
1448 | * | 1473 | * |
1449 | * Input: | 1474 | * Input: |
1450 | * ha = adapter block pointer. | 1475 | * ha = adapter block pointer. |
1451 | * done_q = done queue. | ||
1452 | */ | 1476 | */ |
1453 | static void | 1477 | static void |
1454 | qla1280_done(struct scsi_qla_host *ha) | 1478 | qla1280_done(struct scsi_qla_host *ha) |
@@ -1522,7 +1546,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp) | |||
1522 | int host_status = DID_ERROR; | 1546 | int host_status = DID_ERROR; |
1523 | uint16_t comp_status = le16_to_cpu(sts->comp_status); | 1547 | uint16_t comp_status = le16_to_cpu(sts->comp_status); |
1524 | uint16_t state_flags = le16_to_cpu(sts->state_flags); | 1548 | uint16_t state_flags = le16_to_cpu(sts->state_flags); |
1525 | uint16_t residual_length = le16_to_cpu(sts->residual_length); | 1549 | uint16_t residual_length = le32_to_cpu(sts->residual_length); |
1526 | uint16_t scsi_status = le16_to_cpu(sts->scsi_status); | 1550 | uint16_t scsi_status = le16_to_cpu(sts->scsi_status); |
1527 | #if DEBUG_QLA1280_INTR | 1551 | #if DEBUG_QLA1280_INTR |
1528 | static char *reason[] = { | 1552 | static char *reason[] = { |
@@ -1582,7 +1606,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp) | |||
1582 | 1606 | ||
1583 | case CS_DATA_OVERRUN: | 1607 | case CS_DATA_OVERRUN: |
1584 | dprintk(2, "Data overrun 0x%x\n", residual_length); | 1608 | dprintk(2, "Data overrun 0x%x\n", residual_length); |
1585 | dprintk(2, "qla1280_isr: response packet data\n"); | 1609 | dprintk(2, "qla1280_return_status: response packet data\n"); |
1586 | qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE); | 1610 | qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE); |
1587 | host_status = DID_ERROR; | 1611 | host_status = DID_ERROR; |
1588 | break; | 1612 | break; |
@@ -1617,40 +1641,6 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp) | |||
1617 | /* QLogic ISP1280 Hardware Support Functions. */ | 1641 | /* QLogic ISP1280 Hardware Support Functions. */ |
1618 | /****************************************************************************/ | 1642 | /****************************************************************************/ |
1619 | 1643 | ||
1620 | /* | ||
1621 | * qla2100_enable_intrs | ||
1622 | * qla2100_disable_intrs | ||
1623 | * | ||
1624 | * Input: | ||
1625 | * ha = adapter block pointer. | ||
1626 | * | ||
1627 | * Returns: | ||
1628 | * None | ||
1629 | */ | ||
1630 | static inline void | ||
1631 | qla1280_enable_intrs(struct scsi_qla_host *ha) | ||
1632 | { | ||
1633 | struct device_reg __iomem *reg; | ||
1634 | |||
1635 | reg = ha->iobase; | ||
1636 | /* enable risc and host interrupts */ | ||
1637 | WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); | ||
1638 | RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ | ||
1639 | ha->flags.ints_enabled = 1; | ||
1640 | } | ||
1641 | |||
1642 | static inline void | ||
1643 | qla1280_disable_intrs(struct scsi_qla_host *ha) | ||
1644 | { | ||
1645 | struct device_reg __iomem *reg; | ||
1646 | |||
1647 | reg = ha->iobase; | ||
1648 | /* disable risc and host interrupts */ | ||
1649 | WRT_REG_WORD(®->ictrl, 0); | ||
1650 | RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ | ||
1651 | ha->flags.ints_enabled = 0; | ||
1652 | } | ||
1653 | |||
1654 | /* | 1644 | /* |
1655 | * qla1280_initialize_adapter | 1645 | * qla1280_initialize_adapter |
1656 | * Initialize board. | 1646 | * Initialize board. |
@@ -1679,7 +1669,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) | |||
1679 | ha->flags.reset_active = 0; | 1669 | ha->flags.reset_active = 0; |
1680 | ha->flags.abort_isp_active = 0; | 1670 | ha->flags.abort_isp_active = 0; |
1681 | 1671 | ||
1682 | ha->flags.ints_enabled = 0; | ||
1683 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) | 1672 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) |
1684 | if (ia64_platform_is("sn2")) { | 1673 | if (ia64_platform_is("sn2")) { |
1685 | printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " | 1674 | printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " |
@@ -1758,69 +1747,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) | |||
1758 | return status; | 1747 | return status; |
1759 | } | 1748 | } |
1760 | 1749 | ||
1761 | |||
1762 | /* | ||
1763 | * ISP Firmware Test | ||
1764 | * Checks if present version of RISC firmware is older than | ||
1765 | * driver firmware. | ||
1766 | * | ||
1767 | * Input: | ||
1768 | * ha = adapter block pointer. | ||
1769 | * | ||
1770 | * Returns: | ||
1771 | * 0 = firmware does not need to be loaded. | ||
1772 | */ | ||
1773 | static int | ||
1774 | qla1280_isp_firmware(struct scsi_qla_host *ha) | ||
1775 | { | ||
1776 | struct nvram *nv = (struct nvram *) ha->response_ring; | ||
1777 | int status = 0; /* dg 2/27 always loads RISC */ | ||
1778 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | ||
1779 | |||
1780 | ENTER("qla1280_isp_firmware"); | ||
1781 | |||
1782 | dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no); | ||
1783 | |||
1784 | /* Bad NVRAM data, load RISC code. */ | ||
1785 | if (!ha->nvram_valid) { | ||
1786 | ha->flags.disable_risc_code_load = 0; | ||
1787 | } else | ||
1788 | ha->flags.disable_risc_code_load = | ||
1789 | nv->cntr_flags_1.disable_loading_risc_code; | ||
1790 | |||
1791 | if (ha->flags.disable_risc_code_load) { | ||
1792 | dprintk(3, "qla1280_isp_firmware: Telling RISC to verify " | ||
1793 | "checksum of loaded BIOS code.\n"); | ||
1794 | |||
1795 | /* Verify checksum of loaded RISC code. */ | ||
1796 | mb[0] = MBC_VERIFY_CHECKSUM; | ||
1797 | /* mb[1] = ql12_risc_code_addr01; */ | ||
1798 | mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; | ||
1799 | |||
1800 | if (!(status = | ||
1801 | qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) { | ||
1802 | /* Start firmware execution. */ | ||
1803 | dprintk(3, "qla1280_isp_firmware: Startng F/W " | ||
1804 | "execution.\n"); | ||
1805 | |||
1806 | mb[0] = MBC_EXECUTE_FIRMWARE; | ||
1807 | /* mb[1] = ql12_risc_code_addr01; */ | ||
1808 | mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; | ||
1809 | qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); | ||
1810 | } else | ||
1811 | printk(KERN_INFO "qla1280: RISC checksum failed.\n"); | ||
1812 | } else { | ||
1813 | dprintk(1, "qla1280: NVRAM configured to load RISC load.\n"); | ||
1814 | status = 1; | ||
1815 | } | ||
1816 | |||
1817 | if (status) | ||
1818 | dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n"); | ||
1819 | |||
1820 | LEAVE("qla1280_isp_firmware"); | ||
1821 | return status; | ||
1822 | } | ||
1823 | |||
1824 | /* | 1750 | /* |
1825 | * Chip diagnostics | 1751 | * Chip diagnostics |
1826 | * Test chip for proper operation. | 1752 | * Test chip for proper operation. |
@@ -2006,7 +1932,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha) | |||
2006 | "%d,%d(0x%x)\n", | 1932 | "%d,%d(0x%x)\n", |
2007 | risc_code_address, cnt, num, risc_address); | 1933 | risc_code_address, cnt, num, risc_address); |
2008 | for(i = 0; i < cnt; i++) | 1934 | for(i = 0; i < cnt; i++) |
2009 | ((uint16_t *)ha->request_ring)[i] = | 1935 | ((__le16 *)ha->request_ring)[i] = |
2010 | cpu_to_le16(risc_code_address[i]); | 1936 | cpu_to_le16(risc_code_address[i]); |
2011 | 1937 | ||
2012 | mb[0] = MBC_LOAD_RAM; | 1938 | mb[0] = MBC_LOAD_RAM; |
@@ -2085,7 +2011,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha) | |||
2085 | mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; | 2011 | mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; |
2086 | err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); | 2012 | err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); |
2087 | if (err) { | 2013 | if (err) { |
2088 | printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no); | 2014 | printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no); |
2089 | return err; | 2015 | return err; |
2090 | } | 2016 | } |
2091 | 2017 | ||
@@ -2105,14 +2031,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha) | |||
2105 | static int | 2031 | static int |
2106 | qla1280_load_firmware(struct scsi_qla_host *ha) | 2032 | qla1280_load_firmware(struct scsi_qla_host *ha) |
2107 | { | 2033 | { |
2108 | int err = -ENODEV; | 2034 | int err; |
2109 | |||
2110 | /* If firmware needs to be loaded */ | ||
2111 | if (!qla1280_isp_firmware(ha)) { | ||
2112 | printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n", | ||
2113 | ha->host_no); | ||
2114 | goto out; | ||
2115 | } | ||
2116 | 2035 | ||
2117 | err = qla1280_chip_diag(ha); | 2036 | err = qla1280_chip_diag(ha); |
2118 | if (err) | 2037 | if (err) |
@@ -2246,17 +2165,17 @@ qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target) | |||
2246 | { | 2165 | { |
2247 | struct nvram *nv = &ha->nvram; | 2166 | struct nvram *nv = &ha->nvram; |
2248 | 2167 | ||
2249 | nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1; | 2168 | nv->bus[bus].target[target].parameter.renegotiate_on_error = 1; |
2250 | nv->bus[bus].target[target].parameter.f.auto_request_sense = 1; | 2169 | nv->bus[bus].target[target].parameter.auto_request_sense = 1; |
2251 | nv->bus[bus].target[target].parameter.f.tag_queuing = 1; | 2170 | nv->bus[bus].target[target].parameter.tag_queuing = 1; |
2252 | nv->bus[bus].target[target].parameter.f.enable_sync = 1; | 2171 | nv->bus[bus].target[target].parameter.enable_sync = 1; |
2253 | #if 1 /* Some SCSI Processors do not seem to like this */ | 2172 | #if 1 /* Some SCSI Processors do not seem to like this */ |
2254 | nv->bus[bus].target[target].parameter.f.enable_wide = 1; | 2173 | nv->bus[bus].target[target].parameter.enable_wide = 1; |
2255 | #endif | 2174 | #endif |
2256 | nv->bus[bus].target[target].parameter.f.parity_checking = 1; | ||
2257 | nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1; | ||
2258 | nv->bus[bus].target[target].execution_throttle = | 2175 | nv->bus[bus].target[target].execution_throttle = |
2259 | nv->bus[bus].max_queue_depth - 1; | 2176 | nv->bus[bus].max_queue_depth - 1; |
2177 | nv->bus[bus].target[target].parameter.parity_checking = 1; | ||
2178 | nv->bus[bus].target[target].parameter.disconnect_allowed = 1; | ||
2260 | 2179 | ||
2261 | if (IS_ISP1x160(ha)) { | 2180 | if (IS_ISP1x160(ha)) { |
2262 | nv->bus[bus].target[target].flags.flags1x160.device_enable = 1; | 2181 | nv->bus[bus].target[target].flags.flags1x160.device_enable = 1; |
@@ -2284,9 +2203,9 @@ qla1280_set_defaults(struct scsi_qla_host *ha) | |||
2284 | /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ | 2203 | /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ |
2285 | nv->firmware_feature.f.enable_fast_posting = 1; | 2204 | nv->firmware_feature.f.enable_fast_posting = 1; |
2286 | nv->firmware_feature.f.disable_synchronous_backoff = 1; | 2205 | nv->firmware_feature.f.disable_synchronous_backoff = 1; |
2287 | nv->termination.f.scsi_bus_0_control = 3; | 2206 | nv->termination.scsi_bus_0_control = 3; |
2288 | nv->termination.f.scsi_bus_1_control = 3; | 2207 | nv->termination.scsi_bus_1_control = 3; |
2289 | nv->termination.f.auto_term_support = 1; | 2208 | nv->termination.auto_term_support = 1; |
2290 | 2209 | ||
2291 | /* | 2210 | /* |
2292 | * Set default FIFO magic - What appropriate values would be here | 2211 | * Set default FIFO magic - What appropriate values would be here |
@@ -2296,7 +2215,12 @@ qla1280_set_defaults(struct scsi_qla_host *ha) | |||
2296 | * header file provided by QLogic seems to be bogus or incomplete | 2215 | * header file provided by QLogic seems to be bogus or incomplete |
2297 | * at best. | 2216 | * at best. |
2298 | */ | 2217 | */ |
2299 | nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128; | 2218 | nv->isp_config.burst_enable = 1; |
2219 | if (IS_ISP1040(ha)) | ||
2220 | nv->isp_config.fifo_threshold |= 3; | ||
2221 | else | ||
2222 | nv->isp_config.fifo_threshold |= 4; | ||
2223 | |||
2300 | if (IS_ISP1x160(ha)) | 2224 | if (IS_ISP1x160(ha)) |
2301 | nv->isp_parameter = 0x01; /* fast memory enable */ | 2225 | nv->isp_parameter = 0x01; /* fast memory enable */ |
2302 | 2226 | ||
@@ -2327,66 +2251,53 @@ qla1280_config_target(struct scsi_qla_host *ha, int bus, int target) | |||
2327 | struct nvram *nv = &ha->nvram; | 2251 | struct nvram *nv = &ha->nvram; |
2328 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | 2252 | uint16_t mb[MAILBOX_REGISTER_COUNT]; |
2329 | int status, lun; | 2253 | int status, lun; |
2254 | uint16_t flag; | ||
2330 | 2255 | ||
2331 | /* Set Target Parameters. */ | 2256 | /* Set Target Parameters. */ |
2332 | mb[0] = MBC_SET_TARGET_PARAMETERS; | 2257 | mb[0] = MBC_SET_TARGET_PARAMETERS; |
2333 | mb[1] = (uint16_t) (bus ? target | BIT_7 : target); | 2258 | mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8); |
2334 | mb[1] <<= 8; | ||
2335 | |||
2336 | /* | ||
2337 | * Do not enable wide, sync, and ppr for the initial | ||
2338 | * INQUIRY run. We enable this later if we determine | ||
2339 | * the target actually supports it. | ||
2340 | */ | ||
2341 | nv->bus[bus].target[target].parameter.f. | ||
2342 | auto_request_sense = 1; | ||
2343 | nv->bus[bus].target[target].parameter.f. | ||
2344 | stop_queue_on_check = 0; | ||
2345 | |||
2346 | if (IS_ISP1x160(ha)) | ||
2347 | nv->bus[bus].target[target].ppr_1x160. | ||
2348 | flags.enable_ppr = 0; | ||
2349 | 2259 | ||
2350 | /* | 2260 | /* |
2351 | * No sync, wide, etc. while probing | 2261 | * Do not enable sync and ppr for the initial INQUIRY run. We |
2262 | * enable this later if we determine the target actually | ||
2263 | * supports it. | ||
2352 | */ | 2264 | */ |
2353 | mb[2] = (nv->bus[bus].target[target].parameter.c << 8) & | 2265 | mb[2] = (TP_RENEGOTIATE | TP_AUTO_REQUEST_SENSE | TP_TAGGED_QUEUE |
2354 | ~(TP_SYNC /*| TP_WIDE | TP_PPR*/); | 2266 | | TP_WIDE | TP_PARITY | TP_DISCONNECT); |
2355 | 2267 | ||
2356 | if (IS_ISP1x160(ha)) | 2268 | if (IS_ISP1x160(ha)) |
2357 | mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; | 2269 | mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; |
2358 | else | 2270 | else |
2359 | mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; | 2271 | mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; |
2360 | mb[3] |= nv->bus[bus].target[target].sync_period; | 2272 | mb[3] |= nv->bus[bus].target[target].sync_period; |
2361 | 2273 | status = qla1280_mailbox_command(ha, 0x0f, mb); | |
2362 | status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]); | ||
2363 | 2274 | ||
2364 | /* Save Tag queuing enable flag. */ | 2275 | /* Save Tag queuing enable flag. */ |
2365 | mb[0] = BIT_0 << target; | 2276 | flag = (BIT_0 << target) & mb[0]; |
2366 | if (nv->bus[bus].target[target].parameter.f.tag_queuing) | 2277 | if (nv->bus[bus].target[target].parameter.tag_queuing) |
2367 | ha->bus_settings[bus].qtag_enables |= mb[0]; | 2278 | ha->bus_settings[bus].qtag_enables |= flag; |
2368 | 2279 | ||
2369 | /* Save Device enable flag. */ | 2280 | /* Save Device enable flag. */ |
2370 | if (IS_ISP1x160(ha)) { | 2281 | if (IS_ISP1x160(ha)) { |
2371 | if (nv->bus[bus].target[target].flags.flags1x160.device_enable) | 2282 | if (nv->bus[bus].target[target].flags.flags1x160.device_enable) |
2372 | ha->bus_settings[bus].device_enables |= mb[0]; | 2283 | ha->bus_settings[bus].device_enables |= flag; |
2373 | ha->bus_settings[bus].lun_disables |= 0; | 2284 | ha->bus_settings[bus].lun_disables |= 0; |
2374 | } else { | 2285 | } else { |
2375 | if (nv->bus[bus].target[target].flags.flags1x80.device_enable) | 2286 | if (nv->bus[bus].target[target].flags.flags1x80.device_enable) |
2376 | ha->bus_settings[bus].device_enables |= mb[0]; | 2287 | ha->bus_settings[bus].device_enables |= flag; |
2377 | /* Save LUN disable flag. */ | 2288 | /* Save LUN disable flag. */ |
2378 | if (nv->bus[bus].target[target].flags.flags1x80.lun_disable) | 2289 | if (nv->bus[bus].target[target].flags.flags1x80.lun_disable) |
2379 | ha->bus_settings[bus].lun_disables |= mb[0]; | 2290 | ha->bus_settings[bus].lun_disables |= flag; |
2380 | } | 2291 | } |
2381 | 2292 | ||
2382 | /* Set Device Queue Parameters. */ | 2293 | /* Set Device Queue Parameters. */ |
2383 | for (lun = 0; lun < MAX_LUNS; lun++) { | 2294 | for (lun = 0; lun < MAX_LUNS; lun++) { |
2384 | mb[0] = MBC_SET_DEVICE_QUEUE; | 2295 | mb[0] = MBC_SET_DEVICE_QUEUE; |
2385 | mb[1] = (uint16_t)(bus ? target | BIT_7 : target); | 2296 | mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8); |
2386 | mb[1] = mb[1] << 8 | lun; | 2297 | mb[1] |= lun; |
2387 | mb[2] = nv->bus[bus].max_queue_depth; | 2298 | mb[2] = nv->bus[bus].max_queue_depth; |
2388 | mb[3] = nv->bus[bus].target[target].execution_throttle; | 2299 | mb[3] = nv->bus[bus].target[target].execution_throttle; |
2389 | status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]); | 2300 | status |= qla1280_mailbox_command(ha, 0x0f, mb); |
2390 | } | 2301 | } |
2391 | 2302 | ||
2392 | return status; | 2303 | return status; |
@@ -2431,7 +2342,6 @@ qla1280_nvram_config(struct scsi_qla_host *ha) | |||
2431 | struct nvram *nv = &ha->nvram; | 2342 | struct nvram *nv = &ha->nvram; |
2432 | int bus, target, status = 0; | 2343 | int bus, target, status = 0; |
2433 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | 2344 | uint16_t mb[MAILBOX_REGISTER_COUNT]; |
2434 | uint16_t mask; | ||
2435 | 2345 | ||
2436 | ENTER("qla1280_nvram_config"); | 2346 | ENTER("qla1280_nvram_config"); |
2437 | 2347 | ||
@@ -2439,7 +2349,7 @@ qla1280_nvram_config(struct scsi_qla_host *ha) | |||
2439 | /* Always force AUTO sense for LINUX SCSI */ | 2349 | /* Always force AUTO sense for LINUX SCSI */ |
2440 | for (bus = 0; bus < MAX_BUSES; bus++) | 2350 | for (bus = 0; bus < MAX_BUSES; bus++) |
2441 | for (target = 0; target < MAX_TARGETS; target++) { | 2351 | for (target = 0; target < MAX_TARGETS; target++) { |
2442 | nv->bus[bus].target[target].parameter.f. | 2352 | nv->bus[bus].target[target].parameter. |
2443 | auto_request_sense = 1; | 2353 | auto_request_sense = 1; |
2444 | } | 2354 | } |
2445 | } else { | 2355 | } else { |
@@ -2457,31 +2367,40 @@ qla1280_nvram_config(struct scsi_qla_host *ha) | |||
2457 | 2367 | ||
2458 | hwrev = RD_REG_WORD(®->cfg_0) & ISP_CFG0_HWMSK; | 2368 | hwrev = RD_REG_WORD(®->cfg_0) & ISP_CFG0_HWMSK; |
2459 | 2369 | ||
2460 | cfg1 = RD_REG_WORD(®->cfg_1); | 2370 | cfg1 = RD_REG_WORD(®->cfg_1) & ~(BIT_4 | BIT_5 | BIT_6); |
2461 | cdma_conf = RD_REG_WORD(®->cdma_cfg); | 2371 | cdma_conf = RD_REG_WORD(®->cdma_cfg); |
2462 | ddma_conf = RD_REG_WORD(®->ddma_cfg); | 2372 | ddma_conf = RD_REG_WORD(®->ddma_cfg); |
2463 | 2373 | ||
2464 | /* Busted fifo, says mjacob. */ | 2374 | /* Busted fifo, says mjacob. */ |
2465 | if (hwrev == ISP_CFG0_1040A) | 2375 | if (hwrev != ISP_CFG0_1040A) |
2466 | WRT_REG_WORD(®->cfg_1, cfg1 | ISP_CFG1_F64); | 2376 | cfg1 |= nv->isp_config.fifo_threshold << 4; |
2467 | else | 2377 | |
2468 | WRT_REG_WORD(®->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB); | 2378 | cfg1 |= nv->isp_config.burst_enable << 2; |
2379 | WRT_REG_WORD(®->cfg_1, cfg1); | ||
2469 | 2380 | ||
2470 | WRT_REG_WORD(®->cdma_cfg, cdma_conf | CDMA_CONF_BENAB); | 2381 | WRT_REG_WORD(®->cdma_cfg, cdma_conf | CDMA_CONF_BENAB); |
2471 | WRT_REG_WORD(®->ddma_cfg, cdma_conf | DDMA_CONF_BENAB); | 2382 | WRT_REG_WORD(®->ddma_cfg, cdma_conf | DDMA_CONF_BENAB); |
2472 | } else { | 2383 | } else { |
2384 | uint16_t cfg1, term; | ||
2385 | |||
2473 | /* Set ISP hardware DMA burst */ | 2386 | /* Set ISP hardware DMA burst */ |
2474 | mb[0] = nv->isp_config.c; | 2387 | cfg1 = nv->isp_config.fifo_threshold << 4; |
2388 | cfg1 |= nv->isp_config.burst_enable << 2; | ||
2475 | /* Enable DMA arbitration on dual channel controllers */ | 2389 | /* Enable DMA arbitration on dual channel controllers */ |
2476 | if (ha->ports > 1) | 2390 | if (ha->ports > 1) |
2477 | mb[0] |= BIT_13; | 2391 | cfg1 |= BIT_13; |
2478 | WRT_REG_WORD(®->cfg_1, mb[0]); | 2392 | WRT_REG_WORD(®->cfg_1, cfg1); |
2479 | 2393 | ||
2480 | /* Set SCSI termination. */ | 2394 | /* Set SCSI termination. */ |
2481 | WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0)); | 2395 | WRT_REG_WORD(®->gpio_enable, |
2482 | mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0); | 2396 | BIT_7 | BIT_3 | BIT_2 | BIT_1 | BIT_0); |
2483 | WRT_REG_WORD(®->gpio_data, mb[0]); | 2397 | term = nv->termination.scsi_bus_1_control; |
2398 | term |= nv->termination.scsi_bus_0_control << 2; | ||
2399 | term |= nv->termination.auto_term_support << 7; | ||
2400 | RD_REG_WORD(®->id_l); /* Flush PCI write */ | ||
2401 | WRT_REG_WORD(®->gpio_data, term); | ||
2484 | } | 2402 | } |
2403 | RD_REG_WORD(®->id_l); /* Flush PCI write */ | ||
2485 | 2404 | ||
2486 | /* ISP parameter word. */ | 2405 | /* ISP parameter word. */ |
2487 | mb[0] = MBC_SET_SYSTEM_PARAMETER; | 2406 | mb[0] = MBC_SET_SYSTEM_PARAMETER; |
@@ -2497,16 +2416,17 @@ qla1280_nvram_config(struct scsi_qla_host *ha) | |||
2497 | 2416 | ||
2498 | /* Firmware feature word. */ | 2417 | /* Firmware feature word. */ |
2499 | mb[0] = MBC_SET_FIRMWARE_FEATURES; | 2418 | mb[0] = MBC_SET_FIRMWARE_FEATURES; |
2500 | mask = BIT_5 | BIT_1 | BIT_0; | 2419 | mb[1] = nv->firmware_feature.f.enable_fast_posting; |
2501 | mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask); | 2420 | mb[1] |= nv->firmware_feature.f.report_lvd_bus_transition << 1; |
2421 | mb[1] |= nv->firmware_feature.f.disable_synchronous_backoff << 5; | ||
2502 | #if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2) | 2422 | #if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2) |
2503 | if (ia64_platform_is("sn2")) { | 2423 | if (ia64_platform_is("sn2")) { |
2504 | printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " | 2424 | printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " |
2505 | "workaround\n", ha->host_no); | 2425 | "workaround\n", ha->host_no); |
2506 | mb[1] |= BIT_9; | 2426 | mb[1] |= nv->firmware_feature.f.unused_9 << 9; /* XXX */ |
2507 | } | 2427 | } |
2508 | #endif | 2428 | #endif |
2509 | status |= qla1280_mailbox_command(ha, mask, &mb[0]); | 2429 | status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); |
2510 | 2430 | ||
2511 | /* Retry count and delay. */ | 2431 | /* Retry count and delay. */ |
2512 | mb[0] = MBC_SET_RETRY_COUNT; | 2432 | mb[0] = MBC_SET_RETRY_COUNT; |
@@ -2535,27 +2455,27 @@ qla1280_nvram_config(struct scsi_qla_host *ha) | |||
2535 | mb[2] |= BIT_5; | 2455 | mb[2] |= BIT_5; |
2536 | if (nv->bus[1].config_2.data_line_active_negation) | 2456 | if (nv->bus[1].config_2.data_line_active_negation) |
2537 | mb[2] |= BIT_4; | 2457 | mb[2] |= BIT_4; |
2538 | status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); | 2458 | status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb); |
2539 | 2459 | ||
2540 | mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY; | 2460 | mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY; |
2541 | mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */ | 2461 | mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */ |
2542 | status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); | 2462 | status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); |
2543 | 2463 | ||
2544 | /* thingy */ | 2464 | /* thingy */ |
2545 | mb[0] = MBC_SET_PCI_CONTROL; | 2465 | mb[0] = MBC_SET_PCI_CONTROL; |
2546 | mb[1] = 2; /* Data DMA Channel Burst Enable */ | 2466 | mb[1] = BIT_1; /* Data DMA Channel Burst Enable */ |
2547 | mb[2] = 2; /* Command DMA Channel Burst Enable */ | 2467 | mb[2] = BIT_1; /* Command DMA Channel Burst Enable */ |
2548 | status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); | 2468 | status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb); |
2549 | 2469 | ||
2550 | mb[0] = MBC_SET_TAG_AGE_LIMIT; | 2470 | mb[0] = MBC_SET_TAG_AGE_LIMIT; |
2551 | mb[1] = 8; | 2471 | mb[1] = 8; |
2552 | status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); | 2472 | status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); |
2553 | 2473 | ||
2554 | /* Selection timeout. */ | 2474 | /* Selection timeout. */ |
2555 | mb[0] = MBC_SET_SELECTION_TIMEOUT; | 2475 | mb[0] = MBC_SET_SELECTION_TIMEOUT; |
2556 | mb[1] = nv->bus[0].selection_timeout; | 2476 | mb[1] = nv->bus[0].selection_timeout; |
2557 | mb[2] = nv->bus[1].selection_timeout; | 2477 | mb[2] = nv->bus[1].selection_timeout; |
2558 | status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); | 2478 | status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb); |
2559 | 2479 | ||
2560 | for (bus = 0; bus < ha->ports; bus++) | 2480 | for (bus = 0; bus < ha->ports; bus++) |
2561 | status |= qla1280_config_bus(ha, bus); | 2481 | status |= qla1280_config_bus(ha, bus); |
@@ -3066,7 +2986,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3066 | struct scsi_cmnd *cmd = sp->cmd; | 2986 | struct scsi_cmnd *cmd = sp->cmd; |
3067 | cmd_a64_entry_t *pkt; | 2987 | cmd_a64_entry_t *pkt; |
3068 | struct scatterlist *sg = NULL; | 2988 | struct scatterlist *sg = NULL; |
3069 | u32 *dword_ptr; | 2989 | __le32 *dword_ptr; |
3070 | dma_addr_t dma_handle; | 2990 | dma_addr_t dma_handle; |
3071 | int status = 0; | 2991 | int status = 0; |
3072 | int cnt; | 2992 | int cnt; |
@@ -3104,10 +3024,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3104 | REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); | 3024 | REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); |
3105 | } | 3025 | } |
3106 | 3026 | ||
3027 | dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n", | ||
3028 | ha->req_q_cnt, seg_cnt); | ||
3029 | |||
3107 | /* If room for request in request ring. */ | 3030 | /* If room for request in request ring. */ |
3108 | if ((req_cnt + 2) >= ha->req_q_cnt) { | 3031 | if ((req_cnt + 2) >= ha->req_q_cnt) { |
3109 | status = 1; | 3032 | status = 1; |
3110 | dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt=" | 3033 | dprintk(2, "qla1280_start_scsi: in-ptr=0x%x req_q_cnt=" |
3111 | "0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt, | 3034 | "0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt, |
3112 | req_cnt); | 3035 | req_cnt); |
3113 | goto out; | 3036 | goto out; |
@@ -3119,7 +3042,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3119 | 3042 | ||
3120 | if (cnt >= MAX_OUTSTANDING_COMMANDS) { | 3043 | if (cnt >= MAX_OUTSTANDING_COMMANDS) { |
3121 | status = 1; | 3044 | status = 1; |
3122 | dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN " | 3045 | dprintk(2, "qla1280_start_scsi: NO ROOM IN " |
3123 | "OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt); | 3046 | "OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt); |
3124 | goto out; | 3047 | goto out; |
3125 | } | 3048 | } |
@@ -3128,7 +3051,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3128 | ha->req_q_cnt -= req_cnt; | 3051 | ha->req_q_cnt -= req_cnt; |
3129 | CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1); | 3052 | CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1); |
3130 | 3053 | ||
3131 | dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp, | 3054 | dprintk(2, "start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp, |
3132 | cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd)); | 3055 | cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd)); |
3133 | dprintk(2, " bus %i, target %i, lun %i\n", | 3056 | dprintk(2, " bus %i, target %i, lun %i\n", |
3134 | SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); | 3057 | SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); |
@@ -3350,7 +3273,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3350 | struct scsi_cmnd *cmd = sp->cmd; | 3273 | struct scsi_cmnd *cmd = sp->cmd; |
3351 | struct cmd_entry *pkt; | 3274 | struct cmd_entry *pkt; |
3352 | struct scatterlist *sg = NULL; | 3275 | struct scatterlist *sg = NULL; |
3353 | uint32_t *dword_ptr; | 3276 | __le32 *dword_ptr; |
3354 | int status = 0; | 3277 | int status = 0; |
3355 | int cnt; | 3278 | int cnt; |
3356 | int req_cnt; | 3279 | int req_cnt; |
@@ -3993,21 +3916,21 @@ qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha) | |||
3993 | result = cmd->request_buffer; | 3916 | result = cmd->request_buffer; |
3994 | n = &ha->nvram; | 3917 | n = &ha->nvram; |
3995 | 3918 | ||
3996 | n->bus[bus].target[target].parameter.f.enable_wide = 0; | 3919 | n->bus[bus].target[target].parameter.enable_wide = 0; |
3997 | n->bus[bus].target[target].parameter.f.enable_sync = 0; | 3920 | n->bus[bus].target[target].parameter.enable_sync = 0; |
3998 | n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; | 3921 | n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; |
3999 | 3922 | ||
4000 | if (result[7] & 0x60) | 3923 | if (result[7] & 0x60) |
4001 | n->bus[bus].target[target].parameter.f.enable_wide = 1; | 3924 | n->bus[bus].target[target].parameter.enable_wide = 1; |
4002 | if (result[7] & 0x10) | 3925 | if (result[7] & 0x10) |
4003 | n->bus[bus].target[target].parameter.f.enable_sync = 1; | 3926 | n->bus[bus].target[target].parameter.enable_sync = 1; |
4004 | if ((result[2] >= 3) && (result[4] + 5 > 56) && | 3927 | if ((result[2] >= 3) && (result[4] + 5 > 56) && |
4005 | (result[56] & 0x4)) | 3928 | (result[56] & 0x4)) |
4006 | n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1; | 3929 | n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1; |
4007 | 3930 | ||
4008 | dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n", | 3931 | dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n", |
4009 | n->bus[bus].target[target].parameter.f.enable_wide, | 3932 | n->bus[bus].target[target].parameter.enable_wide, |
4010 | n->bus[bus].target[target].parameter.f.enable_sync, | 3933 | n->bus[bus].target[target].parameter.enable_sync, |
4011 | n->bus[bus].target[target].ppr_1x160.flags.enable_ppr); | 3934 | n->bus[bus].target[target].ppr_1x160.flags.enable_ppr); |
4012 | } | 3935 | } |
4013 | #endif | 3936 | #endif |
@@ -4071,7 +3994,7 @@ qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt, | |||
4071 | /* Save ISP completion status */ | 3994 | /* Save ISP completion status */ |
4072 | CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd); | 3995 | CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd); |
4073 | 3996 | ||
4074 | if (scsi_status & SS_CHECK_CONDITION) { | 3997 | if (scsi_status & SAM_STAT_CHECK_CONDITION) { |
4075 | if (comp_status != CS_ARS_FAILED) { | 3998 | if (comp_status != CS_ARS_FAILED) { |
4076 | uint16_t req_sense_length = | 3999 | uint16_t req_sense_length = |
4077 | le16_to_cpu(pkt->req_sense_length); | 4000 | le16_to_cpu(pkt->req_sense_length); |
@@ -4650,7 +4573,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4650 | if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) { | 4573 | if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) { |
4651 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { | 4574 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { |
4652 | printk(KERN_WARNING "scsi(%li): Unable to set a " | 4575 | printk(KERN_WARNING "scsi(%li): Unable to set a " |
4653 | " suitable DMA mask - aboring\n", ha->host_no); | 4576 | "suitable DMA mask - aborting\n", ha->host_no); |
4654 | error = -ENODEV; | 4577 | error = -ENODEV; |
4655 | goto error_free_irq; | 4578 | goto error_free_irq; |
4656 | } | 4579 | } |
@@ -4660,14 +4583,14 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4660 | #else | 4583 | #else |
4661 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { | 4584 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { |
4662 | printk(KERN_WARNING "scsi(%li): Unable to set a " | 4585 | printk(KERN_WARNING "scsi(%li): Unable to set a " |
4663 | " suitable DMA mask - aboring\n", ha->host_no); | 4586 | "suitable DMA mask - aborting\n", ha->host_no); |
4664 | error = -ENODEV; | 4587 | error = -ENODEV; |
4665 | goto error_free_irq; | 4588 | goto error_free_irq; |
4666 | } | 4589 | } |
4667 | #endif | 4590 | #endif |
4668 | 4591 | ||
4669 | ha->request_ring = pci_alloc_consistent(ha->pdev, | 4592 | ha->request_ring = pci_alloc_consistent(ha->pdev, |
4670 | ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))), | 4593 | ((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)), |
4671 | &ha->request_dma); | 4594 | &ha->request_dma); |
4672 | if (!ha->request_ring) { | 4595 | if (!ha->request_ring) { |
4673 | printk(KERN_INFO "qla1280: Failed to get request memory\n"); | 4596 | printk(KERN_INFO "qla1280: Failed to get request memory\n"); |
@@ -4675,7 +4598,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4675 | } | 4598 | } |
4676 | 4599 | ||
4677 | ha->response_ring = pci_alloc_consistent(ha->pdev, | 4600 | ha->response_ring = pci_alloc_consistent(ha->pdev, |
4678 | ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))), | 4601 | ((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)), |
4679 | &ha->response_dma); | 4602 | &ha->response_dma); |
4680 | if (!ha->response_ring) { | 4603 | if (!ha->response_ring) { |
4681 | printk(KERN_INFO "qla1280: Failed to get response memory\n"); | 4604 | printk(KERN_INFO "qla1280: Failed to get response memory\n"); |
@@ -4758,7 +4681,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4758 | 4681 | ||
4759 | #if LINUX_VERSION_CODE >= 0x020600 | 4682 | #if LINUX_VERSION_CODE >= 0x020600 |
4760 | error_disable_adapter: | 4683 | error_disable_adapter: |
4761 | WRT_REG_WORD(&ha->iobase->ictrl, 0); | 4684 | qla1280_disable_intrs(ha); |
4762 | #endif | 4685 | #endif |
4763 | error_free_irq: | 4686 | error_free_irq: |
4764 | free_irq(pdev->irq, ha); | 4687 | free_irq(pdev->irq, ha); |
@@ -4770,11 +4693,11 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4770 | #endif | 4693 | #endif |
4771 | error_free_response_ring: | 4694 | error_free_response_ring: |
4772 | pci_free_consistent(ha->pdev, | 4695 | pci_free_consistent(ha->pdev, |
4773 | ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))), | 4696 | ((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)), |
4774 | ha->response_ring, ha->response_dma); | 4697 | ha->response_ring, ha->response_dma); |
4775 | error_free_request_ring: | 4698 | error_free_request_ring: |
4776 | pci_free_consistent(ha->pdev, | 4699 | pci_free_consistent(ha->pdev, |
4777 | ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))), | 4700 | ((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)), |
4778 | ha->request_ring, ha->request_dma); | 4701 | ha->request_ring, ha->request_dma); |
4779 | error_put_host: | 4702 | error_put_host: |
4780 | scsi_host_put(host); | 4703 | scsi_host_put(host); |
@@ -4795,7 +4718,7 @@ qla1280_remove_one(struct pci_dev *pdev) | |||
4795 | scsi_remove_host(host); | 4718 | scsi_remove_host(host); |
4796 | #endif | 4719 | #endif |
4797 | 4720 | ||
4798 | WRT_REG_WORD(&ha->iobase->ictrl, 0); | 4721 | qla1280_disable_intrs(ha); |
4799 | 4722 | ||
4800 | free_irq(pdev->irq, ha); | 4723 | free_irq(pdev->irq, ha); |
4801 | 4724 | ||
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h index d245ae07518e..59915fb70301 100644 --- a/drivers/scsi/qla1280.h +++ b/drivers/scsi/qla1280.h | |||
@@ -94,9 +94,6 @@ | |||
94 | #define REQUEST_ENTRY_CNT 256 /* Number of request entries. */ | 94 | #define REQUEST_ENTRY_CNT 256 /* Number of request entries. */ |
95 | #define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */ | 95 | #define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */ |
96 | 96 | ||
97 | /* Number of segments 1 - 65535 */ | ||
98 | #define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ | ||
99 | |||
100 | /* | 97 | /* |
101 | * SCSI Request Block structure (sp) that is placed | 98 | * SCSI Request Block structure (sp) that is placed |
102 | * on cmd->SCp location of every I/O | 99 | * on cmd->SCp location of every I/O |
@@ -378,29 +375,23 @@ struct nvram { | |||
378 | uint16_t unused_12; /* 12, 13 */ | 375 | uint16_t unused_12; /* 12, 13 */ |
379 | uint16_t unused_14; /* 14, 15 */ | 376 | uint16_t unused_14; /* 14, 15 */ |
380 | 377 | ||
381 | union { | 378 | struct { |
382 | uint8_t c; | 379 | uint8_t reserved:2; |
383 | struct { | 380 | uint8_t burst_enable:1; |
384 | uint8_t reserved:2; | 381 | uint8_t reserved_1:1; |
385 | uint8_t burst_enable:1; | 382 | uint8_t fifo_threshold:4; |
386 | uint8_t reserved_1:1; | ||
387 | uint8_t fifo_threshold:4; | ||
388 | } f; | ||
389 | } isp_config; /* 16 */ | 383 | } isp_config; /* 16 */ |
390 | 384 | ||
391 | /* Termination | 385 | /* Termination |
392 | * 0 = Disable, 1 = high only, 3 = Auto term | 386 | * 0 = Disable, 1 = high only, 3 = Auto term |
393 | */ | 387 | */ |
394 | union { | 388 | struct { |
395 | uint8_t c; | 389 | uint8_t scsi_bus_1_control:2; |
396 | struct { | 390 | uint8_t scsi_bus_0_control:2; |
397 | uint8_t scsi_bus_1_control:2; | 391 | uint8_t unused_0:1; |
398 | uint8_t scsi_bus_0_control:2; | 392 | uint8_t unused_1:1; |
399 | uint8_t unused_0:1; | 393 | uint8_t unused_2:1; |
400 | uint8_t unused_1:1; | 394 | uint8_t auto_term_support:1; |
401 | uint8_t unused_2:1; | ||
402 | uint8_t auto_term_support:1; | ||
403 | } f; | ||
404 | } termination; /* 17 */ | 395 | } termination; /* 17 */ |
405 | 396 | ||
406 | uint16_t isp_parameter; /* 18, 19 */ | 397 | uint16_t isp_parameter; /* 18, 19 */ |
@@ -460,18 +451,15 @@ struct nvram { | |||
460 | uint16_t unused_38; /* 38, 39 */ | 451 | uint16_t unused_38; /* 38, 39 */ |
461 | 452 | ||
462 | struct { | 453 | struct { |
463 | union { | 454 | struct { |
464 | uint8_t c; | 455 | uint8_t renegotiate_on_error:1; |
465 | struct { | 456 | uint8_t stop_queue_on_check:1; |
466 | uint8_t renegotiate_on_error:1; | 457 | uint8_t auto_request_sense:1; |
467 | uint8_t stop_queue_on_check:1; | 458 | uint8_t tag_queuing:1; |
468 | uint8_t auto_request_sense:1; | 459 | uint8_t enable_sync:1; |
469 | uint8_t tag_queuing:1; | 460 | uint8_t enable_wide:1; |
470 | uint8_t enable_sync:1; | 461 | uint8_t parity_checking:1; |
471 | uint8_t enable_wide:1; | 462 | uint8_t disconnect_allowed:1; |
472 | uint8_t parity_checking:1; | ||
473 | uint8_t disconnect_allowed:1; | ||
474 | } f; | ||
475 | } parameter; /* 40 */ | 463 | } parameter; /* 40 */ |
476 | 464 | ||
477 | uint8_t execution_throttle; /* 41 */ | 465 | uint8_t execution_throttle; /* 41 */ |
@@ -528,23 +516,23 @@ struct cmd_entry { | |||
528 | uint8_t entry_count; /* Entry count. */ | 516 | uint8_t entry_count; /* Entry count. */ |
529 | uint8_t sys_define; /* System defined. */ | 517 | uint8_t sys_define; /* System defined. */ |
530 | uint8_t entry_status; /* Entry Status. */ | 518 | uint8_t entry_status; /* Entry Status. */ |
531 | uint32_t handle; /* System handle. */ | 519 | __le32 handle; /* System handle. */ |
532 | uint8_t lun; /* SCSI LUN */ | 520 | uint8_t lun; /* SCSI LUN */ |
533 | uint8_t target; /* SCSI ID */ | 521 | uint8_t target; /* SCSI ID */ |
534 | uint16_t cdb_len; /* SCSI command length. */ | 522 | __le16 cdb_len; /* SCSI command length. */ |
535 | uint16_t control_flags; /* Control flags. */ | 523 | __le16 control_flags; /* Control flags. */ |
536 | uint16_t reserved; | 524 | __le16 reserved; |
537 | uint16_t timeout; /* Command timeout. */ | 525 | __le16 timeout; /* Command timeout. */ |
538 | uint16_t dseg_count; /* Data segment count. */ | 526 | __le16 dseg_count; /* Data segment count. */ |
539 | uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ | 527 | uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ |
540 | uint32_t dseg_0_address; /* Data segment 0 address. */ | 528 | __le32 dseg_0_address; /* Data segment 0 address. */ |
541 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 529 | __le32 dseg_0_length; /* Data segment 0 length. */ |
542 | uint32_t dseg_1_address; /* Data segment 1 address. */ | 530 | __le32 dseg_1_address; /* Data segment 1 address. */ |
543 | uint32_t dseg_1_length; /* Data segment 1 length. */ | 531 | __le32 dseg_1_length; /* Data segment 1 length. */ |
544 | uint32_t dseg_2_address; /* Data segment 2 address. */ | 532 | __le32 dseg_2_address; /* Data segment 2 address. */ |
545 | uint32_t dseg_2_length; /* Data segment 2 length. */ | 533 | __le32 dseg_2_length; /* Data segment 2 length. */ |
546 | uint32_t dseg_3_address; /* Data segment 3 address. */ | 534 | __le32 dseg_3_address; /* Data segment 3 address. */ |
547 | uint32_t dseg_3_length; /* Data segment 3 length. */ | 535 | __le32 dseg_3_length; /* Data segment 3 length. */ |
548 | }; | 536 | }; |
549 | 537 | ||
550 | /* | 538 | /* |
@@ -556,21 +544,21 @@ struct cont_entry { | |||
556 | uint8_t entry_count; /* Entry count. */ | 544 | uint8_t entry_count; /* Entry count. */ |
557 | uint8_t sys_define; /* System defined. */ | 545 | uint8_t sys_define; /* System defined. */ |
558 | uint8_t entry_status; /* Entry Status. */ | 546 | uint8_t entry_status; /* Entry Status. */ |
559 | uint32_t reserved; /* Reserved */ | 547 | __le32 reserved; /* Reserved */ |
560 | uint32_t dseg_0_address; /* Data segment 0 address. */ | 548 | __le32 dseg_0_address; /* Data segment 0 address. */ |
561 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 549 | __le32 dseg_0_length; /* Data segment 0 length. */ |
562 | uint32_t dseg_1_address; /* Data segment 1 address. */ | 550 | __le32 dseg_1_address; /* Data segment 1 address. */ |
563 | uint32_t dseg_1_length; /* Data segment 1 length. */ | 551 | __le32 dseg_1_length; /* Data segment 1 length. */ |
564 | uint32_t dseg_2_address; /* Data segment 2 address. */ | 552 | __le32 dseg_2_address; /* Data segment 2 address. */ |
565 | uint32_t dseg_2_length; /* Data segment 2 length. */ | 553 | __le32 dseg_2_length; /* Data segment 2 length. */ |
566 | uint32_t dseg_3_address; /* Data segment 3 address. */ | 554 | __le32 dseg_3_address; /* Data segment 3 address. */ |
567 | uint32_t dseg_3_length; /* Data segment 3 length. */ | 555 | __le32 dseg_3_length; /* Data segment 3 length. */ |
568 | uint32_t dseg_4_address; /* Data segment 4 address. */ | 556 | __le32 dseg_4_address; /* Data segment 4 address. */ |
569 | uint32_t dseg_4_length; /* Data segment 4 length. */ | 557 | __le32 dseg_4_length; /* Data segment 4 length. */ |
570 | uint32_t dseg_5_address; /* Data segment 5 address. */ | 558 | __le32 dseg_5_address; /* Data segment 5 address. */ |
571 | uint32_t dseg_5_length; /* Data segment 5 length. */ | 559 | __le32 dseg_5_length; /* Data segment 5 length. */ |
572 | uint32_t dseg_6_address; /* Data segment 6 address. */ | 560 | __le32 dseg_6_address; /* Data segment 6 address. */ |
573 | uint32_t dseg_6_length; /* Data segment 6 length. */ | 561 | __le32 dseg_6_length; /* Data segment 6 length. */ |
574 | }; | 562 | }; |
575 | 563 | ||
576 | /* | 564 | /* |
@@ -586,22 +574,22 @@ struct response { | |||
586 | #define RF_FULL BIT_1 /* Full */ | 574 | #define RF_FULL BIT_1 /* Full */ |
587 | #define RF_BAD_HEADER BIT_2 /* Bad header. */ | 575 | #define RF_BAD_HEADER BIT_2 /* Bad header. */ |
588 | #define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */ | 576 | #define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */ |
589 | uint32_t handle; /* System handle. */ | 577 | __le32 handle; /* System handle. */ |
590 | uint16_t scsi_status; /* SCSI status. */ | 578 | __le16 scsi_status; /* SCSI status. */ |
591 | uint16_t comp_status; /* Completion status. */ | 579 | __le16 comp_status; /* Completion status. */ |
592 | uint16_t state_flags; /* State flags. */ | 580 | __le16 state_flags; /* State flags. */ |
593 | #define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */ | 581 | #define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */ |
594 | #define SF_GOT_SENSE BIT_13 /* Got Sense */ | 582 | #define SF_GOT_SENSE BIT_13 /* Got Sense */ |
595 | #define SF_GOT_STATUS BIT_12 /* Got Status */ | 583 | #define SF_GOT_STATUS BIT_12 /* Got Status */ |
596 | #define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */ | 584 | #define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */ |
597 | #define SF_SENT_CDB BIT_10 /* Send CDB */ | 585 | #define SF_SENT_CDB BIT_10 /* Send CDB */ |
598 | #define SF_GOT_TARGET BIT_9 /* */ | 586 | #define SF_GOT_TARGET BIT_9 /* */ |
599 | #define SF_GOT_BUS BIT_8 /* */ | 587 | #define SF_GOT_BUS BIT_8 /* */ |
600 | uint16_t status_flags; /* Status flags. */ | 588 | __le16 status_flags; /* Status flags. */ |
601 | uint16_t time; /* Time. */ | 589 | __le16 time; /* Time. */ |
602 | uint16_t req_sense_length; /* Request sense data length. */ | 590 | __le16 req_sense_length;/* Request sense data length. */ |
603 | uint32_t residual_length; /* Residual transfer length. */ | 591 | __le32 residual_length; /* Residual transfer length. */ |
604 | uint16_t reserved[4]; | 592 | __le16 reserved[4]; |
605 | uint8_t req_sense_data[32]; /* Request sense data. */ | 593 | uint8_t req_sense_data[32]; /* Request sense data. */ |
606 | }; | 594 | }; |
607 | 595 | ||
@@ -614,7 +602,7 @@ struct mrk_entry { | |||
614 | uint8_t entry_count; /* Entry count. */ | 602 | uint8_t entry_count; /* Entry count. */ |
615 | uint8_t sys_define; /* System defined. */ | 603 | uint8_t sys_define; /* System defined. */ |
616 | uint8_t entry_status; /* Entry Status. */ | 604 | uint8_t entry_status; /* Entry Status. */ |
617 | uint32_t reserved; | 605 | __le32 reserved; |
618 | uint8_t lun; /* SCSI LUN */ | 606 | uint8_t lun; /* SCSI LUN */ |
619 | uint8_t target; /* SCSI ID */ | 607 | uint8_t target; /* SCSI ID */ |
620 | uint8_t modifier; /* Modifier (7-0). */ | 608 | uint8_t modifier; /* Modifier (7-0). */ |
@@ -638,11 +626,11 @@ struct ecmd_entry { | |||
638 | uint32_t handle; /* System handle. */ | 626 | uint32_t handle; /* System handle. */ |
639 | uint8_t lun; /* SCSI LUN */ | 627 | uint8_t lun; /* SCSI LUN */ |
640 | uint8_t target; /* SCSI ID */ | 628 | uint8_t target; /* SCSI ID */ |
641 | uint16_t cdb_len; /* SCSI command length. */ | 629 | __le16 cdb_len; /* SCSI command length. */ |
642 | uint16_t control_flags; /* Control flags. */ | 630 | __le16 control_flags; /* Control flags. */ |
643 | uint16_t reserved; | 631 | __le16 reserved; |
644 | uint16_t timeout; /* Command timeout. */ | 632 | __le16 timeout; /* Command timeout. */ |
645 | uint16_t dseg_count; /* Data segment count. */ | 633 | __le16 dseg_count; /* Data segment count. */ |
646 | uint8_t scsi_cdb[88]; /* SCSI command words. */ | 634 | uint8_t scsi_cdb[88]; /* SCSI command words. */ |
647 | }; | 635 | }; |
648 | 636 | ||
@@ -655,20 +643,20 @@ typedef struct { | |||
655 | uint8_t entry_count; /* Entry count. */ | 643 | uint8_t entry_count; /* Entry count. */ |
656 | uint8_t sys_define; /* System defined. */ | 644 | uint8_t sys_define; /* System defined. */ |
657 | uint8_t entry_status; /* Entry Status. */ | 645 | uint8_t entry_status; /* Entry Status. */ |
658 | uint32_t handle; /* System handle. */ | 646 | __le32 handle; /* System handle. */ |
659 | uint8_t lun; /* SCSI LUN */ | 647 | uint8_t lun; /* SCSI LUN */ |
660 | uint8_t target; /* SCSI ID */ | 648 | uint8_t target; /* SCSI ID */ |
661 | uint16_t cdb_len; /* SCSI command length. */ | 649 | __le16 cdb_len; /* SCSI command length. */ |
662 | uint16_t control_flags; /* Control flags. */ | 650 | __le16 control_flags; /* Control flags. */ |
663 | uint16_t reserved; | 651 | __le16 reserved; |
664 | uint16_t timeout; /* Command timeout. */ | 652 | __le16 timeout; /* Command timeout. */ |
665 | uint16_t dseg_count; /* Data segment count. */ | 653 | __le16 dseg_count; /* Data segment count. */ |
666 | uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ | 654 | uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ |
667 | uint32_t reserved_1[2]; /* unused */ | 655 | __le32 reserved_1[2]; /* unused */ |
668 | uint32_t dseg_0_address[2]; /* Data segment 0 address. */ | 656 | __le32 dseg_0_address[2]; /* Data segment 0 address. */ |
669 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 657 | __le32 dseg_0_length; /* Data segment 0 length. */ |
670 | uint32_t dseg_1_address[2]; /* Data segment 1 address. */ | 658 | __le32 dseg_1_address[2]; /* Data segment 1 address. */ |
671 | uint32_t dseg_1_length; /* Data segment 1 length. */ | 659 | __le32 dseg_1_length; /* Data segment 1 length. */ |
672 | } cmd_a64_entry_t, request_t; | 660 | } cmd_a64_entry_t, request_t; |
673 | 661 | ||
674 | /* | 662 | /* |
@@ -680,16 +668,16 @@ struct cont_a64_entry { | |||
680 | uint8_t entry_count; /* Entry count. */ | 668 | uint8_t entry_count; /* Entry count. */ |
681 | uint8_t sys_define; /* System defined. */ | 669 | uint8_t sys_define; /* System defined. */ |
682 | uint8_t entry_status; /* Entry Status. */ | 670 | uint8_t entry_status; /* Entry Status. */ |
683 | uint32_t dseg_0_address[2]; /* Data segment 0 address. */ | 671 | __le32 dseg_0_address[2]; /* Data segment 0 address. */ |
684 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 672 | __le32 dseg_0_length; /* Data segment 0 length. */ |
685 | uint32_t dseg_1_address[2]; /* Data segment 1 address. */ | 673 | __le32 dseg_1_address[2]; /* Data segment 1 address. */ |
686 | uint32_t dseg_1_length; /* Data segment 1 length. */ | 674 | __le32 dseg_1_length; /* Data segment 1 length. */ |
687 | uint32_t dseg_2_address[2]; /* Data segment 2 address. */ | 675 | __le32 dseg_2_address[2]; /* Data segment 2 address. */ |
688 | uint32_t dseg_2_length; /* Data segment 2 length. */ | 676 | __le32 dseg_2_length; /* Data segment 2 length. */ |
689 | uint32_t dseg_3_address[2]; /* Data segment 3 address. */ | 677 | __le32 dseg_3_address[2]; /* Data segment 3 address. */ |
690 | uint32_t dseg_3_length; /* Data segment 3 length. */ | 678 | __le32 dseg_3_length; /* Data segment 3 length. */ |
691 | uint32_t dseg_4_address[2]; /* Data segment 4 address. */ | 679 | __le32 dseg_4_address[2]; /* Data segment 4 address. */ |
692 | uint32_t dseg_4_length; /* Data segment 4 length. */ | 680 | __le32 dseg_4_length; /* Data segment 4 length. */ |
693 | }; | 681 | }; |
694 | 682 | ||
695 | /* | 683 | /* |
@@ -701,10 +689,10 @@ struct elun_entry { | |||
701 | uint8_t entry_count; /* Entry count. */ | 689 | uint8_t entry_count; /* Entry count. */ |
702 | uint8_t reserved_1; | 690 | uint8_t reserved_1; |
703 | uint8_t entry_status; /* Entry Status not used. */ | 691 | uint8_t entry_status; /* Entry Status not used. */ |
704 | uint32_t reserved_2; | 692 | __le32 reserved_2; |
705 | uint16_t lun; /* Bit 15 is bus number. */ | 693 | __le16 lun; /* Bit 15 is bus number. */ |
706 | uint16_t reserved_4; | 694 | __le16 reserved_4; |
707 | uint32_t option_flags; | 695 | __le32 option_flags; |
708 | uint8_t status; | 696 | uint8_t status; |
709 | uint8_t reserved_5; | 697 | uint8_t reserved_5; |
710 | uint8_t command_count; /* Number of ATIOs allocated. */ | 698 | uint8_t command_count; /* Number of ATIOs allocated. */ |
@@ -714,8 +702,8 @@ struct elun_entry { | |||
714 | /* commands (2-26). */ | 702 | /* commands (2-26). */ |
715 | uint8_t group_7_length; /* SCSI CDB length for group 7 */ | 703 | uint8_t group_7_length; /* SCSI CDB length for group 7 */ |
716 | /* commands (2-26). */ | 704 | /* commands (2-26). */ |
717 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | 705 | __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */ |
718 | uint16_t reserved_6[20]; | 706 | __le16 reserved_6[20]; |
719 | }; | 707 | }; |
720 | 708 | ||
721 | /* | 709 | /* |
@@ -729,20 +717,20 @@ struct modify_lun_entry { | |||
729 | uint8_t entry_count; /* Entry count. */ | 717 | uint8_t entry_count; /* Entry count. */ |
730 | uint8_t reserved_1; | 718 | uint8_t reserved_1; |
731 | uint8_t entry_status; /* Entry Status. */ | 719 | uint8_t entry_status; /* Entry Status. */ |
732 | uint32_t reserved_2; | 720 | __le32 reserved_2; |
733 | uint8_t lun; /* SCSI LUN */ | 721 | uint8_t lun; /* SCSI LUN */ |
734 | uint8_t reserved_3; | 722 | uint8_t reserved_3; |
735 | uint8_t operators; | 723 | uint8_t operators; |
736 | uint8_t reserved_4; | 724 | uint8_t reserved_4; |
737 | uint32_t option_flags; | 725 | __le32 option_flags; |
738 | uint8_t status; | 726 | uint8_t status; |
739 | uint8_t reserved_5; | 727 | uint8_t reserved_5; |
740 | uint8_t command_count; /* Number of ATIOs allocated. */ | 728 | uint8_t command_count; /* Number of ATIOs allocated. */ |
741 | uint8_t immed_notify_count; /* Number of Immediate Notify */ | 729 | uint8_t immed_notify_count; /* Number of Immediate Notify */ |
742 | /* entries allocated. */ | 730 | /* entries allocated. */ |
743 | uint16_t reserved_6; | 731 | __le16 reserved_6; |
744 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | 732 | __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */ |
745 | uint16_t reserved_7[20]; | 733 | __le16 reserved_7[20]; |
746 | }; | 734 | }; |
747 | 735 | ||
748 | /* | 736 | /* |
@@ -754,20 +742,20 @@ struct notify_entry { | |||
754 | uint8_t entry_count; /* Entry count. */ | 742 | uint8_t entry_count; /* Entry count. */ |
755 | uint8_t reserved_1; | 743 | uint8_t reserved_1; |
756 | uint8_t entry_status; /* Entry Status. */ | 744 | uint8_t entry_status; /* Entry Status. */ |
757 | uint32_t reserved_2; | 745 | __le32 reserved_2; |
758 | uint8_t lun; | 746 | uint8_t lun; |
759 | uint8_t initiator_id; | 747 | uint8_t initiator_id; |
760 | uint8_t reserved_3; | 748 | uint8_t reserved_3; |
761 | uint8_t target_id; | 749 | uint8_t target_id; |
762 | uint32_t option_flags; | 750 | __le32 option_flags; |
763 | uint8_t status; | 751 | uint8_t status; |
764 | uint8_t reserved_4; | 752 | uint8_t reserved_4; |
765 | uint8_t tag_value; /* Received queue tag message value */ | 753 | uint8_t tag_value; /* Received queue tag message value */ |
766 | uint8_t tag_type; /* Received queue tag message type */ | 754 | uint8_t tag_type; /* Received queue tag message type */ |
767 | /* entries allocated. */ | 755 | /* entries allocated. */ |
768 | uint16_t seq_id; | 756 | __le16 seq_id; |
769 | uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */ | 757 | uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */ |
770 | uint16_t reserved_5[8]; | 758 | __le16 reserved_5[8]; |
771 | uint8_t sense_data[18]; | 759 | uint8_t sense_data[18]; |
772 | }; | 760 | }; |
773 | 761 | ||
@@ -780,16 +768,16 @@ struct nack_entry { | |||
780 | uint8_t entry_count; /* Entry count. */ | 768 | uint8_t entry_count; /* Entry count. */ |
781 | uint8_t reserved_1; | 769 | uint8_t reserved_1; |
782 | uint8_t entry_status; /* Entry Status. */ | 770 | uint8_t entry_status; /* Entry Status. */ |
783 | uint32_t reserved_2; | 771 | __le32 reserved_2; |
784 | uint8_t lun; | 772 | uint8_t lun; |
785 | uint8_t initiator_id; | 773 | uint8_t initiator_id; |
786 | uint8_t reserved_3; | 774 | uint8_t reserved_3; |
787 | uint8_t target_id; | 775 | uint8_t target_id; |
788 | uint32_t option_flags; | 776 | __le32 option_flags; |
789 | uint8_t status; | 777 | uint8_t status; |
790 | uint8_t event; | 778 | uint8_t event; |
791 | uint16_t seq_id; | 779 | __le16 seq_id; |
792 | uint16_t reserved_4[22]; | 780 | __le16 reserved_4[22]; |
793 | }; | 781 | }; |
794 | 782 | ||
795 | /* | 783 | /* |
@@ -801,12 +789,12 @@ struct atio_entry { | |||
801 | uint8_t entry_count; /* Entry count. */ | 789 | uint8_t entry_count; /* Entry count. */ |
802 | uint8_t reserved_1; | 790 | uint8_t reserved_1; |
803 | uint8_t entry_status; /* Entry Status. */ | 791 | uint8_t entry_status; /* Entry Status. */ |
804 | uint32_t reserved_2; | 792 | __le32 reserved_2; |
805 | uint8_t lun; | 793 | uint8_t lun; |
806 | uint8_t initiator_id; | 794 | uint8_t initiator_id; |
807 | uint8_t cdb_len; | 795 | uint8_t cdb_len; |
808 | uint8_t target_id; | 796 | uint8_t target_id; |
809 | uint32_t option_flags; | 797 | __le32 option_flags; |
810 | uint8_t status; | 798 | uint8_t status; |
811 | uint8_t scsi_status; | 799 | uint8_t scsi_status; |
812 | uint8_t tag_value; /* Received queue tag message value */ | 800 | uint8_t tag_value; /* Received queue tag message value */ |
@@ -824,28 +812,28 @@ struct ctio_entry { | |||
824 | uint8_t entry_count; /* Entry count. */ | 812 | uint8_t entry_count; /* Entry count. */ |
825 | uint8_t reserved_1; | 813 | uint8_t reserved_1; |
826 | uint8_t entry_status; /* Entry Status. */ | 814 | uint8_t entry_status; /* Entry Status. */ |
827 | uint32_t reserved_2; | 815 | __le32 reserved_2; |
828 | uint8_t lun; /* SCSI LUN */ | 816 | uint8_t lun; /* SCSI LUN */ |
829 | uint8_t initiator_id; | 817 | uint8_t initiator_id; |
830 | uint8_t reserved_3; | 818 | uint8_t reserved_3; |
831 | uint8_t target_id; | 819 | uint8_t target_id; |
832 | uint32_t option_flags; | 820 | __le32 option_flags; |
833 | uint8_t status; | 821 | uint8_t status; |
834 | uint8_t scsi_status; | 822 | uint8_t scsi_status; |
835 | uint8_t tag_value; /* Received queue tag message value */ | 823 | uint8_t tag_value; /* Received queue tag message value */ |
836 | uint8_t tag_type; /* Received queue tag message type */ | 824 | uint8_t tag_type; /* Received queue tag message type */ |
837 | uint32_t transfer_length; | 825 | __le32 transfer_length; |
838 | uint32_t residual; | 826 | __le32 residual; |
839 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | 827 | __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */ |
840 | uint16_t dseg_count; /* Data segment count. */ | 828 | __le16 dseg_count; /* Data segment count. */ |
841 | uint32_t dseg_0_address; /* Data segment 0 address. */ | 829 | __le32 dseg_0_address; /* Data segment 0 address. */ |
842 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 830 | __le32 dseg_0_length; /* Data segment 0 length. */ |
843 | uint32_t dseg_1_address; /* Data segment 1 address. */ | 831 | __le32 dseg_1_address; /* Data segment 1 address. */ |
844 | uint32_t dseg_1_length; /* Data segment 1 length. */ | 832 | __le32 dseg_1_length; /* Data segment 1 length. */ |
845 | uint32_t dseg_2_address; /* Data segment 2 address. */ | 833 | __le32 dseg_2_address; /* Data segment 2 address. */ |
846 | uint32_t dseg_2_length; /* Data segment 2 length. */ | 834 | __le32 dseg_2_length; /* Data segment 2 length. */ |
847 | uint32_t dseg_3_address; /* Data segment 3 address. */ | 835 | __le32 dseg_3_address; /* Data segment 3 address. */ |
848 | uint32_t dseg_3_length; /* Data segment 3 length. */ | 836 | __le32 dseg_3_length; /* Data segment 3 length. */ |
849 | }; | 837 | }; |
850 | 838 | ||
851 | /* | 839 | /* |
@@ -857,24 +845,24 @@ struct ctio_ret_entry { | |||
857 | uint8_t entry_count; /* Entry count. */ | 845 | uint8_t entry_count; /* Entry count. */ |
858 | uint8_t reserved_1; | 846 | uint8_t reserved_1; |
859 | uint8_t entry_status; /* Entry Status. */ | 847 | uint8_t entry_status; /* Entry Status. */ |
860 | uint32_t reserved_2; | 848 | __le32 reserved_2; |
861 | uint8_t lun; /* SCSI LUN */ | 849 | uint8_t lun; /* SCSI LUN */ |
862 | uint8_t initiator_id; | 850 | uint8_t initiator_id; |
863 | uint8_t reserved_3; | 851 | uint8_t reserved_3; |
864 | uint8_t target_id; | 852 | uint8_t target_id; |
865 | uint32_t option_flags; | 853 | __le32 option_flags; |
866 | uint8_t status; | 854 | uint8_t status; |
867 | uint8_t scsi_status; | 855 | uint8_t scsi_status; |
868 | uint8_t tag_value; /* Received queue tag message value */ | 856 | uint8_t tag_value; /* Received queue tag message value */ |
869 | uint8_t tag_type; /* Received queue tag message type */ | 857 | uint8_t tag_type; /* Received queue tag message type */ |
870 | uint32_t transfer_length; | 858 | __le32 transfer_length; |
871 | uint32_t residual; | 859 | __le32 residual; |
872 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | 860 | __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */ |
873 | uint16_t dseg_count; /* Data segment count. */ | 861 | __le16 dseg_count; /* Data segment count. */ |
874 | uint32_t dseg_0_address; /* Data segment 0 address. */ | 862 | __le32 dseg_0_address; /* Data segment 0 address. */ |
875 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 863 | __le32 dseg_0_length; /* Data segment 0 length. */ |
876 | uint32_t dseg_1_address; /* Data segment 1 address. */ | 864 | __le32 dseg_1_address; /* Data segment 1 address. */ |
877 | uint16_t dseg_1_length; /* Data segment 1 length. */ | 865 | __le16 dseg_1_length; /* Data segment 1 length. */ |
878 | uint8_t sense_data[18]; | 866 | uint8_t sense_data[18]; |
879 | }; | 867 | }; |
880 | 868 | ||
@@ -887,25 +875,25 @@ struct ctio_a64_entry { | |||
887 | uint8_t entry_count; /* Entry count. */ | 875 | uint8_t entry_count; /* Entry count. */ |
888 | uint8_t reserved_1; | 876 | uint8_t reserved_1; |
889 | uint8_t entry_status; /* Entry Status. */ | 877 | uint8_t entry_status; /* Entry Status. */ |
890 | uint32_t reserved_2; | 878 | __le32 reserved_2; |
891 | uint8_t lun; /* SCSI LUN */ | 879 | uint8_t lun; /* SCSI LUN */ |
892 | uint8_t initiator_id; | 880 | uint8_t initiator_id; |
893 | uint8_t reserved_3; | 881 | uint8_t reserved_3; |
894 | uint8_t target_id; | 882 | uint8_t target_id; |
895 | uint32_t option_flags; | 883 | __le32 option_flags; |
896 | uint8_t status; | 884 | uint8_t status; |
897 | uint8_t scsi_status; | 885 | uint8_t scsi_status; |
898 | uint8_t tag_value; /* Received queue tag message value */ | 886 | uint8_t tag_value; /* Received queue tag message value */ |
899 | uint8_t tag_type; /* Received queue tag message type */ | 887 | uint8_t tag_type; /* Received queue tag message type */ |
900 | uint32_t transfer_length; | 888 | __le32 transfer_length; |
901 | uint32_t residual; | 889 | __le32 residual; |
902 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | 890 | __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */ |
903 | uint16_t dseg_count; /* Data segment count. */ | 891 | __le16 dseg_count; /* Data segment count. */ |
904 | uint32_t reserved_4[2]; | 892 | __le32 reserved_4[2]; |
905 | uint32_t dseg_0_address[2]; /* Data segment 0 address. */ | 893 | __le32 dseg_0_address[2];/* Data segment 0 address. */ |
906 | uint32_t dseg_0_length; /* Data segment 0 length. */ | 894 | __le32 dseg_0_length; /* Data segment 0 length. */ |
907 | uint32_t dseg_1_address[2]; /* Data segment 1 address. */ | 895 | __le32 dseg_1_address[2];/* Data segment 1 address. */ |
908 | uint32_t dseg_1_length; /* Data segment 1 length. */ | 896 | __le32 dseg_1_length; /* Data segment 1 length. */ |
909 | }; | 897 | }; |
910 | 898 | ||
911 | /* | 899 | /* |
@@ -917,21 +905,21 @@ struct ctio_a64_ret_entry { | |||
917 | uint8_t entry_count; /* Entry count. */ | 905 | uint8_t entry_count; /* Entry count. */ |
918 | uint8_t reserved_1; | 906 | uint8_t reserved_1; |
919 | uint8_t entry_status; /* Entry Status. */ | 907 | uint8_t entry_status; /* Entry Status. */ |
920 | uint32_t reserved_2; | 908 | __le32 reserved_2; |
921 | uint8_t lun; /* SCSI LUN */ | 909 | uint8_t lun; /* SCSI LUN */ |
922 | uint8_t initiator_id; | 910 | uint8_t initiator_id; |
923 | uint8_t reserved_3; | 911 | uint8_t reserved_3; |
924 | uint8_t target_id; | 912 | uint8_t target_id; |
925 | uint32_t option_flags; | 913 | __le32 option_flags; |
926 | uint8_t status; | 914 | uint8_t status; |
927 | uint8_t scsi_status; | 915 | uint8_t scsi_status; |
928 | uint8_t tag_value; /* Received queue tag message value */ | 916 | uint8_t tag_value; /* Received queue tag message value */ |
929 | uint8_t tag_type; /* Received queue tag message type */ | 917 | uint8_t tag_type; /* Received queue tag message type */ |
930 | uint32_t transfer_length; | 918 | __le32 transfer_length; |
931 | uint32_t residual; | 919 | __le32 residual; |
932 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | 920 | __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */ |
933 | uint16_t dseg_count; /* Data segment count. */ | 921 | __le16 dseg_count; /* Data segment count. */ |
934 | uint16_t reserved_4[7]; | 922 | __le16 reserved_4[7]; |
935 | uint8_t sense_data[18]; | 923 | uint8_t sense_data[18]; |
936 | }; | 924 | }; |
937 | 925 | ||
@@ -979,14 +967,6 @@ struct ctio_a64_ret_entry { | |||
979 | #define CS_RETRY 0x82 /* Driver defined */ | 967 | #define CS_RETRY 0x82 /* Driver defined */ |
980 | 968 | ||
981 | /* | 969 | /* |
982 | * ISP status entry - SCSI status byte bit definitions. | ||
983 | */ | ||
984 | #define SS_CHECK_CONDITION BIT_1 | ||
985 | #define SS_CONDITION_MET BIT_2 | ||
986 | #define SS_BUSY_CONDITION BIT_3 | ||
987 | #define SS_RESERVE_CONFLICT (BIT_4 | BIT_3) | ||
988 | |||
989 | /* | ||
990 | * ISP target entries - Option flags bit definitions. | 970 | * ISP target entries - Option flags bit definitions. |
991 | */ | 971 | */ |
992 | #define OF_ENABLE_TAG BIT_1 /* Tagged queue action enable */ | 972 | #define OF_ENABLE_TAG BIT_1 /* Tagged queue action enable */ |
@@ -1082,10 +1062,6 @@ struct scsi_qla_host { | |||
1082 | uint32_t reset_active:1; /* 3 */ | 1062 | uint32_t reset_active:1; /* 3 */ |
1083 | uint32_t abort_isp_active:1; /* 4 */ | 1063 | uint32_t abort_isp_active:1; /* 4 */ |
1084 | uint32_t disable_risc_code_load:1; /* 5 */ | 1064 | uint32_t disable_risc_code_load:1; /* 5 */ |
1085 | uint32_t enable_64bit_addressing:1; /* 6 */ | ||
1086 | uint32_t in_reset:1; /* 7 */ | ||
1087 | uint32_t ints_enabled:1; | ||
1088 | uint32_t ignore_nvram:1; | ||
1089 | #ifdef __ia64__ | 1065 | #ifdef __ia64__ |
1090 | uint32_t use_pci_vchannel:1; | 1066 | uint32_t use_pci_vchannel:1; |
1091 | #endif | 1067 | #endif |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d14523d7e449..a780546eda9c 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask) | |||
268 | } else | 268 | } else |
269 | put_device(&dev->sdev_gendev); | 269 | put_device(&dev->sdev_gendev); |
270 | 270 | ||
271 | cmd->jiffies_at_alloc = jiffies; | ||
271 | return cmd; | 272 | return cmd; |
272 | } | 273 | } |
273 | EXPORT_SYMBOL(scsi_get_command); | 274 | EXPORT_SYMBOL(scsi_get_command); |
@@ -627,7 +628,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) | |||
627 | spin_lock_irqsave(host->host_lock, flags); | 628 | spin_lock_irqsave(host->host_lock, flags); |
628 | scsi_cmd_get_serial(host, cmd); | 629 | scsi_cmd_get_serial(host, cmd); |
629 | 630 | ||
630 | if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) { | 631 | if (unlikely(host->shost_state == SHOST_DEL)) { |
631 | cmd->result = (DID_NO_CONNECT << 16); | 632 | cmd->result = (DID_NO_CONNECT << 16); |
632 | scsi_done(cmd); | 633 | scsi_done(cmd); |
633 | } else { | 634 | } else { |
@@ -798,9 +799,23 @@ static void scsi_softirq(struct softirq_action *h) | |||
798 | while (!list_empty(&local_q)) { | 799 | while (!list_empty(&local_q)) { |
799 | struct scsi_cmnd *cmd = list_entry(local_q.next, | 800 | struct scsi_cmnd *cmd = list_entry(local_q.next, |
800 | struct scsi_cmnd, eh_entry); | 801 | struct scsi_cmnd, eh_entry); |
802 | /* The longest time any command should be outstanding is the | ||
803 | * per command timeout multiplied by the number of retries. | ||
804 | * | ||
805 | * For a typical command, this is 2.5 minutes */ | ||
806 | unsigned long wait_for | ||
807 | = cmd->allowed * cmd->timeout_per_command; | ||
801 | list_del_init(&cmd->eh_entry); | 808 | list_del_init(&cmd->eh_entry); |
802 | 809 | ||
803 | disposition = scsi_decide_disposition(cmd); | 810 | disposition = scsi_decide_disposition(cmd); |
811 | if (disposition != SUCCESS && | ||
812 | time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { | ||
813 | dev_printk(KERN_ERR, &cmd->device->sdev_gendev, | ||
814 | "timing out command, waited %lus\n", | ||
815 | wait_for/HZ); | ||
816 | disposition = SUCCESS; | ||
817 | } | ||
818 | |||
804 | scsi_log_completion(cmd, disposition); | 819 | scsi_log_completion(cmd, disposition); |
805 | switch (disposition) { | 820 | switch (disposition) { |
806 | case SUCCESS: | 821 | case SUCCESS: |
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 6121dc1bfada..b444ec2e1c64 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c | |||
@@ -114,6 +114,7 @@ static struct { | |||
114 | {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ | 114 | {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ |
115 | {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ | 115 | {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ |
116 | {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */ | 116 | {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */ |
117 | {"", "Scanner", "1.80", BLIST_NOLUN}, /* responds to all lun */ | ||
117 | 118 | ||
118 | /* | 119 | /* |
119 | * Other types of devices that have special flags. | 120 | * Other types of devices that have special flags. |
@@ -135,7 +136,7 @@ static struct { | |||
135 | {"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, | 136 | {"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, |
136 | {"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD}, | 137 | {"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD}, |
137 | {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, | 138 | {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, |
138 | {"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, | 139 | {"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD}, |
139 | {"DELL", "PV660F", NULL, BLIST_SPARSELUN}, | 140 | {"DELL", "PV660F", NULL, BLIST_SPARSELUN}, |
140 | {"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN}, | 141 | {"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN}, |
141 | {"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */ | 142 | {"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */ |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 0fc8b48f052b..e9c451ba71fc 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -75,7 +75,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
75 | 75 | ||
76 | scmd->eh_eflags |= eh_flag; | 76 | scmd->eh_eflags |= eh_flag; |
77 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); | 77 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); |
78 | set_bit(SHOST_RECOVERY, &shost->shost_state); | 78 | scsi_host_set_state(shost, SHOST_RECOVERY); |
79 | shost->host_failed++; | 79 | shost->host_failed++; |
80 | scsi_eh_wakeup(shost); | 80 | scsi_eh_wakeup(shost); |
81 | spin_unlock_irqrestore(shost->host_lock, flags); | 81 | spin_unlock_irqrestore(shost->host_lock, flags); |
@@ -197,7 +197,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) | |||
197 | { | 197 | { |
198 | int online; | 198 | int online; |
199 | 199 | ||
200 | wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state))); | 200 | wait_event(sdev->host->host_wait, (sdev->host->shost_state != |
201 | SHOST_RECOVERY)); | ||
201 | 202 | ||
202 | online = scsi_device_online(sdev); | 203 | online = scsi_device_online(sdev); |
203 | 204 | ||
@@ -1458,7 +1459,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1458 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", | 1459 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", |
1459 | __FUNCTION__)); | 1460 | __FUNCTION__)); |
1460 | 1461 | ||
1461 | clear_bit(SHOST_RECOVERY, &shost->shost_state); | 1462 | scsi_host_set_state(shost, SHOST_RUNNING); |
1462 | 1463 | ||
1463 | wake_up(&shost->host_wait); | 1464 | wake_up(&shost->host_wait); |
1464 | 1465 | ||
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 7a6b530115ac..f5bf5c07be91 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -475,8 +475,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | |||
475 | * error processing, as long as the device was opened | 475 | * error processing, as long as the device was opened |
476 | * non-blocking */ | 476 | * non-blocking */ |
477 | if (filp && filp->f_flags & O_NONBLOCK) { | 477 | if (filp && filp->f_flags & O_NONBLOCK) { |
478 | if (test_bit(SHOST_RECOVERY, | 478 | if (sdev->host->shost_state == SHOST_RECOVERY) |
479 | &sdev->host->shost_state)) | ||
480 | return -ENODEV; | 479 | return -ENODEV; |
481 | } else if (!scsi_block_when_processing_errors(sdev)) | 480 | } else if (!scsi_block_when_processing_errors(sdev)) |
482 | return -ENODEV; | 481 | return -ENODEV; |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b8212c563fed..278e0c99b2ae 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -400,7 +400,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) | |||
400 | 400 | ||
401 | spin_lock_irqsave(shost->host_lock, flags); | 401 | spin_lock_irqsave(shost->host_lock, flags); |
402 | shost->host_busy--; | 402 | shost->host_busy--; |
403 | if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) && | 403 | if (unlikely((shost->shost_state == SHOST_RECOVERY) && |
404 | shost->host_failed)) | 404 | shost->host_failed)) |
405 | scsi_eh_wakeup(shost); | 405 | scsi_eh_wakeup(shost); |
406 | spin_unlock(shost->host_lock); | 406 | spin_unlock(shost->host_lock); |
@@ -1281,7 +1281,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, | |||
1281 | struct Scsi_Host *shost, | 1281 | struct Scsi_Host *shost, |
1282 | struct scsi_device *sdev) | 1282 | struct scsi_device *sdev) |
1283 | { | 1283 | { |
1284 | if (test_bit(SHOST_RECOVERY, &shost->shost_state)) | 1284 | if (shost->shost_state == SHOST_RECOVERY) |
1285 | return 0; | 1285 | return 0; |
1286 | if (shost->host_busy == 0 && shost->host_blocked) { | 1286 | if (shost->host_busy == 0 && shost->host_blocked) { |
1287 | /* | 1287 | /* |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d2ca4b8fbc13..0048beaffc9f 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -1251,9 +1251,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1251 | 1251 | ||
1252 | get_device(&starget->dev); | 1252 | get_device(&starget->dev); |
1253 | down(&shost->scan_mutex); | 1253 | down(&shost->scan_mutex); |
1254 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); | 1254 | if (scsi_host_scan_allowed(shost)) { |
1255 | if (res != SCSI_SCAN_LUN_PRESENT) | 1255 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, |
1256 | sdev = ERR_PTR(-ENODEV); | 1256 | hostdata); |
1257 | if (res != SCSI_SCAN_LUN_PRESENT) | ||
1258 | sdev = ERR_PTR(-ENODEV); | ||
1259 | } | ||
1257 | up(&shost->scan_mutex); | 1260 | up(&shost->scan_mutex); |
1258 | scsi_target_reap(starget); | 1261 | scsi_target_reap(starget); |
1259 | put_device(&starget->dev); | 1262 | put_device(&starget->dev); |
@@ -1403,11 +1406,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1403 | return -EINVAL; | 1406 | return -EINVAL; |
1404 | 1407 | ||
1405 | down(&shost->scan_mutex); | 1408 | down(&shost->scan_mutex); |
1406 | if (channel == SCAN_WILD_CARD) | 1409 | if (scsi_host_scan_allowed(shost)) { |
1407 | for (channel = 0; channel <= shost->max_channel; channel++) | 1410 | if (channel == SCAN_WILD_CARD) |
1411 | for (channel = 0; channel <= shost->max_channel; | ||
1412 | channel++) | ||
1413 | scsi_scan_channel(shost, channel, id, lun, | ||
1414 | rescan); | ||
1415 | else | ||
1408 | scsi_scan_channel(shost, channel, id, lun, rescan); | 1416 | scsi_scan_channel(shost, channel, id, lun, rescan); |
1409 | else | 1417 | } |
1410 | scsi_scan_channel(shost, channel, id, lun, rescan); | ||
1411 | up(&shost->scan_mutex); | 1418 | up(&shost->scan_mutex); |
1412 | 1419 | ||
1413 | return 0; | 1420 | return 0; |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index beed7fbe1cbe..dae59d1da07a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -48,6 +48,30 @@ const char *scsi_device_state_name(enum scsi_device_state state) | |||
48 | return name; | 48 | return name; |
49 | } | 49 | } |
50 | 50 | ||
51 | static struct { | ||
52 | enum scsi_host_state value; | ||
53 | char *name; | ||
54 | } shost_states[] = { | ||
55 | { SHOST_CREATED, "created" }, | ||
56 | { SHOST_RUNNING, "running" }, | ||
57 | { SHOST_CANCEL, "cancel" }, | ||
58 | { SHOST_DEL, "deleted" }, | ||
59 | { SHOST_RECOVERY, "recovery" }, | ||
60 | }; | ||
61 | const char *scsi_host_state_name(enum scsi_host_state state) | ||
62 | { | ||
63 | int i; | ||
64 | char *name = NULL; | ||
65 | |||
66 | for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { | ||
67 | if (shost_states[i].value == state) { | ||
68 | name = shost_states[i].name; | ||
69 | break; | ||
70 | } | ||
71 | } | ||
72 | return name; | ||
73 | } | ||
74 | |||
51 | static int check_set(unsigned int *val, char *src) | 75 | static int check_set(unsigned int *val, char *src) |
52 | { | 76 | { |
53 | char *last; | 77 | char *last; |
@@ -124,6 +148,43 @@ static ssize_t store_scan(struct class_device *class_dev, const char *buf, | |||
124 | }; | 148 | }; |
125 | static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); | 149 | static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); |
126 | 150 | ||
151 | static ssize_t | ||
152 | store_shost_state(struct class_device *class_dev, const char *buf, size_t count) | ||
153 | { | ||
154 | int i; | ||
155 | struct Scsi_Host *shost = class_to_shost(class_dev); | ||
156 | enum scsi_host_state state = 0; | ||
157 | |||
158 | for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { | ||
159 | const int len = strlen(shost_states[i].name); | ||
160 | if (strncmp(shost_states[i].name, buf, len) == 0 && | ||
161 | buf[len] == '\n') { | ||
162 | state = shost_states[i].value; | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | if (!state) | ||
167 | return -EINVAL; | ||
168 | |||
169 | if (scsi_host_set_state(shost, state)) | ||
170 | return -EINVAL; | ||
171 | return count; | ||
172 | } | ||
173 | |||
174 | static ssize_t | ||
175 | show_shost_state(struct class_device *class_dev, char *buf) | ||
176 | { | ||
177 | struct Scsi_Host *shost = class_to_shost(class_dev); | ||
178 | const char *name = scsi_host_state_name(shost->shost_state); | ||
179 | |||
180 | if (!name) | ||
181 | return -EINVAL; | ||
182 | |||
183 | return snprintf(buf, 20, "%s\n", name); | ||
184 | } | ||
185 | |||
186 | static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state); | ||
187 | |||
127 | shost_rd_attr(unique_id, "%u\n"); | 188 | shost_rd_attr(unique_id, "%u\n"); |
128 | shost_rd_attr(host_busy, "%hu\n"); | 189 | shost_rd_attr(host_busy, "%hu\n"); |
129 | shost_rd_attr(cmd_per_lun, "%hd\n"); | 190 | shost_rd_attr(cmd_per_lun, "%hd\n"); |
@@ -139,6 +200,7 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { | |||
139 | &class_device_attr_unchecked_isa_dma, | 200 | &class_device_attr_unchecked_isa_dma, |
140 | &class_device_attr_proc_name, | 201 | &class_device_attr_proc_name, |
141 | &class_device_attr_scan, | 202 | &class_device_attr_scan, |
203 | &class_device_attr_state, | ||
142 | NULL | 204 | NULL |
143 | }; | 205 | }; |
144 | 206 | ||
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index e6412fce423c..2cab556b6e82 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -252,7 +252,8 @@ struct fc_internal { | |||
252 | 252 | ||
253 | #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) | 253 | #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) |
254 | 254 | ||
255 | static int fc_target_setup(struct device *dev) | 255 | static int fc_target_setup(struct transport_container *tc, struct device *dev, |
256 | struct class_device *cdev) | ||
256 | { | 257 | { |
257 | struct scsi_target *starget = to_scsi_target(dev); | 258 | struct scsi_target *starget = to_scsi_target(dev); |
258 | struct fc_rport *rport = starget_to_rport(starget); | 259 | struct fc_rport *rport = starget_to_rport(starget); |
@@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class, | |||
281 | NULL, | 282 | NULL, |
282 | NULL); | 283 | NULL); |
283 | 284 | ||
284 | static int fc_host_setup(struct device *dev) | 285 | static int fc_host_setup(struct transport_container *tc, struct device *dev, |
286 | struct class_device *cdev) | ||
285 | { | 287 | { |
286 | struct Scsi_Host *shost = dev_to_shost(dev); | 288 | struct Scsi_Host *shost = dev_to_shost(dev); |
287 | 289 | ||
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 7670919a087a..89f6b7feb9c2 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) | 36 | #define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) |
37 | 37 | ||
38 | #define SPI_NUM_ATTRS 13 /* increase this if you add attributes */ | 38 | #define SPI_NUM_ATTRS 14 /* increase this if you add attributes */ |
39 | #define SPI_OTHER_ATTRS 1 /* Increase this if you add "always | 39 | #define SPI_OTHER_ATTRS 1 /* Increase this if you add "always |
40 | * on" attributes */ | 40 | * on" attributes */ |
41 | #define SPI_HOST_ATTRS 1 | 41 | #define SPI_HOST_ATTRS 1 |
@@ -162,7 +162,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name) | |||
162 | return SPI_SIGNAL_UNKNOWN; | 162 | return SPI_SIGNAL_UNKNOWN; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int spi_host_setup(struct device *dev) | 165 | static int spi_host_setup(struct transport_container *tc, struct device *dev, |
166 | struct class_device *cdev) | ||
166 | { | 167 | { |
167 | struct Scsi_Host *shost = dev_to_shost(dev); | 168 | struct Scsi_Host *shost = dev_to_shost(dev); |
168 | 169 | ||
@@ -196,7 +197,9 @@ static int spi_host_match(struct attribute_container *cont, | |||
196 | return &i->t.host_attrs.ac == cont; | 197 | return &i->t.host_attrs.ac == cont; |
197 | } | 198 | } |
198 | 199 | ||
199 | static int spi_device_configure(struct device *dev) | 200 | static int spi_device_configure(struct transport_container *tc, |
201 | struct device *dev, | ||
202 | struct class_device *cdev) | ||
200 | { | 203 | { |
201 | struct scsi_device *sdev = to_scsi_device(dev); | 204 | struct scsi_device *sdev = to_scsi_device(dev); |
202 | struct scsi_target *starget = sdev->sdev_target; | 205 | struct scsi_target *starget = sdev->sdev_target; |
@@ -214,7 +217,9 @@ static int spi_device_configure(struct device *dev) | |||
214 | return 0; | 217 | return 0; |
215 | } | 218 | } |
216 | 219 | ||
217 | static int spi_setup_transport_attrs(struct device *dev) | 220 | static int spi_setup_transport_attrs(struct transport_container *tc, |
221 | struct device *dev, | ||
222 | struct class_device *cdev) | ||
218 | { | 223 | { |
219 | struct scsi_target *starget = to_scsi_target(dev); | 224 | struct scsi_target *starget = to_scsi_target(dev); |
220 | 225 | ||
@@ -231,6 +236,7 @@ static int spi_setup_transport_attrs(struct device *dev) | |||
231 | spi_rd_strm(starget) = 0; | 236 | spi_rd_strm(starget) = 0; |
232 | spi_rti(starget) = 0; | 237 | spi_rti(starget) = 0; |
233 | spi_pcomp_en(starget) = 0; | 238 | spi_pcomp_en(starget) = 0; |
239 | spi_hold_mcs(starget) = 0; | ||
234 | spi_dv_pending(starget) = 0; | 240 | spi_dv_pending(starget) = 0; |
235 | spi_initial_dv(starget) = 0; | 241 | spi_initial_dv(starget) = 0; |
236 | init_MUTEX(&spi_dv_sem(starget)); | 242 | init_MUTEX(&spi_dv_sem(starget)); |
@@ -347,6 +353,7 @@ spi_transport_rd_attr(wr_flow, "%d\n"); | |||
347 | spi_transport_rd_attr(rd_strm, "%d\n"); | 353 | spi_transport_rd_attr(rd_strm, "%d\n"); |
348 | spi_transport_rd_attr(rti, "%d\n"); | 354 | spi_transport_rd_attr(rti, "%d\n"); |
349 | spi_transport_rd_attr(pcomp_en, "%d\n"); | 355 | spi_transport_rd_attr(pcomp_en, "%d\n"); |
356 | spi_transport_rd_attr(hold_mcs, "%d\n"); | ||
350 | 357 | ||
351 | /* we only care about the first child device so we return 1 */ | 358 | /* we only care about the first child device so we return 1 */ |
352 | static int child_iter(struct device *dev, void *data) | 359 | static int child_iter(struct device *dev, void *data) |
@@ -1028,10 +1035,17 @@ void spi_display_xfer_agreement(struct scsi_target *starget) | |||
1028 | sprint_frac(tmp, picosec, 1000); | 1035 | sprint_frac(tmp, picosec, 1000); |
1029 | 1036 | ||
1030 | dev_info(&starget->dev, | 1037 | dev_info(&starget->dev, |
1031 | "%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n", | 1038 | "%s %sSCSI %d.%d MB/s %s%s%s%s%s%s%s%s (%s ns, offset %d)\n", |
1032 | scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10, | 1039 | scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10, |
1033 | tp->dt ? "DT" : "ST", tp->iu ? " IU" : "", | 1040 | tp->dt ? "DT" : "ST", |
1034 | tp->qas ? " QAS" : "", tmp, tp->offset); | 1041 | tp->iu ? " IU" : "", |
1042 | tp->qas ? " QAS" : "", | ||
1043 | tp->rd_strm ? " RDSTRM" : "", | ||
1044 | tp->rti ? " RTI" : "", | ||
1045 | tp->wr_flow ? " WRFLOW" : "", | ||
1046 | tp->pcomp_en ? " PCOMP" : "", | ||
1047 | tp->hold_mcs ? " HMCS" : "", | ||
1048 | tmp, tp->offset); | ||
1035 | } else { | 1049 | } else { |
1036 | dev_info(&starget->dev, "%sasynchronous.\n", | 1050 | dev_info(&starget->dev, "%sasynchronous.\n", |
1037 | tp->width ? "wide " : ""); | 1051 | tp->width ? "wide " : ""); |
@@ -1073,6 +1087,7 @@ static int spi_device_match(struct attribute_container *cont, | |||
1073 | { | 1087 | { |
1074 | struct scsi_device *sdev; | 1088 | struct scsi_device *sdev; |
1075 | struct Scsi_Host *shost; | 1089 | struct Scsi_Host *shost; |
1090 | struct spi_internal *i; | ||
1076 | 1091 | ||
1077 | if (!scsi_is_sdev_device(dev)) | 1092 | if (!scsi_is_sdev_device(dev)) |
1078 | return 0; | 1093 | return 0; |
@@ -1085,6 +1100,9 @@ static int spi_device_match(struct attribute_container *cont, | |||
1085 | /* Note: this class has no device attributes, so it has | 1100 | /* Note: this class has no device attributes, so it has |
1086 | * no per-HBA allocation and thus we don't need to distinguish | 1101 | * no per-HBA allocation and thus we don't need to distinguish |
1087 | * the attribute containers for the device */ | 1102 | * the attribute containers for the device */ |
1103 | i = to_spi_internal(shost->transportt); | ||
1104 | if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target)) | ||
1105 | return 0; | ||
1088 | return 1; | 1106 | return 1; |
1089 | } | 1107 | } |
1090 | 1108 | ||
@@ -1092,6 +1110,7 @@ static int spi_target_match(struct attribute_container *cont, | |||
1092 | struct device *dev) | 1110 | struct device *dev) |
1093 | { | 1111 | { |
1094 | struct Scsi_Host *shost; | 1112 | struct Scsi_Host *shost; |
1113 | struct scsi_target *starget; | ||
1095 | struct spi_internal *i; | 1114 | struct spi_internal *i; |
1096 | 1115 | ||
1097 | if (!scsi_is_target_device(dev)) | 1116 | if (!scsi_is_target_device(dev)) |
@@ -1103,7 +1122,11 @@ static int spi_target_match(struct attribute_container *cont, | |||
1103 | return 0; | 1122 | return 0; |
1104 | 1123 | ||
1105 | i = to_spi_internal(shost->transportt); | 1124 | i = to_spi_internal(shost->transportt); |
1106 | 1125 | starget = to_scsi_target(dev); | |
1126 | |||
1127 | if (i->f->deny_binding && i->f->deny_binding(starget)) | ||
1128 | return 0; | ||
1129 | |||
1107 | return &i->t.target_attrs.ac == cont; | 1130 | return &i->t.target_attrs.ac == cont; |
1108 | } | 1131 | } |
1109 | 1132 | ||
@@ -1154,6 +1177,7 @@ spi_attach_transport(struct spi_function_template *ft) | |||
1154 | SETUP_ATTRIBUTE(rd_strm); | 1177 | SETUP_ATTRIBUTE(rd_strm); |
1155 | SETUP_ATTRIBUTE(rti); | 1178 | SETUP_ATTRIBUTE(rti); |
1156 | SETUP_ATTRIBUTE(pcomp_en); | 1179 | SETUP_ATTRIBUTE(pcomp_en); |
1180 | SETUP_ATTRIBUTE(hold_mcs); | ||
1157 | 1181 | ||
1158 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS | 1182 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS |
1159 | * this bug will trigger */ | 1183 | * this bug will trigger */ |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index e822ca0e97cf..052d55c167d4 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1027,8 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
1027 | if (sdp->detached) | 1027 | if (sdp->detached) |
1028 | return -ENODEV; | 1028 | return -ENODEV; |
1029 | if (filp->f_flags & O_NONBLOCK) { | 1029 | if (filp->f_flags & O_NONBLOCK) { |
1030 | if (test_bit(SHOST_RECOVERY, | 1030 | if (sdp->device->host->shost_state == SHOST_RECOVERY) |
1031 | &sdp->device->host->shost_state)) | ||
1032 | return -EBUSY; | 1031 | return -EBUSY; |
1033 | } else if (!scsi_block_when_processing_errors(sdp->device)) | 1032 | } else if (!scsi_block_when_processing_errors(sdp->device)) |
1034 | return -EBUSY; | 1033 | return -EBUSY; |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0a7839db5752..9aadf2fcad6a 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -17,7 +17,7 @@ | |||
17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support | 17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support |
18 | */ | 18 | */ |
19 | 19 | ||
20 | static char *verstr = "20050501"; | 20 | static char *verstr = "20050802"; |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | 23 | ||
@@ -219,6 +219,12 @@ static int switch_partition(struct scsi_tape *); | |||
219 | 219 | ||
220 | static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long); | 220 | static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long); |
221 | 221 | ||
222 | static void scsi_tape_release(struct kref *); | ||
223 | |||
224 | #define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref) | ||
225 | |||
226 | static DECLARE_MUTEX(st_ref_sem); | ||
227 | |||
222 | 228 | ||
223 | #include "osst_detect.h" | 229 | #include "osst_detect.h" |
224 | #ifndef SIGS_FROM_OSST | 230 | #ifndef SIGS_FROM_OSST |
@@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long); | |||
230 | {"OnStream", "FW-", "", "osst"} | 236 | {"OnStream", "FW-", "", "osst"} |
231 | #endif | 237 | #endif |
232 | 238 | ||
239 | static struct scsi_tape *scsi_tape_get(int dev) | ||
240 | { | ||
241 | struct scsi_tape *STp = NULL; | ||
242 | |||
243 | down(&st_ref_sem); | ||
244 | write_lock(&st_dev_arr_lock); | ||
245 | |||
246 | if (dev < st_dev_max && scsi_tapes != NULL) | ||
247 | STp = scsi_tapes[dev]; | ||
248 | if (!STp) goto out; | ||
249 | |||
250 | kref_get(&STp->kref); | ||
251 | |||
252 | if (!STp->device) | ||
253 | goto out_put; | ||
254 | |||
255 | if (scsi_device_get(STp->device)) | ||
256 | goto out_put; | ||
257 | |||
258 | goto out; | ||
259 | |||
260 | out_put: | ||
261 | kref_put(&STp->kref, scsi_tape_release); | ||
262 | STp = NULL; | ||
263 | out: | ||
264 | write_unlock(&st_dev_arr_lock); | ||
265 | up(&st_ref_sem); | ||
266 | return STp; | ||
267 | } | ||
268 | |||
269 | static void scsi_tape_put(struct scsi_tape *STp) | ||
270 | { | ||
271 | struct scsi_device *sdev = STp->device; | ||
272 | |||
273 | down(&st_ref_sem); | ||
274 | kref_put(&STp->kref, scsi_tape_release); | ||
275 | scsi_device_put(sdev); | ||
276 | up(&st_ref_sem); | ||
277 | } | ||
278 | |||
233 | struct st_reject_data { | 279 | struct st_reject_data { |
234 | char *vendor; | 280 | char *vendor; |
235 | char *model; | 281 | char *model; |
@@ -311,7 +357,7 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt) | |||
311 | return 0; | 357 | return 0; |
312 | 358 | ||
313 | cmdstatp = &STp->buffer->cmdstat; | 359 | cmdstatp = &STp->buffer->cmdstat; |
314 | st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp); | 360 | st_analyze_sense(SRpnt, cmdstatp); |
315 | 361 | ||
316 | if (cmdstatp->have_sense) | 362 | if (cmdstatp->have_sense) |
317 | scode = STp->buffer->cmdstat.sense_hdr.sense_key; | 363 | scode = STp->buffer->cmdstat.sense_hdr.sense_key; |
@@ -399,10 +445,10 @@ static void st_sleep_done(struct scsi_cmnd * SCpnt) | |||
399 | 445 | ||
400 | (STp->buffer)->cmdstat.midlevel_result = SCpnt->result; | 446 | (STp->buffer)->cmdstat.midlevel_result = SCpnt->result; |
401 | SCpnt->request->rq_status = RQ_SCSI_DONE; | 447 | SCpnt->request->rq_status = RQ_SCSI_DONE; |
402 | (STp->buffer)->last_SRpnt = SCpnt->sc_request; | ||
403 | DEB( STp->write_pending = 0; ) | 448 | DEB( STp->write_pending = 0; ) |
404 | 449 | ||
405 | complete(SCpnt->request->waiting); | 450 | if (SCpnt->request->waiting) |
451 | complete(SCpnt->request->waiting); | ||
406 | } | 452 | } |
407 | 453 | ||
408 | /* Do the scsi command. Waits until command performed if do_wait is true. | 454 | /* Do the scsi command. Waits until command performed if do_wait is true. |
@@ -412,8 +458,20 @@ static struct scsi_request * | |||
412 | st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd, | 458 | st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd, |
413 | int bytes, int direction, int timeout, int retries, int do_wait) | 459 | int bytes, int direction, int timeout, int retries, int do_wait) |
414 | { | 460 | { |
461 | struct completion *waiting; | ||
415 | unsigned char *bp; | 462 | unsigned char *bp; |
416 | 463 | ||
464 | /* if async, make sure there's no command outstanding */ | ||
465 | if (!do_wait && ((STp->buffer)->last_SRpnt)) { | ||
466 | printk(KERN_ERR "%s: Async command already active.\n", | ||
467 | tape_name(STp)); | ||
468 | if (signal_pending(current)) | ||
469 | (STp->buffer)->syscall_result = (-EINTR); | ||
470 | else | ||
471 | (STp->buffer)->syscall_result = (-EBUSY); | ||
472 | return NULL; | ||
473 | } | ||
474 | |||
417 | if (SRpnt == NULL) { | 475 | if (SRpnt == NULL) { |
418 | SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC); | 476 | SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC); |
419 | if (SRpnt == NULL) { | 477 | if (SRpnt == NULL) { |
@@ -427,7 +485,13 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c | |||
427 | } | 485 | } |
428 | } | 486 | } |
429 | 487 | ||
430 | init_completion(&STp->wait); | 488 | /* If async IO, set last_SRpnt. This ptr tells write_behind_check |
489 | which IO is outstanding. It's nulled out when the IO completes. */ | ||
490 | if (!do_wait) | ||
491 | (STp->buffer)->last_SRpnt = SRpnt; | ||
492 | |||
493 | waiting = &STp->wait; | ||
494 | init_completion(waiting); | ||
431 | SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length); | 495 | SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length); |
432 | if (SRpnt->sr_use_sg) { | 496 | if (SRpnt->sr_use_sg) { |
433 | if (!STp->buffer->do_dio) | 497 | if (!STp->buffer->do_dio) |
@@ -438,17 +502,20 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c | |||
438 | bp = (STp->buffer)->b_data; | 502 | bp = (STp->buffer)->b_data; |
439 | SRpnt->sr_data_direction = direction; | 503 | SRpnt->sr_data_direction = direction; |
440 | SRpnt->sr_cmd_len = 0; | 504 | SRpnt->sr_cmd_len = 0; |
441 | SRpnt->sr_request->waiting = &(STp->wait); | 505 | SRpnt->sr_request->waiting = waiting; |
442 | SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; | 506 | SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; |
443 | SRpnt->sr_request->rq_disk = STp->disk; | 507 | SRpnt->sr_request->rq_disk = STp->disk; |
508 | SRpnt->sr_request->end_io = blk_end_sync_rq; | ||
444 | STp->buffer->cmdstat.have_sense = 0; | 509 | STp->buffer->cmdstat.have_sense = 0; |
445 | 510 | ||
446 | scsi_do_req(SRpnt, (void *) cmd, bp, bytes, | 511 | scsi_do_req(SRpnt, (void *) cmd, bp, bytes, |
447 | st_sleep_done, timeout, retries); | 512 | st_sleep_done, timeout, retries); |
448 | 513 | ||
449 | if (do_wait) { | 514 | if (do_wait) { |
450 | wait_for_completion(SRpnt->sr_request->waiting); | 515 | wait_for_completion(waiting); |
451 | SRpnt->sr_request->waiting = NULL; | 516 | SRpnt->sr_request->waiting = NULL; |
517 | if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE) | ||
518 | SRpnt->sr_result |= (DRIVER_ERROR << 24); | ||
452 | (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt); | 519 | (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt); |
453 | } | 520 | } |
454 | return SRpnt; | 521 | return SRpnt; |
@@ -465,6 +532,7 @@ static int write_behind_check(struct scsi_tape * STp) | |||
465 | struct st_buffer *STbuffer; | 532 | struct st_buffer *STbuffer; |
466 | struct st_partstat *STps; | 533 | struct st_partstat *STps; |
467 | struct st_cmdstatus *cmdstatp; | 534 | struct st_cmdstatus *cmdstatp; |
535 | struct scsi_request *SRpnt; | ||
468 | 536 | ||
469 | STbuffer = STp->buffer; | 537 | STbuffer = STp->buffer; |
470 | if (!STbuffer->writing) | 538 | if (!STbuffer->writing) |
@@ -478,10 +546,14 @@ static int write_behind_check(struct scsi_tape * STp) | |||
478 | ) /* end DEB */ | 546 | ) /* end DEB */ |
479 | 547 | ||
480 | wait_for_completion(&(STp->wait)); | 548 | wait_for_completion(&(STp->wait)); |
481 | (STp->buffer)->last_SRpnt->sr_request->waiting = NULL; | 549 | SRpnt = STbuffer->last_SRpnt; |
550 | STbuffer->last_SRpnt = NULL; | ||
551 | SRpnt->sr_request->waiting = NULL; | ||
552 | if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE) | ||
553 | SRpnt->sr_result |= (DRIVER_ERROR << 24); | ||
482 | 554 | ||
483 | (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt); | 555 | (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt); |
484 | scsi_release_request((STp->buffer)->last_SRpnt); | 556 | scsi_release_request(SRpnt); |
485 | 557 | ||
486 | STbuffer->buffer_bytes -= STbuffer->writing; | 558 | STbuffer->buffer_bytes -= STbuffer->writing; |
487 | STps = &(STp->ps[STp->partition]); | 559 | STps = &(STp->ps[STp->partition]); |
@@ -1055,25 +1127,20 @@ static int st_open(struct inode *inode, struct file *filp) | |||
1055 | */ | 1127 | */ |
1056 | filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); | 1128 | filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); |
1057 | 1129 | ||
1130 | if (!(STp = scsi_tape_get(dev))) | ||
1131 | return -ENXIO; | ||
1132 | |||
1058 | write_lock(&st_dev_arr_lock); | 1133 | write_lock(&st_dev_arr_lock); |
1059 | if (dev >= st_dev_max || scsi_tapes == NULL || | ||
1060 | ((STp = scsi_tapes[dev]) == NULL)) { | ||
1061 | write_unlock(&st_dev_arr_lock); | ||
1062 | return (-ENXIO); | ||
1063 | } | ||
1064 | filp->private_data = STp; | 1134 | filp->private_data = STp; |
1065 | name = tape_name(STp); | 1135 | name = tape_name(STp); |
1066 | 1136 | ||
1067 | if (STp->in_use) { | 1137 | if (STp->in_use) { |
1068 | write_unlock(&st_dev_arr_lock); | 1138 | write_unlock(&st_dev_arr_lock); |
1139 | scsi_tape_put(STp); | ||
1069 | DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) | 1140 | DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) |
1070 | return (-EBUSY); | 1141 | return (-EBUSY); |
1071 | } | 1142 | } |
1072 | 1143 | ||
1073 | if(scsi_device_get(STp->device)) { | ||
1074 | write_unlock(&st_dev_arr_lock); | ||
1075 | return (-ENXIO); | ||
1076 | } | ||
1077 | STp->in_use = 1; | 1144 | STp->in_use = 1; |
1078 | write_unlock(&st_dev_arr_lock); | 1145 | write_unlock(&st_dev_arr_lock); |
1079 | STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0; | 1146 | STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0; |
@@ -1118,7 +1185,7 @@ static int st_open(struct inode *inode, struct file *filp) | |||
1118 | err_out: | 1185 | err_out: |
1119 | normalize_buffer(STp->buffer); | 1186 | normalize_buffer(STp->buffer); |
1120 | STp->in_use = 0; | 1187 | STp->in_use = 0; |
1121 | scsi_device_put(STp->device); | 1188 | scsi_tape_put(STp); |
1122 | return retval; | 1189 | return retval; |
1123 | 1190 | ||
1124 | } | 1191 | } |
@@ -1250,7 +1317,7 @@ static int st_release(struct inode *inode, struct file *filp) | |||
1250 | write_lock(&st_dev_arr_lock); | 1317 | write_lock(&st_dev_arr_lock); |
1251 | STp->in_use = 0; | 1318 | STp->in_use = 0; |
1252 | write_unlock(&st_dev_arr_lock); | 1319 | write_unlock(&st_dev_arr_lock); |
1253 | scsi_device_put(STp->device); | 1320 | scsi_tape_put(STp); |
1254 | 1321 | ||
1255 | return result; | 1322 | return result; |
1256 | } | 1323 | } |
@@ -3887,6 +3954,7 @@ static int st_probe(struct device *dev) | |||
3887 | goto out_put_disk; | 3954 | goto out_put_disk; |
3888 | } | 3955 | } |
3889 | memset(tpnt, 0, sizeof(struct scsi_tape)); | 3956 | memset(tpnt, 0, sizeof(struct scsi_tape)); |
3957 | kref_init(&tpnt->kref); | ||
3890 | tpnt->disk = disk; | 3958 | tpnt->disk = disk; |
3891 | sprintf(disk->disk_name, "st%d", i); | 3959 | sprintf(disk->disk_name, "st%d", i); |
3892 | disk->private_data = &tpnt->driver; | 3960 | disk->private_data = &tpnt->driver; |
@@ -3902,6 +3970,7 @@ static int st_probe(struct device *dev) | |||
3902 | tpnt->tape_type = MT_ISSCSI2; | 3970 | tpnt->tape_type = MT_ISSCSI2; |
3903 | 3971 | ||
3904 | tpnt->buffer = buffer; | 3972 | tpnt->buffer = buffer; |
3973 | tpnt->buffer->last_SRpnt = NULL; | ||
3905 | 3974 | ||
3906 | tpnt->inited = 0; | 3975 | tpnt->inited = 0; |
3907 | tpnt->dirty = 0; | 3976 | tpnt->dirty = 0; |
@@ -4076,15 +4145,10 @@ static int st_remove(struct device *dev) | |||
4076 | tpnt->modes[mode].cdevs[j] = NULL; | 4145 | tpnt->modes[mode].cdevs[j] = NULL; |
4077 | } | 4146 | } |
4078 | } | 4147 | } |
4079 | tpnt->device = NULL; | ||
4080 | 4148 | ||
4081 | if (tpnt->buffer) { | 4149 | down(&st_ref_sem); |
4082 | tpnt->buffer->orig_frp_segs = 0; | 4150 | kref_put(&tpnt->kref, scsi_tape_release); |
4083 | normalize_buffer(tpnt->buffer); | 4151 | up(&st_ref_sem); |
4084 | kfree(tpnt->buffer); | ||
4085 | } | ||
4086 | put_disk(tpnt->disk); | ||
4087 | kfree(tpnt); | ||
4088 | return 0; | 4152 | return 0; |
4089 | } | 4153 | } |
4090 | } | 4154 | } |
@@ -4093,6 +4157,34 @@ static int st_remove(struct device *dev) | |||
4093 | return 0; | 4157 | return 0; |
4094 | } | 4158 | } |
4095 | 4159 | ||
4160 | /** | ||
4161 | * scsi_tape_release - Called to free the Scsi_Tape structure | ||
4162 | * @kref: pointer to embedded kref | ||
4163 | * | ||
4164 | * st_ref_sem must be held entering this routine. Because it is | ||
4165 | * called on last put, you should always use the scsi_tape_get() | ||
4166 | * scsi_tape_put() helpers which manipulate the semaphore directly | ||
4167 | * and never do a direct kref_put(). | ||
4168 | **/ | ||
4169 | static void scsi_tape_release(struct kref *kref) | ||
4170 | { | ||
4171 | struct scsi_tape *tpnt = to_scsi_tape(kref); | ||
4172 | struct gendisk *disk = tpnt->disk; | ||
4173 | |||
4174 | tpnt->device = NULL; | ||
4175 | |||
4176 | if (tpnt->buffer) { | ||
4177 | tpnt->buffer->orig_frp_segs = 0; | ||
4178 | normalize_buffer(tpnt->buffer); | ||
4179 | kfree(tpnt->buffer); | ||
4180 | } | ||
4181 | |||
4182 | disk->private_data = NULL; | ||
4183 | put_disk(disk); | ||
4184 | kfree(tpnt); | ||
4185 | return; | ||
4186 | } | ||
4187 | |||
4096 | static void st_intr(struct scsi_cmnd *SCpnt) | 4188 | static void st_intr(struct scsi_cmnd *SCpnt) |
4097 | { | 4189 | { |
4098 | scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1); | 4190 | scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1); |
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 061da111398e..790acac160bc 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h | |||
@@ -3,7 +3,7 @@ | |||
3 | #define _ST_H | 3 | #define _ST_H |
4 | 4 | ||
5 | #include <linux/completion.h> | 5 | #include <linux/completion.h> |
6 | 6 | #include <linux/kref.h> | |
7 | 7 | ||
8 | /* Descriptor for analyzed sense data */ | 8 | /* Descriptor for analyzed sense data */ |
9 | struct st_cmdstatus { | 9 | struct st_cmdstatus { |
@@ -156,6 +156,7 @@ struct scsi_tape { | |||
156 | unsigned char last_sense[16]; | 156 | unsigned char last_sense[16]; |
157 | #endif | 157 | #endif |
158 | struct gendisk *disk; | 158 | struct gendisk *disk; |
159 | struct kref kref; | ||
159 | }; | 160 | }; |
160 | 161 | ||
161 | /* Bit masks for use_pf */ | 162 | /* Bit masks for use_pf */ |