diff options
| author | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:18:35 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:18:35 -0400 |
| commit | 7a93aef7fbac6f4db40b6fec5c0c6b654ae7a93c (patch) | |
| tree | 4cd7aae38012dfc1ff6c62be20ef8840e56d8383 /drivers/scsi | |
| parent | 392160335c798bbe94ab3aae6ea0c85d32b81bbc (diff) | |
| parent | 8224bfa84d510630b40ea460b2bb380c91acb8ae (diff) | |
Merge HEAD from ../scsi-misc-2.6-tmp
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 */ |
