diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 20:31:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 20:31:27 -0400 |
commit | 0481990b758628e12f4b0a9e15094e70cefc7cd1 (patch) | |
tree | 67a4b4b7acc6a688b87ef2a2d3ec0e296e6e480c /drivers/scsi | |
parent | db400b3c4ee89d384d9163836a55577abdae772d (diff) | |
parent | 17fa53da1239b8712c5cebbd72a74c713b6c2db9 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6
Diffstat (limited to 'drivers/scsi')
86 files changed, 5044 insertions, 8118 deletions
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 973c51fb0fe2..ae9e0203e9de 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c | |||
@@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id) | |||
1499 | return 0; | 1499 | return 0; |
1500 | } /* End tw_scsiop_inquiry() */ | 1500 | } /* End tw_scsiop_inquiry() */ |
1501 | 1501 | ||
1502 | static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, | ||
1503 | void *data, unsigned int len) | ||
1504 | { | ||
1505 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; | ||
1506 | void *buf; | ||
1507 | unsigned int transfer_len; | ||
1508 | |||
1509 | if (cmd->use_sg) { | ||
1510 | struct scatterlist *sg = | ||
1511 | (struct scatterlist *)cmd->request_buffer; | ||
1512 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
1513 | transfer_len = min(sg->length, len); | ||
1514 | } else { | ||
1515 | buf = cmd->request_buffer; | ||
1516 | transfer_len = min(cmd->request_bufflen, len); | ||
1517 | } | ||
1518 | |||
1519 | memcpy(buf, data, transfer_len); | ||
1520 | |||
1521 | if (cmd->use_sg) { | ||
1522 | struct scatterlist *sg; | ||
1523 | |||
1524 | sg = (struct scatterlist *)cmd->request_buffer; | ||
1525 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
1526 | } | ||
1527 | } | ||
1528 | |||
1502 | /* This function is called by the isr to complete an inquiry command */ | 1529 | /* This function is called by the isr to complete an inquiry command */ |
1503 | static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) | 1530 | static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) |
1504 | { | 1531 | { |
1505 | unsigned char *is_unit_present; | 1532 | unsigned char *is_unit_present; |
1506 | unsigned char *request_buffer; | 1533 | unsigned char request_buffer[36]; |
1507 | TW_Param *param; | 1534 | TW_Param *param; |
1508 | 1535 | ||
1509 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); | 1536 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); |
1510 | 1537 | ||
1511 | /* Fill request buffer */ | 1538 | memset(request_buffer, 0, sizeof(request_buffer)); |
1512 | if (tw_dev->srb[request_id]->request_buffer == NULL) { | ||
1513 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n"); | ||
1514 | return 1; | ||
1515 | } | ||
1516 | request_buffer = tw_dev->srb[request_id]->request_buffer; | ||
1517 | memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); | ||
1518 | request_buffer[0] = TYPE_DISK; /* Peripheral device type */ | 1539 | request_buffer[0] = TYPE_DISK; /* Peripheral device type */ |
1519 | request_buffer[1] = 0; /* Device type modifier */ | 1540 | request_buffer[1] = 0; /* Device type modifier */ |
1520 | request_buffer[2] = 0; /* No ansi/iso compliance */ | 1541 | request_buffer[2] = 0; /* No ansi/iso compliance */ |
@@ -1522,6 +1543,8 @@ static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_i | |||
1522 | memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ | 1543 | memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ |
1523 | sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); | 1544 | sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); |
1524 | memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); | 1545 | memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); |
1546 | tw_transfer_internal(tw_dev, request_id, request_buffer, | ||
1547 | sizeof(request_buffer)); | ||
1525 | 1548 | ||
1526 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; | 1549 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; |
1527 | if (param == NULL) { | 1550 | if (param == NULL) { |
@@ -1612,7 +1635,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques | |||
1612 | { | 1635 | { |
1613 | TW_Param *param; | 1636 | TW_Param *param; |
1614 | unsigned char *flags; | 1637 | unsigned char *flags; |
1615 | unsigned char *request_buffer; | 1638 | unsigned char request_buffer[8]; |
1616 | 1639 | ||
1617 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); | 1640 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); |
1618 | 1641 | ||
@@ -1622,8 +1645,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques | |||
1622 | return 1; | 1645 | return 1; |
1623 | } | 1646 | } |
1624 | flags = (char *)&(param->data[0]); | 1647 | flags = (char *)&(param->data[0]); |
1625 | request_buffer = tw_dev->srb[request_id]->buffer; | 1648 | memset(request_buffer, 0, sizeof(request_buffer)); |
1626 | memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); | ||
1627 | 1649 | ||
1628 | request_buffer[0] = 0xf; /* mode data length */ | 1650 | request_buffer[0] = 0xf; /* mode data length */ |
1629 | request_buffer[1] = 0; /* default medium type */ | 1651 | request_buffer[1] = 0; /* default medium type */ |
@@ -1635,6 +1657,8 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques | |||
1635 | request_buffer[6] = 0x4; /* WCE on */ | 1657 | request_buffer[6] = 0x4; /* WCE on */ |
1636 | else | 1658 | else |
1637 | request_buffer[6] = 0x0; /* WCE off */ | 1659 | request_buffer[6] = 0x0; /* WCE off */ |
1660 | tw_transfer_internal(tw_dev, request_id, request_buffer, | ||
1661 | sizeof(request_buffer)); | ||
1638 | 1662 | ||
1639 | return 0; | 1663 | return 0; |
1640 | } /* End tw_scsiop_mode_sense_complete() */ | 1664 | } /* End tw_scsiop_mode_sense_complete() */ |
@@ -1701,17 +1725,12 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req | |||
1701 | { | 1725 | { |
1702 | unsigned char *param_data; | 1726 | unsigned char *param_data; |
1703 | u32 capacity; | 1727 | u32 capacity; |
1704 | char *buff; | 1728 | char buff[8]; |
1705 | TW_Param *param; | 1729 | TW_Param *param; |
1706 | 1730 | ||
1707 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); | 1731 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); |
1708 | 1732 | ||
1709 | buff = tw_dev->srb[request_id]->request_buffer; | 1733 | memset(buff, 0, sizeof(buff)); |
1710 | if (buff == NULL) { | ||
1711 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n"); | ||
1712 | return 1; | ||
1713 | } | ||
1714 | memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); | ||
1715 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; | 1734 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; |
1716 | if (param == NULL) { | 1735 | if (param == NULL) { |
1717 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n"); | 1736 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n"); |
@@ -1739,6 +1758,8 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req | |||
1739 | buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; | 1758 | buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; |
1740 | buff[7] = TW_BLOCK_SIZE & 0xff; | 1759 | buff[7] = TW_BLOCK_SIZE & 0xff; |
1741 | 1760 | ||
1761 | tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff)); | ||
1762 | |||
1742 | return 0; | 1763 | return 0; |
1743 | } /* End tw_scsiop_read_capacity_complete() */ | 1764 | } /* End tw_scsiop_read_capacity_complete() */ |
1744 | 1765 | ||
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a261b9eea139..2d21265e650b 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -1,5 +1,11 @@ | |||
1 | menu "SCSI device support" | 1 | menu "SCSI device support" |
2 | 2 | ||
3 | config RAID_ATTRS | ||
4 | tristate "RAID Transport Class" | ||
5 | default n | ||
6 | ---help--- | ||
7 | Provides RAID | ||
8 | |||
3 | config SCSI | 9 | config SCSI |
4 | tristate "SCSI device support" | 10 | tristate "SCSI device support" |
5 | ---help--- | 11 | ---help--- |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index c662b8c8cc6d..4b4fd94c2674 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -22,6 +22,8 @@ subdir-$(CONFIG_PCMCIA) += pcmcia | |||
22 | 22 | ||
23 | obj-$(CONFIG_SCSI) += scsi_mod.o | 23 | obj-$(CONFIG_SCSI) += scsi_mod.o |
24 | 24 | ||
25 | obj-$(CONFIG_RAID_ATTRS) += raid_class.o | ||
26 | |||
25 | # --- NOTE ORDERING HERE --- | 27 | # --- NOTE ORDERING HERE --- |
26 | # For kernel non-modular link, transport attributes need to | 28 | # For kernel non-modular link, transport attributes need to |
27 | # be initialised before drivers | 29 | # be initialised before drivers |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index ccdf440021fb..a8e3dfcd0dc7 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); |
@@ -968,7 +972,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
968 | fibsize = sizeof(struct aac_read64) + | 972 | fibsize = sizeof(struct aac_read64) + |
969 | ((le32_to_cpu(readcmd->sg.count) - 1) * | 973 | ((le32_to_cpu(readcmd->sg.count) - 1) * |
970 | sizeof (struct sgentry64)); | 974 | sizeof (struct sgentry64)); |
971 | BUG_ON (fibsize > (sizeof(struct hw_fib) - | 975 | BUG_ON (fibsize > (dev->max_fib_size - |
972 | sizeof(struct aac_fibhdr))); | 976 | sizeof(struct aac_fibhdr))); |
973 | /* | 977 | /* |
974 | * Now send the Fib to the adapter | 978 | * Now send the Fib to the adapter |
@@ -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..6b6d4e287793 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -46,32 +46,14 @@ | |||
46 | #include "aic79xx_inline.h" | 46 | #include "aic79xx_inline.h" |
47 | #include <scsi/scsicam.h> | 47 | #include <scsi/scsicam.h> |
48 | 48 | ||
49 | /* | 49 | static struct scsi_transport_template *ahd_linux_transport_template = NULL; |
50 | * Include aiclib.c as part of our | ||
51 | * "module dependencies are hard" work around. | ||
52 | */ | ||
53 | #include "aiclib.c" | ||
54 | 50 | ||
55 | #include <linux/init.h> /* __setup */ | 51 | #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 */ | 52 | #include <linux/mm.h> /* For fetching system memory size */ |
53 | #include <linux/blkdev.h> /* For block_size() */ | ||
62 | #include <linux/delay.h> /* For ssleep/msleep */ | 54 | #include <linux/delay.h> /* For ssleep/msleep */ |
63 | 55 | ||
64 | /* | 56 | /* |
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. | 57 | * Bucket size for counting good commands in between bad ones. |
76 | */ | 58 | */ |
77 | #define AHD_LINUX_ERR_THRESH 1000 | 59 | #define AHD_LINUX_ERR_THRESH 1000 |
@@ -188,71 +170,6 @@ static adapter_tag_info_t aic79xx_tag_info[] = | |||
188 | }; | 170 | }; |
189 | 171 | ||
190 | /* | 172 | /* |
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 | 173 | * 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 | 174 | * characteristics. Set the defaults here; they can be overriden with |
258 | * the proper insmod parameters. | 175 | * the proper insmod parameters. |
@@ -375,13 +292,6 @@ static uint32_t aic79xx_pci_parity = ~0; | |||
375 | uint32_t aic79xx_allow_memio = ~0; | 292 | uint32_t aic79xx_allow_memio = ~0; |
376 | 293 | ||
377 | /* | 294 | /* |
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. | 295 | * So that we can set how long each device is given as a selection timeout. |
386 | * The table of values goes like this: | 296 | * The table of values goes like this: |
387 | * 0 - 256ms | 297 | * 0 - 256ms |
@@ -412,7 +322,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>"); | |||
412 | MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); | 322 | MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); |
413 | MODULE_LICENSE("Dual BSD/GPL"); | 323 | MODULE_LICENSE("Dual BSD/GPL"); |
414 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); | 324 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); |
415 | module_param(aic79xx, charp, 0); | 325 | module_param(aic79xx, charp, 0444); |
416 | MODULE_PARM_DESC(aic79xx, | 326 | MODULE_PARM_DESC(aic79xx, |
417 | "period delimited, options string.\n" | 327 | "period delimited, options string.\n" |
418 | " verbose Enable verbose/diagnostic logging\n" | 328 | " verbose Enable verbose/diagnostic logging\n" |
@@ -427,8 +337,6 @@ MODULE_PARM_DESC(aic79xx, | |||
427 | " reverse_scan Sort PCI devices highest Bus/Slot to lowest\n" | 337 | " reverse_scan Sort PCI devices highest Bus/Slot to lowest\n" |
428 | " tag_info:<tag_str> Set per-target tag depth\n" | 338 | " 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" | 339 | " 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" | 340 | " slewrate:<slewrate_list>Set the signal slew rate (0-15).\n" |
433 | " precomp:<pcomp_list> Set the signal precompensation (0-7).\n" | 341 | " precomp:<pcomp_list> Set the signal precompensation (0-7).\n" |
434 | " amplitude:<int> Set the signal amplitude (0-7).\n" | 342 | " amplitude:<int> Set the signal amplitude (0-7).\n" |
@@ -441,249 +349,35 @@ MODULE_PARM_DESC(aic79xx, | |||
441 | " Shorten the selection timeout to 128ms\n" | 349 | " Shorten the selection timeout to 128ms\n" |
442 | "\n" | 350 | "\n" |
443 | " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" | 351 | " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" |
444 | "\n" | 352 | "\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 | 353 | ||
450 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, | 354 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, |
451 | struct ahd_linux_device *, | 355 | struct scsi_device *, |
452 | struct scb *); | 356 | struct scb *); |
453 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, | 357 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, |
454 | Scsi_Cmnd *cmd); | 358 | 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); | 359 | static void ahd_linux_sem_timeout(u_long arg); |
360 | 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); | 361 | 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, | 362 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, |
505 | struct ahd_devinfo *devinfo); | 363 | struct ahd_devinfo *devinfo); |
506 | static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd); | 364 | static void ahd_linux_device_queue_depth(struct scsi_device *); |
507 | static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd); | 365 | static int ahd_linux_run_command(struct ahd_softc*, |
508 | static void ahd_linux_device_queue_depth(struct ahd_softc *ahd, | 366 | struct ahd_linux_device *, |
509 | struct ahd_linux_device *dev); | 367 | 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); | 368 | static void ahd_linux_setup_tag_info_global(char *p); |
522 | static aic_option_callback_t ahd_linux_setup_tag_info; | 369 | static int aic79xx_setup(char *c); |
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; | ||
526 | static int ahd_linux_next_unit(void); | ||
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 | 370 | ||
572 | static __inline void | 371 | 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 | 372 | ||
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 | 373 | ||
586 | target_offset = target; | 374 | /****************************** Inlines ***************************************/ |
587 | if (channel != 0) | 375 | 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 | 376 | ||
683 | static __inline void | 377 | static __inline void |
684 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) | 378 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) |
685 | { | 379 | { |
686 | Scsi_Cmnd *cmd; | 380 | struct scsi_cmnd *cmd; |
687 | int direction; | 381 | int direction; |
688 | 382 | ||
689 | cmd = scb->io_ctx; | 383 | cmd = scb->io_ctx; |
@@ -705,197 +399,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) | |||
705 | #define BUILD_SCSIID(ahd, cmd) \ | 399 | #define BUILD_SCSIID(ahd, cmd) \ |
706 | ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id) | 400 | ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id) |
707 | 401 | ||
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 | /* | 402 | /* |
900 | * Return a string describing the driver. | 403 | * Return a string describing the driver. |
901 | */ | 404 | */ |
@@ -928,220 +431,177 @@ ahd_linux_info(struct Scsi_Host *host) | |||
928 | * Queue an SCB to the controller. | 431 | * Queue an SCB to the controller. |
929 | */ | 432 | */ |
930 | static int | 433 | static int |
931 | ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | 434 | ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) |
932 | { | 435 | { |
933 | struct ahd_softc *ahd; | 436 | struct ahd_softc *ahd; |
934 | struct ahd_linux_device *dev; | 437 | struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device); |
935 | u_long flags; | ||
936 | 438 | ||
937 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | 439 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
938 | 440 | ||
939 | /* | 441 | /* |
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 | 442 | * Close the race of a command that was in the process of |
948 | * being queued to us just as our simq was frozen. Let | 443 | * being queued to us just as our simq was frozen. Let |
949 | * DV commands through so long as we are only frozen to | 444 | * DV commands through so long as we are only frozen to |
950 | * perform DV. | 445 | * perform DV. |
951 | */ | 446 | */ |
952 | if (ahd->platform_data->qfrozen != 0 | 447 | if (ahd->platform_data->qfrozen != 0) { |
953 | && AHD_DV_CMD(cmd) == 0) { | 448 | printf("%s: queue frozen\n", ahd_name(ahd)); |
954 | 449 | ||
955 | ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); | 450 | 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 | } | 451 | } |
973 | if (cmd->cmd_len > MAX_CDB_LEN) | 452 | |
974 | return (-EINVAL); | 453 | /* |
454 | * Save the callback on completion function. | ||
455 | */ | ||
456 | cmd->scsi_done = scsi_done; | ||
457 | |||
975 | cmd->result = CAM_REQ_INPROG << 16; | 458 | cmd->result = CAM_REQ_INPROG << 16; |
976 | TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe); | 459 | |
977 | if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { | 460 | return ahd_linux_run_command(ahd, dev, cmd); |
978 | TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); | 461 | } |
979 | dev->flags |= AHD_DEV_ON_RUN_LIST; | 462 | |
980 | ahd_linux_run_device_queues(ahd); | 463 | static inline struct scsi_target ** |
981 | } | 464 | ahd_linux_target_in_softc(struct scsi_target *starget) |
982 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | 465 | { |
983 | return (0); | 466 | struct ahd_softc *ahd = |
467 | *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); | ||
468 | unsigned int target_offset; | ||
469 | |||
470 | target_offset = starget->id; | ||
471 | if (starget->channel != 0) | ||
472 | target_offset += 8; | ||
473 | |||
474 | return &ahd->platform_data->starget[target_offset]; | ||
984 | } | 475 | } |
985 | 476 | ||
986 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
987 | static int | 477 | static int |
988 | ahd_linux_slave_alloc(Scsi_Device *device) | 478 | ahd_linux_target_alloc(struct scsi_target *starget) |
989 | { | 479 | { |
990 | struct ahd_softc *ahd; | 480 | struct ahd_softc *ahd = |
481 | *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); | ||
482 | unsigned long flags; | ||
483 | struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); | ||
484 | struct ahd_linux_target *targ = scsi_transport_target_data(starget); | ||
485 | struct ahd_devinfo devinfo; | ||
486 | struct ahd_initiator_tinfo *tinfo; | ||
487 | struct ahd_tmode_tstate *tstate; | ||
488 | char channel = starget->channel + 'A'; | ||
991 | 489 | ||
992 | ahd = *((struct ahd_softc **)device->host->hostdata); | 490 | ahd_lock(ahd, &flags); |
993 | if (bootverbose) | 491 | |
994 | printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id); | 492 | BUG_ON(*ahd_targp != NULL); |
995 | return (0); | 493 | |
494 | *ahd_targp = starget; | ||
495 | memset(targ, 0, sizeof(*targ)); | ||
496 | |||
497 | tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, | ||
498 | starget->id, &tstate); | ||
499 | ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id, | ||
500 | CAM_LUN_WILDCARD, channel, | ||
501 | ROLE_INITIATOR); | ||
502 | spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */ | ||
503 | if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) | ||
504 | spi_max_offset(starget) = MAX_OFFSET_PACED_BUG; | ||
505 | else | ||
506 | spi_max_offset(starget) = MAX_OFFSET_PACED; | ||
507 | spi_max_width(starget) = ahd->features & AHD_WIDE; | ||
508 | |||
509 | ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, | ||
510 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
511 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, | ||
512 | AHD_TRANS_GOAL, /*paused*/FALSE); | ||
513 | ahd_unlock(ahd, &flags); | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static void | ||
519 | ahd_linux_target_destroy(struct scsi_target *starget) | ||
520 | { | ||
521 | struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); | ||
522 | |||
523 | *ahd_targp = NULL; | ||
996 | } | 524 | } |
997 | 525 | ||
998 | static int | 526 | static int |
999 | ahd_linux_slave_configure(Scsi_Device *device) | 527 | ahd_linux_slave_alloc(struct scsi_device *sdev) |
1000 | { | 528 | { |
1001 | struct ahd_softc *ahd; | 529 | struct ahd_softc *ahd = |
1002 | struct ahd_linux_device *dev; | 530 | *((struct ahd_softc **)sdev->host->hostdata); |
1003 | u_long flags; | 531 | struct scsi_target *starget = sdev->sdev_target; |
532 | struct ahd_linux_target *targ = scsi_transport_target_data(starget); | ||
533 | struct ahd_linux_device *dev; | ||
1004 | 534 | ||
1005 | ahd = *((struct ahd_softc **)device->host->hostdata); | ||
1006 | if (bootverbose) | 535 | if (bootverbose) |
1007 | printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id); | 536 | printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id); |
1008 | ahd_midlayer_entrypoint_lock(ahd, &flags); | 537 | |
538 | BUG_ON(targ->sdev[sdev->lun] != NULL); | ||
539 | |||
540 | dev = scsi_transport_device_data(sdev); | ||
541 | memset(dev, 0, sizeof(*dev)); | ||
542 | |||
1009 | /* | 543 | /* |
1010 | * Since Linux has attached to the device, configure | 544 | * We start out life using untagged |
1011 | * it so we don't free and allocate the device | 545 | * transactions of which we allow one. |
1012 | * structure on every command. | ||
1013 | */ | 546 | */ |
1014 | dev = ahd_linux_get_device(ahd, device->channel, | 547 | dev->openings = 1; |
1015 | device->id, device->lun, | 548 | |
1016 | /*alloc*/TRUE); | 549 | /* |
1017 | if (dev != NULL) { | 550 | * Set maxtags to 0. This will be changed if we |
1018 | dev->flags &= ~AHD_DEV_UNCONFIGURED; | 551 | * later determine that we are dealing with |
1019 | dev->flags |= AHD_DEV_SLAVE_CONFIGURED; | 552 | * a tagged queuing capable device. |
1020 | dev->scsi_device = device; | 553 | */ |
1021 | ahd_linux_device_queue_depth(ahd, dev); | 554 | dev->maxtags = 0; |
1022 | } | 555 | |
1023 | ahd_midlayer_entrypoint_unlock(ahd, &flags); | 556 | targ->sdev[sdev->lun] = sdev; |
557 | |||
1024 | return (0); | 558 | return (0); |
1025 | } | 559 | } |
1026 | 560 | ||
1027 | static void | 561 | static int |
1028 | ahd_linux_slave_destroy(Scsi_Device *device) | 562 | ahd_linux_slave_configure(struct scsi_device *sdev) |
1029 | { | 563 | { |
1030 | struct ahd_softc *ahd; | 564 | struct ahd_softc *ahd; |
1031 | struct ahd_linux_device *dev; | ||
1032 | u_long flags; | ||
1033 | 565 | ||
1034 | ahd = *((struct ahd_softc **)device->host->hostdata); | 566 | ahd = *((struct ahd_softc **)sdev->host->hostdata); |
1035 | if (bootverbose) | 567 | if (bootverbose) |
1036 | printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id); | 568 | 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 | 569 | ||
1042 | /* | 570 | ahd_linux_device_queue_depth(sdev); |
1043 | * Filter out "silly" deletions of real devices by only | 571 | |
1044 | * deleting devices that have had slave_configure() | 572 | /* Initial Domain Validation */ |
1045 | * called on them. All other devices that have not | 573 | if (!spi_initial_dv(sdev->sdev_target)) |
1046 | * been configured will automatically be deleted by | 574 | spi_dv_device(sdev); |
1047 | * the refcounting process. | 575 | |
1048 | */ | 576 | 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 | } | 577 | } |
1059 | #else | 578 | |
1060 | /* | ||
1061 | * Sets the queue depth for each SCSI device hanging | ||
1062 | * off the input host adapter. | ||
1063 | */ | ||
1064 | static void | 579 | static void |
1065 | ahd_linux_select_queue_depth(struct Scsi_Host * host, | 580 | ahd_linux_slave_destroy(struct scsi_device *sdev) |
1066 | Scsi_Device * scsi_devs) | ||
1067 | { | 581 | { |
1068 | Scsi_Device *device; | ||
1069 | Scsi_Device *ldev; | ||
1070 | struct ahd_softc *ahd; | 582 | struct ahd_softc *ahd; |
1071 | u_long flags; | 583 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); |
584 | struct ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target); | ||
1072 | 585 | ||
1073 | ahd = *((struct ahd_softc **)host->hostdata); | 586 | ahd = *((struct ahd_softc **)sdev->host->hostdata); |
1074 | ahd_lock(ahd, &flags); | 587 | if (bootverbose) |
1075 | for (device = scsi_devs; device != NULL; device = device->next) { | 588 | printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id); |
1076 | 589 | ||
1077 | /* | 590 | 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 | 591 | ||
1093 | if (device->host == host) { | 592 | targ->sdev[sdev->lun] = NULL; |
1094 | struct ahd_linux_device *dev; | ||
1095 | 593 | ||
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 | } | 594 | } |
1126 | #endif | ||
1127 | 595 | ||
1128 | #if defined(__i386__) | 596 | #if defined(__i386__) |
1129 | /* | 597 | /* |
1130 | * Return the disk geometry for the given SCSI device. | 598 | * Return the disk geometry for the given SCSI device. |
1131 | */ | 599 | */ |
1132 | static int | 600 | static int |
1133 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1134 | ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, | 601 | ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, |
1135 | sector_t capacity, int geom[]) | 602 | sector_t capacity, int geom[]) |
1136 | { | 603 | { |
1137 | uint8_t *bh; | 604 | 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; | 605 | int heads; |
1146 | int sectors; | 606 | int sectors; |
1147 | int cylinders; | 607 | int cylinders; |
@@ -1151,22 +611,11 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) | |||
1151 | 611 | ||
1152 | ahd = *((struct ahd_softc **)sdev->host->hostdata); | 612 | ahd = *((struct ahd_softc **)sdev->host->hostdata); |
1153 | 613 | ||
1154 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1155 | bh = scsi_bios_ptable(bdev); | 614 | 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) { | 615 | if (bh) { |
1163 | ret = scsi_partsize(bh, capacity, | 616 | ret = scsi_partsize(bh, capacity, |
1164 | &geom[2], &geom[0], &geom[1]); | 617 | &geom[2], &geom[0], &geom[1]); |
1165 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1166 | kfree(bh); | 618 | kfree(bh); |
1167 | #else | ||
1168 | brelse(bh); | ||
1169 | #endif | ||
1170 | if (ret != -1) | 619 | if (ret != -1) |
1171 | return (ret); | 620 | return (ret); |
1172 | } | 621 | } |
@@ -1194,392 +643,35 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) | |||
1194 | * Abort the current SCSI command(s). | 643 | * Abort the current SCSI command(s). |
1195 | */ | 644 | */ |
1196 | static int | 645 | static int |
1197 | ahd_linux_abort(Scsi_Cmnd *cmd) | 646 | ahd_linux_abort(struct scsi_cmnd *cmd) |
1198 | { | 647 | { |
1199 | struct ahd_softc *ahd; | 648 | 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 | 649 | ||
1284 | /* | 650 | error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT); |
1285 | * See if we can find a matching cmd in the pending list. | 651 | if (error != 0) |
1286 | */ | 652 | printf("aic79xx_abort returns 0x%x\n", error); |
1287 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | 653 | return error; |
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 | |||
1454 | pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; | ||
1455 | spin_unlock_irq(&ahd->platform_data->spin_lock); | ||
1456 | init_timer(&timer); | ||
1457 | timer.data = (u_long)pending_scb; | ||
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 | } | 654 | } |
1483 | 655 | ||
1484 | /* | 656 | /* |
1485 | * Attempt to send a target reset message to the device that timed out. | 657 | * Attempt to send a target reset message to the device that timed out. |
1486 | */ | 658 | */ |
1487 | static int | 659 | static int |
1488 | ahd_linux_dev_reset(Scsi_Cmnd *cmd) | 660 | ahd_linux_dev_reset(struct scsi_cmnd *cmd) |
1489 | { | 661 | { |
1490 | struct ahd_softc *ahd; | 662 | 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 | |||
1501 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | ||
1502 | recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK); | ||
1503 | if (!recovery_cmd) | ||
1504 | return (FAILED); | ||
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 | 663 | ||
1555 | scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; | 664 | error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); |
1556 | ahd_unlock(ahd, &s); | 665 | if (error != 0) |
1557 | init_timer(&timer); | 666 | printf("aic79xx_dev_reset returns 0x%x\n", error); |
1558 | timer.data = (u_long)scb; | 667 | return error; |
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 | } | 668 | } |
1577 | 669 | ||
1578 | /* | 670 | /* |
1579 | * Reset the SCSI bus. | 671 | * Reset the SCSI bus. |
1580 | */ | 672 | */ |
1581 | static int | 673 | static int |
1582 | ahd_linux_bus_reset(Scsi_Cmnd *cmd) | 674 | ahd_linux_bus_reset(struct scsi_cmnd *cmd) |
1583 | { | 675 | { |
1584 | struct ahd_softc *ahd; | 676 | struct ahd_softc *ahd; |
1585 | u_long s; | 677 | u_long s; |
@@ -1594,7 +686,6 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) | |||
1594 | ahd_lock(ahd, &s); | 686 | ahd_lock(ahd, &s); |
1595 | found = ahd_reset_channel(ahd, cmd->device->channel + 'A', | 687 | found = ahd_reset_channel(ahd, cmd->device->channel + 'A', |
1596 | /*initiate reset*/TRUE); | 688 | /*initiate reset*/TRUE); |
1597 | ahd_linux_run_complete_queue(ahd); | ||
1598 | ahd_unlock(ahd, &s); | 689 | ahd_unlock(ahd, &s); |
1599 | 690 | ||
1600 | if (bootverbose) | 691 | if (bootverbose) |
@@ -1604,9 +695,10 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) | |||
1604 | return (SUCCESS); | 695 | return (SUCCESS); |
1605 | } | 696 | } |
1606 | 697 | ||
1607 | Scsi_Host_Template aic79xx_driver_template = { | 698 | struct scsi_host_template aic79xx_driver_template = { |
1608 | .module = THIS_MODULE, | 699 | .module = THIS_MODULE, |
1609 | .name = "aic79xx", | 700 | .name = "aic79xx", |
701 | .proc_name = "aic79xx", | ||
1610 | .proc_info = ahd_linux_proc_info, | 702 | .proc_info = ahd_linux_proc_info, |
1611 | .info = ahd_linux_info, | 703 | .info = ahd_linux_info, |
1612 | .queuecommand = ahd_linux_queue, | 704 | .queuecommand = ahd_linux_queue, |
@@ -1623,37 +715,10 @@ Scsi_Host_Template aic79xx_driver_template = { | |||
1623 | .slave_alloc = ahd_linux_slave_alloc, | 715 | .slave_alloc = ahd_linux_slave_alloc, |
1624 | .slave_configure = ahd_linux_slave_configure, | 716 | .slave_configure = ahd_linux_slave_configure, |
1625 | .slave_destroy = ahd_linux_slave_destroy, | 717 | .slave_destroy = ahd_linux_slave_destroy, |
718 | .target_alloc = ahd_linux_target_alloc, | ||
719 | .target_destroy = ahd_linux_target_destroy, | ||
1626 | }; | 720 | }; |
1627 | 721 | ||
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 *************************************/ | 722 | /******************************** Bus DMA *************************************/ |
1658 | int | 723 | int |
1659 | ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, | 724 | ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, |
@@ -1693,36 +758,10 @@ int | |||
1693 | ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, | 758 | ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, |
1694 | int flags, bus_dmamap_t *mapp) | 759 | int flags, bus_dmamap_t *mapp) |
1695 | { | 760 | { |
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, | 761 | *vaddr = pci_alloc_consistent(ahd->dev_softc, |
1715 | dmat->maxsize, &map->bus_addr); | 762 | 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) | 763 | if (*vaddr == NULL) |
1724 | return (ENOMEM); | 764 | return (ENOMEM); |
1725 | *mapp = map; | ||
1726 | return(0); | 765 | return(0); |
1727 | } | 766 | } |
1728 | 767 | ||
@@ -1731,7 +770,7 @@ ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, | |||
1731 | void* vaddr, bus_dmamap_t map) | 770 | void* vaddr, bus_dmamap_t map) |
1732 | { | 771 | { |
1733 | pci_free_consistent(ahd->dev_softc, dmat->maxsize, | 772 | pci_free_consistent(ahd->dev_softc, dmat->maxsize, |
1734 | vaddr, map->bus_addr); | 773 | vaddr, map); |
1735 | } | 774 | } |
1736 | 775 | ||
1737 | int | 776 | int |
@@ -1745,7 +784,7 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, | |||
1745 | */ | 784 | */ |
1746 | bus_dma_segment_t stack_sg; | 785 | bus_dma_segment_t stack_sg; |
1747 | 786 | ||
1748 | stack_sg.ds_addr = map->bus_addr; | 787 | stack_sg.ds_addr = map; |
1749 | stack_sg.ds_len = dmat->maxsize; | 788 | stack_sg.ds_len = dmat->maxsize; |
1750 | cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); | 789 | cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); |
1751 | return (0); | 790 | return (0); |
@@ -1754,11 +793,6 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, | |||
1754 | void | 793 | void |
1755 | ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) | 794 | ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) |
1756 | { | 795 | { |
1757 | /* | ||
1758 | * The map may is NULL in our < 2.3.X implementation. | ||
1759 | */ | ||
1760 | if (map != NULL) | ||
1761 | free(map, M_DEVBUF); | ||
1762 | } | 796 | } |
1763 | 797 | ||
1764 | int | 798 | int |
@@ -1823,41 +857,6 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) | |||
1823 | } | 857 | } |
1824 | 858 | ||
1825 | static void | 859 | 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) | 860 | ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) |
1862 | { | 861 | { |
1863 | 862 | ||
@@ -1887,6 +886,99 @@ ahd_linux_setup_tag_info_global(char *p) | |||
1887 | } | 886 | } |
1888 | } | 887 | } |
1889 | 888 | ||
889 | static void | ||
890 | ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | ||
891 | { | ||
892 | |||
893 | if ((instance >= 0) && (targ >= 0) | ||
894 | && (instance < NUM_ELEMENTS(aic79xx_tag_info)) | ||
895 | && (targ < AHD_NUM_TARGETS)) { | ||
896 | aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; | ||
897 | if (bootverbose) | ||
898 | printf("tag_info[%d:%d] = %d\n", instance, targ, value); | ||
899 | } | ||
900 | } | ||
901 | |||
902 | static char * | ||
903 | ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | ||
904 | void (*callback)(u_long, int, int, int32_t), | ||
905 | u_long callback_arg) | ||
906 | { | ||
907 | char *tok_end; | ||
908 | char *tok_end2; | ||
909 | int i; | ||
910 | int instance; | ||
911 | int targ; | ||
912 | int done; | ||
913 | char tok_list[] = {'.', ',', '{', '}', '\0'}; | ||
914 | |||
915 | /* All options use a ':' name/arg separator */ | ||
916 | if (*opt_arg != ':') | ||
917 | return (opt_arg); | ||
918 | opt_arg++; | ||
919 | instance = -1; | ||
920 | targ = -1; | ||
921 | done = FALSE; | ||
922 | /* | ||
923 | * Restore separator that may be in | ||
924 | * the middle of our option argument. | ||
925 | */ | ||
926 | tok_end = strchr(opt_arg, '\0'); | ||
927 | if (tok_end < end) | ||
928 | *tok_end = ','; | ||
929 | while (!done) { | ||
930 | switch (*opt_arg) { | ||
931 | case '{': | ||
932 | if (instance == -1) { | ||
933 | instance = 0; | ||
934 | } else { | ||
935 | if (depth > 1) { | ||
936 | if (targ == -1) | ||
937 | targ = 0; | ||
938 | } else { | ||
939 | printf("Malformed Option %s\n", | ||
940 | opt_name); | ||
941 | done = TRUE; | ||
942 | } | ||
943 | } | ||
944 | opt_arg++; | ||
945 | break; | ||
946 | case '}': | ||
947 | if (targ != -1) | ||
948 | targ = -1; | ||
949 | else if (instance != -1) | ||
950 | instance = -1; | ||
951 | opt_arg++; | ||
952 | break; | ||
953 | case ',': | ||
954 | case '.': | ||
955 | if (instance == -1) | ||
956 | done = TRUE; | ||
957 | else if (targ >= 0) | ||
958 | targ++; | ||
959 | else if (instance >= 0) | ||
960 | instance++; | ||
961 | opt_arg++; | ||
962 | break; | ||
963 | case '\0': | ||
964 | done = TRUE; | ||
965 | break; | ||
966 | default: | ||
967 | tok_end = end; | ||
968 | for (i = 0; tok_list[i]; i++) { | ||
969 | tok_end2 = strchr(opt_arg, tok_list[i]); | ||
970 | if ((tok_end2) && (tok_end2 < tok_end)) | ||
971 | tok_end = tok_end2; | ||
972 | } | ||
973 | callback(callback_arg, instance, targ, | ||
974 | simple_strtol(opt_arg, NULL, 0)); | ||
975 | opt_arg = tok_end; | ||
976 | break; | ||
977 | } | ||
978 | } | ||
979 | return (opt_arg); | ||
980 | } | ||
981 | |||
1890 | /* | 982 | /* |
1891 | * Handle Linux boot parameters. This routine allows for assigning a value | 983 | * Handle Linux boot parameters. This routine allows for assigning a value |
1892 | * to a parameter with a ':' between the parameter and the value. | 984 | * to a parameter with a ':' between the parameter and the value. |
@@ -1916,8 +1008,6 @@ aic79xx_setup(char *s) | |||
1916 | { "seltime", &aic79xx_seltime }, | 1008 | { "seltime", &aic79xx_seltime }, |
1917 | { "tag_info", NULL }, | 1009 | { "tag_info", NULL }, |
1918 | { "global_tag_depth", NULL}, | 1010 | { "global_tag_depth", NULL}, |
1919 | { "rd_strm", NULL }, | ||
1920 | { "dv", NULL }, | ||
1921 | { "slewrate", NULL }, | 1011 | { "slewrate", NULL }, |
1922 | { "precomp", NULL }, | 1012 | { "precomp", NULL }, |
1923 | { "amplitude", NULL }, | 1013 | { "amplitude", NULL }, |
@@ -1946,24 +1036,18 @@ aic79xx_setup(char *s) | |||
1946 | if (strncmp(p, "global_tag_depth", n) == 0) { | 1036 | if (strncmp(p, "global_tag_depth", n) == 0) { |
1947 | ahd_linux_setup_tag_info_global(p + n); | 1037 | ahd_linux_setup_tag_info_global(p + n); |
1948 | } else if (strncmp(p, "tag_info", n) == 0) { | 1038 | } else if (strncmp(p, "tag_info", n) == 0) { |
1949 | s = aic_parse_brace_option("tag_info", p + n, end, | 1039 | s = ahd_parse_brace_option("tag_info", p + n, end, |
1950 | 2, ahd_linux_setup_tag_info, 0); | 1040 | 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) { | 1041 | } else if (strncmp(p, "slewrate", n) == 0) { |
1958 | s = aic_parse_brace_option("slewrate", | 1042 | s = ahd_parse_brace_option("slewrate", |
1959 | p + n, end, 1, ahd_linux_setup_iocell_info, | 1043 | p + n, end, 1, ahd_linux_setup_iocell_info, |
1960 | AIC79XX_SLEWRATE_INDEX); | 1044 | AIC79XX_SLEWRATE_INDEX); |
1961 | } else if (strncmp(p, "precomp", n) == 0) { | 1045 | } else if (strncmp(p, "precomp", n) == 0) { |
1962 | s = aic_parse_brace_option("precomp", | 1046 | s = ahd_parse_brace_option("precomp", |
1963 | p + n, end, 1, ahd_linux_setup_iocell_info, | 1047 | p + n, end, 1, ahd_linux_setup_iocell_info, |
1964 | AIC79XX_PRECOMP_INDEX); | 1048 | AIC79XX_PRECOMP_INDEX); |
1965 | } else if (strncmp(p, "amplitude", n) == 0) { | 1049 | } else if (strncmp(p, "amplitude", n) == 0) { |
1966 | s = aic_parse_brace_option("amplitude", | 1050 | s = ahd_parse_brace_option("amplitude", |
1967 | p + n, end, 1, ahd_linux_setup_iocell_info, | 1051 | p + n, end, 1, ahd_linux_setup_iocell_info, |
1968 | AIC79XX_AMPLITUDE_INDEX); | 1052 | AIC79XX_AMPLITUDE_INDEX); |
1969 | } else if (p[n] == ':') { | 1053 | } else if (p[n] == ':') { |
@@ -1982,13 +1066,12 @@ __setup("aic79xx=", aic79xx_setup); | |||
1982 | uint32_t aic79xx_verbose; | 1066 | uint32_t aic79xx_verbose; |
1983 | 1067 | ||
1984 | int | 1068 | int |
1985 | ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | 1069 | ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template) |
1986 | { | 1070 | { |
1987 | char buf[80]; | 1071 | char buf[80]; |
1988 | struct Scsi_Host *host; | 1072 | struct Scsi_Host *host; |
1989 | char *new_name; | 1073 | char *new_name; |
1990 | u_long s; | 1074 | u_long s; |
1991 | u_long target; | ||
1992 | 1075 | ||
1993 | template->name = ahd->description; | 1076 | template->name = ahd->description; |
1994 | host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); | 1077 | host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); |
@@ -1997,11 +1080,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | |||
1997 | 1080 | ||
1998 | *((struct ahd_softc **)host->hostdata) = ahd; | 1081 | *((struct ahd_softc **)host->hostdata) = ahd; |
1999 | ahd_lock(ahd, &s); | 1082 | ahd_lock(ahd, &s); |
2000 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
2001 | scsi_assign_lock(host, &ahd->platform_data->spin_lock); | 1083 | 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; | 1084 | ahd->platform_data->host = host; |
2006 | host->can_queue = AHD_MAX_QUEUE; | 1085 | host->can_queue = AHD_MAX_QUEUE; |
2007 | host->cmd_per_lun = 2; | 1086 | host->cmd_per_lun = 2; |
@@ -2012,7 +1091,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | |||
2012 | host->max_lun = AHD_NUM_LUNS; | 1091 | host->max_lun = AHD_NUM_LUNS; |
2013 | host->max_channel = 0; | 1092 | host->max_channel = 0; |
2014 | host->sg_tablesize = AHD_NSEG; | 1093 | host->sg_tablesize = AHD_NSEG; |
2015 | ahd_set_unit(ahd, ahd_linux_next_unit()); | 1094 | ahd_set_unit(ahd, ahd_linux_unit++); |
2016 | sprintf(buf, "scsi%d", host->host_no); | 1095 | sprintf(buf, "scsi%d", host->host_no); |
2017 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | 1096 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); |
2018 | if (new_name != NULL) { | 1097 | if (new_name != NULL) { |
@@ -2020,54 +1099,14 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | |||
2020 | ahd_set_name(ahd, new_name); | 1099 | ahd_set_name(ahd, new_name); |
2021 | } | 1100 | } |
2022 | host->unique_id = ahd->unit; | 1101 | 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); | 1102 | 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); | 1103 | ahd_intr_enable(ahd, TRUE); |
2064 | ahd_linux_start_dv(ahd); | ||
2065 | ahd_unlock(ahd, &s); | 1104 | ahd_unlock(ahd, &s); |
2066 | 1105 | ||
2067 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1106 | host->transportt = ahd_linux_transport_template; |
1107 | |||
2068 | scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */ | 1108 | scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */ |
2069 | scsi_scan_host(host); | 1109 | scsi_scan_host(host); |
2070 | #endif | ||
2071 | return (0); | 1110 | return (0); |
2072 | } | 1111 | } |
2073 | 1112 | ||
@@ -2081,29 +1120,6 @@ ahd_linux_get_memsize(void) | |||
2081 | } | 1120 | } |
2082 | 1121 | ||
2083 | /* | 1122 | /* |
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, | 1123 | * Place the SCSI bus into a known state by either resetting it, |
2108 | * or forcing transfer negotiations on the next command to any | 1124 | * or forcing transfer negotiations on the next command to any |
2109 | * target. | 1125 | * target. |
@@ -2162,20 +1178,9 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) | |||
2162 | if (ahd->platform_data == NULL) | 1178 | if (ahd->platform_data == NULL) |
2163 | return (ENOMEM); | 1179 | return (ENOMEM); |
2164 | memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); | 1180 | 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; | 1181 | ahd->platform_data->irq = AHD_LINUX_NOIRQ; |
2168 | ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; | ||
2169 | ahd_lockinit(ahd); | 1182 | 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); | 1183 | 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; | 1184 | ahd->seltime = (aic79xx_seltime & 0x3) << 4; |
2180 | return (0); | 1185 | return (0); |
2181 | } | 1186 | } |
@@ -2183,39 +1188,27 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) | |||
2183 | void | 1188 | void |
2184 | ahd_platform_free(struct ahd_softc *ahd) | 1189 | ahd_platform_free(struct ahd_softc *ahd) |
2185 | { | 1190 | { |
2186 | struct ahd_linux_target *targ; | 1191 | struct scsi_target *starget; |
2187 | struct ahd_linux_device *dev; | ||
2188 | int i, j; | 1192 | int i, j; |
2189 | 1193 | ||
2190 | if (ahd->platform_data != NULL) { | 1194 | 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) { | 1195 | if (ahd->platform_data->host != NULL) { |
2195 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
2196 | scsi_remove_host(ahd->platform_data->host); | 1196 | scsi_remove_host(ahd->platform_data->host); |
2197 | #endif | ||
2198 | scsi_host_put(ahd->platform_data->host); | 1197 | scsi_host_put(ahd->platform_data->host); |
2199 | } | 1198 | } |
2200 | 1199 | ||
2201 | /* destroy all of the device and target objects */ | 1200 | /* destroy all of the device and target objects */ |
2202 | for (i = 0; i < AHD_NUM_TARGETS; i++) { | 1201 | for (i = 0; i < AHD_NUM_TARGETS; i++) { |
2203 | targ = ahd->platform_data->targets[i]; | 1202 | starget = ahd->platform_data->starget[i]; |
2204 | if (targ != NULL) { | 1203 | if (starget != NULL) { |
2205 | /* Keep target around through the loop. */ | ||
2206 | targ->refcount++; | ||
2207 | for (j = 0; j < AHD_NUM_LUNS; j++) { | 1204 | for (j = 0; j < AHD_NUM_LUNS; j++) { |
2208 | 1205 | struct ahd_linux_target *targ = | |
2209 | if (targ->devices[j] == NULL) | 1206 | scsi_transport_target_data(starget); |
1207 | if (targ->sdev[j] == NULL) | ||
2210 | continue; | 1208 | continue; |
2211 | dev = targ->devices[j]; | 1209 | targ->sdev[j] = NULL; |
2212 | ahd_linux_free_device(ahd, dev); | ||
2213 | } | 1210 | } |
2214 | /* | 1211 | 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 | } | 1212 | } |
2220 | } | 1213 | } |
2221 | 1214 | ||
@@ -2233,16 +1226,6 @@ ahd_platform_free(struct ahd_softc *ahd) | |||
2233 | release_mem_region(ahd->platform_data->mem_busaddr, | 1226 | release_mem_region(ahd->platform_data->mem_busaddr, |
2234 | 0x1000); | 1227 | 0x1000); |
2235 | } | 1228 | } |
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); | 1229 | free(ahd->platform_data, M_DEVBUF); |
2247 | } | 1230 | } |
2248 | } | 1231 | } |
@@ -2280,13 +1263,22 @@ void | |||
2280 | ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | 1263 | ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
2281 | ahd_queue_alg alg) | 1264 | ahd_queue_alg alg) |
2282 | { | 1265 | { |
1266 | struct scsi_target *starget; | ||
1267 | struct ahd_linux_target *targ; | ||
2283 | struct ahd_linux_device *dev; | 1268 | struct ahd_linux_device *dev; |
1269 | struct scsi_device *sdev; | ||
2284 | int was_queuing; | 1270 | int was_queuing; |
2285 | int now_queuing; | 1271 | int now_queuing; |
2286 | 1272 | ||
2287 | dev = ahd_linux_get_device(ahd, devinfo->channel - 'A', | 1273 | starget = ahd->platform_data->starget[devinfo->target]; |
2288 | devinfo->target, | 1274 | targ = scsi_transport_target_data(starget); |
2289 | devinfo->lun, /*alloc*/FALSE); | 1275 | BUG_ON(targ == NULL); |
1276 | sdev = targ->sdev[devinfo->lun]; | ||
1277 | if (sdev == NULL) | ||
1278 | return; | ||
1279 | |||
1280 | dev = scsi_transport_device_data(sdev); | ||
1281 | |||
2290 | if (dev == NULL) | 1282 | if (dev == NULL) |
2291 | return; | 1283 | return; |
2292 | was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); | 1284 | was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); |
@@ -2339,1434 +1331,37 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | |||
2339 | dev->maxtags = 0; | 1331 | dev->maxtags = 0; |
2340 | dev->openings = 1 - dev->active; | 1332 | dev->openings = 1 - dev->active; |
2341 | } | 1333 | } |
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 | 1334 | ||
2849 | switch (targ->dv_state) { | 1335 | switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { |
2850 | case AHD_DV_STATE_INQ_SHORT_ASYNC: | 1336 | case AHD_DEV_Q_BASIC: |
2851 | case AHD_DV_STATE_INQ_ASYNC: | 1337 | scsi_adjust_queue_depth(sdev, |
2852 | switch (status & SS_MASK) { | 1338 | MSG_SIMPLE_TASK, |
2853 | case SS_NOP: | 1339 | dev->openings + dev->active); |
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; | 1340 | break; |
2884 | case AHD_DV_STATE_INQ_ASYNC_VERIFY: | 1341 | case AHD_DEV_Q_TAGGED: |
2885 | switch (status & SS_MASK) { | 1342 | scsi_adjust_queue_depth(sdev, |
2886 | case SS_NOP: | 1343 | MSG_ORDERED_TASK, |
2887 | { | 1344 | dev->openings + dev->active); |
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; | 1345 | 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 | |||
3078 | break; | ||
3079 | case SS_START: | ||
3080 | AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU); | ||
3081 | break; | ||
3082 | case SS_INQ_REFRESH: | ||
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; | ||
3091 | |||
3092 | case AHD_DV_STATE_REBD: | ||
3093 | switch (status & SS_MASK) { | ||
3094 | case SS_NOP: | ||
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; | ||
3296 | |||
3297 | default: | 1346 | 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 | /* | ||
3527 | * Paced/DT/IU_REQ only transfer speeds. All we | ||
3528 | * can do is fallback in terms of syncrate. | ||
3529 | */ | ||
3530 | period++; | ||
3531 | } else if (cur_speed > 80000) { | ||
3532 | if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
3533 | /* | ||
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 | /* | 1347 | /* |
3549 | * In this range we the following | 1348 | * We allow the OS to queue 2 untagged transactions to |
3550 | * options ordered from highest to | 1349 | * us at any time even though we can only execute them |
3551 | * lowest desireability: | 1350 | * serially on the controller/device. This should |
3552 | * | 1351 | * remove some latency. |
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 | */ | 1352 | */ |
3560 | if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | 1353 | scsi_adjust_queue_depth(sdev, |
3561 | 1354 | /*NON-TAGGED*/0, | |
3562 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | 1355 | /*queue depth*/2); |
3563 | } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { | 1356 | break; |
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 | } | 1357 | } |
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 | } | 1358 | } |
3714 | 1359 | ||
3715 | static void | 1360 | int |
3716 | ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ) | 1361 | ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, |
1362 | int lun, u_int tag, role_t role, uint32_t status) | ||
3717 | { | 1363 | { |
3718 | uint16_t b; | 1364 | 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 | } | 1365 | } |
3771 | 1366 | ||
3772 | static u_int | 1367 | static u_int |
@@ -3800,100 +1395,23 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | |||
3800 | return (tags); | 1395 | return (tags); |
3801 | } | 1396 | } |
3802 | 1397 | ||
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 | /* | 1398 | /* |
3879 | * Determines the queue depth for a given device. | 1399 | * Determines the queue depth for a given device. |
3880 | */ | 1400 | */ |
3881 | static void | 1401 | static void |
3882 | ahd_linux_device_queue_depth(struct ahd_softc *ahd, | 1402 | ahd_linux_device_queue_depth(struct scsi_device *sdev) |
3883 | struct ahd_linux_device *dev) | ||
3884 | { | 1403 | { |
3885 | struct ahd_devinfo devinfo; | 1404 | struct ahd_devinfo devinfo; |
3886 | u_int tags; | 1405 | u_int tags; |
1406 | struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata); | ||
3887 | 1407 | ||
3888 | ahd_compile_devinfo(&devinfo, | 1408 | ahd_compile_devinfo(&devinfo, |
3889 | ahd->our_id, | 1409 | ahd->our_id, |
3890 | dev->target->target, dev->lun, | 1410 | sdev->sdev_target->id, sdev->lun, |
3891 | dev->target->channel == 0 ? 'A' : 'B', | 1411 | sdev->sdev_target->channel == 0 ? 'A' : 'B', |
3892 | ROLE_INITIATOR); | 1412 | ROLE_INITIATOR); |
3893 | tags = ahd_linux_user_tagdepth(ahd, &devinfo); | 1413 | tags = ahd_linux_user_tagdepth(ahd, &devinfo); |
3894 | if (tags != 0 | 1414 | if (tags != 0 && sdev->tagged_supported != 0) { |
3895 | && dev->scsi_device != NULL | ||
3896 | && dev->scsi_device->tagged_supported != 0) { | ||
3897 | 1415 | ||
3898 | ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); | 1416 | ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); |
3899 | ahd_print_devinfo(ahd, &devinfo); | 1417 | ahd_print_devinfo(ahd, &devinfo); |
@@ -3903,11 +1421,10 @@ ahd_linux_device_queue_depth(struct ahd_softc *ahd, | |||
3903 | } | 1421 | } |
3904 | } | 1422 | } |
3905 | 1423 | ||
3906 | static void | 1424 | static int |
3907 | ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) | 1425 | ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, |
1426 | struct scsi_cmnd *cmd) | ||
3908 | { | 1427 | { |
3909 | struct ahd_cmd *acmd; | ||
3910 | struct scsi_cmnd *cmd; | ||
3911 | struct scb *scb; | 1428 | struct scb *scb; |
3912 | struct hardware_scb *hscb; | 1429 | struct hardware_scb *hscb; |
3913 | struct ahd_initiator_tinfo *tinfo; | 1430 | struct ahd_initiator_tinfo *tinfo; |
@@ -3915,157 +1432,122 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) | |||
3915 | u_int col_idx; | 1432 | u_int col_idx; |
3916 | uint16_t mask; | 1433 | uint16_t mask; |
3917 | 1434 | ||
3918 | if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0) | 1435 | /* |
3919 | panic("running device on run list"); | 1436 | * Get an scb to use. |
3920 | 1437 | */ | |
3921 | while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL | 1438 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, |
3922 | && dev->openings > 0 && dev->qfrozen == 0) { | 1439 | cmd->device->id, &tstate); |
3923 | 1440 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0 | |
3924 | /* | 1441 | || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { |
3925 | * Schedule us to run later. The only reason we are not | 1442 | col_idx = AHD_NEVER_COL_IDX; |
3926 | * running is because the whole controller Q is frozen. | 1443 | } else { |
3927 | */ | 1444 | col_idx = AHD_BUILD_COL_IDX(cmd->device->id, |
3928 | if (ahd->platform_data->qfrozen != 0 | 1445 | cmd->device->lun); |
3929 | && AHD_DV_SIMQ_FROZEN(ahd) == 0) { | 1446 | } |
3930 | 1447 | if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { | |
3931 | TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, | 1448 | ahd->flags |= AHD_RESOURCE_SHORTAGE; |
3932 | dev, links); | 1449 | return SCSI_MLQUEUE_HOST_BUSY; |
3933 | dev->flags |= AHD_DEV_ON_RUN_LIST; | 1450 | } |
3934 | return; | ||
3935 | } | ||
3936 | |||
3937 | cmd = &acmd_scsi_cmd(acmd); | ||
3938 | 1451 | ||
3939 | /* | 1452 | scb->io_ctx = cmd; |
3940 | * Get an scb to use. | 1453 | scb->platform_data->dev = dev; |
3941 | */ | 1454 | hscb = scb->hscb; |
3942 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, | 1455 | 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 | 1456 | ||
3964 | /* | 1457 | /* |
3965 | * Fill out basics of the HSCB. | 1458 | * Fill out basics of the HSCB. |
3966 | */ | 1459 | */ |
3967 | hscb->control = 0; | 1460 | hscb->control = 0; |
3968 | hscb->scsiid = BUILD_SCSIID(ahd, cmd); | 1461 | hscb->scsiid = BUILD_SCSIID(ahd, cmd); |
3969 | hscb->lun = cmd->device->lun; | 1462 | hscb->lun = cmd->device->lun; |
3970 | scb->hscb->task_management = 0; | 1463 | scb->hscb->task_management = 0; |
3971 | mask = SCB_GET_TARGET_MASK(ahd, scb); | 1464 | mask = SCB_GET_TARGET_MASK(ahd, scb); |
3972 | 1465 | ||
3973 | if ((ahd->user_discenable & mask) != 0) | 1466 | if ((ahd->user_discenable & mask) != 0) |
3974 | hscb->control |= DISCENB; | 1467 | hscb->control |= DISCENB; |
3975 | 1468 | ||
3976 | if (AHD_DV_CMD(cmd) != 0) | 1469 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) |
3977 | scb->flags |= SCB_SILENT; | 1470 | scb->flags |= SCB_PACKETIZED; |
3978 | 1471 | ||
3979 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) | 1472 | if ((tstate->auto_negotiate & mask) != 0) { |
3980 | scb->flags |= SCB_PACKETIZED; | 1473 | scb->flags |= SCB_AUTO_NEGOTIATE; |
1474 | scb->hscb->control |= MK_MESSAGE; | ||
1475 | } | ||
3981 | 1476 | ||
3982 | if ((tstate->auto_negotiate & mask) != 0) { | 1477 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { |
3983 | scb->flags |= SCB_AUTO_NEGOTIATE; | 1478 | int msg_bytes; |
3984 | scb->hscb->control |= MK_MESSAGE; | 1479 | uint8_t tag_msgs[2]; |
3985 | } | ||
3986 | 1480 | ||
3987 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { | 1481 | msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs); |
3988 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1482 | if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) { |
3989 | int msg_bytes; | 1483 | hscb->control |= tag_msgs[0]; |
3990 | uint8_t tag_msgs[2]; | 1484 | 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; | 1485 | dev->commands_since_idle_or_otag = 0; |
4003 | } else { | 1486 | } else |
4004 | hscb->control |= MSG_SIMPLE_TASK; | 1487 | if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH |
4005 | } | 1488 | && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { |
1489 | hscb->control |= MSG_ORDERED_TASK; | ||
1490 | dev->commands_since_idle_or_otag = 0; | ||
1491 | } else { | ||
1492 | hscb->control |= MSG_SIMPLE_TASK; | ||
4006 | } | 1493 | } |
1494 | } | ||
4007 | 1495 | ||
4008 | hscb->cdb_len = cmd->cmd_len; | 1496 | hscb->cdb_len = cmd->cmd_len; |
4009 | memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); | 1497 | memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); |
4010 | 1498 | ||
4011 | scb->sg_count = 0; | 1499 | scb->platform_data->xfer_len = 0; |
4012 | ahd_set_residual(scb, 0); | 1500 | ahd_set_residual(scb, 0); |
4013 | ahd_set_sense_residual(scb, 0); | 1501 | ahd_set_sense_residual(scb, 0); |
4014 | if (cmd->use_sg != 0) { | 1502 | scb->sg_count = 0; |
4015 | void *sg; | 1503 | if (cmd->use_sg != 0) { |
4016 | struct scatterlist *cur_seg; | 1504 | void *sg; |
4017 | u_int nseg; | 1505 | struct scatterlist *cur_seg; |
4018 | int dir; | 1506 | u_int nseg; |
4019 | 1507 | int dir; | |
4020 | cur_seg = (struct scatterlist *)cmd->request_buffer; | 1508 | |
4021 | dir = cmd->sc_data_direction; | 1509 | cur_seg = (struct scatterlist *)cmd->request_buffer; |
4022 | nseg = pci_map_sg(ahd->dev_softc, cur_seg, | 1510 | dir = cmd->sc_data_direction; |
4023 | cmd->use_sg, dir); | 1511 | nseg = pci_map_sg(ahd->dev_softc, cur_seg, |
4024 | scb->platform_data->xfer_len = 0; | 1512 | cmd->use_sg, dir); |
4025 | for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { | 1513 | scb->platform_data->xfer_len = 0; |
4026 | dma_addr_t addr; | 1514 | 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; | 1515 | dma_addr_t addr; |
4038 | int dir; | 1516 | 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 | 1517 | ||
4051 | LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); | 1518 | addr = sg_dma_address(cur_seg); |
4052 | dev->openings--; | 1519 | len = sg_dma_len(cur_seg); |
4053 | dev->active++; | 1520 | scb->platform_data->xfer_len += len; |
4054 | dev->commands_issued++; | 1521 | sg = ahd_sg_setup(ahd, scb, sg, addr, len, |
4055 | 1522 | /*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 | } | 1523 | } |
1524 | } else if (cmd->request_bufflen != 0) { | ||
1525 | void *sg; | ||
1526 | dma_addr_t addr; | ||
1527 | int dir; | ||
4063 | 1528 | ||
4064 | if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) | 1529 | sg = scb->sg_list; |
4065 | dev->commands_since_idle_or_otag++; | 1530 | dir = cmd->sc_data_direction; |
4066 | scb->flags |= SCB_ACTIVE; | 1531 | addr = pci_map_single(ahd->dev_softc, |
4067 | ahd_queue_scb(ahd, scb); | 1532 | cmd->request_buffer, |
1533 | cmd->request_bufflen, dir); | ||
1534 | scb->platform_data->xfer_len = cmd->request_bufflen; | ||
1535 | scb->platform_data->buf_busaddr = addr; | ||
1536 | sg = ahd_sg_setup(ahd, scb, sg, addr, | ||
1537 | cmd->request_bufflen, /*last*/TRUE); | ||
4068 | } | 1538 | } |
1539 | |||
1540 | LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); | ||
1541 | dev->openings--; | ||
1542 | dev->active++; | ||
1543 | dev->commands_issued++; | ||
1544 | |||
1545 | if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) | ||
1546 | dev->commands_since_idle_or_otag++; | ||
1547 | scb->flags |= SCB_ACTIVE; | ||
1548 | ahd_queue_scb(ahd, scb); | ||
1549 | |||
1550 | return 0; | ||
4069 | } | 1551 | } |
4070 | 1552 | ||
4071 | /* | 1553 | /* |
@@ -4081,9 +1563,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs) | |||
4081 | ahd = (struct ahd_softc *) dev_id; | 1563 | ahd = (struct ahd_softc *) dev_id; |
4082 | ahd_lock(ahd, &flags); | 1564 | ahd_lock(ahd, &flags); |
4083 | ours = ahd_intr(ahd); | 1565 | 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); | 1566 | ahd_unlock(ahd, &flags); |
4088 | return IRQ_RETVAL(ours); | 1567 | return IRQ_RETVAL(ours); |
4089 | } | 1568 | } |
@@ -4092,111 +1571,6 @@ void | |||
4092 | ahd_platform_flushwork(struct ahd_softc *ahd) | 1571 | ahd_platform_flushwork(struct ahd_softc *ahd) |
4093 | { | 1572 | { |
4094 | 1573 | ||
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 | } | 1574 | } |
4201 | 1575 | ||
4202 | void | 1576 | void |
@@ -4207,10 +1581,14 @@ ahd_send_async(struct ahd_softc *ahd, char channel, | |||
4207 | case AC_TRANSFER_NEG: | 1581 | case AC_TRANSFER_NEG: |
4208 | { | 1582 | { |
4209 | char buf[80]; | 1583 | char buf[80]; |
1584 | struct scsi_target *starget; | ||
4210 | struct ahd_linux_target *targ; | 1585 | struct ahd_linux_target *targ; |
4211 | struct info_str info; | 1586 | struct info_str info; |
4212 | struct ahd_initiator_tinfo *tinfo; | 1587 | struct ahd_initiator_tinfo *tinfo; |
4213 | struct ahd_tmode_tstate *tstate; | 1588 | struct ahd_tmode_tstate *tstate; |
1589 | unsigned int target_ppr_options; | ||
1590 | |||
1591 | BUG_ON(target == CAM_TARGET_WILDCARD); | ||
4214 | 1592 | ||
4215 | info.buffer = buf; | 1593 | info.buffer = buf; |
4216 | info.length = sizeof(buf); | 1594 | info.length = sizeof(buf); |
@@ -4234,58 +1612,47 @@ ahd_send_async(struct ahd_softc *ahd, char channel, | |||
4234 | * Don't bother reporting results that | 1612 | * Don't bother reporting results that |
4235 | * are identical to those last reported. | 1613 | * are identical to those last reported. |
4236 | */ | 1614 | */ |
4237 | targ = ahd->platform_data->targets[target]; | 1615 | starget = ahd->platform_data->starget[target]; |
4238 | if (targ == NULL) | 1616 | if (starget == NULL) |
4239 | break; | 1617 | break; |
4240 | if (tinfo->curr.period == targ->last_tinfo.period | 1618 | targ = scsi_transport_target_data(starget); |
4241 | && tinfo->curr.width == targ->last_tinfo.width | 1619 | |
4242 | && tinfo->curr.offset == targ->last_tinfo.offset | 1620 | target_ppr_options = |
4243 | && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options) | 1621 | (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) |
1622 | + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0) | ||
1623 | + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0) | ||
1624 | + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0) | ||
1625 | + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0) | ||
1626 | + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0) | ||
1627 | + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0) | ||
1628 | + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0); | ||
1629 | |||
1630 | if (tinfo->curr.period == spi_period(starget) | ||
1631 | && tinfo->curr.width == spi_width(starget) | ||
1632 | && tinfo->curr.offset == spi_offset(starget) | ||
1633 | && tinfo->curr.ppr_options == target_ppr_options) | ||
4244 | if (bootverbose == 0) | 1634 | if (bootverbose == 0) |
4245 | break; | 1635 | break; |
4246 | 1636 | ||
4247 | targ->last_tinfo.period = tinfo->curr.period; | 1637 | spi_period(starget) = tinfo->curr.period; |
4248 | targ->last_tinfo.width = tinfo->curr.width; | 1638 | spi_width(starget) = tinfo->curr.width; |
4249 | targ->last_tinfo.offset = tinfo->curr.offset; | 1639 | spi_offset(starget) = tinfo->curr.offset; |
4250 | targ->last_tinfo.ppr_options = tinfo->curr.ppr_options; | 1640 | spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0; |
4251 | 1641 | spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0; | |
4252 | printf("(%s:%c:", ahd_name(ahd), channel); | 1642 | spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0; |
4253 | if (target == CAM_TARGET_WILDCARD) | 1643 | spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0; |
4254 | printf("*): "); | 1644 | spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0; |
4255 | else | 1645 | spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0; |
4256 | printf("%d): ", target); | 1646 | spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0; |
4257 | ahd_format_transinfo(&info, &tinfo->curr); | 1647 | spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0; |
4258 | if (info.pos < info.length) | 1648 | spi_display_xfer_agreement(starget); |
4259 | *info.buffer = '\0'; | ||
4260 | else | ||
4261 | buf[info.length - 1] = '\0'; | ||
4262 | printf("%s", buf); | ||
4263 | break; | 1649 | break; |
4264 | } | 1650 | } |
4265 | case AC_SENT_BDR: | 1651 | case AC_SENT_BDR: |
4266 | { | 1652 | { |
4267 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
4268 | WARN_ON(lun != CAM_LUN_WILDCARD); | 1653 | WARN_ON(lun != CAM_LUN_WILDCARD); |
4269 | scsi_report_device_reset(ahd->platform_data->host, | 1654 | scsi_report_device_reset(ahd->platform_data->host, |
4270 | channel - 'A', target); | 1655 | 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; | 1656 | break; |
4290 | } | 1657 | } |
4291 | case AC_BUS_RESET: | 1658 | case AC_BUS_RESET: |
@@ -4305,7 +1672,7 @@ ahd_send_async(struct ahd_softc *ahd, char channel, | |||
4305 | void | 1672 | void |
4306 | ahd_done(struct ahd_softc *ahd, struct scb *scb) | 1673 | ahd_done(struct ahd_softc *ahd, struct scb *scb) |
4307 | { | 1674 | { |
4308 | Scsi_Cmnd *cmd; | 1675 | struct scsi_cmnd *cmd; |
4309 | struct ahd_linux_device *dev; | 1676 | struct ahd_linux_device *dev; |
4310 | 1677 | ||
4311 | if ((scb->flags & SCB_ACTIVE) == 0) { | 1678 | if ((scb->flags & SCB_ACTIVE) == 0) { |
@@ -4373,19 +1740,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) | |||
4373 | ahd_set_transaction_status(scb, CAM_REQ_CMP); | 1740 | ahd_set_transaction_status(scb, CAM_REQ_CMP); |
4374 | } | 1741 | } |
4375 | } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { | 1742 | } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { |
4376 | ahd_linux_handle_scsi_status(ahd, dev, scb); | 1743 | 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 | } | 1744 | } |
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 | 1745 | ||
4390 | if (dev->openings == 1 | 1746 | if (dev->openings == 1 |
4391 | && ahd_get_transaction_status(scb) == CAM_REQ_CMP | 1747 | && ahd_get_transaction_status(scb) == CAM_REQ_CMP |
@@ -4406,47 +1762,32 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) | |||
4406 | if (dev->active == 0) | 1762 | if (dev->active == 0) |
4407 | dev->commands_since_idle_or_otag = 0; | 1763 | dev->commands_since_idle_or_otag = 0; |
4408 | 1764 | ||
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) { | 1765 | if ((scb->flags & SCB_RECOVERY_SCB) != 0) { |
4420 | printf("Recovery SCB completes\n"); | 1766 | printf("Recovery SCB completes\n"); |
4421 | if (ahd_get_transaction_status(scb) == CAM_BDR_SENT | 1767 | if (ahd_get_transaction_status(scb) == CAM_BDR_SENT |
4422 | || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) | 1768 | || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) |
4423 | ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); | 1769 | ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); |
4424 | if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { | 1770 | if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { |
4425 | scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; | 1771 | ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; |
4426 | up(&ahd->platform_data->eh_sem); | 1772 | up(&ahd->platform_data->eh_sem); |
4427 | } | 1773 | } |
4428 | } | 1774 | } |
4429 | 1775 | ||
4430 | ahd_free_scb(ahd, scb); | 1776 | ahd_free_scb(ahd, scb); |
4431 | ahd_linux_queue_cmd_complete(ahd, cmd); | 1777 | 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 | } | 1778 | } |
4439 | 1779 | ||
4440 | static void | 1780 | static void |
4441 | ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | 1781 | ahd_linux_handle_scsi_status(struct ahd_softc *ahd, |
4442 | struct ahd_linux_device *dev, struct scb *scb) | 1782 | struct scsi_device *sdev, struct scb *scb) |
4443 | { | 1783 | { |
4444 | struct ahd_devinfo devinfo; | 1784 | struct ahd_devinfo devinfo; |
1785 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); | ||
4445 | 1786 | ||
4446 | ahd_compile_devinfo(&devinfo, | 1787 | ahd_compile_devinfo(&devinfo, |
4447 | ahd->our_id, | 1788 | ahd->our_id, |
4448 | dev->target->target, dev->lun, | 1789 | sdev->sdev_target->id, sdev->lun, |
4449 | dev->target->channel == 0 ? 'A' : 'B', | 1790 | sdev->sdev_target->channel == 0 ? 'A' : 'B', |
4450 | ROLE_INITIATOR); | 1791 | ROLE_INITIATOR); |
4451 | 1792 | ||
4452 | /* | 1793 | /* |
@@ -4465,7 +1806,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
4465 | case SCSI_STATUS_CHECK_COND: | 1806 | case SCSI_STATUS_CHECK_COND: |
4466 | case SCSI_STATUS_CMD_TERMINATED: | 1807 | case SCSI_STATUS_CMD_TERMINATED: |
4467 | { | 1808 | { |
4468 | Scsi_Cmnd *cmd; | 1809 | struct scsi_cmnd *cmd; |
4469 | 1810 | ||
4470 | /* | 1811 | /* |
4471 | * Copy sense information to the OS's cmd | 1812 | * Copy sense information to the OS's cmd |
@@ -4518,7 +1859,6 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
4518 | break; | 1859 | break; |
4519 | } | 1860 | } |
4520 | case SCSI_STATUS_QUEUE_FULL: | 1861 | case SCSI_STATUS_QUEUE_FULL: |
4521 | { | ||
4522 | /* | 1862 | /* |
4523 | * By the time the core driver has returned this | 1863 | * By the time the core driver has returned this |
4524 | * command, all other commands that were queued | 1864 | * command, all other commands that were queued |
@@ -4579,98 +1919,23 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
4579 | (dev->flags & AHD_DEV_Q_BASIC) | 1919 | (dev->flags & AHD_DEV_Q_BASIC) |
4580 | ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); | 1920 | ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); |
4581 | ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); | 1921 | 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 | } | 1922 | } |
4604 | } | 1923 | } |
4605 | 1924 | ||
4606 | static void | 1925 | static void |
4607 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd) | 1926 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) |
4608 | { | 1927 | { |
4609 | /* | 1928 | /* |
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 | 1929 | * Map CAM error codes into Linux Error codes. We |
4627 | * avoid the conversion so that the DV code has the | 1930 | * avoid the conversion so that the DV code has the |
4628 | * full error information available when making | 1931 | * full error information available when making |
4629 | * state change decisions. | 1932 | * state change decisions. |
4630 | */ | 1933 | */ |
4631 | if (AHD_DV_CMD(cmd) == FALSE) { | 1934 | { |
4632 | uint32_t status; | 1935 | uint32_t status; |
4633 | u_int new_status; | 1936 | u_int new_status; |
4634 | 1937 | ||
4635 | status = ahd_cmd_get_transaction_status(cmd); | 1938 | 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) { | 1939 | switch (status) { |
4675 | case CAM_REQ_INPROG: | 1940 | case CAM_REQ_INPROG: |
4676 | case CAM_REQ_CMP: | 1941 | case CAM_REQ_CMP: |
@@ -4715,26 +1980,7 @@ no_fallback: | |||
4715 | new_status = DID_ERROR; | 1980 | new_status = DID_ERROR; |
4716 | break; | 1981 | break; |
4717 | case CAM_REQUEUE_REQ: | 1982 | case CAM_REQUEUE_REQ: |
4718 | /* | 1983 | 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; | 1984 | break; |
4739 | default: | 1985 | default: |
4740 | /* We should never get here */ | 1986 | /* We should never get here */ |
@@ -4745,116 +1991,23 @@ no_fallback: | |||
4745 | ahd_cmd_set_transaction_status(cmd, new_status); | 1991 | ahd_cmd_set_transaction_status(cmd, new_status); |
4746 | } | 1992 | } |
4747 | 1993 | ||
4748 | completeq = &ahd->platform_data->completeq; | 1994 | 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 | } | 1995 | } |
4760 | 1996 | ||
4761 | static void | 1997 | static void |
4762 | ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | 1998 | ahd_linux_sem_timeout(u_long arg) |
4763 | { | 1999 | { |
4764 | struct scsi_inquiry_data *sid; | 2000 | struct ahd_softc *ahd; |
4765 | struct ahd_initiator_tinfo *tinfo; | 2001 | 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 | 2002 | ||
4798 | /* | 2003 | 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 | 2004 | ||
4815 | /* | 2005 | ahd_lock(ahd, &s); |
4816 | * Only attempt SPI3/4 once we've verified that | 2006 | if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { |
4817 | * the device claims to support SPI3/4 features. | 2007 | ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; |
4818 | */ | 2008 | 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 | } | 2009 | } |
4852 | /* Apply our filtered user settings. */ | 2010 | 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 | } | 2011 | } |
4859 | 2012 | ||
4860 | void | 2013 | void |
@@ -4882,12 +2035,6 @@ ahd_release_simq(struct ahd_softc *ahd) | |||
4882 | if (ahd->platform_data->qfrozen == 0) { | 2035 | if (ahd->platform_data->qfrozen == 0) { |
4883 | unblock_reqs = 1; | 2036 | unblock_reqs = 1; |
4884 | } | 2037 | } |
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); | 2038 | ahd_unlock(ahd, &s); |
4892 | /* | 2039 | /* |
4893 | * There is still a race here. The mid-layer | 2040 | * There is still a race here. The mid-layer |
@@ -4899,118 +2046,743 @@ ahd_release_simq(struct ahd_softc *ahd) | |||
4899 | scsi_unblock_requests(ahd->platform_data->host); | 2046 | scsi_unblock_requests(ahd->platform_data->host); |
4900 | } | 2047 | } |
4901 | 2048 | ||
4902 | static void | 2049 | static int |
4903 | ahd_linux_sem_timeout(u_long arg) | 2050 | ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) |
4904 | { | 2051 | { |
4905 | struct scb *scb; | 2052 | struct ahd_softc *ahd; |
4906 | struct ahd_softc *ahd; | 2053 | struct ahd_linux_device *dev; |
4907 | u_long s; | 2054 | struct scb *pending_scb; |
2055 | u_int saved_scbptr; | ||
2056 | u_int active_scbptr; | ||
2057 | u_int last_phase; | ||
2058 | u_int saved_scsiid; | ||
2059 | u_int cdb_byte; | ||
2060 | int retval; | ||
2061 | int was_paused; | ||
2062 | int paused; | ||
2063 | int wait; | ||
2064 | int disconnected; | ||
2065 | ahd_mode_state saved_modes; | ||
4908 | 2066 | ||
4909 | scb = (struct scb *)arg; | 2067 | pending_scb = NULL; |
4910 | ahd = scb->ahd_softc; | 2068 | paused = FALSE; |
4911 | ahd_lock(ahd, &s); | 2069 | wait = FALSE; |
4912 | if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { | 2070 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
4913 | scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; | 2071 | |
4914 | up(&ahd->platform_data->eh_sem); | 2072 | printf("%s:%d:%d:%d: Attempting to queue a%s message:", |
2073 | ahd_name(ahd), cmd->device->channel, | ||
2074 | cmd->device->id, cmd->device->lun, | ||
2075 | flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); | ||
2076 | |||
2077 | printf("CDB:"); | ||
2078 | for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) | ||
2079 | printf(" 0x%x", cmd->cmnd[cdb_byte]); | ||
2080 | printf("\n"); | ||
2081 | |||
2082 | spin_lock_irq(&ahd->platform_data->spin_lock); | ||
2083 | |||
2084 | /* | ||
2085 | * First determine if we currently own this command. | ||
2086 | * Start by searching the device queue. If not found | ||
2087 | * there, check the pending_scb list. If not found | ||
2088 | * at all, and the system wanted us to just abort the | ||
2089 | * command, return success. | ||
2090 | */ | ||
2091 | dev = scsi_transport_device_data(cmd->device); | ||
2092 | |||
2093 | if (dev == NULL) { | ||
2094 | /* | ||
2095 | * No target device for this command exists, | ||
2096 | * so we must not still own the command. | ||
2097 | */ | ||
2098 | printf("%s:%d:%d:%d: Is not an active device\n", | ||
2099 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
2100 | cmd->device->lun); | ||
2101 | retval = SUCCESS; | ||
2102 | goto no_cmd; | ||
4915 | } | 2103 | } |
4916 | ahd_unlock(ahd, &s); | 2104 | |
2105 | /* | ||
2106 | * See if we can find a matching cmd in the pending list. | ||
2107 | */ | ||
2108 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | ||
2109 | if (pending_scb->io_ctx == cmd) | ||
2110 | break; | ||
2111 | } | ||
2112 | |||
2113 | if (pending_scb == NULL && flag == SCB_DEVICE_RESET) { | ||
2114 | |||
2115 | /* Any SCB for this device will do for a target reset */ | ||
2116 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | ||
2117 | if (ahd_match_scb(ahd, pending_scb, cmd->device->id, | ||
2118 | cmd->device->channel + 'A', | ||
2119 | CAM_LUN_WILDCARD, | ||
2120 | SCB_LIST_NULL, ROLE_INITIATOR) == 0) | ||
2121 | break; | ||
2122 | } | ||
2123 | } | ||
2124 | |||
2125 | if (pending_scb == NULL) { | ||
2126 | printf("%s:%d:%d:%d: Command not found\n", | ||
2127 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
2128 | cmd->device->lun); | ||
2129 | goto no_cmd; | ||
2130 | } | ||
2131 | |||
2132 | if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { | ||
2133 | /* | ||
2134 | * We can't queue two recovery actions using the same SCB | ||
2135 | */ | ||
2136 | retval = FAILED; | ||
2137 | goto done; | ||
2138 | } | ||
2139 | |||
2140 | /* | ||
2141 | * Ensure that the card doesn't do anything | ||
2142 | * behind our back. Also make sure that we | ||
2143 | * didn't "just" miss an interrupt that would | ||
2144 | * affect this cmd. | ||
2145 | */ | ||
2146 | was_paused = ahd_is_paused(ahd); | ||
2147 | ahd_pause_and_flushwork(ahd); | ||
2148 | paused = TRUE; | ||
2149 | |||
2150 | if ((pending_scb->flags & SCB_ACTIVE) == 0) { | ||
2151 | printf("%s:%d:%d:%d: Command already completed\n", | ||
2152 | ahd_name(ahd), cmd->device->channel, cmd->device->id, | ||
2153 | cmd->device->lun); | ||
2154 | goto no_cmd; | ||
2155 | } | ||
2156 | |||
2157 | printf("%s: At time of recovery, card was %spaused\n", | ||
2158 | ahd_name(ahd), was_paused ? "" : "not "); | ||
2159 | ahd_dump_card_state(ahd); | ||
2160 | |||
2161 | disconnected = TRUE; | ||
2162 | if (flag == SCB_ABORT) { | ||
2163 | if (ahd_search_qinfifo(ahd, cmd->device->id, | ||
2164 | cmd->device->channel + 'A', | ||
2165 | cmd->device->lun, | ||
2166 | pending_scb->hscb->tag, | ||
2167 | ROLE_INITIATOR, CAM_REQ_ABORTED, | ||
2168 | SEARCH_COMPLETE) > 0) { | ||
2169 | printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", | ||
2170 | ahd_name(ahd), cmd->device->channel, | ||
2171 | cmd->device->id, cmd->device->lun); | ||
2172 | retval = SUCCESS; | ||
2173 | goto done; | ||
2174 | } | ||
2175 | } else if (ahd_search_qinfifo(ahd, cmd->device->id, | ||
2176 | cmd->device->channel + 'A', | ||
2177 | cmd->device->lun, pending_scb->hscb->tag, | ||
2178 | ROLE_INITIATOR, /*status*/0, | ||
2179 | SEARCH_COUNT) > 0) { | ||
2180 | disconnected = FALSE; | ||
2181 | } | ||
2182 | |||
2183 | saved_modes = ahd_save_modes(ahd); | ||
2184 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
2185 | last_phase = ahd_inb(ahd, LASTPHASE); | ||
2186 | saved_scbptr = ahd_get_scbptr(ahd); | ||
2187 | active_scbptr = saved_scbptr; | ||
2188 | if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { | ||
2189 | struct scb *bus_scb; | ||
2190 | |||
2191 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); | ||
2192 | if (bus_scb == pending_scb) | ||
2193 | disconnected = FALSE; | ||
2194 | else if (flag != SCB_ABORT | ||
2195 | && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid | ||
2196 | && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb)) | ||
2197 | disconnected = FALSE; | ||
2198 | } | ||
2199 | |||
2200 | /* | ||
2201 | * At this point, pending_scb is the scb associated with the | ||
2202 | * passed in command. That command is currently active on the | ||
2203 | * bus or is in the disconnected state. | ||
2204 | */ | ||
2205 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); | ||
2206 | if (last_phase != P_BUSFREE | ||
2207 | && (SCB_GET_TAG(pending_scb) == active_scbptr | ||
2208 | || (flag == SCB_DEVICE_RESET | ||
2209 | && SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) { | ||
2210 | |||
2211 | /* | ||
2212 | * We're active on the bus, so assert ATN | ||
2213 | * and hope that the target responds. | ||
2214 | */ | ||
2215 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); | ||
2216 | pending_scb->flags |= SCB_RECOVERY_SCB|flag; | ||
2217 | ahd_outb(ahd, MSG_OUT, HOST_MSG); | ||
2218 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); | ||
2219 | printf("%s:%d:%d:%d: Device is active, asserting ATN\n", | ||
2220 | ahd_name(ahd), cmd->device->channel, | ||
2221 | cmd->device->id, cmd->device->lun); | ||
2222 | wait = TRUE; | ||
2223 | } else if (disconnected) { | ||
2224 | |||
2225 | /* | ||
2226 | * Actually re-queue this SCB in an attempt | ||
2227 | * to select the device before it reconnects. | ||
2228 | */ | ||
2229 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; | ||
2230 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); | ||
2231 | pending_scb->hscb->cdb_len = 0; | ||
2232 | pending_scb->hscb->task_attribute = 0; | ||
2233 | pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; | ||
2234 | |||
2235 | if ((pending_scb->flags & SCB_PACKETIZED) != 0) { | ||
2236 | /* | ||
2237 | * Mark the SCB has having an outstanding | ||
2238 | * task management function. Should the command | ||
2239 | * complete normally before the task management | ||
2240 | * function can be sent, the host will be notified | ||
2241 | * to abort our requeued SCB. | ||
2242 | */ | ||
2243 | ahd_outb(ahd, SCB_TASK_MANAGEMENT, | ||
2244 | pending_scb->hscb->task_management); | ||
2245 | } else { | ||
2246 | /* | ||
2247 | * If non-packetized, set the MK_MESSAGE control | ||
2248 | * bit indicating that we desire to send a message. | ||
2249 | * We also set the disconnected flag since there is | ||
2250 | * no guarantee that our SCB control byte matches | ||
2251 | * the version on the card. We don't want the | ||
2252 | * sequencer to abort the command thinking an | ||
2253 | * unsolicited reselection occurred. | ||
2254 | */ | ||
2255 | pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED; | ||
2256 | |||
2257 | /* | ||
2258 | * The sequencer will never re-reference the | ||
2259 | * in-core SCB. To make sure we are notified | ||
2260 | * during reslection, set the MK_MESSAGE flag in | ||
2261 | * the card's copy of the SCB. | ||
2262 | */ | ||
2263 | ahd_outb(ahd, SCB_CONTROL, | ||
2264 | ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); | ||
2265 | } | ||
2266 | |||
2267 | /* | ||
2268 | * Clear out any entries in the QINFIFO first | ||
2269 | * so we are the next SCB for this target | ||
2270 | * to run. | ||
2271 | */ | ||
2272 | ahd_search_qinfifo(ahd, cmd->device->id, | ||
2273 | cmd->device->channel + 'A', cmd->device->lun, | ||
2274 | SCB_LIST_NULL, ROLE_INITIATOR, | ||
2275 | CAM_REQUEUE_REQ, SEARCH_COMPLETE); | ||
2276 | ahd_qinfifo_requeue_tail(ahd, pending_scb); | ||
2277 | ahd_set_scbptr(ahd, saved_scbptr); | ||
2278 | ahd_print_path(ahd, pending_scb); | ||
2279 | printf("Device is disconnected, re-queuing SCB\n"); | ||
2280 | wait = TRUE; | ||
2281 | } else { | ||
2282 | printf("%s:%d:%d:%d: Unable to deliver message\n", | ||
2283 | ahd_name(ahd), cmd->device->channel, | ||
2284 | cmd->device->id, cmd->device->lun); | ||
2285 | retval = FAILED; | ||
2286 | goto done; | ||
2287 | } | ||
2288 | |||
2289 | no_cmd: | ||
2290 | /* | ||
2291 | * Our assumption is that if we don't have the command, no | ||
2292 | * recovery action was required, so we return success. Again, | ||
2293 | * the semantics of the mid-layer recovery engine are not | ||
2294 | * well defined, so this may change in time. | ||
2295 | */ | ||
2296 | retval = SUCCESS; | ||
2297 | done: | ||
2298 | if (paused) | ||
2299 | ahd_unpause(ahd); | ||
2300 | if (wait) { | ||
2301 | struct timer_list timer; | ||
2302 | int ret; | ||
2303 | |||
2304 | ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM; | ||
2305 | spin_unlock_irq(&ahd->platform_data->spin_lock); | ||
2306 | init_timer(&timer); | ||
2307 | timer.data = (u_long)ahd; | ||
2308 | timer.expires = jiffies + (5 * HZ); | ||
2309 | timer.function = ahd_linux_sem_timeout; | ||
2310 | add_timer(&timer); | ||
2311 | printf("Recovery code sleeping\n"); | ||
2312 | down(&ahd->platform_data->eh_sem); | ||
2313 | printf("Recovery code awake\n"); | ||
2314 | ret = del_timer_sync(&timer); | ||
2315 | if (ret == 0) { | ||
2316 | printf("Timer Expired\n"); | ||
2317 | retval = FAILED; | ||
2318 | } | ||
2319 | spin_lock_irq(&ahd->platform_data->spin_lock); | ||
2320 | } | ||
2321 | spin_unlock_irq(&ahd->platform_data->spin_lock); | ||
2322 | return (retval); | ||
4917 | } | 2323 | } |
4918 | 2324 | ||
4919 | static void | 2325 | static void ahd_linux_set_width(struct scsi_target *starget, int width) |
4920 | ahd_linux_dev_timed_unfreeze(u_long arg) | ||
4921 | { | 2326 | { |
4922 | struct ahd_linux_device *dev; | 2327 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
4923 | struct ahd_softc *ahd; | 2328 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); |
4924 | u_long s; | 2329 | struct ahd_devinfo devinfo; |
2330 | unsigned long flags; | ||
4925 | 2331 | ||
4926 | dev = (struct ahd_linux_device *)arg; | 2332 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, |
4927 | ahd = dev->target->ahd; | 2333 | starget->channel + 'A', ROLE_INITIATOR); |
4928 | ahd_lock(ahd, &s); | 2334 | ahd_lock(ahd, &flags); |
4929 | dev->flags &= ~AHD_DEV_TIMER_ACTIVE; | 2335 | ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE); |
4930 | if (dev->qfrozen > 0) | 2336 | 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 | } | 2337 | } |
4940 | 2338 | ||
4941 | void | 2339 | static void ahd_linux_set_period(struct scsi_target *starget, int period) |
4942 | ahd_platform_dump_card_state(struct ahd_softc *ahd) | ||
4943 | { | 2340 | { |
4944 | struct ahd_linux_device *dev; | 2341 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
4945 | int target; | 2342 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); |
4946 | int maxtarget; | 2343 | struct ahd_tmode_tstate *tstate; |
4947 | int lun; | 2344 | struct ahd_initiator_tinfo *tinfo |
4948 | int i; | 2345 | = ahd_fetch_transinfo(ahd, |
4949 | 2346 | starget->channel + 'A', | |
4950 | maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7; | 2347 | shost->this_id, starget->id, &tstate); |
4951 | for (target = 0; target <=maxtarget; target++) { | 2348 | struct ahd_devinfo devinfo; |
4952 | 2349 | unsigned int ppr_options = tinfo->goal.ppr_options; | |
4953 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { | 2350 | unsigned int dt; |
4954 | struct ahd_cmd *acmd; | 2351 | unsigned long flags; |
4955 | 2352 | unsigned long offset = tinfo->goal.offset; | |
4956 | dev = ahd_linux_get_device(ahd, 0, target, | 2353 | |
4957 | lun, /*alloc*/FALSE); | 2354 | #ifdef AHD_DEBUG |
4958 | if (dev == NULL) | 2355 | if ((ahd_debug & AHD_SHOW_DV) != 0) |
4959 | continue; | 2356 | printf("%s: set period to %d\n", ahd_name(ahd), period); |
4960 | 2357 | #endif | |
4961 | printf("DevQ(%d:%d:%d): ", 0, target, lun); | 2358 | if (offset == 0) |
4962 | i = 0; | 2359 | offset = MAX_OFFSET; |
4963 | TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) { | 2360 | |
4964 | if (i++ > AHD_SCB_MAX) | 2361 | if (period < 8) |
4965 | break; | 2362 | period = 8; |
4966 | } | 2363 | if (period < 10) { |
4967 | printf("%d waiting\n", i); | 2364 | ppr_options |= MSG_EXT_PPR_DT_REQ; |
4968 | } | 2365 | if (period == 8) |
2366 | ppr_options |= MSG_EXT_PPR_IU_REQ; | ||
4969 | } | 2367 | } |
2368 | |||
2369 | dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2370 | |||
2371 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2372 | starget->channel + 'A', ROLE_INITIATOR); | ||
2373 | |||
2374 | /* all PPR requests apart from QAS require wide transfers */ | ||
2375 | if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) { | ||
2376 | if (spi_width(starget) == 0) | ||
2377 | ppr_options &= MSG_EXT_PPR_QAS_REQ; | ||
2378 | } | ||
2379 | |||
2380 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2381 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2382 | |||
2383 | ahd_lock(ahd, &flags); | ||
2384 | ahd_set_syncrate(ahd, &devinfo, period, offset, | ||
2385 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2386 | ahd_unlock(ahd, &flags); | ||
4970 | } | 2387 | } |
4971 | 2388 | ||
4972 | static int __init | 2389 | static void ahd_linux_set_offset(struct scsi_target *starget, int offset) |
4973 | ahd_linux_init(void) | ||
4974 | { | 2390 | { |
4975 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 2391 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
4976 | return ahd_linux_detect(&aic79xx_driver_template); | 2392 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); |
4977 | #else | 2393 | struct ahd_tmode_tstate *tstate; |
4978 | scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template); | 2394 | struct ahd_initiator_tinfo *tinfo |
4979 | if (aic79xx_driver_template.present == 0) { | 2395 | = ahd_fetch_transinfo(ahd, |
4980 | scsi_unregister_module(MODULE_SCSI_HA, | 2396 | starget->channel + 'A', |
4981 | &aic79xx_driver_template); | 2397 | shost->this_id, starget->id, &tstate); |
4982 | return (-ENODEV); | 2398 | struct ahd_devinfo devinfo; |
2399 | unsigned int ppr_options = 0; | ||
2400 | unsigned int period = 0; | ||
2401 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2402 | unsigned long flags; | ||
2403 | |||
2404 | #ifdef AHD_DEBUG | ||
2405 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2406 | printf("%s: set offset to %d\n", ahd_name(ahd), offset); | ||
2407 | #endif | ||
2408 | |||
2409 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2410 | starget->channel + 'A', ROLE_INITIATOR); | ||
2411 | if (offset != 0) { | ||
2412 | period = tinfo->goal.period; | ||
2413 | ppr_options = tinfo->goal.ppr_options; | ||
2414 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2415 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
4983 | } | 2416 | } |
4984 | 2417 | ||
4985 | return (0); | 2418 | ahd_lock(ahd, &flags); |
2419 | ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options, | ||
2420 | AHD_TRANS_GOAL, FALSE); | ||
2421 | ahd_unlock(ahd, &flags); | ||
2422 | } | ||
2423 | |||
2424 | static void ahd_linux_set_dt(struct scsi_target *starget, int dt) | ||
2425 | { | ||
2426 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2427 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2428 | struct ahd_tmode_tstate *tstate; | ||
2429 | struct ahd_initiator_tinfo *tinfo | ||
2430 | = ahd_fetch_transinfo(ahd, | ||
2431 | starget->channel + 'A', | ||
2432 | shost->this_id, starget->id, &tstate); | ||
2433 | struct ahd_devinfo devinfo; | ||
2434 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2435 | & ~MSG_EXT_PPR_DT_REQ; | ||
2436 | unsigned int period = tinfo->goal.period; | ||
2437 | unsigned int width = tinfo->goal.width; | ||
2438 | unsigned long flags; | ||
2439 | |||
2440 | #ifdef AHD_DEBUG | ||
2441 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2442 | printf("%s: %s DT\n", ahd_name(ahd), | ||
2443 | dt ? "enabling" : "disabling"); | ||
2444 | #endif | ||
2445 | if (dt) { | ||
2446 | ppr_options |= MSG_EXT_PPR_DT_REQ; | ||
2447 | if (!width) | ||
2448 | ahd_linux_set_width(starget, 1); | ||
2449 | } else { | ||
2450 | if (period <= 9) | ||
2451 | period = 10; /* If resetting DT, period must be >= 25ns */ | ||
2452 | /* IU is invalid without DT set */ | ||
2453 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | ||
2454 | } | ||
2455 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2456 | starget->channel + 'A', ROLE_INITIATOR); | ||
2457 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2458 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2459 | |||
2460 | ahd_lock(ahd, &flags); | ||
2461 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2462 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2463 | ahd_unlock(ahd, &flags); | ||
2464 | } | ||
2465 | |||
2466 | static void ahd_linux_set_qas(struct scsi_target *starget, int qas) | ||
2467 | { | ||
2468 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2469 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2470 | struct ahd_tmode_tstate *tstate; | ||
2471 | struct ahd_initiator_tinfo *tinfo | ||
2472 | = ahd_fetch_transinfo(ahd, | ||
2473 | starget->channel + 'A', | ||
2474 | shost->this_id, starget->id, &tstate); | ||
2475 | struct ahd_devinfo devinfo; | ||
2476 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2477 | & ~MSG_EXT_PPR_QAS_REQ; | ||
2478 | unsigned int period = tinfo->goal.period; | ||
2479 | unsigned int dt; | ||
2480 | unsigned long flags; | ||
2481 | |||
2482 | #ifdef AHD_DEBUG | ||
2483 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2484 | printf("%s: %s QAS\n", ahd_name(ahd), | ||
2485 | qas ? "enabling" : "disabling"); | ||
2486 | #endif | ||
2487 | |||
2488 | if (qas) { | ||
2489 | ppr_options |= MSG_EXT_PPR_QAS_REQ; | ||
2490 | } | ||
2491 | |||
2492 | dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2493 | |||
2494 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2495 | starget->channel + 'A', ROLE_INITIATOR); | ||
2496 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2497 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2498 | |||
2499 | ahd_lock(ahd, &flags); | ||
2500 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2501 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2502 | ahd_unlock(ahd, &flags); | ||
2503 | } | ||
2504 | |||
2505 | static void ahd_linux_set_iu(struct scsi_target *starget, int iu) | ||
2506 | { | ||
2507 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2508 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2509 | struct ahd_tmode_tstate *tstate; | ||
2510 | struct ahd_initiator_tinfo *tinfo | ||
2511 | = ahd_fetch_transinfo(ahd, | ||
2512 | starget->channel + 'A', | ||
2513 | shost->this_id, starget->id, &tstate); | ||
2514 | struct ahd_devinfo devinfo; | ||
2515 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2516 | & ~MSG_EXT_PPR_IU_REQ; | ||
2517 | unsigned int period = tinfo->goal.period; | ||
2518 | unsigned int dt; | ||
2519 | unsigned long flags; | ||
2520 | |||
2521 | #ifdef AHD_DEBUG | ||
2522 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2523 | printf("%s: %s IU\n", ahd_name(ahd), | ||
2524 | iu ? "enabling" : "disabling"); | ||
4986 | #endif | 2525 | #endif |
2526 | |||
2527 | if (iu) { | ||
2528 | ppr_options |= MSG_EXT_PPR_IU_REQ; | ||
2529 | ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */ | ||
2530 | } | ||
2531 | |||
2532 | dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
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); | ||
4987 | } | 2543 | } |
4988 | 2544 | ||
4989 | static void __exit | 2545 | static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) |
4990 | ahd_linux_exit(void) | ||
4991 | { | 2546 | { |
4992 | struct ahd_softc *ahd; | 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_RD_STRM; | ||
2557 | unsigned int period = tinfo->goal.period; | ||
2558 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2559 | unsigned long flags; | ||
4993 | 2560 | ||
4994 | /* | 2561 | #ifdef AHD_DEBUG |
4995 | * Shutdown DV threads before going into the SCSI mid-layer. | 2562 | if ((ahd_debug & AHD_SHOW_DV) != 0) |
4996 | * This avoids situations where the mid-layer locks the entire | 2563 | printf("%s: %s Read Streaming\n", ahd_name(ahd), |
4997 | * kernel so that waiting for our DV threads to exit leads | 2564 | rdstrm ? "enabling" : "disabling"); |
4998 | * to deadlock. | 2565 | #endif |
4999 | */ | 2566 | |
5000 | TAILQ_FOREACH(ahd, &ahd_tailq, links) { | 2567 | if (rdstrm) |
2568 | ppr_options |= MSG_EXT_PPR_RD_STRM; | ||
2569 | |||
2570 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2571 | starget->channel + 'A', ROLE_INITIATOR); | ||
2572 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2573 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
5001 | 2574 | ||
5002 | ahd_linux_kill_dv_thread(ahd); | 2575 | ahd_lock(ahd, &flags); |
2576 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2577 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2578 | ahd_unlock(ahd, &flags); | ||
2579 | } | ||
2580 | |||
2581 | static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow) | ||
2582 | { | ||
2583 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2584 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2585 | struct ahd_tmode_tstate *tstate; | ||
2586 | struct ahd_initiator_tinfo *tinfo | ||
2587 | = ahd_fetch_transinfo(ahd, | ||
2588 | starget->channel + 'A', | ||
2589 | shost->this_id, starget->id, &tstate); | ||
2590 | struct ahd_devinfo devinfo; | ||
2591 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2592 | & ~MSG_EXT_PPR_WR_FLOW; | ||
2593 | unsigned int period = tinfo->goal.period; | ||
2594 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2595 | unsigned long flags; | ||
2596 | |||
2597 | #ifdef AHD_DEBUG | ||
2598 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2599 | printf("%s: %s Write Flow Control\n", ahd_name(ahd), | ||
2600 | wrflow ? "enabling" : "disabling"); | ||
2601 | #endif | ||
2602 | |||
2603 | if (wrflow) | ||
2604 | ppr_options |= MSG_EXT_PPR_WR_FLOW; | ||
2605 | |||
2606 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2607 | starget->channel + 'A', ROLE_INITIATOR); | ||
2608 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2609 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2610 | |||
2611 | ahd_lock(ahd, &flags); | ||
2612 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2613 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2614 | ahd_unlock(ahd, &flags); | ||
2615 | } | ||
2616 | |||
2617 | static void ahd_linux_set_rti(struct scsi_target *starget, int rti) | ||
2618 | { | ||
2619 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2620 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2621 | struct ahd_tmode_tstate *tstate; | ||
2622 | struct ahd_initiator_tinfo *tinfo | ||
2623 | = ahd_fetch_transinfo(ahd, | ||
2624 | starget->channel + 'A', | ||
2625 | shost->this_id, starget->id, &tstate); | ||
2626 | struct ahd_devinfo devinfo; | ||
2627 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2628 | & ~MSG_EXT_PPR_RTI; | ||
2629 | unsigned int period = tinfo->goal.period; | ||
2630 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2631 | unsigned long flags; | ||
2632 | |||
2633 | if ((ahd->features & AHD_RTI) == 0) { | ||
2634 | #ifdef AHD_DEBUG | ||
2635 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2636 | printf("%s: RTI not available\n", ahd_name(ahd)); | ||
2637 | #endif | ||
2638 | return; | ||
5003 | } | 2639 | } |
5004 | 2640 | ||
5005 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 2641 | #ifdef AHD_DEBUG |
2642 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2643 | printf("%s: %s RTI\n", ahd_name(ahd), | ||
2644 | rti ? "enabling" : "disabling"); | ||
2645 | #endif | ||
2646 | |||
2647 | if (rti) | ||
2648 | ppr_options |= MSG_EXT_PPR_RTI; | ||
2649 | |||
2650 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2651 | starget->channel + 'A', ROLE_INITIATOR); | ||
2652 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2653 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2654 | |||
2655 | ahd_lock(ahd, &flags); | ||
2656 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2657 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2658 | ahd_unlock(ahd, &flags); | ||
2659 | } | ||
2660 | |||
2661 | static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) | ||
2662 | { | ||
2663 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2664 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2665 | struct ahd_tmode_tstate *tstate; | ||
2666 | struct ahd_initiator_tinfo *tinfo | ||
2667 | = ahd_fetch_transinfo(ahd, | ||
2668 | starget->channel + 'A', | ||
2669 | shost->this_id, starget->id, &tstate); | ||
2670 | struct ahd_devinfo devinfo; | ||
2671 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2672 | & ~MSG_EXT_PPR_PCOMP_EN; | ||
2673 | unsigned int period = tinfo->goal.period; | ||
2674 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2675 | unsigned long flags; | ||
2676 | |||
2677 | #ifdef AHD_DEBUG | ||
2678 | if ((ahd_debug & AHD_SHOW_DV) != 0) | ||
2679 | printf("%s: %s Precompensation\n", ahd_name(ahd), | ||
2680 | pcomp ? "Enable" : "Disable"); | ||
2681 | #endif | ||
2682 | |||
2683 | if (pcomp) | ||
2684 | ppr_options |= MSG_EXT_PPR_PCOMP_EN; | ||
2685 | |||
2686 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2687 | starget->channel + 'A', ROLE_INITIATOR); | ||
2688 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2689 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2690 | |||
2691 | ahd_lock(ahd, &flags); | ||
2692 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2693 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2694 | ahd_unlock(ahd, &flags); | ||
2695 | } | ||
2696 | |||
2697 | static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold) | ||
2698 | { | ||
2699 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2700 | struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); | ||
2701 | struct ahd_tmode_tstate *tstate; | ||
2702 | struct ahd_initiator_tinfo *tinfo | ||
2703 | = ahd_fetch_transinfo(ahd, | ||
2704 | starget->channel + 'A', | ||
2705 | shost->this_id, starget->id, &tstate); | ||
2706 | struct ahd_devinfo devinfo; | ||
2707 | unsigned int ppr_options = tinfo->goal.ppr_options | ||
2708 | & ~MSG_EXT_PPR_HOLD_MCS; | ||
2709 | unsigned int period = tinfo->goal.period; | ||
2710 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
2711 | unsigned long flags; | ||
2712 | |||
2713 | if (hold) | ||
2714 | ppr_options |= MSG_EXT_PPR_HOLD_MCS; | ||
2715 | |||
2716 | ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
2717 | starget->channel + 'A', ROLE_INITIATOR); | ||
2718 | ahd_find_syncrate(ahd, &period, &ppr_options, | ||
2719 | dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); | ||
2720 | |||
2721 | ahd_lock(ahd, &flags); | ||
2722 | ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, | ||
2723 | ppr_options, AHD_TRANS_GOAL, FALSE); | ||
2724 | ahd_unlock(ahd, &flags); | ||
2725 | } | ||
2726 | |||
2727 | |||
2728 | |||
2729 | static struct spi_function_template ahd_linux_transport_functions = { | ||
2730 | .set_offset = ahd_linux_set_offset, | ||
2731 | .show_offset = 1, | ||
2732 | .set_period = ahd_linux_set_period, | ||
2733 | .show_period = 1, | ||
2734 | .set_width = ahd_linux_set_width, | ||
2735 | .show_width = 1, | ||
2736 | .set_dt = ahd_linux_set_dt, | ||
2737 | .show_dt = 1, | ||
2738 | .set_iu = ahd_linux_set_iu, | ||
2739 | .show_iu = 1, | ||
2740 | .set_qas = ahd_linux_set_qas, | ||
2741 | .show_qas = 1, | ||
2742 | .set_rd_strm = ahd_linux_set_rd_strm, | ||
2743 | .show_rd_strm = 1, | ||
2744 | .set_wr_flow = ahd_linux_set_wr_flow, | ||
2745 | .show_wr_flow = 1, | ||
2746 | .set_rti = ahd_linux_set_rti, | ||
2747 | .show_rti = 1, | ||
2748 | .set_pcomp_en = ahd_linux_set_pcomp_en, | ||
2749 | .show_pcomp_en = 1, | ||
2750 | .set_hold_mcs = ahd_linux_set_hold_mcs, | ||
2751 | .show_hold_mcs = 1, | ||
2752 | }; | ||
2753 | |||
2754 | static int __init | ||
2755 | ahd_linux_init(void) | ||
2756 | { | ||
2757 | int error = 0; | ||
2758 | |||
5006 | /* | 2759 | /* |
5007 | * In 2.4 we have to unregister from the PCI core _after_ | 2760 | * If we've been passed any parameters, process them now. |
5008 | * unregistering from the scsi midlayer to avoid dangling | ||
5009 | * references. | ||
5010 | */ | 2761 | */ |
5011 | scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template); | 2762 | if (aic79xx) |
5012 | #endif | 2763 | aic79xx_setup(aic79xx); |
2764 | |||
2765 | ahd_linux_transport_template = | ||
2766 | spi_attach_transport(&ahd_linux_transport_functions); | ||
2767 | if (!ahd_linux_transport_template) | ||
2768 | return -ENODEV; | ||
2769 | |||
2770 | scsi_transport_reserve_target(ahd_linux_transport_template, | ||
2771 | sizeof(struct ahd_linux_target)); | ||
2772 | scsi_transport_reserve_device(ahd_linux_transport_template, | ||
2773 | sizeof(struct ahd_linux_device)); | ||
2774 | |||
2775 | error = ahd_linux_pci_init(); | ||
2776 | if (error) | ||
2777 | spi_release_transport(ahd_linux_transport_template); | ||
2778 | return error; | ||
2779 | } | ||
2780 | |||
2781 | static void __exit | ||
2782 | ahd_linux_exit(void) | ||
2783 | { | ||
5013 | ahd_linux_pci_exit(); | 2784 | ahd_linux_pci_exit(); |
2785 | spi_release_transport(ahd_linux_transport_template); | ||
5014 | } | 2786 | } |
5015 | 2787 | ||
5016 | module_init(ahd_linux_init); | 2788 | 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..39a27840fce6 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c | |||
@@ -49,10 +49,53 @@ 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 | ||
56 | /* | ||
57 | * Table of syncrates that don't follow the "divisible by 4" | ||
58 | * rule. This table will be expanded in future SCSI specs. | ||
59 | */ | ||
60 | static struct { | ||
61 | u_int period_factor; | ||
62 | u_int period; /* in 100ths of ns */ | ||
63 | } scsi_syncrates[] = { | ||
64 | { 0x08, 625 }, /* FAST-160 */ | ||
65 | { 0x09, 1250 }, /* FAST-80 */ | ||
66 | { 0x0a, 2500 }, /* FAST-40 40MHz */ | ||
67 | { 0x0b, 3030 }, /* FAST-40 33MHz */ | ||
68 | { 0x0c, 5000 } /* FAST-20 */ | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * Return the frequency in kHz corresponding to the given | ||
73 | * sync period factor. | ||
74 | */ | ||
75 | static u_int | ||
76 | ahd_calc_syncsrate(u_int period_factor) | ||
77 | { | ||
78 | int i; | ||
79 | int num_syncrates; | ||
80 | |||
81 | num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); | ||
82 | /* See if the period is in the "exception" table */ | ||
83 | for (i = 0; i < num_syncrates; i++) { | ||
84 | |||
85 | if (period_factor == scsi_syncrates[i].period_factor) { | ||
86 | /* Period in kHz */ | ||
87 | return (100000000 / scsi_syncrates[i].period); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Wasn't in the table, so use the standard | ||
93 | * 4 times conversion. | ||
94 | */ | ||
95 | return (10000000 / (period_factor * 4 * 10)); | ||
96 | } | ||
97 | |||
98 | |||
56 | static void | 99 | static void |
57 | copy_mem_info(struct info_str *info, char *data, int len) | 100 | copy_mem_info(struct info_str *info, char *data, int len) |
58 | { | 101 | { |
@@ -109,7 +152,7 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) | |||
109 | speed = 3300; | 152 | speed = 3300; |
110 | freq = 0; | 153 | freq = 0; |
111 | if (tinfo->offset != 0) { | 154 | if (tinfo->offset != 0) { |
112 | freq = aic_calc_syncsrate(tinfo->period); | 155 | freq = ahd_calc_syncsrate(tinfo->period); |
113 | speed = freq; | 156 | speed = freq; |
114 | } | 157 | } |
115 | speed *= (0x01 << tinfo->width); | 158 | speed *= (0x01 << tinfo->width); |
@@ -167,6 +210,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
167 | u_int target_offset) | 210 | u_int target_offset) |
168 | { | 211 | { |
169 | struct ahd_linux_target *targ; | 212 | struct ahd_linux_target *targ; |
213 | struct scsi_target *starget; | ||
170 | struct ahd_initiator_tinfo *tinfo; | 214 | struct ahd_initiator_tinfo *tinfo; |
171 | struct ahd_tmode_tstate *tstate; | 215 | struct ahd_tmode_tstate *tstate; |
172 | int lun; | 216 | int lun; |
@@ -176,20 +220,20 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
176 | copy_info(info, "Target %d Negotiation Settings\n", target_id); | 220 | copy_info(info, "Target %d Negotiation Settings\n", target_id); |
177 | copy_info(info, "\tUser: "); | 221 | copy_info(info, "\tUser: "); |
178 | ahd_format_transinfo(info, &tinfo->user); | 222 | ahd_format_transinfo(info, &tinfo->user); |
179 | targ = ahd->platform_data->targets[target_offset]; | 223 | starget = ahd->platform_data->starget[target_offset]; |
180 | if (targ == NULL) | 224 | if (starget == NULL) |
181 | return; | 225 | return; |
226 | targ = scsi_transport_target_data(starget); | ||
182 | 227 | ||
183 | copy_info(info, "\tGoal: "); | 228 | copy_info(info, "\tGoal: "); |
184 | ahd_format_transinfo(info, &tinfo->goal); | 229 | ahd_format_transinfo(info, &tinfo->goal); |
185 | copy_info(info, "\tCurr: "); | 230 | copy_info(info, "\tCurr: "); |
186 | ahd_format_transinfo(info, &tinfo->curr); | 231 | ahd_format_transinfo(info, &tinfo->curr); |
187 | copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected); | ||
188 | 232 | ||
189 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { | 233 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { |
190 | struct ahd_linux_device *dev; | 234 | struct scsi_device *dev; |
191 | 235 | ||
192 | dev = targ->devices[lun]; | 236 | dev = targ->sdev[lun]; |
193 | 237 | ||
194 | if (dev == NULL) | 238 | if (dev == NULL) |
195 | continue; | 239 | continue; |
@@ -199,10 +243,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
199 | } | 243 | } |
200 | 244 | ||
201 | static void | 245 | static void |
202 | ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) | 246 | ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev) |
203 | { | 247 | { |
248 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); | ||
249 | |||
204 | copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", | 250 | copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", |
205 | dev->target->channel + 'A', dev->target->target, dev->lun); | 251 | sdev->sdev_target->channel + 'A', |
252 | sdev->sdev_target->id, sdev->lun); | ||
206 | 253 | ||
207 | copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); | 254 | copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); |
208 | copy_info(info, "\t\tCommands Active %d\n", dev->active); | 255 | copy_info(info, "\t\tCommands Active %d\n", dev->active); |
@@ -278,36 +325,16 @@ done: | |||
278 | * Return information to handle /proc support for the driver. | 325 | * Return information to handle /proc support for the driver. |
279 | */ | 326 | */ |
280 | int | 327 | 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, | 328 | ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, |
286 | off_t offset, int length, int inout) | 329 | off_t offset, int length, int inout) |
287 | #endif | ||
288 | { | 330 | { |
289 | struct ahd_softc *ahd; | 331 | struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; |
290 | struct info_str info; | 332 | struct info_str info; |
291 | char ahd_info[256]; | 333 | char ahd_info[256]; |
292 | u_long l; | ||
293 | u_int max_targ; | 334 | u_int max_targ; |
294 | u_int i; | 335 | u_int i; |
295 | int retval; | 336 | int retval; |
296 | 337 | ||
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? */ | 338 | /* Has data been written to the file? */ |
312 | if (inout == TRUE) { | 339 | if (inout == TRUE) { |
313 | retval = ahd_proc_write_seeprom(ahd, buffer, length); | 340 | retval = ahd_proc_write_seeprom(ahd, buffer, length); |
@@ -357,6 +384,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | |||
357 | } | 384 | } |
358 | retval = info.pos > info.offset ? info.pos - info.offset : 0; | 385 | retval = info.pos > info.offset ? info.pos - info.offset : 0; |
359 | done: | 386 | done: |
360 | ahd_list_unlock(&l); | ||
361 | return (retval); | 387 | return (retval); |
362 | } | 388 | } |
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..c932b3b94490 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -125,12 +125,6 @@ | |||
125 | 125 | ||
126 | static struct scsi_transport_template *ahc_linux_transport_template = NULL; | 126 | static struct scsi_transport_template *ahc_linux_transport_template = NULL; |
127 | 127 | ||
128 | /* | ||
129 | * Include aiclib.c as part of our | ||
130 | * "module dependencies are hard" work around. | ||
131 | */ | ||
132 | #include "aiclib.c" | ||
133 | |||
134 | #include <linux/init.h> /* __setup */ | 128 | #include <linux/init.h> /* __setup */ |
135 | #include <linux/mm.h> /* For fetching system memory size */ | 129 | #include <linux/mm.h> /* For fetching system memory size */ |
136 | #include <linux/blkdev.h> /* For block_size() */ | 130 | #include <linux/blkdev.h> /* For block_size() */ |
@@ -391,7 +385,6 @@ static int ahc_linux_run_command(struct ahc_softc*, | |||
391 | struct ahc_linux_device *, | 385 | struct ahc_linux_device *, |
392 | struct scsi_cmnd *); | 386 | struct scsi_cmnd *); |
393 | static void ahc_linux_setup_tag_info_global(char *p); | 387 | static void ahc_linux_setup_tag_info_global(char *p); |
394 | static aic_option_callback_t ahc_linux_setup_tag_info; | ||
395 | static int aic7xxx_setup(char *s); | 388 | static int aic7xxx_setup(char *s); |
396 | 389 | ||
397 | static int ahc_linux_unit; | 390 | static int ahc_linux_unit; |
@@ -635,6 +628,8 @@ ahc_linux_slave_alloc(struct scsi_device *sdev) | |||
635 | 628 | ||
636 | targ->sdev[sdev->lun] = sdev; | 629 | targ->sdev[sdev->lun] = sdev; |
637 | 630 | ||
631 | spi_period(starget) = 0; | ||
632 | |||
638 | return 0; | 633 | return 0; |
639 | } | 634 | } |
640 | 635 | ||
@@ -918,6 +913,86 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | |||
918 | } | 913 | } |
919 | } | 914 | } |
920 | 915 | ||
916 | static char * | ||
917 | ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | ||
918 | void (*callback)(u_long, int, int, int32_t), | ||
919 | u_long callback_arg) | ||
920 | { | ||
921 | char *tok_end; | ||
922 | char *tok_end2; | ||
923 | int i; | ||
924 | int instance; | ||
925 | int targ; | ||
926 | int done; | ||
927 | char tok_list[] = {'.', ',', '{', '}', '\0'}; | ||
928 | |||
929 | /* All options use a ':' name/arg separator */ | ||
930 | if (*opt_arg != ':') | ||
931 | return (opt_arg); | ||
932 | opt_arg++; | ||
933 | instance = -1; | ||
934 | targ = -1; | ||
935 | done = FALSE; | ||
936 | /* | ||
937 | * Restore separator that may be in | ||
938 | * the middle of our option argument. | ||
939 | */ | ||
940 | tok_end = strchr(opt_arg, '\0'); | ||
941 | if (tok_end < end) | ||
942 | *tok_end = ','; | ||
943 | while (!done) { | ||
944 | switch (*opt_arg) { | ||
945 | case '{': | ||
946 | if (instance == -1) { | ||
947 | instance = 0; | ||
948 | } else { | ||
949 | if (depth > 1) { | ||
950 | if (targ == -1) | ||
951 | targ = 0; | ||
952 | } else { | ||
953 | printf("Malformed Option %s\n", | ||
954 | opt_name); | ||
955 | done = TRUE; | ||
956 | } | ||
957 | } | ||
958 | opt_arg++; | ||
959 | break; | ||
960 | case '}': | ||
961 | if (targ != -1) | ||
962 | targ = -1; | ||
963 | else if (instance != -1) | ||
964 | instance = -1; | ||
965 | opt_arg++; | ||
966 | break; | ||
967 | case ',': | ||
968 | case '.': | ||
969 | if (instance == -1) | ||
970 | done = TRUE; | ||
971 | else if (targ >= 0) | ||
972 | targ++; | ||
973 | else if (instance >= 0) | ||
974 | instance++; | ||
975 | opt_arg++; | ||
976 | break; | ||
977 | case '\0': | ||
978 | done = TRUE; | ||
979 | break; | ||
980 | default: | ||
981 | tok_end = end; | ||
982 | for (i = 0; tok_list[i]; i++) { | ||
983 | tok_end2 = strchr(opt_arg, tok_list[i]); | ||
984 | if ((tok_end2) && (tok_end2 < tok_end)) | ||
985 | tok_end = tok_end2; | ||
986 | } | ||
987 | callback(callback_arg, instance, targ, | ||
988 | simple_strtol(opt_arg, NULL, 0)); | ||
989 | opt_arg = tok_end; | ||
990 | break; | ||
991 | } | ||
992 | } | ||
993 | return (opt_arg); | ||
994 | } | ||
995 | |||
921 | /* | 996 | /* |
922 | * Handle Linux boot parameters. This routine allows for assigning a value | 997 | * Handle Linux boot parameters. This routine allows for assigning a value |
923 | * to a parameter with a ':' between the parameter and the value. | 998 | * to a parameter with a ':' between the parameter and the value. |
@@ -972,7 +1047,7 @@ aic7xxx_setup(char *s) | |||
972 | if (strncmp(p, "global_tag_depth", n) == 0) { | 1047 | if (strncmp(p, "global_tag_depth", n) == 0) { |
973 | ahc_linux_setup_tag_info_global(p + n); | 1048 | ahc_linux_setup_tag_info_global(p + n); |
974 | } else if (strncmp(p, "tag_info", n) == 0) { | 1049 | } else if (strncmp(p, "tag_info", n) == 0) { |
975 | s = aic_parse_brace_option("tag_info", p + n, end, | 1050 | s = ahc_parse_brace_option("tag_info", p + n, end, |
976 | 2, ahc_linux_setup_tag_info, 0); | 1051 | 2, ahc_linux_setup_tag_info, 0); |
977 | } else if (p[n] == ':') { | 1052 | } else if (p[n] == ':') { |
978 | *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); | 1053 | *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); |
@@ -1612,9 +1687,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel, | |||
1612 | if (channel == 'B') | 1687 | if (channel == 'B') |
1613 | target_offset += 8; | 1688 | target_offset += 8; |
1614 | starget = ahc->platform_data->starget[target_offset]; | 1689 | starget = ahc->platform_data->starget[target_offset]; |
1615 | targ = scsi_transport_target_data(starget); | 1690 | if (starget == NULL) |
1616 | if (targ == NULL) | ||
1617 | break; | 1691 | break; |
1692 | targ = scsi_transport_target_data(starget); | ||
1618 | 1693 | ||
1619 | target_ppr_options = | 1694 | target_ppr_options = |
1620 | (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) | 1695 | (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) |
@@ -2329,8 +2404,6 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) | |||
2329 | { | 2404 | { |
2330 | } | 2405 | } |
2331 | 2406 | ||
2332 | static void ahc_linux_exit(void); | ||
2333 | |||
2334 | static void ahc_linux_set_width(struct scsi_target *starget, int width) | 2407 | static void ahc_linux_set_width(struct scsi_target *starget, int width) |
2335 | { | 2408 | { |
2336 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 2409 | 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_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 3802c91f0b07..04a3506cf340 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c | |||
@@ -54,6 +54,49 @@ static void ahc_dump_device_state(struct info_str *info, | |||
54 | static int ahc_proc_write_seeprom(struct ahc_softc *ahc, | 54 | static int ahc_proc_write_seeprom(struct ahc_softc *ahc, |
55 | char *buffer, int length); | 55 | char *buffer, int length); |
56 | 56 | ||
57 | /* | ||
58 | * Table of syncrates that don't follow the "divisible by 4" | ||
59 | * rule. This table will be expanded in future SCSI specs. | ||
60 | */ | ||
61 | static struct { | ||
62 | u_int period_factor; | ||
63 | u_int period; /* in 100ths of ns */ | ||
64 | } scsi_syncrates[] = { | ||
65 | { 0x08, 625 }, /* FAST-160 */ | ||
66 | { 0x09, 1250 }, /* FAST-80 */ | ||
67 | { 0x0a, 2500 }, /* FAST-40 40MHz */ | ||
68 | { 0x0b, 3030 }, /* FAST-40 33MHz */ | ||
69 | { 0x0c, 5000 } /* FAST-20 */ | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * Return the frequency in kHz corresponding to the given | ||
74 | * sync period factor. | ||
75 | */ | ||
76 | static u_int | ||
77 | ahc_calc_syncsrate(u_int period_factor) | ||
78 | { | ||
79 | int i; | ||
80 | int num_syncrates; | ||
81 | |||
82 | num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); | ||
83 | /* See if the period is in the "exception" table */ | ||
84 | for (i = 0; i < num_syncrates; i++) { | ||
85 | |||
86 | if (period_factor == scsi_syncrates[i].period_factor) { | ||
87 | /* Period in kHz */ | ||
88 | return (100000000 / scsi_syncrates[i].period); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Wasn't in the table, so use the standard | ||
94 | * 4 times conversion. | ||
95 | */ | ||
96 | return (10000000 / (period_factor * 4 * 10)); | ||
97 | } | ||
98 | |||
99 | |||
57 | static void | 100 | static void |
58 | copy_mem_info(struct info_str *info, char *data, int len) | 101 | copy_mem_info(struct info_str *info, char *data, int len) |
59 | { | 102 | { |
@@ -106,7 +149,7 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo) | |||
106 | speed = 3300; | 149 | speed = 3300; |
107 | freq = 0; | 150 | freq = 0; |
108 | if (tinfo->offset != 0) { | 151 | if (tinfo->offset != 0) { |
109 | freq = aic_calc_syncsrate(tinfo->period); | 152 | freq = ahc_calc_syncsrate(tinfo->period); |
110 | speed = freq; | 153 | speed = freq; |
111 | } | 154 | } |
112 | speed *= (0x01 << tinfo->width); | 155 | speed *= (0x01 << tinfo->width); |
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..828ae3d9a510 100644 --- a/drivers/scsi/aic7xxx/aiclib.c +++ b/drivers/scsi/aic7xxx/aiclib.c | |||
@@ -30,1382 +30,5 @@ | |||
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 | |||
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 | |||
1190 | /* | ||
1191 | * Table of syncrates that don't follow the "divisible by 4" | ||
1192 | * rule. This table will be expanded in future SCSI specs. | ||
1193 | */ | ||
1194 | static struct { | ||
1195 | u_int period_factor; | ||
1196 | u_int period; /* in 100ths of ns */ | ||
1197 | } scsi_syncrates[] = { | ||
1198 | { 0x08, 625 }, /* FAST-160 */ | ||
1199 | { 0x09, 1250 }, /* FAST-80 */ | ||
1200 | { 0x0a, 2500 }, /* FAST-40 40MHz */ | ||
1201 | { 0x0b, 3030 }, /* FAST-40 33MHz */ | ||
1202 | { 0x0c, 5000 } /* FAST-20 */ | ||
1203 | }; | ||
1204 | |||
1205 | /* | ||
1206 | * Return the frequency in kHz corresponding to the given | ||
1207 | * sync period factor. | ||
1208 | */ | ||
1209 | u_int | ||
1210 | aic_calc_syncsrate(u_int period_factor) | ||
1211 | { | ||
1212 | int i; | ||
1213 | int num_syncrates; | ||
1214 | |||
1215 | num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); | ||
1216 | /* See if the period is in the "exception" table */ | ||
1217 | for (i = 0; i < num_syncrates; i++) { | ||
1218 | |||
1219 | if (period_factor == scsi_syncrates[i].period_factor) { | ||
1220 | /* Period in kHz */ | ||
1221 | return (100000000 / scsi_syncrates[i].period); | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1225 | /* | ||
1226 | * Wasn't in the table, so use the standard | ||
1227 | * 4 times conversion. | ||
1228 | */ | ||
1229 | return (10000000 / (period_factor * 4 * 10)); | ||
1230 | } | ||
1231 | |||
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 * | ||
1335 | aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | ||
1336 | aic_option_callback_t *callback, u_long callback_arg) | ||
1337 | { | ||
1338 | char *tok_end; | ||
1339 | char *tok_end2; | ||
1340 | int i; | ||
1341 | int instance; | ||
1342 | int targ; | ||
1343 | int done; | ||
1344 | char tok_list[] = {'.', ',', '{', '}', '\0'}; | ||
1345 | 34 | ||
1346 | /* All options use a ':' name/arg separator */ | ||
1347 | if (*opt_arg != ':') | ||
1348 | return (opt_arg); | ||
1349 | opt_arg++; | ||
1350 | instance = -1; | ||
1351 | targ = -1; | ||
1352 | done = FALSE; | ||
1353 | /* | ||
1354 | * Restore separator that may be in | ||
1355 | * the middle of our option argument. | ||
1356 | */ | ||
1357 | tok_end = strchr(opt_arg, '\0'); | ||
1358 | if (tok_end < end) | ||
1359 | *tok_end = ','; | ||
1360 | while (!done) { | ||
1361 | switch (*opt_arg) { | ||
1362 | case '{': | ||
1363 | if (instance == -1) { | ||
1364 | instance = 0; | ||
1365 | } else { | ||
1366 | if (depth > 1) { | ||
1367 | if (targ == -1) | ||
1368 | targ = 0; | ||
1369 | } else { | ||
1370 | printf("Malformed Option %s\n", | ||
1371 | opt_name); | ||
1372 | done = TRUE; | ||
1373 | } | ||
1374 | } | ||
1375 | opt_arg++; | ||
1376 | break; | ||
1377 | case '}': | ||
1378 | if (targ != -1) | ||
1379 | targ = -1; | ||
1380 | else if (instance != -1) | ||
1381 | instance = -1; | ||
1382 | opt_arg++; | ||
1383 | break; | ||
1384 | case ',': | ||
1385 | case '.': | ||
1386 | if (instance == -1) | ||
1387 | done = TRUE; | ||
1388 | else if (targ >= 0) | ||
1389 | targ++; | ||
1390 | else if (instance >= 0) | ||
1391 | instance++; | ||
1392 | opt_arg++; | ||
1393 | break; | ||
1394 | case '\0': | ||
1395 | done = TRUE; | ||
1396 | break; | ||
1397 | default: | ||
1398 | tok_end = end; | ||
1399 | for (i = 0; tok_list[i]; i++) { | ||
1400 | tok_end2 = strchr(opt_arg, tok_list[i]); | ||
1401 | if ((tok_end2) && (tok_end2 < tok_end)) | ||
1402 | tok_end = tok_end2; | ||
1403 | } | ||
1404 | callback(callback_arg, instance, targ, | ||
1405 | simple_strtol(opt_arg, NULL, 0)); | ||
1406 | opt_arg = tok_end; | ||
1407 | break; | ||
1408 | } | ||
1409 | } | ||
1410 | return (opt_arg); | ||
1411 | } | ||
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h index bfe6f954d3c4..3bfbf0fe1ec2 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,152 +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 | |||
889 | /**************************** Module Library Hack *****************************/ | ||
890 | /* | ||
891 | * What we'd like to do is have a single "scsi library" module that both the | ||
892 | * aic7xxx and aic79xx drivers could load and depend on. A cursory examination | ||
893 | * of implementing module dependencies in Linux (handling the install and | ||
894 | * initrd cases) does not look promissing. For now, we just duplicate this | ||
895 | * code in both drivers using a simple symbol renaming scheme that hides this | ||
896 | * hack from the drivers. | ||
897 | */ | ||
898 | #define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x | ||
899 | #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) | ||
901 | |||
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) | ||
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 | |||
939 | 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 | |||
949 | typedef void aic_option_callback_t(u_long, int, int, int32_t); | ||
950 | char * aic_parse_brace_option(char *opt_name, char *opt_arg, | ||
951 | char *end, int depth, | ||
952 | aic_option_callback_t *, u_long); | ||
953 | |||
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 | 143 | ||
1034 | static __inline uint32_t | 144 | static __inline uint32_t |
1035 | scsi_4btoul(uint8_t *bytes) | 145 | scsi_4btoul(uint8_t *bytes) |
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 3900e28ac7d6..bd0e1b6be1ea 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 */ |
@@ -31,7 +30,7 @@ | |||
31 | #include <scsi/scsi_ioctl.h> | 30 | #include <scsi/scsi_ioctl.h> |
32 | #include <scsi/scsi_host.h> | 31 | #include <scsi/scsi_host.h> |
33 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
34 | #include <scsi/scsi_request.h> | 33 | #include <scsi/scsi_eh.h> |
35 | #include <scsi/scsi_dbg.h> | 34 | #include <scsi/scsi_dbg.h> |
36 | 35 | ||
37 | #define CH_DT_MAX 16 | 36 | #define CH_DT_MAX 16 |
@@ -181,17 +180,17 @@ static struct { | |||
181 | 180 | ||
182 | /* ------------------------------------------------------------------- */ | 181 | /* ------------------------------------------------------------------- */ |
183 | 182 | ||
184 | static int ch_find_errno(unsigned char *sense_buffer) | 183 | static int ch_find_errno(struct scsi_sense_hdr *sshdr) |
185 | { | 184 | { |
186 | int i,errno = 0; | 185 | int i,errno = 0; |
187 | 186 | ||
188 | /* Check to see if additional sense information is available */ | 187 | /* Check to see if additional sense information is available */ |
189 | if (sense_buffer[7] > 5 && | 188 | if (scsi_sense_valid(sshdr) && |
190 | sense_buffer[12] != 0) { | 189 | sshdr->asc != 0) { |
191 | for (i = 0; err[i].errno != 0; i++) { | 190 | for (i = 0; err[i].errno != 0; i++) { |
192 | if (err[i].sense == sense_buffer[ 2] && | 191 | if (err[i].sense == sshdr->sense_key && |
193 | err[i].asc == sense_buffer[12] && | 192 | err[i].asc == sshdr->asc && |
194 | err[i].ascq == sense_buffer[13]) { | 193 | err[i].ascq == sshdr->ascq) { |
195 | errno = -err[i].errno; | 194 | errno = -err[i].errno; |
196 | break; | 195 | break; |
197 | } | 196 | } |
@@ -207,13 +206,9 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, | |||
207 | void *buffer, unsigned buflength, | 206 | void *buffer, unsigned buflength, |
208 | enum dma_data_direction direction) | 207 | enum dma_data_direction direction) |
209 | { | 208 | { |
210 | int errno, retries = 0, timeout; | 209 | int errno, retries = 0, timeout, result; |
211 | struct scsi_request *sr; | 210 | struct scsi_sense_hdr sshdr; |
212 | 211 | ||
213 | sr = scsi_allocate_request(ch->device, GFP_KERNEL); | ||
214 | if (NULL == sr) | ||
215 | return -ENOMEM; | ||
216 | |||
217 | timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS) | 212 | timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS) |
218 | ? timeout_init : timeout_move; | 213 | ? timeout_init : timeout_move; |
219 | 214 | ||
@@ -224,16 +219,17 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, | |||
224 | __scsi_print_command(cmd); | 219 | __scsi_print_command(cmd); |
225 | } | 220 | } |
226 | 221 | ||
227 | scsi_wait_req(sr, cmd, buffer, buflength, | 222 | result = scsi_execute_req(ch->device, cmd, direction, buffer, |
228 | timeout * HZ, MAX_RETRIES); | 223 | buflength, &sshdr, timeout * HZ, |
224 | MAX_RETRIES); | ||
229 | 225 | ||
230 | dprintk("result: 0x%x\n",sr->sr_result); | 226 | dprintk("result: 0x%x\n",result); |
231 | if (driver_byte(sr->sr_result) & DRIVER_SENSE) { | 227 | if (driver_byte(result) & DRIVER_SENSE) { |
232 | if (debug) | 228 | if (debug) |
233 | scsi_print_req_sense(ch->name, sr); | 229 | scsi_print_sense_hdr(ch->name, &sshdr); |
234 | errno = ch_find_errno(sr->sr_sense_buffer); | 230 | errno = ch_find_errno(&sshdr); |
235 | 231 | ||
236 | switch(sr->sr_sense_buffer[2] & 0xf) { | 232 | switch(sshdr.sense_key) { |
237 | case UNIT_ATTENTION: | 233 | case UNIT_ATTENTION: |
238 | ch->unit_attention = 1; | 234 | ch->unit_attention = 1; |
239 | if (retries++ < 3) | 235 | if (retries++ < 3) |
@@ -241,7 +237,6 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, | |||
241 | break; | 237 | break; |
242 | } | 238 | } |
243 | } | 239 | } |
244 | scsi_release_request(sr); | ||
245 | return errno; | 240 | return errno; |
246 | } | 241 | } |
247 | 242 | ||
@@ -940,8 +935,6 @@ static int ch_probe(struct device *dev) | |||
940 | if (init) | 935 | if (init) |
941 | ch_init_elem(ch); | 936 | ch_init_elem(ch); |
942 | 937 | ||
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, | 938 | class_device_create(ch_sysfs_class, |
946 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor), | 939 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor), |
947 | dev, "s%s", ch->name); | 940 | dev, "s%s", ch->name); |
@@ -974,7 +967,6 @@ static int ch_remove(struct device *dev) | |||
974 | 967 | ||
975 | class_device_destroy(ch_sysfs_class, | 968 | class_device_destroy(ch_sysfs_class, |
976 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor)); | 969 | MKDEV(SCSI_CHANGER_MAJOR,ch->minor)); |
977 | devfs_remove(ch->name); | ||
978 | kfree(ch->dt); | 970 | kfree(ch->dt); |
979 | kfree(ch); | 971 | kfree(ch); |
980 | ch_devcount--; | 972 | ch_devcount--; |
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index ec161733a82b..f6be2c1c3942 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 | ||
@@ -1155,6 +1156,31 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq) | |||
1155 | } | 1156 | } |
1156 | } | 1157 | } |
1157 | 1158 | ||
1159 | void | ||
1160 | scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) | ||
1161 | { | ||
1162 | const char *sense_txt; | ||
1163 | /* An example of deferred is when an earlier write to disk cache | ||
1164 | * succeeded, but now the disk discovers that it cannot write the | ||
1165 | * data to the magnetic media. | ||
1166 | */ | ||
1167 | const char *error = scsi_sense_is_deferred(sshdr) ? | ||
1168 | "<<DEFERRED>>" : "Current"; | ||
1169 | printk(KERN_INFO "%s: %s", name, error); | ||
1170 | if (sshdr->response_code >= 0x72) | ||
1171 | printk(" [descriptor]"); | ||
1172 | |||
1173 | sense_txt = scsi_sense_key_string(sshdr->sense_key); | ||
1174 | if (sense_txt) | ||
1175 | printk(": sense key: %s\n", sense_txt); | ||
1176 | else | ||
1177 | printk(": sense key=0x%x\n", sshdr->sense_key); | ||
1178 | printk(KERN_INFO " "); | ||
1179 | scsi_show_extd_sense(sshdr->asc, sshdr->ascq); | ||
1180 | printk("\n"); | ||
1181 | } | ||
1182 | EXPORT_SYMBOL(scsi_print_sense_hdr); | ||
1183 | |||
1158 | /* Print sense information */ | 1184 | /* Print sense information */ |
1159 | void | 1185 | void |
1160 | __scsi_print_sense(const char *name, const unsigned char *sense_buffer, | 1186 | __scsi_print_sense(const char *name, const unsigned char *sense_buffer, |
@@ -1162,8 +1188,6 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, | |||
1162 | { | 1188 | { |
1163 | int k, num, res; | 1189 | int k, num, res; |
1164 | unsigned int info; | 1190 | unsigned int info; |
1165 | const char *error; | ||
1166 | const char *sense_txt; | ||
1167 | struct scsi_sense_hdr ssh; | 1191 | struct scsi_sense_hdr ssh; |
1168 | 1192 | ||
1169 | res = scsi_normalize_sense(sense_buffer, sense_len, &ssh); | 1193 | res = scsi_normalize_sense(sense_buffer, sense_len, &ssh); |
@@ -1181,26 +1205,7 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, | |||
1181 | printk("\n"); | 1205 | printk("\n"); |
1182 | return; | 1206 | return; |
1183 | } | 1207 | } |
1184 | 1208 | scsi_print_sense_hdr(name, &ssh); | |
1185 | /* An example of deferred is when an earlier write to disk cache | ||
1186 | * succeeded, but now the disk discovers that it cannot write the | ||
1187 | * data to the magnetic media. | ||
1188 | */ | ||
1189 | error = scsi_sense_is_deferred(&ssh) ? | ||
1190 | "<<DEFERRED>>" : "Current"; | ||
1191 | printk(KERN_INFO "%s: %s", name, error); | ||
1192 | if (ssh.response_code >= 0x72) | ||
1193 | printk(" [descriptor]"); | ||
1194 | |||
1195 | sense_txt = scsi_sense_key_string(ssh.sense_key); | ||
1196 | if (sense_txt) | ||
1197 | printk(": sense key: %s\n", sense_txt); | ||
1198 | else | ||
1199 | printk(": sense key=0x%x\n", ssh.sense_key); | ||
1200 | printk(KERN_INFO " "); | ||
1201 | scsi_show_extd_sense(ssh.asc, ssh.ascq); | ||
1202 | printk("\n"); | ||
1203 | |||
1204 | if (ssh.response_code < 0x72) { | 1209 | if (ssh.response_code < 0x72) { |
1205 | /* only decode extras for "fixed" format now */ | 1210 | /* only decode extras for "fixed" format now */ |
1206 | char buff[80]; | 1211 | char buff[80]; |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 5feb886c3392..85503fad789a 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/kthread.h> | ||
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
28 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
29 | #include <linux/init.h> | 30 | #include <linux/init.h> |
@@ -52,21 +53,80 @@ static struct class shost_class = { | |||
52 | }; | 53 | }; |
53 | 54 | ||
54 | /** | 55 | /** |
55 | * scsi_host_cancel - cancel outstanding IO to this host | 56 | * scsi_host_set_state - Take the given host through the host |
56 | * @shost: pointer to struct Scsi_Host | 57 | * state model. |
57 | * recovery: recovery requested to run. | 58 | * @shost: scsi host to change the state of. |
59 | * @state: state to change to. | ||
60 | * | ||
61 | * Returns zero if unsuccessful or an error if the requested | ||
62 | * transition is illegal. | ||
58 | **/ | 63 | **/ |
59 | static void scsi_host_cancel(struct Scsi_Host *shost, int recovery) | 64 | int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) |
60 | { | 65 | { |
61 | struct scsi_device *sdev; | 66 | enum scsi_host_state oldstate = shost->shost_state; |
67 | |||
68 | if (state == oldstate) | ||
69 | return 0; | ||
70 | |||
71 | switch (state) { | ||
72 | case SHOST_CREATED: | ||
73 | /* There are no legal states that come back to | ||
74 | * created. This is the manually initialised start | ||
75 | * state */ | ||
76 | goto illegal; | ||
77 | |||
78 | case SHOST_RUNNING: | ||
79 | switch (oldstate) { | ||
80 | case SHOST_CREATED: | ||
81 | case SHOST_RECOVERY: | ||
82 | break; | ||
83 | default: | ||
84 | goto illegal; | ||
85 | } | ||
86 | break; | ||
87 | |||
88 | case SHOST_RECOVERY: | ||
89 | switch (oldstate) { | ||
90 | case SHOST_RUNNING: | ||
91 | break; | ||
92 | default: | ||
93 | goto illegal; | ||
94 | } | ||
95 | break; | ||
96 | |||
97 | case SHOST_CANCEL: | ||
98 | switch (oldstate) { | ||
99 | case SHOST_CREATED: | ||
100 | case SHOST_RUNNING: | ||
101 | break; | ||
102 | default: | ||
103 | goto illegal; | ||
104 | } | ||
105 | break; | ||
106 | |||
107 | case SHOST_DEL: | ||
108 | switch (oldstate) { | ||
109 | case SHOST_CANCEL: | ||
110 | break; | ||
111 | default: | ||
112 | goto illegal; | ||
113 | } | ||
114 | break; | ||
62 | 115 | ||
63 | set_bit(SHOST_CANCEL, &shost->shost_state); | ||
64 | shost_for_each_device(sdev, shost) { | ||
65 | scsi_device_cancel(sdev, recovery); | ||
66 | } | 116 | } |
67 | wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY, | 117 | shost->shost_state = state; |
68 | &shost->shost_state))); | 118 | return 0; |
119 | |||
120 | illegal: | ||
121 | SCSI_LOG_ERROR_RECOVERY(1, | ||
122 | dev_printk(KERN_ERR, &shost->shost_gendev, | ||
123 | "Illegal host state transition" | ||
124 | "%s->%s\n", | ||
125 | scsi_host_state_name(oldstate), | ||
126 | scsi_host_state_name(state))); | ||
127 | return -EINVAL; | ||
69 | } | 128 | } |
129 | EXPORT_SYMBOL(scsi_host_set_state); | ||
70 | 130 | ||
71 | /** | 131 | /** |
72 | * scsi_remove_host - remove a scsi host | 132 | * scsi_remove_host - remove a scsi host |
@@ -74,11 +134,13 @@ static void scsi_host_cancel(struct Scsi_Host *shost, int recovery) | |||
74 | **/ | 134 | **/ |
75 | void scsi_remove_host(struct Scsi_Host *shost) | 135 | void scsi_remove_host(struct Scsi_Host *shost) |
76 | { | 136 | { |
137 | down(&shost->scan_mutex); | ||
138 | scsi_host_set_state(shost, SHOST_CANCEL); | ||
139 | up(&shost->scan_mutex); | ||
77 | scsi_forget_host(shost); | 140 | scsi_forget_host(shost); |
78 | scsi_host_cancel(shost, 0); | ||
79 | scsi_proc_host_rm(shost); | 141 | scsi_proc_host_rm(shost); |
80 | 142 | ||
81 | set_bit(SHOST_DEL, &shost->shost_state); | 143 | scsi_host_set_state(shost, SHOST_DEL); |
82 | 144 | ||
83 | transport_unregister_device(&shost->shost_gendev); | 145 | transport_unregister_device(&shost->shost_gendev); |
84 | class_device_unregister(&shost->shost_classdev); | 146 | class_device_unregister(&shost->shost_classdev); |
@@ -115,7 +177,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) | |||
115 | if (error) | 177 | if (error) |
116 | goto out; | 178 | goto out; |
117 | 179 | ||
118 | set_bit(SHOST_ADD, &shost->shost_state); | 180 | scsi_host_set_state(shost, SHOST_RUNNING); |
119 | get_device(shost->shost_gendev.parent); | 181 | get_device(shost->shost_gendev.parent); |
120 | 182 | ||
121 | error = class_device_add(&shost->shost_classdev); | 183 | error = class_device_add(&shost->shost_classdev); |
@@ -164,15 +226,8 @@ static void scsi_host_dev_release(struct device *dev) | |||
164 | struct Scsi_Host *shost = dev_to_shost(dev); | 226 | struct Scsi_Host *shost = dev_to_shost(dev); |
165 | struct device *parent = dev->parent; | 227 | struct device *parent = dev->parent; |
166 | 228 | ||
167 | if (shost->ehandler) { | 229 | if (shost->ehandler) |
168 | DECLARE_COMPLETION(sem); | 230 | kthread_stop(shost->ehandler); |
169 | shost->eh_notify = &sem; | ||
170 | shost->eh_kill = 1; | ||
171 | up(shost->eh_wait); | ||
172 | wait_for_completion(&sem); | ||
173 | shost->eh_notify = NULL; | ||
174 | } | ||
175 | |||
176 | if (shost->work_q) | 231 | if (shost->work_q) |
177 | destroy_workqueue(shost->work_q); | 232 | destroy_workqueue(shost->work_q); |
178 | 233 | ||
@@ -202,7 +257,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
202 | { | 257 | { |
203 | struct Scsi_Host *shost; | 258 | struct Scsi_Host *shost; |
204 | int gfp_mask = GFP_KERNEL, rval; | 259 | int gfp_mask = GFP_KERNEL, rval; |
205 | DECLARE_COMPLETION(complete); | ||
206 | 260 | ||
207 | if (sht->unchecked_isa_dma && privsize) | 261 | if (sht->unchecked_isa_dma && privsize) |
208 | gfp_mask |= __GFP_DMA; | 262 | gfp_mask |= __GFP_DMA; |
@@ -226,6 +280,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
226 | 280 | ||
227 | spin_lock_init(&shost->default_lock); | 281 | spin_lock_init(&shost->default_lock); |
228 | scsi_assign_lock(shost, &shost->default_lock); | 282 | scsi_assign_lock(shost, &shost->default_lock); |
283 | shost->shost_state = SHOST_CREATED; | ||
229 | INIT_LIST_HEAD(&shost->__devices); | 284 | INIT_LIST_HEAD(&shost->__devices); |
230 | INIT_LIST_HEAD(&shost->__targets); | 285 | INIT_LIST_HEAD(&shost->__targets); |
231 | INIT_LIST_HEAD(&shost->eh_cmd_q); | 286 | INIT_LIST_HEAD(&shost->eh_cmd_q); |
@@ -307,12 +362,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
307 | snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d", | 362 | snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d", |
308 | shost->host_no); | 363 | shost->host_no); |
309 | 364 | ||
310 | shost->eh_notify = &complete; | 365 | shost->ehandler = kthread_run(scsi_error_handler, shost, |
311 | rval = kernel_thread(scsi_error_handler, shost, 0); | 366 | "scsi_eh_%d", shost->host_no); |
312 | if (rval < 0) | 367 | if (IS_ERR(shost->ehandler)) { |
368 | rval = PTR_ERR(shost->ehandler); | ||
313 | goto fail_destroy_freelist; | 369 | goto fail_destroy_freelist; |
314 | wait_for_completion(&complete); | 370 | } |
315 | shost->eh_notify = NULL; | ||
316 | 371 | ||
317 | scsi_proc_hostdir_add(shost->hostt); | 372 | scsi_proc_hostdir_add(shost->hostt); |
318 | return shost; | 373 | return shost; |
@@ -382,7 +437,7 @@ EXPORT_SYMBOL(scsi_host_lookup); | |||
382 | **/ | 437 | **/ |
383 | struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) | 438 | struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) |
384 | { | 439 | { |
385 | if (test_bit(SHOST_DEL, &shost->shost_state) || | 440 | if ((shost->shost_state == SHOST_DEL) || |
386 | !get_device(&shost->shost_gendev)) | 441 | !get_device(&shost->shost_gendev)) |
387 | return NULL; | 442 | return NULL; |
388 | return shost; | 443 | return shost; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 2cb3c8340ca8..5b14934ba861 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -87,7 +87,7 @@ static int max_channel = 3; | |||
87 | static int init_timeout = 5; | 87 | static int init_timeout = 5; |
88 | static int max_requests = 50; | 88 | static int max_requests = 50; |
89 | 89 | ||
90 | #define IBMVSCSI_VERSION "1.5.6" | 90 | #define IBMVSCSI_VERSION "1.5.7" |
91 | 91 | ||
92 | MODULE_DESCRIPTION("IBM Virtual SCSI"); | 92 | MODULE_DESCRIPTION("IBM Virtual SCSI"); |
93 | MODULE_AUTHOR("Dave Boutcher"); | 93 | MODULE_AUTHOR("Dave Boutcher"); |
@@ -145,6 +145,8 @@ static int initialize_event_pool(struct event_pool *pool, | |||
145 | sizeof(*evt->xfer_iu) * i; | 145 | sizeof(*evt->xfer_iu) * i; |
146 | evt->xfer_iu = pool->iu_storage + i; | 146 | evt->xfer_iu = pool->iu_storage + i; |
147 | evt->hostdata = hostdata; | 147 | evt->hostdata = hostdata; |
148 | evt->ext_list = NULL; | ||
149 | evt->ext_list_token = 0; | ||
148 | } | 150 | } |
149 | 151 | ||
150 | return 0; | 152 | return 0; |
@@ -161,9 +163,16 @@ static void release_event_pool(struct event_pool *pool, | |||
161 | struct ibmvscsi_host_data *hostdata) | 163 | struct ibmvscsi_host_data *hostdata) |
162 | { | 164 | { |
163 | int i, in_use = 0; | 165 | int i, in_use = 0; |
164 | for (i = 0; i < pool->size; ++i) | 166 | for (i = 0; i < pool->size; ++i) { |
165 | if (atomic_read(&pool->events[i].free) != 1) | 167 | if (atomic_read(&pool->events[i].free) != 1) |
166 | ++in_use; | 168 | ++in_use; |
169 | if (pool->events[i].ext_list) { | ||
170 | dma_free_coherent(hostdata->dev, | ||
171 | SG_ALL * sizeof(struct memory_descriptor), | ||
172 | pool->events[i].ext_list, | ||
173 | pool->events[i].ext_list_token); | ||
174 | } | ||
175 | } | ||
167 | if (in_use) | 176 | if (in_use) |
168 | printk(KERN_WARNING | 177 | printk(KERN_WARNING |
169 | "ibmvscsi: releasing event pool with %d " | 178 | "ibmvscsi: releasing event pool with %d " |
@@ -286,24 +295,41 @@ static void set_srp_direction(struct scsi_cmnd *cmd, | |||
286 | } else { | 295 | } else { |
287 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 296 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
288 | srp_cmd->data_out_format = SRP_INDIRECT_BUFFER; | 297 | srp_cmd->data_out_format = SRP_INDIRECT_BUFFER; |
289 | srp_cmd->data_out_count = numbuf; | 298 | srp_cmd->data_out_count = |
299 | numbuf < MAX_INDIRECT_BUFS ? | ||
300 | numbuf: MAX_INDIRECT_BUFS; | ||
290 | } else { | 301 | } else { |
291 | srp_cmd->data_in_format = SRP_INDIRECT_BUFFER; | 302 | srp_cmd->data_in_format = SRP_INDIRECT_BUFFER; |
292 | srp_cmd->data_in_count = numbuf; | 303 | srp_cmd->data_in_count = |
304 | numbuf < MAX_INDIRECT_BUFS ? | ||
305 | numbuf: MAX_INDIRECT_BUFS; | ||
293 | } | 306 | } |
294 | } | 307 | } |
295 | } | 308 | } |
296 | 309 | ||
310 | static void unmap_sg_list(int num_entries, | ||
311 | struct device *dev, | ||
312 | struct memory_descriptor *md) | ||
313 | { | ||
314 | int i; | ||
315 | |||
316 | for (i = 0; i < num_entries; ++i) { | ||
317 | dma_unmap_single(dev, | ||
318 | md[i].virtual_address, | ||
319 | md[i].length, DMA_BIDIRECTIONAL); | ||
320 | } | ||
321 | } | ||
322 | |||
297 | /** | 323 | /** |
298 | * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format | 324 | * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format |
299 | * @cmd: srp_cmd whose additional_data member will be unmapped | 325 | * @cmd: srp_cmd whose additional_data member will be unmapped |
300 | * @dev: device for which the memory is mapped | 326 | * @dev: device for which the memory is mapped |
301 | * | 327 | * |
302 | */ | 328 | */ |
303 | static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev) | 329 | static void unmap_cmd_data(struct srp_cmd *cmd, |
330 | struct srp_event_struct *evt_struct, | ||
331 | struct device *dev) | ||
304 | { | 332 | { |
305 | int i; | ||
306 | |||
307 | if ((cmd->data_out_format == SRP_NO_BUFFER) && | 333 | if ((cmd->data_out_format == SRP_NO_BUFFER) && |
308 | (cmd->data_in_format == SRP_NO_BUFFER)) | 334 | (cmd->data_in_format == SRP_NO_BUFFER)) |
309 | return; | 335 | return; |
@@ -318,15 +344,34 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev) | |||
318 | (struct indirect_descriptor *)cmd->additional_data; | 344 | (struct indirect_descriptor *)cmd->additional_data; |
319 | int num_mapped = indirect->head.length / | 345 | int num_mapped = indirect->head.length / |
320 | sizeof(indirect->list[0]); | 346 | sizeof(indirect->list[0]); |
321 | for (i = 0; i < num_mapped; ++i) { | 347 | |
322 | struct memory_descriptor *data = &indirect->list[i]; | 348 | if (num_mapped <= MAX_INDIRECT_BUFS) { |
323 | dma_unmap_single(dev, | 349 | unmap_sg_list(num_mapped, dev, &indirect->list[0]); |
324 | data->virtual_address, | 350 | return; |
325 | data->length, DMA_BIDIRECTIONAL); | ||
326 | } | 351 | } |
352 | |||
353 | unmap_sg_list(num_mapped, dev, evt_struct->ext_list); | ||
327 | } | 354 | } |
328 | } | 355 | } |
329 | 356 | ||
357 | static int map_sg_list(int num_entries, | ||
358 | struct scatterlist *sg, | ||
359 | struct memory_descriptor *md) | ||
360 | { | ||
361 | int i; | ||
362 | u64 total_length = 0; | ||
363 | |||
364 | for (i = 0; i < num_entries; ++i) { | ||
365 | struct memory_descriptor *descr = md + i; | ||
366 | struct scatterlist *sg_entry = &sg[i]; | ||
367 | descr->virtual_address = sg_dma_address(sg_entry); | ||
368 | descr->length = sg_dma_len(sg_entry); | ||
369 | descr->memory_handle = 0; | ||
370 | total_length += sg_dma_len(sg_entry); | ||
371 | } | ||
372 | return total_length; | ||
373 | } | ||
374 | |||
330 | /** | 375 | /** |
331 | * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields | 376 | * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields |
332 | * @cmd: Scsi_Cmnd with the scatterlist | 377 | * @cmd: Scsi_Cmnd with the scatterlist |
@@ -337,10 +382,11 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev) | |||
337 | * Returns 1 on success. | 382 | * Returns 1 on success. |
338 | */ | 383 | */ |
339 | static int map_sg_data(struct scsi_cmnd *cmd, | 384 | static int map_sg_data(struct scsi_cmnd *cmd, |
385 | struct srp_event_struct *evt_struct, | ||
340 | struct srp_cmd *srp_cmd, struct device *dev) | 386 | struct srp_cmd *srp_cmd, struct device *dev) |
341 | { | 387 | { |
342 | 388 | ||
343 | int i, sg_mapped; | 389 | int sg_mapped; |
344 | u64 total_length = 0; | 390 | u64 total_length = 0; |
345 | struct scatterlist *sg = cmd->request_buffer; | 391 | struct scatterlist *sg = cmd->request_buffer; |
346 | struct memory_descriptor *data = | 392 | struct memory_descriptor *data = |
@@ -363,27 +409,46 @@ static int map_sg_data(struct scsi_cmnd *cmd, | |||
363 | return 1; | 409 | return 1; |
364 | } | 410 | } |
365 | 411 | ||
366 | if (sg_mapped > MAX_INDIRECT_BUFS) { | 412 | if (sg_mapped > SG_ALL) { |
367 | printk(KERN_ERR | 413 | printk(KERN_ERR |
368 | "ibmvscsi: More than %d mapped sg entries, got %d\n", | 414 | "ibmvscsi: More than %d mapped sg entries, got %d\n", |
369 | MAX_INDIRECT_BUFS, sg_mapped); | 415 | SG_ALL, sg_mapped); |
370 | return 0; | 416 | return 0; |
371 | } | 417 | } |
372 | 418 | ||
373 | indirect->head.virtual_address = 0; | 419 | indirect->head.virtual_address = 0; |
374 | indirect->head.length = sg_mapped * sizeof(indirect->list[0]); | 420 | indirect->head.length = sg_mapped * sizeof(indirect->list[0]); |
375 | indirect->head.memory_handle = 0; | 421 | indirect->head.memory_handle = 0; |
376 | for (i = 0; i < sg_mapped; ++i) { | 422 | |
377 | struct memory_descriptor *descr = &indirect->list[i]; | 423 | if (sg_mapped <= MAX_INDIRECT_BUFS) { |
378 | struct scatterlist *sg_entry = &sg[i]; | 424 | total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]); |
379 | descr->virtual_address = sg_dma_address(sg_entry); | 425 | indirect->total_length = total_length; |
380 | descr->length = sg_dma_len(sg_entry); | 426 | return 1; |
381 | descr->memory_handle = 0; | ||
382 | total_length += sg_dma_len(sg_entry); | ||
383 | } | 427 | } |
384 | indirect->total_length = total_length; | ||
385 | 428 | ||
386 | return 1; | 429 | /* get indirect table */ |
430 | if (!evt_struct->ext_list) { | ||
431 | evt_struct->ext_list =(struct memory_descriptor*) | ||
432 | dma_alloc_coherent(dev, | ||
433 | SG_ALL * sizeof(struct memory_descriptor), | ||
434 | &evt_struct->ext_list_token, 0); | ||
435 | if (!evt_struct->ext_list) { | ||
436 | printk(KERN_ERR | ||
437 | "ibmvscsi: Can't allocate memory for indirect table\n"); | ||
438 | return 0; | ||
439 | |||
440 | } | ||
441 | } | ||
442 | |||
443 | total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list); | ||
444 | |||
445 | indirect->total_length = total_length; | ||
446 | indirect->head.virtual_address = evt_struct->ext_list_token; | ||
447 | indirect->head.length = sg_mapped * sizeof(indirect->list[0]); | ||
448 | memcpy(indirect->list, evt_struct->ext_list, | ||
449 | MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor)); | ||
450 | |||
451 | return 1; | ||
387 | } | 452 | } |
388 | 453 | ||
389 | /** | 454 | /** |
@@ -428,6 +493,7 @@ static int map_single_data(struct scsi_cmnd *cmd, | |||
428 | * Returns 1 on success. | 493 | * Returns 1 on success. |
429 | */ | 494 | */ |
430 | static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, | 495 | static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, |
496 | struct srp_event_struct *evt_struct, | ||
431 | struct srp_cmd *srp_cmd, struct device *dev) | 497 | struct srp_cmd *srp_cmd, struct device *dev) |
432 | { | 498 | { |
433 | switch (cmd->sc_data_direction) { | 499 | switch (cmd->sc_data_direction) { |
@@ -450,7 +516,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, | |||
450 | if (!cmd->request_buffer) | 516 | if (!cmd->request_buffer) |
451 | return 1; | 517 | return 1; |
452 | if (cmd->use_sg) | 518 | if (cmd->use_sg) |
453 | return map_sg_data(cmd, srp_cmd, dev); | 519 | return map_sg_data(cmd, evt_struct, srp_cmd, dev); |
454 | return map_single_data(cmd, srp_cmd, dev); | 520 | return map_single_data(cmd, srp_cmd, dev); |
455 | } | 521 | } |
456 | 522 | ||
@@ -486,6 +552,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
486 | printk(KERN_WARNING | 552 | printk(KERN_WARNING |
487 | "ibmvscsi: Warning, request_limit exceeded\n"); | 553 | "ibmvscsi: Warning, request_limit exceeded\n"); |
488 | unmap_cmd_data(&evt_struct->iu.srp.cmd, | 554 | unmap_cmd_data(&evt_struct->iu.srp.cmd, |
555 | evt_struct, | ||
489 | hostdata->dev); | 556 | hostdata->dev); |
490 | free_event_struct(&hostdata->pool, evt_struct); | 557 | free_event_struct(&hostdata->pool, evt_struct); |
491 | return SCSI_MLQUEUE_HOST_BUSY; | 558 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -513,7 +580,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
513 | return 0; | 580 | return 0; |
514 | 581 | ||
515 | send_error: | 582 | send_error: |
516 | unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev); | 583 | unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); |
517 | 584 | ||
518 | if ((cmnd = evt_struct->cmnd) != NULL) { | 585 | if ((cmnd = evt_struct->cmnd) != NULL) { |
519 | cmnd->result = DID_ERROR << 16; | 586 | cmnd->result = DID_ERROR << 16; |
@@ -551,6 +618,7 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct) | |||
551 | rsp->sense_and_response_data, | 618 | rsp->sense_and_response_data, |
552 | rsp->sense_data_list_length); | 619 | rsp->sense_data_list_length); |
553 | unmap_cmd_data(&evt_struct->iu.srp.cmd, | 620 | unmap_cmd_data(&evt_struct->iu.srp.cmd, |
621 | evt_struct, | ||
554 | evt_struct->hostdata->dev); | 622 | evt_struct->hostdata->dev); |
555 | 623 | ||
556 | if (rsp->doover) | 624 | if (rsp->doover) |
@@ -583,6 +651,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
583 | { | 651 | { |
584 | struct srp_cmd *srp_cmd; | 652 | struct srp_cmd *srp_cmd; |
585 | struct srp_event_struct *evt_struct; | 653 | struct srp_event_struct *evt_struct; |
654 | struct indirect_descriptor *indirect; | ||
586 | struct ibmvscsi_host_data *hostdata = | 655 | struct ibmvscsi_host_data *hostdata = |
587 | (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata; | 656 | (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata; |
588 | u16 lun = lun_from_dev(cmnd->device); | 657 | u16 lun = lun_from_dev(cmnd->device); |
@@ -591,14 +660,6 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
591 | if (!evt_struct) | 660 | if (!evt_struct) |
592 | return SCSI_MLQUEUE_HOST_BUSY; | 661 | return SCSI_MLQUEUE_HOST_BUSY; |
593 | 662 | ||
594 | init_event_struct(evt_struct, | ||
595 | handle_cmd_rsp, | ||
596 | VIOSRP_SRP_FORMAT, | ||
597 | cmnd->timeout); | ||
598 | |||
599 | evt_struct->cmnd = cmnd; | ||
600 | evt_struct->cmnd_done = done; | ||
601 | |||
602 | /* Set up the actual SRP IU */ | 663 | /* Set up the actual SRP IU */ |
603 | srp_cmd = &evt_struct->iu.srp.cmd; | 664 | srp_cmd = &evt_struct->iu.srp.cmd; |
604 | memset(srp_cmd, 0x00, sizeof(*srp_cmd)); | 665 | memset(srp_cmd, 0x00, sizeof(*srp_cmd)); |
@@ -606,17 +667,25 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
606 | memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); | 667 | memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); |
607 | srp_cmd->lun = ((u64) lun) << 48; | 668 | srp_cmd->lun = ((u64) lun) << 48; |
608 | 669 | ||
609 | if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) { | 670 | if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { |
610 | printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n"); | 671 | printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n"); |
611 | free_event_struct(&hostdata->pool, evt_struct); | 672 | free_event_struct(&hostdata->pool, evt_struct); |
612 | return SCSI_MLQUEUE_HOST_BUSY; | 673 | return SCSI_MLQUEUE_HOST_BUSY; |
613 | } | 674 | } |
614 | 675 | ||
676 | init_event_struct(evt_struct, | ||
677 | handle_cmd_rsp, | ||
678 | VIOSRP_SRP_FORMAT, | ||
679 | cmnd->timeout_per_command/HZ); | ||
680 | |||
681 | evt_struct->cmnd = cmnd; | ||
682 | evt_struct->cmnd_done = done; | ||
683 | |||
615 | /* Fix up dma address of the buffer itself */ | 684 | /* Fix up dma address of the buffer itself */ |
616 | if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) || | 685 | indirect = (struct indirect_descriptor *)srp_cmd->additional_data; |
617 | (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) { | 686 | if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) || |
618 | struct indirect_descriptor *indirect = | 687 | (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) && |
619 | (struct indirect_descriptor *)srp_cmd->additional_data; | 688 | (indirect->head.virtual_address == 0)) { |
620 | indirect->head.virtual_address = evt_struct->crq.IU_data_ptr + | 689 | indirect->head.virtual_address = evt_struct->crq.IU_data_ptr + |
621 | offsetof(struct srp_cmd, additional_data) + | 690 | offsetof(struct srp_cmd, additional_data) + |
622 | offsetof(struct indirect_descriptor, list); | 691 | offsetof(struct indirect_descriptor, list); |
@@ -826,11 +895,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
826 | struct srp_event_struct *tmp_evt, *found_evt; | 895 | struct srp_event_struct *tmp_evt, *found_evt; |
827 | union viosrp_iu srp_rsp; | 896 | union viosrp_iu srp_rsp; |
828 | int rsp_rc; | 897 | int rsp_rc; |
898 | unsigned long flags; | ||
829 | u16 lun = lun_from_dev(cmd->device); | 899 | u16 lun = lun_from_dev(cmd->device); |
830 | 900 | ||
831 | /* First, find this command in our sent list so we can figure | 901 | /* First, find this command in our sent list so we can figure |
832 | * out the correct tag | 902 | * out the correct tag |
833 | */ | 903 | */ |
904 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
834 | found_evt = NULL; | 905 | found_evt = NULL; |
835 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | 906 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { |
836 | if (tmp_evt->cmnd == cmd) { | 907 | if (tmp_evt->cmnd == cmd) { |
@@ -839,11 +910,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
839 | } | 910 | } |
840 | } | 911 | } |
841 | 912 | ||
842 | if (!found_evt) | 913 | if (!found_evt) { |
914 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
843 | return FAILED; | 915 | return FAILED; |
916 | } | ||
844 | 917 | ||
845 | evt = get_event_struct(&hostdata->pool); | 918 | evt = get_event_struct(&hostdata->pool); |
846 | if (evt == NULL) { | 919 | if (evt == NULL) { |
920 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
847 | printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n"); | 921 | printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n"); |
848 | return FAILED; | 922 | return FAILED; |
849 | } | 923 | } |
@@ -867,7 +941,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
867 | 941 | ||
868 | evt->sync_srp = &srp_rsp; | 942 | evt->sync_srp = &srp_rsp; |
869 | init_completion(&evt->comp); | 943 | init_completion(&evt->comp); |
870 | if (ibmvscsi_send_srp_event(evt, hostdata) != 0) { | 944 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata); |
945 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
946 | if (rsp_rc != 0) { | ||
871 | printk(KERN_ERR "ibmvscsi: failed to send abort() event\n"); | 947 | printk(KERN_ERR "ibmvscsi: failed to send abort() event\n"); |
872 | return FAILED; | 948 | return FAILED; |
873 | } | 949 | } |
@@ -901,6 +977,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 | 977 | * The event is no longer in our list. Make sure it didn't |
902 | * complete while we were aborting | 978 | * complete while we were aborting |
903 | */ | 979 | */ |
980 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
904 | found_evt = NULL; | 981 | found_evt = NULL; |
905 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | 982 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { |
906 | if (tmp_evt->cmnd == cmd) { | 983 | if (tmp_evt->cmnd == cmd) { |
@@ -910,6 +987,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
910 | } | 987 | } |
911 | 988 | ||
912 | if (found_evt == NULL) { | 989 | if (found_evt == NULL) { |
990 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
913 | printk(KERN_INFO | 991 | printk(KERN_INFO |
914 | "ibmvscsi: aborted task tag 0x%lx completed\n", | 992 | "ibmvscsi: aborted task tag 0x%lx completed\n", |
915 | tsk_mgmt->managed_task_tag); | 993 | tsk_mgmt->managed_task_tag); |
@@ -922,8 +1000,10 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
922 | 1000 | ||
923 | cmd->result = (DID_ABORT << 16); | 1001 | cmd->result = (DID_ABORT << 16); |
924 | list_del(&found_evt->list); | 1002 | list_del(&found_evt->list); |
925 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev); | 1003 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt, |
1004 | found_evt->hostdata->dev); | ||
926 | free_event_struct(&found_evt->hostdata->pool, found_evt); | 1005 | free_event_struct(&found_evt->hostdata->pool, found_evt); |
1006 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
927 | atomic_inc(&hostdata->request_limit); | 1007 | atomic_inc(&hostdata->request_limit); |
928 | return SUCCESS; | 1008 | return SUCCESS; |
929 | } | 1009 | } |
@@ -943,10 +1023,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
943 | struct srp_event_struct *tmp_evt, *pos; | 1023 | struct srp_event_struct *tmp_evt, *pos; |
944 | union viosrp_iu srp_rsp; | 1024 | union viosrp_iu srp_rsp; |
945 | int rsp_rc; | 1025 | int rsp_rc; |
1026 | unsigned long flags; | ||
946 | u16 lun = lun_from_dev(cmd->device); | 1027 | u16 lun = lun_from_dev(cmd->device); |
947 | 1028 | ||
1029 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
948 | evt = get_event_struct(&hostdata->pool); | 1030 | evt = get_event_struct(&hostdata->pool); |
949 | if (evt == NULL) { | 1031 | if (evt == NULL) { |
1032 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
950 | printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n"); | 1033 | printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n"); |
951 | return FAILED; | 1034 | return FAILED; |
952 | } | 1035 | } |
@@ -969,7 +1052,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
969 | 1052 | ||
970 | evt->sync_srp = &srp_rsp; | 1053 | evt->sync_srp = &srp_rsp; |
971 | init_completion(&evt->comp); | 1054 | init_completion(&evt->comp); |
972 | if (ibmvscsi_send_srp_event(evt, hostdata) != 0) { | 1055 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata); |
1056 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1057 | if (rsp_rc != 0) { | ||
973 | printk(KERN_ERR "ibmvscsi: failed to send reset event\n"); | 1058 | printk(KERN_ERR "ibmvscsi: failed to send reset event\n"); |
974 | return FAILED; | 1059 | return FAILED; |
975 | } | 1060 | } |
@@ -1002,12 +1087,14 @@ 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 | 1087 | /* We need to find all commands for this LUN that have not yet been |
1003 | * responded to, and fail them with DID_RESET | 1088 | * responded to, and fail them with DID_RESET |
1004 | */ | 1089 | */ |
1090 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
1005 | list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { | 1091 | list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { |
1006 | if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { | 1092 | if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { |
1007 | if (tmp_evt->cmnd) | 1093 | if (tmp_evt->cmnd) |
1008 | tmp_evt->cmnd->result = (DID_RESET << 16); | 1094 | tmp_evt->cmnd->result = (DID_RESET << 16); |
1009 | list_del(&tmp_evt->list); | 1095 | list_del(&tmp_evt->list); |
1010 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev); | 1096 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt, |
1097 | tmp_evt->hostdata->dev); | ||
1011 | free_event_struct(&tmp_evt->hostdata->pool, | 1098 | free_event_struct(&tmp_evt->hostdata->pool, |
1012 | tmp_evt); | 1099 | tmp_evt); |
1013 | atomic_inc(&hostdata->request_limit); | 1100 | atomic_inc(&hostdata->request_limit); |
@@ -1017,6 +1104,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1017 | tmp_evt->done(tmp_evt); | 1104 | tmp_evt->done(tmp_evt); |
1018 | } | 1105 | } |
1019 | } | 1106 | } |
1107 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1020 | return SUCCESS; | 1108 | return SUCCESS; |
1021 | } | 1109 | } |
1022 | 1110 | ||
@@ -1035,6 +1123,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata) | |||
1035 | if (tmp_evt->cmnd) { | 1123 | if (tmp_evt->cmnd) { |
1036 | tmp_evt->cmnd->result = (DID_ERROR << 16); | 1124 | tmp_evt->cmnd->result = (DID_ERROR << 16); |
1037 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, | 1125 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, |
1126 | tmp_evt, | ||
1038 | tmp_evt->hostdata->dev); | 1127 | tmp_evt->hostdata->dev); |
1039 | if (tmp_evt->cmnd_done) | 1128 | if (tmp_evt->cmnd_done) |
1040 | tmp_evt->cmnd_done(tmp_evt->cmnd); | 1129 | tmp_evt->cmnd_done(tmp_evt->cmnd); |
@@ -1339,7 +1428,7 @@ static struct scsi_host_template driver_template = { | |||
1339 | .cmd_per_lun = 16, | 1428 | .cmd_per_lun = 16, |
1340 | .can_queue = 1, /* Updated after SRP_LOGIN */ | 1429 | .can_queue = 1, /* Updated after SRP_LOGIN */ |
1341 | .this_id = -1, | 1430 | .this_id = -1, |
1342 | .sg_tablesize = MAX_INDIRECT_BUFS, | 1431 | .sg_tablesize = SG_ALL, |
1343 | .use_clustering = ENABLE_CLUSTERING, | 1432 | .use_clustering = ENABLE_CLUSTERING, |
1344 | .shost_attrs = ibmvscsi_attrs, | 1433 | .shost_attrs = ibmvscsi_attrs, |
1345 | }; | 1434 | }; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 1030b703c30e..8bec0438dc8a 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h | |||
@@ -68,6 +68,8 @@ struct srp_event_struct { | |||
68 | void (*cmnd_done) (struct scsi_cmnd *); | 68 | void (*cmnd_done) (struct scsi_cmnd *); |
69 | struct completion comp; | 69 | struct completion comp; |
70 | union viosrp_iu *sync_srp; | 70 | union viosrp_iu *sync_srp; |
71 | struct memory_descriptor *ext_list; | ||
72 | dma_addr_t ext_list_token; | ||
71 | }; | 73 | }; |
72 | 74 | ||
73 | /* a pool of event structs for use */ | 75 | /* a pool of event structs for use */ |
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/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 659a5d63467d..fe0fce71adc7 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -211,6 +211,138 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) | |||
211 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); | 211 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); |
212 | } | 212 | } |
213 | 213 | ||
214 | /* Scsi_Host attributes. */ | ||
215 | |||
216 | static ssize_t | ||
217 | qla2x00_drvr_version_show(struct class_device *cdev, char *buf) | ||
218 | { | ||
219 | return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str); | ||
220 | } | ||
221 | |||
222 | static ssize_t | ||
223 | qla2x00_fw_version_show(struct class_device *cdev, char *buf) | ||
224 | { | ||
225 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
226 | char fw_str[30]; | ||
227 | |||
228 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
229 | ha->isp_ops.fw_version_str(ha, fw_str)); | ||
230 | } | ||
231 | |||
232 | static ssize_t | ||
233 | qla2x00_serial_num_show(struct class_device *cdev, char *buf) | ||
234 | { | ||
235 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
236 | uint32_t sn; | ||
237 | |||
238 | sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; | ||
239 | return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, | ||
240 | sn % 100000); | ||
241 | } | ||
242 | |||
243 | static ssize_t | ||
244 | qla2x00_isp_name_show(struct class_device *cdev, char *buf) | ||
245 | { | ||
246 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
247 | return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name); | ||
248 | } | ||
249 | |||
250 | static ssize_t | ||
251 | qla2x00_isp_id_show(struct class_device *cdev, char *buf) | ||
252 | { | ||
253 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
254 | return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", | ||
255 | ha->product_id[0], ha->product_id[1], ha->product_id[2], | ||
256 | ha->product_id[3]); | ||
257 | } | ||
258 | |||
259 | static ssize_t | ||
260 | qla2x00_model_name_show(struct class_device *cdev, char *buf) | ||
261 | { | ||
262 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
263 | return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number); | ||
264 | } | ||
265 | |||
266 | static ssize_t | ||
267 | qla2x00_model_desc_show(struct class_device *cdev, char *buf) | ||
268 | { | ||
269 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
270 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
271 | ha->model_desc ? ha->model_desc: ""); | ||
272 | } | ||
273 | |||
274 | static ssize_t | ||
275 | qla2x00_pci_info_show(struct class_device *cdev, char *buf) | ||
276 | { | ||
277 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
278 | char pci_info[30]; | ||
279 | |||
280 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
281 | ha->isp_ops.pci_info_str(ha, pci_info)); | ||
282 | } | ||
283 | |||
284 | static ssize_t | ||
285 | qla2x00_state_show(struct class_device *cdev, char *buf) | ||
286 | { | ||
287 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
288 | int len = 0; | ||
289 | |||
290 | if (atomic_read(&ha->loop_state) == LOOP_DOWN || | ||
291 | atomic_read(&ha->loop_state) == LOOP_DEAD) | ||
292 | len = snprintf(buf, PAGE_SIZE, "Link Down\n"); | ||
293 | else if (atomic_read(&ha->loop_state) != LOOP_READY || | ||
294 | test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || | ||
295 | test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) | ||
296 | len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n"); | ||
297 | else { | ||
298 | len = snprintf(buf, PAGE_SIZE, "Link Up - "); | ||
299 | |||
300 | switch (ha->current_topology) { | ||
301 | case ISP_CFG_NL: | ||
302 | len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); | ||
303 | break; | ||
304 | case ISP_CFG_FL: | ||
305 | len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n"); | ||
306 | break; | ||
307 | case ISP_CFG_N: | ||
308 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
309 | "N_Port to N_Port\n"); | ||
310 | break; | ||
311 | case ISP_CFG_F: | ||
312 | len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n"); | ||
313 | break; | ||
314 | default: | ||
315 | len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); | ||
316 | break; | ||
317 | } | ||
318 | } | ||
319 | return len; | ||
320 | } | ||
321 | |||
322 | static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, | ||
323 | NULL); | ||
324 | static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); | ||
325 | static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); | ||
326 | static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL); | ||
327 | static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL); | ||
328 | static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL); | ||
329 | static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL); | ||
330 | static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL); | ||
331 | static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL); | ||
332 | |||
333 | struct class_device_attribute *qla2x00_host_attrs[] = { | ||
334 | &class_device_attr_driver_version, | ||
335 | &class_device_attr_fw_version, | ||
336 | &class_device_attr_serial_num, | ||
337 | &class_device_attr_isp_name, | ||
338 | &class_device_attr_isp_id, | ||
339 | &class_device_attr_model_name, | ||
340 | &class_device_attr_model_desc, | ||
341 | &class_device_attr_pci_info, | ||
342 | &class_device_attr_state, | ||
343 | NULL, | ||
344 | }; | ||
345 | |||
214 | /* Host attributes. */ | 346 | /* Host attributes. */ |
215 | 347 | ||
216 | static void | 348 | static void |
@@ -304,10 +436,13 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
304 | 436 | ||
305 | .show_host_node_name = 1, | 437 | .show_host_node_name = 1, |
306 | .show_host_port_name = 1, | 438 | .show_host_port_name = 1, |
439 | .show_host_supported_classes = 1, | ||
440 | |||
307 | .get_host_port_id = qla2x00_get_host_port_id, | 441 | .get_host_port_id = qla2x00_get_host_port_id, |
308 | .show_host_port_id = 1, | 442 | .show_host_port_id = 1, |
309 | 443 | ||
310 | .dd_fcrport_size = sizeof(struct fc_port *), | 444 | .dd_fcrport_size = sizeof(struct fc_port *), |
445 | .show_rport_supported_classes = 1, | ||
311 | 446 | ||
312 | .get_starget_node_name = qla2x00_get_starget_node_name, | 447 | .get_starget_node_name = qla2x00_get_starget_node_name, |
313 | .show_starget_node_name = 1, | 448 | .show_starget_node_name = 1, |
@@ -329,4 +464,5 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) | |||
329 | be64_to_cpu(*(uint64_t *)ha->init_cb->node_name); | 464 | be64_to_cpu(*(uint64_t *)ha->init_cb->node_name); |
330 | fc_host_port_name(ha->host) = | 465 | fc_host_port_name(ha->host) = |
331 | be64_to_cpu(*(uint64_t *)ha->init_cb->port_name); | 466 | be64_to_cpu(*(uint64_t *)ha->init_cb->port_name); |
467 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; | ||
332 | } | 468 | } |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index b8d90e97e017..9684e7a91fa9 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define DEBUG2_3_11(x) do {x;} while (0); | 81 | #define DEBUG2_3_11(x) do {x;} while (0); |
82 | #define DEBUG2_9_10(x) do {x;} while (0); | 82 | #define DEBUG2_9_10(x) do {x;} while (0); |
83 | #define DEBUG2_11(x) do {x;} while (0); | 83 | #define DEBUG2_11(x) do {x;} while (0); |
84 | #define DEBUG2_13(x) do {x;} while (0); | ||
84 | #else | 85 | #else |
85 | #define DEBUG2(x) do {} while (0); | 86 | #define DEBUG2(x) do {} while (0); |
86 | #endif | 87 | #endif |
@@ -169,8 +170,14 @@ | |||
169 | 170 | ||
170 | #if defined(QL_DEBUG_LEVEL_13) | 171 | #if defined(QL_DEBUG_LEVEL_13) |
171 | #define DEBUG13(x) do {x;} while (0) | 172 | #define DEBUG13(x) do {x;} while (0) |
173 | #if !defined(DEBUG2_13) | ||
174 | #define DEBUG2_13(x) do {x;} while(0) | ||
175 | #endif | ||
172 | #else | 176 | #else |
173 | #define DEBUG13(x) do {} while (0) | 177 | #define DEBUG13(x) do {} while (0) |
178 | #if !defined(QL_DEBUG_LEVEL_2) | ||
179 | #define DEBUG2_13(x) do {} while(0) | ||
180 | #endif | ||
174 | #endif | 181 | #endif |
175 | 182 | ||
176 | #if defined(QL_DEBUG_LEVEL_14) | 183 | #if defined(QL_DEBUG_LEVEL_14) |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 1c6d366f4fad..b455c31405e4 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -214,6 +214,7 @@ | |||
214 | * valid range of an N-PORT id is 0 through 0x7ef. | 214 | * valid range of an N-PORT id is 0 through 0x7ef. |
215 | */ | 215 | */ |
216 | #define NPH_LAST_HANDLE 0x7ef | 216 | #define NPH_LAST_HANDLE 0x7ef |
217 | #define NPH_MGMT_SERVER 0x7fa /* FFFFFA */ | ||
217 | #define NPH_SNS 0x7fc /* FFFFFC */ | 218 | #define NPH_SNS 0x7fc /* FFFFFC */ |
218 | #define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */ | 219 | #define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */ |
219 | #define NPH_F_PORT 0x7fe /* FFFFFE */ | 220 | #define NPH_F_PORT 0x7fe /* FFFFFE */ |
@@ -630,6 +631,7 @@ typedef struct { | |||
630 | #define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */ | 631 | #define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */ |
631 | #define MBC_READ_RAM_EXTENDED 0xf /* Read RAM extended. */ | 632 | #define MBC_READ_RAM_EXTENDED 0xf /* Read RAM extended. */ |
632 | #define MBC_IOCB_COMMAND 0x12 /* Execute IOCB command. */ | 633 | #define MBC_IOCB_COMMAND 0x12 /* Execute IOCB command. */ |
634 | #define MBC_STOP_FIRMWARE 0x14 /* Stop firmware. */ | ||
633 | #define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ | 635 | #define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ |
634 | #define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ | 636 | #define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ |
635 | #define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ | 637 | #define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ |
@@ -913,7 +915,7 @@ typedef struct { | |||
913 | * MSB BIT 1 = | 915 | * MSB BIT 1 = |
914 | * MSB BIT 2 = | 916 | * MSB BIT 2 = |
915 | * MSB BIT 3 = | 917 | * MSB BIT 3 = |
916 | * MSB BIT 4 = | 918 | * MSB BIT 4 = LED mode |
917 | * MSB BIT 5 = enable 50 ohm termination | 919 | * MSB BIT 5 = enable 50 ohm termination |
918 | * MSB BIT 6 = Data Rate (2300 only) | 920 | * MSB BIT 6 = Data Rate (2300 only) |
919 | * MSB BIT 7 = Data Rate (2300 only) | 921 | * MSB BIT 7 = Data Rate (2300 only) |
@@ -1035,7 +1037,7 @@ typedef struct { | |||
1035 | * MSB BIT 1 = | 1037 | * MSB BIT 1 = |
1036 | * MSB BIT 2 = | 1038 | * MSB BIT 2 = |
1037 | * MSB BIT 3 = | 1039 | * MSB BIT 3 = |
1038 | * MSB BIT 4 = | 1040 | * MSB BIT 4 = LED mode |
1039 | * MSB BIT 5 = enable 50 ohm termination | 1041 | * MSB BIT 5 = enable 50 ohm termination |
1040 | * MSB BIT 6 = Data Rate (2300 only) | 1042 | * MSB BIT 6 = Data Rate (2300 only) |
1041 | * MSB BIT 7 = Data Rate (2300 only) | 1043 | * MSB BIT 7 = Data Rate (2300 only) |
@@ -1131,10 +1133,7 @@ typedef struct { | |||
1131 | 1133 | ||
1132 | uint8_t link_down_timeout; | 1134 | uint8_t link_down_timeout; |
1133 | 1135 | ||
1134 | uint8_t adapter_id_0[4]; | 1136 | uint8_t adapter_id[16]; |
1135 | uint8_t adapter_id_1[4]; | ||
1136 | uint8_t adapter_id_2[4]; | ||
1137 | uint8_t adapter_id_3[4]; | ||
1138 | 1137 | ||
1139 | uint8_t alt1_boot_node_name[WWN_SIZE]; | 1138 | uint8_t alt1_boot_node_name[WWN_SIZE]; |
1140 | uint16_t alt1_boot_lun_number; | 1139 | uint16_t alt1_boot_lun_number; |
@@ -1673,6 +1672,7 @@ typedef struct fc_port { | |||
1673 | uint8_t cur_path; /* current path id */ | 1672 | uint8_t cur_path; /* current path id */ |
1674 | 1673 | ||
1675 | struct fc_rport *rport; | 1674 | struct fc_rport *rport; |
1675 | u32 supported_classes; | ||
1676 | } fc_port_t; | 1676 | } fc_port_t; |
1677 | 1677 | ||
1678 | /* | 1678 | /* |
@@ -1727,6 +1727,8 @@ typedef struct fc_port { | |||
1727 | 1727 | ||
1728 | #define CT_REJECT_RESPONSE 0x8001 | 1728 | #define CT_REJECT_RESPONSE 0x8001 |
1729 | #define CT_ACCEPT_RESPONSE 0x8002 | 1729 | #define CT_ACCEPT_RESPONSE 0x8002 |
1730 | #define CT_REASON_CANNOT_PERFORM 0x09 | ||
1731 | #define CT_EXPL_ALREADY_REGISTERED 0x10 | ||
1730 | 1732 | ||
1731 | #define NS_N_PORT_TYPE 0x01 | 1733 | #define NS_N_PORT_TYPE 0x01 |
1732 | #define NS_NL_PORT_TYPE 0x02 | 1734 | #define NS_NL_PORT_TYPE 0x02 |
@@ -1768,6 +1770,100 @@ typedef struct fc_port { | |||
1768 | #define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) | 1770 | #define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) |
1769 | #define RSNN_NN_RSP_SIZE 16 | 1771 | #define RSNN_NN_RSP_SIZE 16 |
1770 | 1772 | ||
1773 | /* | ||
1774 | * HBA attribute types. | ||
1775 | */ | ||
1776 | #define FDMI_HBA_ATTR_COUNT 9 | ||
1777 | #define FDMI_HBA_NODE_NAME 1 | ||
1778 | #define FDMI_HBA_MANUFACTURER 2 | ||
1779 | #define FDMI_HBA_SERIAL_NUMBER 3 | ||
1780 | #define FDMI_HBA_MODEL 4 | ||
1781 | #define FDMI_HBA_MODEL_DESCRIPTION 5 | ||
1782 | #define FDMI_HBA_HARDWARE_VERSION 6 | ||
1783 | #define FDMI_HBA_DRIVER_VERSION 7 | ||
1784 | #define FDMI_HBA_OPTION_ROM_VERSION 8 | ||
1785 | #define FDMI_HBA_FIRMWARE_VERSION 9 | ||
1786 | #define FDMI_HBA_OS_NAME_AND_VERSION 0xa | ||
1787 | #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb | ||
1788 | |||
1789 | struct ct_fdmi_hba_attr { | ||
1790 | uint16_t type; | ||
1791 | uint16_t len; | ||
1792 | union { | ||
1793 | uint8_t node_name[WWN_SIZE]; | ||
1794 | uint8_t manufacturer[32]; | ||
1795 | uint8_t serial_num[8]; | ||
1796 | uint8_t model[16]; | ||
1797 | uint8_t model_desc[80]; | ||
1798 | uint8_t hw_version[16]; | ||
1799 | uint8_t driver_version[32]; | ||
1800 | uint8_t orom_version[16]; | ||
1801 | uint8_t fw_version[16]; | ||
1802 | uint8_t os_version[128]; | ||
1803 | uint8_t max_ct_len[4]; | ||
1804 | } a; | ||
1805 | }; | ||
1806 | |||
1807 | struct ct_fdmi_hba_attributes { | ||
1808 | uint32_t count; | ||
1809 | struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT]; | ||
1810 | }; | ||
1811 | |||
1812 | /* | ||
1813 | * Port attribute types. | ||
1814 | */ | ||
1815 | #define FDMI_PORT_ATTR_COUNT 5 | ||
1816 | #define FDMI_PORT_FC4_TYPES 1 | ||
1817 | #define FDMI_PORT_SUPPORT_SPEED 2 | ||
1818 | #define FDMI_PORT_CURRENT_SPEED 3 | ||
1819 | #define FDMI_PORT_MAX_FRAME_SIZE 4 | ||
1820 | #define FDMI_PORT_OS_DEVICE_NAME 5 | ||
1821 | #define FDMI_PORT_HOST_NAME 6 | ||
1822 | |||
1823 | struct ct_fdmi_port_attr { | ||
1824 | uint16_t type; | ||
1825 | uint16_t len; | ||
1826 | union { | ||
1827 | uint8_t fc4_types[32]; | ||
1828 | uint32_t sup_speed; | ||
1829 | uint32_t cur_speed; | ||
1830 | uint32_t max_frame_size; | ||
1831 | uint8_t os_dev_name[32]; | ||
1832 | uint8_t host_name[32]; | ||
1833 | } a; | ||
1834 | }; | ||
1835 | |||
1836 | /* | ||
1837 | * Port Attribute Block. | ||
1838 | */ | ||
1839 | struct ct_fdmi_port_attributes { | ||
1840 | uint32_t count; | ||
1841 | struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT]; | ||
1842 | }; | ||
1843 | |||
1844 | /* FDMI definitions. */ | ||
1845 | #define GRHL_CMD 0x100 | ||
1846 | #define GHAT_CMD 0x101 | ||
1847 | #define GRPL_CMD 0x102 | ||
1848 | #define GPAT_CMD 0x110 | ||
1849 | |||
1850 | #define RHBA_CMD 0x200 | ||
1851 | #define RHBA_RSP_SIZE 16 | ||
1852 | |||
1853 | #define RHAT_CMD 0x201 | ||
1854 | #define RPRT_CMD 0x210 | ||
1855 | |||
1856 | #define RPA_CMD 0x211 | ||
1857 | #define RPA_RSP_SIZE 16 | ||
1858 | |||
1859 | #define DHBA_CMD 0x300 | ||
1860 | #define DHBA_REQ_SIZE (16 + 8) | ||
1861 | #define DHBA_RSP_SIZE 16 | ||
1862 | |||
1863 | #define DHAT_CMD 0x301 | ||
1864 | #define DPRT_CMD 0x310 | ||
1865 | #define DPA_CMD 0x311 | ||
1866 | |||
1771 | /* CT command header -- request/response common fields */ | 1867 | /* CT command header -- request/response common fields */ |
1772 | struct ct_cmd_hdr { | 1868 | struct ct_cmd_hdr { |
1773 | uint8_t revision; | 1869 | uint8_t revision; |
@@ -1825,6 +1921,43 @@ struct ct_sns_req { | |||
1825 | uint8_t name_len; | 1921 | uint8_t name_len; |
1826 | uint8_t sym_node_name[255]; | 1922 | uint8_t sym_node_name[255]; |
1827 | } rsnn_nn; | 1923 | } rsnn_nn; |
1924 | |||
1925 | struct { | ||
1926 | uint8_t hba_indentifier[8]; | ||
1927 | } ghat; | ||
1928 | |||
1929 | struct { | ||
1930 | uint8_t hba_identifier[8]; | ||
1931 | uint32_t entry_count; | ||
1932 | uint8_t port_name[8]; | ||
1933 | struct ct_fdmi_hba_attributes attrs; | ||
1934 | } rhba; | ||
1935 | |||
1936 | struct { | ||
1937 | uint8_t hba_identifier[8]; | ||
1938 | struct ct_fdmi_hba_attributes attrs; | ||
1939 | } rhat; | ||
1940 | |||
1941 | struct { | ||
1942 | uint8_t port_name[8]; | ||
1943 | struct ct_fdmi_port_attributes attrs; | ||
1944 | } rpa; | ||
1945 | |||
1946 | struct { | ||
1947 | uint8_t port_name[8]; | ||
1948 | } dhba; | ||
1949 | |||
1950 | struct { | ||
1951 | uint8_t port_name[8]; | ||
1952 | } dhat; | ||
1953 | |||
1954 | struct { | ||
1955 | uint8_t port_name[8]; | ||
1956 | } dprt; | ||
1957 | |||
1958 | struct { | ||
1959 | uint8_t port_name[8]; | ||
1960 | } dpa; | ||
1828 | } req; | 1961 | } req; |
1829 | }; | 1962 | }; |
1830 | 1963 | ||
@@ -1882,6 +2015,12 @@ struct ct_sns_rsp { | |||
1882 | struct { | 2015 | struct { |
1883 | uint8_t fc4_types[32]; | 2016 | uint8_t fc4_types[32]; |
1884 | } gft_id; | 2017 | } gft_id; |
2018 | |||
2019 | struct { | ||
2020 | uint32_t entry_count; | ||
2021 | uint8_t port_name[8]; | ||
2022 | struct ct_fdmi_hba_attributes attrs; | ||
2023 | } ghat; | ||
1885 | } rsp; | 2024 | } rsp; |
1886 | }; | 2025 | }; |
1887 | 2026 | ||
@@ -2032,6 +2171,8 @@ struct isp_operations { | |||
2032 | uint16_t (*calc_req_entries) (uint16_t); | 2171 | uint16_t (*calc_req_entries) (uint16_t); |
2033 | void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t); | 2172 | void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t); |
2034 | void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t); | 2173 | void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t); |
2174 | void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t, | ||
2175 | uint32_t); | ||
2035 | 2176 | ||
2036 | uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *, | 2177 | uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *, |
2037 | uint32_t, uint32_t); | 2178 | uint32_t, uint32_t); |
@@ -2111,6 +2252,7 @@ typedef struct scsi_qla_host { | |||
2111 | #define IOCTL_ERROR_RECOVERY 23 | 2252 | #define IOCTL_ERROR_RECOVERY 23 |
2112 | #define LOOP_RESET_NEEDED 24 | 2253 | #define LOOP_RESET_NEEDED 24 |
2113 | #define BEACON_BLINK_NEEDED 25 | 2254 | #define BEACON_BLINK_NEEDED 25 |
2255 | #define REGISTER_FDMI_NEEDED 26 | ||
2114 | 2256 | ||
2115 | uint32_t device_flags; | 2257 | uint32_t device_flags; |
2116 | #define DFLG_LOCAL_DEVICES BIT_0 | 2258 | #define DFLG_LOCAL_DEVICES BIT_0 |
@@ -2204,6 +2346,7 @@ typedef struct scsi_qla_host { | |||
2204 | int port_down_retry_count; | 2346 | int port_down_retry_count; |
2205 | uint8_t mbx_count; | 2347 | uint8_t mbx_count; |
2206 | uint16_t last_loop_id; | 2348 | uint16_t last_loop_id; |
2349 | uint16_t mgmt_svr_loop_id; | ||
2207 | 2350 | ||
2208 | uint32_t login_retry_count; | 2351 | uint32_t login_retry_count; |
2209 | 2352 | ||
@@ -2318,6 +2461,7 @@ typedef struct scsi_qla_host { | |||
2318 | uint8_t model_number[16+1]; | 2461 | uint8_t model_number[16+1]; |
2319 | #define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 2462 | #define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
2320 | char *model_desc; | 2463 | char *model_desc; |
2464 | uint8_t adapter_id[16+1]; | ||
2321 | 2465 | ||
2322 | uint8_t *node_name; | 2466 | uint8_t *node_name; |
2323 | uint8_t *port_name; | 2467 | uint8_t *port_name; |
@@ -2377,6 +2521,7 @@ typedef struct scsi_qla_host { | |||
2377 | #define QLA_SUSPENDED 0x106 | 2521 | #define QLA_SUSPENDED 0x106 |
2378 | #define QLA_BUSY 0x107 | 2522 | #define QLA_BUSY 0x107 |
2379 | #define QLA_RSCNS_HANDLED 0x108 | 2523 | #define QLA_RSCNS_HANDLED 0x108 |
2524 | #define QLA_ALREADY_REGISTERED 0x109 | ||
2380 | 2525 | ||
2381 | /* | 2526 | /* |
2382 | * Stat info for all adpaters | 2527 | * Stat info for all adpaters |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 665c203e0675..1ed32e7b5472 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -79,6 +79,7 @@ extern int ql2xplogiabsentdevice; | |||
79 | extern int ql2xenablezio; | 79 | extern int ql2xenablezio; |
80 | extern int ql2xintrdelaytimer; | 80 | extern int ql2xintrdelaytimer; |
81 | extern int ql2xloginretrycount; | 81 | extern int ql2xloginretrycount; |
82 | extern int ql2xfdmienable; | ||
82 | 83 | ||
83 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); | 84 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); |
84 | 85 | ||
@@ -147,9 +148,6 @@ qla2x00_abort_target(fc_port_t *); | |||
147 | #endif | 148 | #endif |
148 | 149 | ||
149 | extern int | 150 | extern int |
150 | qla2x00_target_reset(scsi_qla_host_t *, struct fc_port *); | ||
151 | |||
152 | extern int | ||
153 | qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, | 151 | qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, |
154 | uint8_t *, uint16_t *); | 152 | uint8_t *, uint16_t *); |
155 | 153 | ||
@@ -215,6 +213,9 @@ qla2x00_get_serdes_params(scsi_qla_host_t *, uint16_t *, uint16_t *, | |||
215 | extern int | 213 | extern int |
216 | qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); | 214 | qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); |
217 | 215 | ||
216 | extern int | ||
217 | qla2x00_stop_firmware(scsi_qla_host_t *); | ||
218 | |||
218 | /* | 219 | /* |
219 | * Global Function Prototypes in qla_isr.c source file. | 220 | * Global Function Prototypes in qla_isr.c source file. |
220 | */ | 221 | */ |
@@ -269,6 +270,9 @@ extern int qla2x00_rft_id(scsi_qla_host_t *); | |||
269 | extern int qla2x00_rff_id(scsi_qla_host_t *); | 270 | extern int qla2x00_rff_id(scsi_qla_host_t *); |
270 | extern int qla2x00_rnn_id(scsi_qla_host_t *); | 271 | extern int qla2x00_rnn_id(scsi_qla_host_t *); |
271 | extern int qla2x00_rsnn_nn(scsi_qla_host_t *); | 272 | extern int qla2x00_rsnn_nn(scsi_qla_host_t *); |
273 | extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); | ||
274 | extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); | ||
275 | extern int qla2x00_fdmi_register(scsi_qla_host_t *); | ||
272 | 276 | ||
273 | /* | 277 | /* |
274 | * Global Function Prototypes in qla_rscn.c source file. | 278 | * Global Function Prototypes in qla_rscn.c source file. |
@@ -289,6 +293,8 @@ extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *); | |||
289 | /* | 293 | /* |
290 | * Global Function Prototypes in qla_attr.c source file. | 294 | * Global Function Prototypes in qla_attr.c source file. |
291 | */ | 295 | */ |
296 | struct class_device_attribute; | ||
297 | extern struct class_device_attribute *qla2x00_host_attrs[]; | ||
292 | struct fc_function_template; | 298 | struct fc_function_template; |
293 | extern struct fc_function_template qla2xxx_transport_functions; | 299 | extern struct fc_function_template qla2xxx_transport_functions; |
294 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); | 300 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 31ce4f62da13..e7b138c2e339 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -1099,3 +1099,567 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha) | |||
1099 | 1099 | ||
1100 | return (rval); | 1100 | return (rval); |
1101 | } | 1101 | } |
1102 | |||
1103 | /** | ||
1104 | * qla2x00_mgmt_svr_login() - Login to fabric Managment Service. | ||
1105 | * @ha: HA context | ||
1106 | * | ||
1107 | * Returns 0 on success. | ||
1108 | */ | ||
1109 | static int | ||
1110 | qla2x00_mgmt_svr_login(scsi_qla_host_t *ha) | ||
1111 | { | ||
1112 | int ret; | ||
1113 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | ||
1114 | |||
1115 | ret = QLA_SUCCESS; | ||
1116 | if (ha->flags.management_server_logged_in) | ||
1117 | return ret; | ||
1118 | |||
1119 | ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, | ||
1120 | mb, BIT_1); | ||
1121 | if (mb[0] != MBS_COMMAND_COMPLETE) { | ||
1122 | DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: " | ||
1123 | "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n", | ||
1124 | __func__, ha->host_no, ha->mgmt_svr_loop_id, mb[0], mb[1], | ||
1125 | mb[2], mb[6], mb[7])); | ||
1126 | ret = QLA_FUNCTION_FAILED; | ||
1127 | } else | ||
1128 | ha->flags.management_server_logged_in = 1; | ||
1129 | |||
1130 | return ret; | ||
1131 | } | ||
1132 | |||
1133 | /** | ||
1134 | * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query. | ||
1135 | * @ha: HA context | ||
1136 | * @req_size: request size in bytes | ||
1137 | * @rsp_size: response size in bytes | ||
1138 | * | ||
1139 | * Returns a pointer to the @ha's ms_iocb. | ||
1140 | */ | ||
1141 | void * | ||
1142 | qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | ||
1143 | uint32_t rsp_size) | ||
1144 | { | ||
1145 | ms_iocb_entry_t *ms_pkt; | ||
1146 | |||
1147 | ms_pkt = ha->ms_iocb; | ||
1148 | memset(ms_pkt, 0, sizeof(ms_iocb_entry_t)); | ||
1149 | |||
1150 | ms_pkt->entry_type = MS_IOCB_TYPE; | ||
1151 | ms_pkt->entry_count = 1; | ||
1152 | SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id); | ||
1153 | ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); | ||
1154 | ms_pkt->timeout = __constant_cpu_to_le16(59); | ||
1155 | ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | ||
1156 | ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); | ||
1157 | ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); | ||
1158 | ms_pkt->req_bytecount = cpu_to_le32(req_size); | ||
1159 | |||
1160 | ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1161 | ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1162 | ms_pkt->dseg_req_length = ms_pkt->req_bytecount; | ||
1163 | |||
1164 | ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1165 | ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1166 | ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; | ||
1167 | |||
1168 | return ms_pkt; | ||
1169 | } | ||
1170 | |||
1171 | /** | ||
1172 | * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query. | ||
1173 | * @ha: HA context | ||
1174 | * @req_size: request size in bytes | ||
1175 | * @rsp_size: response size in bytes | ||
1176 | * | ||
1177 | * Returns a pointer to the @ha's ms_iocb. | ||
1178 | */ | ||
1179 | void * | ||
1180 | qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | ||
1181 | uint32_t rsp_size) | ||
1182 | { | ||
1183 | struct ct_entry_24xx *ct_pkt; | ||
1184 | |||
1185 | ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; | ||
1186 | memset(ct_pkt, 0, sizeof(struct ct_entry_24xx)); | ||
1187 | |||
1188 | ct_pkt->entry_type = CT_IOCB_TYPE; | ||
1189 | ct_pkt->entry_count = 1; | ||
1190 | ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); | ||
1191 | ct_pkt->timeout = __constant_cpu_to_le16(59); | ||
1192 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | ||
1193 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); | ||
1194 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); | ||
1195 | ct_pkt->cmd_byte_count = cpu_to_le32(req_size); | ||
1196 | |||
1197 | ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1198 | ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1199 | ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; | ||
1200 | |||
1201 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1202 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1203 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; | ||
1204 | |||
1205 | return ct_pkt; | ||
1206 | } | ||
1207 | |||
1208 | static inline ms_iocb_entry_t * | ||
1209 | qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) | ||
1210 | { | ||
1211 | ms_iocb_entry_t *ms_pkt = ha->ms_iocb; | ||
1212 | struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; | ||
1213 | |||
1214 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
1215 | ct_pkt->cmd_byte_count = cpu_to_le32(req_size); | ||
1216 | ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; | ||
1217 | } else { | ||
1218 | ms_pkt->req_bytecount = cpu_to_le32(req_size); | ||
1219 | ms_pkt->dseg_req_length = ms_pkt->req_bytecount; | ||
1220 | } | ||
1221 | |||
1222 | return ms_pkt; | ||
1223 | } | ||
1224 | |||
1225 | /** | ||
1226 | * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query. | ||
1227 | * @ct_req: CT request buffer | ||
1228 | * @cmd: GS command | ||
1229 | * @rsp_size: response size in bytes | ||
1230 | * | ||
1231 | * Returns a pointer to the intitialized @ct_req. | ||
1232 | */ | ||
1233 | static inline struct ct_sns_req * | ||
1234 | qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd, | ||
1235 | uint16_t rsp_size) | ||
1236 | { | ||
1237 | memset(ct_req, 0, sizeof(struct ct_sns_pkt)); | ||
1238 | |||
1239 | ct_req->header.revision = 0x01; | ||
1240 | ct_req->header.gs_type = 0xFA; | ||
1241 | ct_req->header.gs_subtype = 0x10; | ||
1242 | ct_req->command = cpu_to_be16(cmd); | ||
1243 | ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); | ||
1244 | |||
1245 | return ct_req; | ||
1246 | } | ||
1247 | |||
1248 | /** | ||
1249 | * qla2x00_fdmi_rhba() - | ||
1250 | * @ha: HA context | ||
1251 | * | ||
1252 | * Returns 0 on success. | ||
1253 | */ | ||
1254 | static int | ||
1255 | qla2x00_fdmi_rhba(scsi_qla_host_t *ha) | ||
1256 | { | ||
1257 | int rval, alen; | ||
1258 | uint32_t size, sn; | ||
1259 | |||
1260 | ms_iocb_entry_t *ms_pkt; | ||
1261 | struct ct_sns_req *ct_req; | ||
1262 | struct ct_sns_rsp *ct_rsp; | ||
1263 | uint8_t *entries; | ||
1264 | struct ct_fdmi_hba_attr *eiter; | ||
1265 | |||
1266 | /* Issue RHBA */ | ||
1267 | /* Prepare common MS IOCB */ | ||
1268 | /* Request size adjusted after CT preparation */ | ||
1269 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); | ||
1270 | |||
1271 | /* Prepare CT request */ | ||
1272 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, | ||
1273 | RHBA_RSP_SIZE); | ||
1274 | ct_rsp = &ha->ct_sns->p.rsp; | ||
1275 | |||
1276 | /* Prepare FDMI command arguments -- attribute block, attributes. */ | ||
1277 | memcpy(ct_req->req.rhba.hba_identifier, ha->port_name, WWN_SIZE); | ||
1278 | ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1); | ||
1279 | memcpy(ct_req->req.rhba.port_name, ha->port_name, WWN_SIZE); | ||
1280 | size = 2 * WWN_SIZE + 4 + 4; | ||
1281 | |||
1282 | /* Attributes */ | ||
1283 | ct_req->req.rhba.attrs.count = | ||
1284 | __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT); | ||
1285 | entries = ct_req->req.rhba.hba_identifier; | ||
1286 | |||
1287 | /* Nodename. */ | ||
1288 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1289 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME); | ||
1290 | eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE); | ||
1291 | memcpy(eiter->a.node_name, ha->node_name, WWN_SIZE); | ||
1292 | size += 4 + WWN_SIZE; | ||
1293 | |||
1294 | DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n", | ||
1295 | __func__, ha->host_no, | ||
1296 | eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2], | ||
1297 | eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5], | ||
1298 | eiter->a.node_name[6], eiter->a.node_name[7])); | ||
1299 | |||
1300 | /* Manufacturer. */ | ||
1301 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1302 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER); | ||
1303 | strcpy(eiter->a.manufacturer, "QLogic Corporation"); | ||
1304 | alen = strlen(eiter->a.manufacturer); | ||
1305 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1306 | eiter->len = cpu_to_be16(4 + alen); | ||
1307 | size += 4 + alen; | ||
1308 | |||
1309 | DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, ha->host_no, | ||
1310 | eiter->a.manufacturer)); | ||
1311 | |||
1312 | /* Serial number. */ | ||
1313 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1314 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); | ||
1315 | sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; | ||
1316 | sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000); | ||
1317 | alen = strlen(eiter->a.serial_num); | ||
1318 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1319 | eiter->len = cpu_to_be16(4 + alen); | ||
1320 | size += 4 + alen; | ||
1321 | |||
1322 | DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, ha->host_no, | ||
1323 | eiter->a.serial_num)); | ||
1324 | |||
1325 | /* Model name. */ | ||
1326 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1327 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL); | ||
1328 | strcpy(eiter->a.model, ha->model_number); | ||
1329 | alen = strlen(eiter->a.model); | ||
1330 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1331 | eiter->len = cpu_to_be16(4 + alen); | ||
1332 | size += 4 + alen; | ||
1333 | |||
1334 | DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, ha->host_no, | ||
1335 | eiter->a.model)); | ||
1336 | |||
1337 | /* Model description. */ | ||
1338 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1339 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); | ||
1340 | if (ha->model_desc) | ||
1341 | strncpy(eiter->a.model_desc, ha->model_desc, 80); | ||
1342 | alen = strlen(eiter->a.model_desc); | ||
1343 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1344 | eiter->len = cpu_to_be16(4 + alen); | ||
1345 | size += 4 + alen; | ||
1346 | |||
1347 | DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, ha->host_no, | ||
1348 | eiter->a.model_desc)); | ||
1349 | |||
1350 | /* Hardware version. */ | ||
1351 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1352 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); | ||
1353 | strcpy(eiter->a.hw_version, ha->adapter_id); | ||
1354 | alen = strlen(eiter->a.hw_version); | ||
1355 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1356 | eiter->len = cpu_to_be16(4 + alen); | ||
1357 | size += 4 + alen; | ||
1358 | |||
1359 | DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, ha->host_no, | ||
1360 | eiter->a.hw_version)); | ||
1361 | |||
1362 | /* Driver version. */ | ||
1363 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1364 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION); | ||
1365 | strcpy(eiter->a.driver_version, qla2x00_version_str); | ||
1366 | alen = strlen(eiter->a.driver_version); | ||
1367 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1368 | eiter->len = cpu_to_be16(4 + alen); | ||
1369 | size += 4 + alen; | ||
1370 | |||
1371 | DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, ha->host_no, | ||
1372 | eiter->a.driver_version)); | ||
1373 | |||
1374 | /* Option ROM version. */ | ||
1375 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1376 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); | ||
1377 | strcpy(eiter->a.orom_version, "0.00"); | ||
1378 | alen = strlen(eiter->a.orom_version); | ||
1379 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1380 | eiter->len = cpu_to_be16(4 + alen); | ||
1381 | size += 4 + alen; | ||
1382 | |||
1383 | DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, ha->host_no, | ||
1384 | eiter->a.orom_version)); | ||
1385 | |||
1386 | /* Firmware version */ | ||
1387 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1388 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); | ||
1389 | ha->isp_ops.fw_version_str(ha, eiter->a.fw_version); | ||
1390 | alen = strlen(eiter->a.fw_version); | ||
1391 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1392 | eiter->len = cpu_to_be16(4 + alen); | ||
1393 | size += 4 + alen; | ||
1394 | |||
1395 | DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, ha->host_no, | ||
1396 | eiter->a.fw_version)); | ||
1397 | |||
1398 | /* Update MS request size. */ | ||
1399 | qla2x00_update_ms_fdmi_iocb(ha, size + 16); | ||
1400 | |||
1401 | DEBUG13(printk("%s(%ld): RHBA identifier=" | ||
1402 | "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__, | ||
1403 | ha->host_no, ct_req->req.rhba.hba_identifier[0], | ||
1404 | ct_req->req.rhba.hba_identifier[1], | ||
1405 | ct_req->req.rhba.hba_identifier[2], | ||
1406 | ct_req->req.rhba.hba_identifier[3], | ||
1407 | ct_req->req.rhba.hba_identifier[4], | ||
1408 | ct_req->req.rhba.hba_identifier[5], | ||
1409 | ct_req->req.rhba.hba_identifier[6], | ||
1410 | ct_req->req.rhba.hba_identifier[7], size)); | ||
1411 | DEBUG13(qla2x00_dump_buffer(entries, size)); | ||
1412 | |||
1413 | /* Execute MS IOCB */ | ||
1414 | rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, | ||
1415 | sizeof(ms_iocb_entry_t)); | ||
1416 | if (rval != QLA_SUCCESS) { | ||
1417 | /*EMPTY*/ | ||
1418 | DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n", | ||
1419 | ha->host_no, rval)); | ||
1420 | } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RHBA") != | ||
1421 | QLA_SUCCESS) { | ||
1422 | rval = QLA_FUNCTION_FAILED; | ||
1423 | if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && | ||
1424 | ct_rsp->header.explanation_code == | ||
1425 | CT_EXPL_ALREADY_REGISTERED) { | ||
1426 | DEBUG2_13(printk("%s(%ld): HBA already registered.\n", | ||
1427 | __func__, ha->host_no)); | ||
1428 | rval = QLA_ALREADY_REGISTERED; | ||
1429 | } | ||
1430 | } else { | ||
1431 | DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n", | ||
1432 | ha->host_no)); | ||
1433 | } | ||
1434 | |||
1435 | return rval; | ||
1436 | } | ||
1437 | |||
1438 | /** | ||
1439 | * qla2x00_fdmi_dhba() - | ||
1440 | * @ha: HA context | ||
1441 | * | ||
1442 | * Returns 0 on success. | ||
1443 | */ | ||
1444 | static int | ||
1445 | qla2x00_fdmi_dhba(scsi_qla_host_t *ha) | ||
1446 | { | ||
1447 | int rval; | ||
1448 | |||
1449 | ms_iocb_entry_t *ms_pkt; | ||
1450 | struct ct_sns_req *ct_req; | ||
1451 | struct ct_sns_rsp *ct_rsp; | ||
1452 | |||
1453 | /* Issue RPA */ | ||
1454 | /* Prepare common MS IOCB */ | ||
1455 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, | ||
1456 | DHBA_RSP_SIZE); | ||
1457 | |||
1458 | /* Prepare CT request */ | ||
1459 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD, | ||
1460 | DHBA_RSP_SIZE); | ||
1461 | ct_rsp = &ha->ct_sns->p.rsp; | ||
1462 | |||
1463 | /* Prepare FDMI command arguments -- portname. */ | ||
1464 | memcpy(ct_req->req.dhba.port_name, ha->port_name, WWN_SIZE); | ||
1465 | |||
1466 | DEBUG13(printk("%s(%ld): DHBA portname=" | ||
1467 | "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no, | ||
1468 | ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1], | ||
1469 | ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3], | ||
1470 | ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5], | ||
1471 | ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7])); | ||
1472 | |||
1473 | /* Execute MS IOCB */ | ||
1474 | rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, | ||
1475 | sizeof(ms_iocb_entry_t)); | ||
1476 | if (rval != QLA_SUCCESS) { | ||
1477 | /*EMPTY*/ | ||
1478 | DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n", | ||
1479 | ha->host_no, rval)); | ||
1480 | } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "DHBA") != | ||
1481 | QLA_SUCCESS) { | ||
1482 | rval = QLA_FUNCTION_FAILED; | ||
1483 | } else { | ||
1484 | DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n", | ||
1485 | ha->host_no)); | ||
1486 | } | ||
1487 | |||
1488 | return rval; | ||
1489 | } | ||
1490 | |||
1491 | /** | ||
1492 | * qla2x00_fdmi_rpa() - | ||
1493 | * @ha: HA context | ||
1494 | * | ||
1495 | * Returns 0 on success. | ||
1496 | */ | ||
1497 | static int | ||
1498 | qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | ||
1499 | { | ||
1500 | int rval, alen; | ||
1501 | uint32_t size, max_frame_size; | ||
1502 | |||
1503 | ms_iocb_entry_t *ms_pkt; | ||
1504 | struct ct_sns_req *ct_req; | ||
1505 | struct ct_sns_rsp *ct_rsp; | ||
1506 | uint8_t *entries; | ||
1507 | struct ct_fdmi_port_attr *eiter; | ||
1508 | struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; | ||
1509 | |||
1510 | /* Issue RPA */ | ||
1511 | /* Prepare common MS IOCB */ | ||
1512 | /* Request size adjusted after CT preparation */ | ||
1513 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); | ||
1514 | |||
1515 | /* Prepare CT request */ | ||
1516 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, | ||
1517 | RPA_RSP_SIZE); | ||
1518 | ct_rsp = &ha->ct_sns->p.rsp; | ||
1519 | |||
1520 | /* Prepare FDMI command arguments -- attribute block, attributes. */ | ||
1521 | memcpy(ct_req->req.rpa.port_name, ha->port_name, WWN_SIZE); | ||
1522 | size = WWN_SIZE + 4; | ||
1523 | |||
1524 | /* Attributes */ | ||
1525 | ct_req->req.rpa.attrs.count = | ||
1526 | __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); | ||
1527 | entries = ct_req->req.rpa.port_name; | ||
1528 | |||
1529 | /* FC4 types. */ | ||
1530 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1531 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES); | ||
1532 | eiter->len = __constant_cpu_to_be16(4 + 32); | ||
1533 | eiter->a.fc4_types[2] = 0x01; | ||
1534 | size += 4 + 32; | ||
1535 | |||
1536 | DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__, ha->host_no, | ||
1537 | eiter->a.fc4_types[2], eiter->a.fc4_types[1])); | ||
1538 | |||
1539 | /* Supported speed. */ | ||
1540 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1541 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); | ||
1542 | eiter->len = __constant_cpu_to_be16(4 + 4); | ||
1543 | if (IS_QLA25XX(ha)) | ||
1544 | eiter->a.sup_speed = __constant_cpu_to_be32(4); | ||
1545 | else if (IS_QLA24XX(ha)) | ||
1546 | eiter->a.sup_speed = __constant_cpu_to_be32(8); | ||
1547 | else if (IS_QLA23XX(ha)) | ||
1548 | eiter->a.sup_speed = __constant_cpu_to_be32(2); | ||
1549 | else | ||
1550 | eiter->a.sup_speed = __constant_cpu_to_be32(1); | ||
1551 | size += 4 + 4; | ||
1552 | |||
1553 | DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no, | ||
1554 | eiter->a.sup_speed)); | ||
1555 | |||
1556 | /* Current speed. */ | ||
1557 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1558 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED); | ||
1559 | eiter->len = __constant_cpu_to_be16(4 + 4); | ||
1560 | switch (ha->link_data_rate) { | ||
1561 | case 0: | ||
1562 | eiter->a.cur_speed = __constant_cpu_to_be32(1); | ||
1563 | break; | ||
1564 | case 1: | ||
1565 | eiter->a.cur_speed = __constant_cpu_to_be32(2); | ||
1566 | break; | ||
1567 | case 3: | ||
1568 | eiter->a.cur_speed = __constant_cpu_to_be32(8); | ||
1569 | break; | ||
1570 | case 4: | ||
1571 | eiter->a.cur_speed = __constant_cpu_to_be32(4); | ||
1572 | break; | ||
1573 | } | ||
1574 | size += 4 + 4; | ||
1575 | |||
1576 | DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, ha->host_no, | ||
1577 | eiter->a.cur_speed)); | ||
1578 | |||
1579 | /* Max frame size. */ | ||
1580 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1581 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); | ||
1582 | eiter->len = __constant_cpu_to_be16(4 + 4); | ||
1583 | max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ? | ||
1584 | (uint32_t) icb24->frame_payload_size: | ||
1585 | (uint32_t) ha->init_cb->frame_payload_size; | ||
1586 | eiter->a.max_frame_size = cpu_to_be32(max_frame_size); | ||
1587 | size += 4 + 4; | ||
1588 | |||
1589 | DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, ha->host_no, | ||
1590 | eiter->a.max_frame_size)); | ||
1591 | |||
1592 | /* OS device name. */ | ||
1593 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1594 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); | ||
1595 | sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no); | ||
1596 | alen = strlen(eiter->a.os_dev_name); | ||
1597 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1598 | eiter->len = cpu_to_be16(4 + alen); | ||
1599 | size += 4 + alen; | ||
1600 | |||
1601 | DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no, | ||
1602 | eiter->a.os_dev_name)); | ||
1603 | |||
1604 | /* Update MS request size. */ | ||
1605 | qla2x00_update_ms_fdmi_iocb(ha, size + 16); | ||
1606 | |||
1607 | DEBUG13(printk("%s(%ld): RPA portname=" | ||
1608 | "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__, | ||
1609 | ha->host_no, ct_req->req.rpa.port_name[0], | ||
1610 | ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2], | ||
1611 | ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4], | ||
1612 | ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6], | ||
1613 | ct_req->req.rpa.port_name[7], size)); | ||
1614 | DEBUG13(qla2x00_dump_buffer(entries, size)); | ||
1615 | |||
1616 | /* Execute MS IOCB */ | ||
1617 | rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, | ||
1618 | sizeof(ms_iocb_entry_t)); | ||
1619 | if (rval != QLA_SUCCESS) { | ||
1620 | /*EMPTY*/ | ||
1621 | DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n", | ||
1622 | ha->host_no, rval)); | ||
1623 | } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RPA") != | ||
1624 | QLA_SUCCESS) { | ||
1625 | rval = QLA_FUNCTION_FAILED; | ||
1626 | } else { | ||
1627 | DEBUG2(printk("scsi(%ld): RPA exiting normally.\n", | ||
1628 | ha->host_no)); | ||
1629 | } | ||
1630 | |||
1631 | return rval; | ||
1632 | } | ||
1633 | |||
1634 | /** | ||
1635 | * qla2x00_fdmi_register() - | ||
1636 | * @ha: HA context | ||
1637 | * | ||
1638 | * Returns 0 on success. | ||
1639 | */ | ||
1640 | int | ||
1641 | qla2x00_fdmi_register(scsi_qla_host_t *ha) | ||
1642 | { | ||
1643 | int rval; | ||
1644 | |||
1645 | rval = qla2x00_mgmt_svr_login(ha); | ||
1646 | if (rval) | ||
1647 | return rval; | ||
1648 | |||
1649 | rval = qla2x00_fdmi_rhba(ha); | ||
1650 | if (rval) { | ||
1651 | if (rval != QLA_ALREADY_REGISTERED) | ||
1652 | return rval; | ||
1653 | |||
1654 | rval = qla2x00_fdmi_dhba(ha); | ||
1655 | if (rval) | ||
1656 | return rval; | ||
1657 | |||
1658 | rval = qla2x00_fdmi_rhba(ha); | ||
1659 | if (rval) | ||
1660 | return rval; | ||
1661 | } | ||
1662 | rval = qla2x00_fdmi_rpa(ha); | ||
1663 | |||
1664 | return rval; | ||
1665 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a6d2559217cd..c619583e646b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -88,6 +88,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
88 | ha->mbx_flags = 0; | 88 | ha->mbx_flags = 0; |
89 | ha->isp_abort_cnt = 0; | 89 | ha->isp_abort_cnt = 0; |
90 | ha->beacon_blink_led = 0; | 90 | ha->beacon_blink_led = 0; |
91 | set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); | ||
91 | 92 | ||
92 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); | 93 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); |
93 | rval = ha->isp_ops.pci_config(ha); | 94 | rval = ha->isp_ops.pci_config(ha); |
@@ -1563,7 +1564,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1563 | ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0); | 1564 | ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0); |
1564 | ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); | 1565 | ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); |
1565 | ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); | 1566 | ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); |
1566 | ha->flags.enable_led_scheme = ((nv->efi_parameters & BIT_3) ? 1 : 0); | 1567 | ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0; |
1567 | 1568 | ||
1568 | ha->operating_mode = | 1569 | ha->operating_mode = |
1569 | (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; | 1570 | (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; |
@@ -1697,6 +1698,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags) | |||
1697 | fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; | 1698 | fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; |
1698 | atomic_set(&fcport->state, FCS_UNCONFIGURED); | 1699 | atomic_set(&fcport->state, FCS_UNCONFIGURED); |
1699 | fcport->flags = FCF_RLC_SUPPORT; | 1700 | fcport->flags = FCF_RLC_SUPPORT; |
1701 | fcport->supported_classes = FC_COS_UNSPECIFIED; | ||
1700 | 1702 | ||
1701 | return (fcport); | 1703 | return (fcport); |
1702 | } | 1704 | } |
@@ -1898,7 +1900,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
1898 | continue; | 1900 | continue; |
1899 | 1901 | ||
1900 | /* Bypass if not same domain and area of adapter. */ | 1902 | /* Bypass if not same domain and area of adapter. */ |
1901 | if (area != ha->d_id.b.area || domain != ha->d_id.b.domain) | 1903 | if (area && domain && |
1904 | (area != ha->d_id.b.area || domain != ha->d_id.b.domain)) | ||
1902 | continue; | 1905 | continue; |
1903 | 1906 | ||
1904 | /* Bypass invalid local loop ID. */ | 1907 | /* Bypass invalid local loop ID. */ |
@@ -2075,6 +2078,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
2075 | return; | 2078 | return; |
2076 | } | 2079 | } |
2077 | rport->dd_data = fcport; | 2080 | rport->dd_data = fcport; |
2081 | rport->supported_classes = fcport->supported_classes; | ||
2078 | 2082 | ||
2079 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | 2083 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; |
2080 | if (fcport->port_type == FCT_INITIATOR) | 2084 | if (fcport->port_type == FCT_INITIATOR) |
@@ -2130,6 +2134,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2130 | return (QLA_SUCCESS); | 2134 | return (QLA_SUCCESS); |
2131 | } | 2135 | } |
2132 | do { | 2136 | do { |
2137 | /* FDMI support. */ | ||
2138 | if (ql2xfdmienable && | ||
2139 | test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags)) | ||
2140 | qla2x00_fdmi_register(ha); | ||
2141 | |||
2133 | /* Ensure we are logged into the SNS. */ | 2142 | /* Ensure we are logged into the SNS. */ |
2134 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) | 2143 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
2135 | loop_id = NPH_SNS; | 2144 | loop_id = NPH_SNS; |
@@ -2392,6 +2401,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2392 | if (new_fcport->d_id.b24 == ha->d_id.b24) | 2401 | if (new_fcport->d_id.b24 == ha->d_id.b24) |
2393 | continue; | 2402 | continue; |
2394 | 2403 | ||
2404 | /* Bypass if same domain and area of adapter. */ | ||
2405 | if (((new_fcport->d_id.b24 & 0xffff00) == | ||
2406 | (ha->d_id.b24 & 0xffff00)) && ha->current_topology == | ||
2407 | ISP_CFG_FL) | ||
2408 | continue; | ||
2409 | |||
2395 | /* Bypass reserved domain fields. */ | 2410 | /* Bypass reserved domain fields. */ |
2396 | if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0) | 2411 | if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0) |
2397 | continue; | 2412 | continue; |
@@ -2794,6 +2809,11 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
2794 | } | 2809 | } |
2795 | } | 2810 | } |
2796 | 2811 | ||
2812 | if (mb[10] & BIT_0) | ||
2813 | fcport->supported_classes |= FC_COS_CLASS2; | ||
2814 | if (mb[10] & BIT_1) | ||
2815 | fcport->supported_classes |= FC_COS_CLASS3; | ||
2816 | |||
2797 | rval = QLA_SUCCESS; | 2817 | rval = QLA_SUCCESS; |
2798 | break; | 2818 | break; |
2799 | } else if (mb[0] == MBS_LOOP_ID_USED) { | 2819 | } else if (mb[0] == MBS_LOOP_ID_USED) { |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index ebdc3c54d155..37f82e2cd7fb 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -810,12 +810,8 @@ qla24xx_start_scsi(srb_t *sp) | |||
810 | ha->req_q_cnt = ha->request_q_length - | 810 | ha->req_q_cnt = ha->request_q_length - |
811 | (ha->req_ring_index - cnt); | 811 | (ha->req_ring_index - cnt); |
812 | } | 812 | } |
813 | if (ha->req_q_cnt < (req_cnt + 2)) { | 813 | if (ha->req_q_cnt < (req_cnt + 2)) |
814 | if (cmd->use_sg) | ||
815 | pci_unmap_sg(ha->pdev, sg, cmd->use_sg, | ||
816 | cmd->sc_data_direction); | ||
817 | goto queuing_error; | 814 | goto queuing_error; |
818 | } | ||
819 | 815 | ||
820 | /* Build command packet. */ | 816 | /* Build command packet. */ |
821 | ha->current_outstanding_cmd = handle; | 817 | ha->current_outstanding_cmd = handle; |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f910de6dd437..c255bb0268a9 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -451,6 +451,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
451 | 451 | ||
452 | ha->flags.management_server_logged_in = 0; | 452 | ha->flags.management_server_logged_in = 0; |
453 | ha->link_data_rate = 0; | 453 | ha->link_data_rate = 0; |
454 | if (ql2xfdmienable) | ||
455 | set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); | ||
454 | 456 | ||
455 | /* Update AEN queue. */ | 457 | /* Update AEN queue. */ |
456 | qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL); | 458 | qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL); |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 409ea0ac4032..13e1c9047079 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "qla_def.h" | 19 | #include "qla_def.h" |
20 | 20 | ||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <scsi/scsi_transport_fc.h> | ||
22 | 23 | ||
23 | static void | 24 | static void |
24 | qla2x00_mbx_sem_timeout(unsigned long data) | 25 | qla2x00_mbx_sem_timeout(unsigned long data) |
@@ -251,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
251 | mb0 = RD_REG_WORD(®->isp24.mailbox0); | 252 | mb0 = RD_REG_WORD(®->isp24.mailbox0); |
252 | ictrl = RD_REG_DWORD(®->isp24.ictrl); | 253 | ictrl = RD_REG_DWORD(®->isp24.ictrl); |
253 | } else { | 254 | } else { |
254 | mb0 = RD_MAILBOX_REG(ha, reg->isp, 0); | 255 | mb0 = RD_MAILBOX_REG(ha, ®->isp, 0); |
255 | ictrl = RD_REG_WORD(®->isp.ictrl); | 256 | ictrl = RD_REG_WORD(®->isp.ictrl); |
256 | } | 257 | } |
257 | printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n", | 258 | printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n", |
@@ -983,58 +984,6 @@ qla2x00_abort_target(fc_port_t *fcport) | |||
983 | #endif | 984 | #endif |
984 | 985 | ||
985 | /* | 986 | /* |
986 | * qla2x00_target_reset | ||
987 | * Issue target reset mailbox command. | ||
988 | * | ||
989 | * Input: | ||
990 | * ha = adapter block pointer. | ||
991 | * TARGET_QUEUE_LOCK must be released. | ||
992 | * ADAPTER_STATE_LOCK must be released. | ||
993 | * | ||
994 | * Returns: | ||
995 | * qla2x00 local function return status code. | ||
996 | * | ||
997 | * Context: | ||
998 | * Kernel context. | ||
999 | */ | ||
1000 | int | ||
1001 | qla2x00_target_reset(scsi_qla_host_t *ha, struct fc_port *fcport) | ||
1002 | { | ||
1003 | int rval; | ||
1004 | mbx_cmd_t mc; | ||
1005 | mbx_cmd_t *mcp = &mc; | ||
1006 | |||
1007 | DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);) | ||
1008 | |||
1009 | if (atomic_read(&fcport->state) != FCS_ONLINE) | ||
1010 | return 0; | ||
1011 | |||
1012 | mcp->mb[0] = MBC_TARGET_RESET; | ||
1013 | if (HAS_EXTENDED_IDS(ha)) | ||
1014 | mcp->mb[1] = fcport->loop_id; | ||
1015 | else | ||
1016 | mcp->mb[1] = fcport->loop_id << 8; | ||
1017 | mcp->mb[2] = ha->loop_reset_delay; | ||
1018 | mcp->out_mb = MBX_2|MBX_1|MBX_0; | ||
1019 | mcp->in_mb = MBX_0; | ||
1020 | mcp->tov = 30; | ||
1021 | mcp->flags = 0; | ||
1022 | rval = qla2x00_mailbox_command(ha, mcp); | ||
1023 | |||
1024 | if (rval != QLA_SUCCESS) { | ||
1025 | /*EMPTY*/ | ||
1026 | DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n", | ||
1027 | ha->host_no, rval);) | ||
1028 | } else { | ||
1029 | /*EMPTY*/ | ||
1030 | DEBUG11(printk("qla2x00_target_reset(%ld): done.\n", | ||
1031 | ha->host_no);) | ||
1032 | } | ||
1033 | |||
1034 | return rval; | ||
1035 | } | ||
1036 | |||
1037 | /* | ||
1038 | * qla2x00_get_adapter_id | 987 | * qla2x00_get_adapter_id |
1039 | * Get adapter ID and topology. | 988 | * Get adapter ID and topology. |
1040 | * | 989 | * |
@@ -1326,6 +1275,10 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
1326 | fcport->port_type = FCT_INITIATOR; | 1275 | fcport->port_type = FCT_INITIATOR; |
1327 | else | 1276 | else |
1328 | fcport->port_type = FCT_TARGET; | 1277 | fcport->port_type = FCT_TARGET; |
1278 | |||
1279 | /* Passback COS information. */ | ||
1280 | fcport->supported_classes = (pd->options & BIT_4) ? | ||
1281 | FC_COS_CLASS2: FC_COS_CLASS3; | ||
1329 | } | 1282 | } |
1330 | 1283 | ||
1331 | gpd_error_out: | 1284 | gpd_error_out: |
@@ -1661,6 +1614,13 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1661 | mb[1] |= BIT_1; | 1614 | mb[1] |= BIT_1; |
1662 | } else | 1615 | } else |
1663 | mb[1] = BIT_0; | 1616 | mb[1] = BIT_0; |
1617 | |||
1618 | /* Passback COS information. */ | ||
1619 | mb[10] = 0; | ||
1620 | if (lg->io_parameter[7] || lg->io_parameter[8]) | ||
1621 | mb[10] |= BIT_0; /* Class 2. */ | ||
1622 | if (lg->io_parameter[9] || lg->io_parameter[10]) | ||
1623 | mb[10] |= BIT_1; /* Class 3. */ | ||
1664 | } | 1624 | } |
1665 | 1625 | ||
1666 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); | 1626 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); |
@@ -1723,6 +1683,8 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1723 | mb[2] = mcp->mb[2]; | 1683 | mb[2] = mcp->mb[2]; |
1724 | mb[6] = mcp->mb[6]; | 1684 | mb[6] = mcp->mb[6]; |
1725 | mb[7] = mcp->mb[7]; | 1685 | mb[7] = mcp->mb[7]; |
1686 | /* COS retrieved from Get-Port-Database mailbox command. */ | ||
1687 | mb[10] = 0; | ||
1726 | } | 1688 | } |
1727 | 1689 | ||
1728 | if (rval != QLA_SUCCESS) { | 1690 | if (rval != QLA_SUCCESS) { |
@@ -2465,3 +2427,32 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g, | |||
2465 | 2427 | ||
2466 | return rval; | 2428 | return rval; |
2467 | } | 2429 | } |
2430 | |||
2431 | int | ||
2432 | qla2x00_stop_firmware(scsi_qla_host_t *ha) | ||
2433 | { | ||
2434 | int rval; | ||
2435 | mbx_cmd_t mc; | ||
2436 | mbx_cmd_t *mcp = &mc; | ||
2437 | |||
2438 | if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) | ||
2439 | return QLA_FUNCTION_FAILED; | ||
2440 | |||
2441 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2442 | |||
2443 | mcp->mb[0] = MBC_STOP_FIRMWARE; | ||
2444 | mcp->out_mb = MBX_0; | ||
2445 | mcp->in_mb = MBX_0; | ||
2446 | mcp->tov = 5; | ||
2447 | mcp->flags = 0; | ||
2448 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2449 | |||
2450 | if (rval != QLA_SUCCESS) { | ||
2451 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | ||
2452 | ha->host_no, rval)); | ||
2453 | } else { | ||
2454 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2455 | } | ||
2456 | |||
2457 | return rval; | ||
2458 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9000659bfbcf..8982978c42fd 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -79,7 +79,7 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); | |||
79 | MODULE_PARM_DESC(ql2xloginretrycount, | 79 | MODULE_PARM_DESC(ql2xloginretrycount, |
80 | "Specify an alternate value for the NVRAM login retry count."); | 80 | "Specify an alternate value for the NVRAM login retry count."); |
81 | 81 | ||
82 | int ql2xfwloadbin; | 82 | int ql2xfwloadbin=1; |
83 | module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); | 83 | module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); |
84 | MODULE_PARM_DESC(ql2xfwloadbin, | 84 | MODULE_PARM_DESC(ql2xfwloadbin, |
85 | "Load ISP2xxx firmware image via hotplug."); | 85 | "Load ISP2xxx firmware image via hotplug."); |
@@ -88,6 +88,12 @@ static void qla2x00_free_device(scsi_qla_host_t *); | |||
88 | 88 | ||
89 | static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); | 89 | static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); |
90 | 90 | ||
91 | int ql2xfdmienable; | ||
92 | module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR); | ||
93 | MODULE_PARM_DESC(ql2xfdmienable, | ||
94 | "Enables FDMI registratons " | ||
95 | "Default is 0 - no FDMI. 1 - perfom FDMI."); | ||
96 | |||
91 | /* | 97 | /* |
92 | * SCSI host template entry points | 98 | * SCSI host template entry points |
93 | */ | 99 | */ |
@@ -105,6 +111,9 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *); | |||
105 | static int qla2x00_loop_reset(scsi_qla_host_t *ha); | 111 | static int qla2x00_loop_reset(scsi_qla_host_t *ha); |
106 | static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); | 112 | static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); |
107 | 113 | ||
114 | static int qla2x00_change_queue_depth(struct scsi_device *, int); | ||
115 | static int qla2x00_change_queue_type(struct scsi_device *, int); | ||
116 | |||
108 | static struct scsi_host_template qla2x00_driver_template = { | 117 | static struct scsi_host_template qla2x00_driver_template = { |
109 | .module = THIS_MODULE, | 118 | .module = THIS_MODULE, |
110 | .name = "qla2xxx", | 119 | .name = "qla2xxx", |
@@ -119,6 +128,8 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
119 | 128 | ||
120 | .slave_alloc = qla2xxx_slave_alloc, | 129 | .slave_alloc = qla2xxx_slave_alloc, |
121 | .slave_destroy = qla2xxx_slave_destroy, | 130 | .slave_destroy = qla2xxx_slave_destroy, |
131 | .change_queue_depth = qla2x00_change_queue_depth, | ||
132 | .change_queue_type = qla2x00_change_queue_type, | ||
122 | .this_id = -1, | 133 | .this_id = -1, |
123 | .cmd_per_lun = 3, | 134 | .cmd_per_lun = 3, |
124 | .use_clustering = ENABLE_CLUSTERING, | 135 | .use_clustering = ENABLE_CLUSTERING, |
@@ -129,6 +140,7 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
129 | * which equates to 0x800000 sectors. | 140 | * which equates to 0x800000 sectors. |
130 | */ | 141 | */ |
131 | .max_sectors = 0xFFFF, | 142 | .max_sectors = 0xFFFF, |
143 | .shost_attrs = qla2x00_host_attrs, | ||
132 | }; | 144 | }; |
133 | 145 | ||
134 | static struct scsi_host_template qla24xx_driver_template = { | 146 | static struct scsi_host_template qla24xx_driver_template = { |
@@ -145,12 +157,15 @@ static struct scsi_host_template qla24xx_driver_template = { | |||
145 | 157 | ||
146 | .slave_alloc = qla2xxx_slave_alloc, | 158 | .slave_alloc = qla2xxx_slave_alloc, |
147 | .slave_destroy = qla2xxx_slave_destroy, | 159 | .slave_destroy = qla2xxx_slave_destroy, |
160 | .change_queue_depth = qla2x00_change_queue_depth, | ||
161 | .change_queue_type = qla2x00_change_queue_type, | ||
148 | .this_id = -1, | 162 | .this_id = -1, |
149 | .cmd_per_lun = 3, | 163 | .cmd_per_lun = 3, |
150 | .use_clustering = ENABLE_CLUSTERING, | 164 | .use_clustering = ENABLE_CLUSTERING, |
151 | .sg_tablesize = SG_ALL, | 165 | .sg_tablesize = SG_ALL, |
152 | 166 | ||
153 | .max_sectors = 0xFFFF, | 167 | .max_sectors = 0xFFFF, |
168 | .shost_attrs = qla2x00_host_attrs, | ||
154 | }; | 169 | }; |
155 | 170 | ||
156 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; | 171 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; |
@@ -487,14 +502,13 @@ qc24_fail_command: | |||
487 | static int | 502 | static int |
488 | qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) | 503 | qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) |
489 | { | 504 | { |
490 | #define ABORT_POLLING_PERIOD HZ | 505 | #define ABORT_POLLING_PERIOD 1000 |
491 | #define ABORT_WAIT_ITER ((10 * HZ) / (ABORT_POLLING_PERIOD)) | 506 | #define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD)) |
492 | unsigned long wait_iter = ABORT_WAIT_ITER; | 507 | unsigned long wait_iter = ABORT_WAIT_ITER; |
493 | int ret = QLA_SUCCESS; | 508 | int ret = QLA_SUCCESS; |
494 | 509 | ||
495 | while (CMD_SP(cmd)) { | 510 | while (CMD_SP(cmd)) { |
496 | set_current_state(TASK_UNINTERRUPTIBLE); | 511 | msleep(ABORT_POLLING_PERIOD); |
497 | schedule_timeout(ABORT_POLLING_PERIOD); | ||
498 | 512 | ||
499 | if (--wait_iter) | 513 | if (--wait_iter) |
500 | break; | 514 | break; |
@@ -1016,7 +1030,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha) | |||
1016 | if (fcport->port_type != FCT_TARGET) | 1030 | if (fcport->port_type != FCT_TARGET) |
1017 | continue; | 1031 | continue; |
1018 | 1032 | ||
1019 | status = qla2x00_target_reset(ha, fcport); | 1033 | status = qla2x00_device_reset(ha, fcport); |
1020 | if (status != QLA_SUCCESS) | 1034 | if (status != QLA_SUCCESS) |
1021 | break; | 1035 | break; |
1022 | } | 1036 | } |
@@ -1103,6 +1117,28 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) | |||
1103 | sdev->hostdata = NULL; | 1117 | sdev->hostdata = NULL; |
1104 | } | 1118 | } |
1105 | 1119 | ||
1120 | static int | ||
1121 | qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth) | ||
1122 | { | ||
1123 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); | ||
1124 | return sdev->queue_depth; | ||
1125 | } | ||
1126 | |||
1127 | static int | ||
1128 | qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type) | ||
1129 | { | ||
1130 | if (sdev->tagged_supported) { | ||
1131 | scsi_set_tag_type(sdev, tag_type); | ||
1132 | if (tag_type) | ||
1133 | scsi_activate_tcq(sdev, sdev->queue_depth); | ||
1134 | else | ||
1135 | scsi_deactivate_tcq(sdev, sdev->queue_depth); | ||
1136 | } else | ||
1137 | tag_type = 0; | ||
1138 | |||
1139 | return tag_type; | ||
1140 | } | ||
1141 | |||
1106 | /** | 1142 | /** |
1107 | * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. | 1143 | * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. |
1108 | * @ha: HA context | 1144 | * @ha: HA context |
@@ -1113,36 +1149,23 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) | |||
1113 | static void | 1149 | static void |
1114 | qla2x00_config_dma_addressing(scsi_qla_host_t *ha) | 1150 | qla2x00_config_dma_addressing(scsi_qla_host_t *ha) |
1115 | { | 1151 | { |
1116 | /* Assume 32bit DMA address */ | 1152 | /* Assume a 32bit DMA mask. */ |
1117 | ha->flags.enable_64bit_addressing = 0; | 1153 | ha->flags.enable_64bit_addressing = 0; |
1118 | 1154 | ||
1119 | /* | 1155 | if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) { |
1120 | * Given the two variants pci_set_dma_mask(), allow the compiler to | 1156 | /* Any upper-dword bits set? */ |
1121 | * assist in setting the proper dma mask. | 1157 | if (MSD(dma_get_required_mask(&ha->pdev->dev)) && |
1122 | */ | 1158 | !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { |
1123 | if (sizeof(dma_addr_t) > 4) { | 1159 | /* Ok, a 64bit DMA mask is applicable. */ |
1124 | if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) { | ||
1125 | ha->flags.enable_64bit_addressing = 1; | 1160 | ha->flags.enable_64bit_addressing = 1; |
1126 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; | 1161 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; |
1127 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; | 1162 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; |
1128 | 1163 | return; | |
1129 | if (pci_set_consistent_dma_mask(ha->pdev, | ||
1130 | DMA_64BIT_MASK)) { | ||
1131 | qla_printk(KERN_DEBUG, ha, | ||
1132 | "Failed to set 64 bit PCI consistent mask; " | ||
1133 | "using 32 bit.\n"); | ||
1134 | pci_set_consistent_dma_mask(ha->pdev, | ||
1135 | DMA_32BIT_MASK); | ||
1136 | } | ||
1137 | } else { | ||
1138 | qla_printk(KERN_DEBUG, ha, | ||
1139 | "Failed to set 64 bit PCI DMA mask, falling back " | ||
1140 | "to 32 bit MASK.\n"); | ||
1141 | pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); | ||
1142 | } | 1164 | } |
1143 | } else { | ||
1144 | pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); | ||
1145 | } | 1165 | } |
1166 | |||
1167 | dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK); | ||
1168 | pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); | ||
1146 | } | 1169 | } |
1147 | 1170 | ||
1148 | static int | 1171 | static int |
@@ -1316,6 +1339,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1316 | ha->prev_topology = 0; | 1339 | ha->prev_topology = 0; |
1317 | ha->ports = MAX_BUSES; | 1340 | ha->ports = MAX_BUSES; |
1318 | ha->init_cb_size = sizeof(init_cb_t); | 1341 | ha->init_cb_size = sizeof(init_cb_t); |
1342 | ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; | ||
1319 | 1343 | ||
1320 | /* Assign ISP specific operations. */ | 1344 | /* Assign ISP specific operations. */ |
1321 | ha->isp_ops.pci_config = qla2100_pci_config; | 1345 | ha->isp_ops.pci_config = qla2100_pci_config; |
@@ -1338,6 +1362,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1338 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; | 1362 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; |
1339 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; | 1363 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; |
1340 | ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; | 1364 | ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; |
1365 | ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb; | ||
1341 | ha->isp_ops.read_nvram = qla2x00_read_nvram_data; | 1366 | ha->isp_ops.read_nvram = qla2x00_read_nvram_data; |
1342 | ha->isp_ops.write_nvram = qla2x00_write_nvram_data; | 1367 | ha->isp_ops.write_nvram = qla2x00_write_nvram_data; |
1343 | ha->isp_ops.fw_dump = qla2100_fw_dump; | 1368 | ha->isp_ops.fw_dump = qla2100_fw_dump; |
@@ -1375,6 +1400,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1375 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; | 1400 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; |
1376 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | 1401 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; |
1377 | ha->init_cb_size = sizeof(struct init_cb_24xx); | 1402 | ha->init_cb_size = sizeof(struct init_cb_24xx); |
1403 | ha->mgmt_svr_loop_id = 10; | ||
1378 | ha->isp_ops.pci_config = qla24xx_pci_config; | 1404 | ha->isp_ops.pci_config = qla24xx_pci_config; |
1379 | ha->isp_ops.reset_chip = qla24xx_reset_chip; | 1405 | ha->isp_ops.reset_chip = qla24xx_reset_chip; |
1380 | ha->isp_ops.chip_diag = qla24xx_chip_diag; | 1406 | ha->isp_ops.chip_diag = qla24xx_chip_diag; |
@@ -1395,6 +1421,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1395 | ha->isp_ops.fabric_login = qla24xx_login_fabric; | 1421 | ha->isp_ops.fabric_login = qla24xx_login_fabric; |
1396 | ha->isp_ops.fabric_logout = qla24xx_fabric_logout; | 1422 | ha->isp_ops.fabric_logout = qla24xx_fabric_logout; |
1397 | ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; | 1423 | ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; |
1424 | ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb; | ||
1398 | ha->isp_ops.read_nvram = qla24xx_read_nvram_data; | 1425 | ha->isp_ops.read_nvram = qla24xx_read_nvram_data; |
1399 | ha->isp_ops.write_nvram = qla24xx_write_nvram_data; | 1426 | ha->isp_ops.write_nvram = qla24xx_write_nvram_data; |
1400 | ha->isp_ops.fw_dump = qla24xx_fw_dump; | 1427 | ha->isp_ops.fw_dump = qla24xx_fw_dump; |
@@ -1558,8 +1585,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1558 | return 0; | 1585 | return 0; |
1559 | 1586 | ||
1560 | probe_failed: | 1587 | probe_failed: |
1561 | fc_remove_host(ha->host); | ||
1562 | |||
1563 | qla2x00_free_device(ha); | 1588 | qla2x00_free_device(ha); |
1564 | 1589 | ||
1565 | scsi_host_put(host); | 1590 | scsi_host_put(host); |
@@ -1601,10 +1626,6 @@ qla2x00_free_device(scsi_qla_host_t *ha) | |||
1601 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) | 1626 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) |
1602 | qla2x00_cancel_io_descriptors(ha); | 1627 | qla2x00_cancel_io_descriptors(ha); |
1603 | 1628 | ||
1604 | /* turn-off interrupts on the card */ | ||
1605 | if (ha->interrupts_on) | ||
1606 | ha->isp_ops.disable_intrs(ha); | ||
1607 | |||
1608 | /* Disable timer */ | 1629 | /* Disable timer */ |
1609 | if (ha->timer_active) | 1630 | if (ha->timer_active) |
1610 | qla2x00_stop_timer(ha); | 1631 | qla2x00_stop_timer(ha); |
@@ -1624,8 +1645,14 @@ qla2x00_free_device(scsi_qla_host_t *ha) | |||
1624 | } | 1645 | } |
1625 | } | 1646 | } |
1626 | 1647 | ||
1627 | qla2x00_mem_free(ha); | 1648 | /* Stop currently executing firmware. */ |
1649 | qla2x00_stop_firmware(ha); | ||
1650 | |||
1651 | /* turn-off interrupts on the card */ | ||
1652 | if (ha->interrupts_on) | ||
1653 | ha->isp_ops.disable_intrs(ha); | ||
1628 | 1654 | ||
1655 | qla2x00_mem_free(ha); | ||
1629 | 1656 | ||
1630 | ha->flags.online = 0; | 1657 | ha->flags.online = 0; |
1631 | 1658 | ||
@@ -1934,7 +1961,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
1934 | { | 1961 | { |
1935 | struct list_head *fcpl, *fcptemp; | 1962 | struct list_head *fcpl, *fcptemp; |
1936 | fc_port_t *fcport; | 1963 | fc_port_t *fcport; |
1937 | unsigned long wtime;/* max wait time if mbx cmd is busy. */ | 1964 | unsigned int wtime;/* max wait time if mbx cmd is busy. */ |
1938 | 1965 | ||
1939 | if (ha == NULL) { | 1966 | if (ha == NULL) { |
1940 | /* error */ | 1967 | /* error */ |
@@ -1943,11 +1970,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
1943 | } | 1970 | } |
1944 | 1971 | ||
1945 | /* Make sure all other threads are stopped. */ | 1972 | /* Make sure all other threads are stopped. */ |
1946 | wtime = 60 * HZ; | 1973 | wtime = 60 * 1000; |
1947 | while (ha->dpc_wait && wtime) { | 1974 | while (ha->dpc_wait && wtime) |
1948 | set_current_state(TASK_INTERRUPTIBLE); | 1975 | wtime = msleep_interruptible(wtime); |
1949 | wtime = schedule_timeout(wtime); | ||
1950 | } | ||
1951 | 1976 | ||
1952 | /* free ioctl memory */ | 1977 | /* free ioctl memory */ |
1953 | qla2x00_free_ioctl_mem(ha); | 1978 | qla2x00_free_ioctl_mem(ha); |
@@ -2478,15 +2503,15 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2478 | int | 2503 | int |
2479 | qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) | 2504 | qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) |
2480 | { | 2505 | { |
2481 | const unsigned int step = HZ/10; | 2506 | const unsigned int step = 100; /* msecs */ |
2507 | unsigned int iterations = jiffies_to_msecs(timeout)/100; | ||
2482 | 2508 | ||
2483 | do { | 2509 | do { |
2484 | if (!down_trylock(sema)) | 2510 | if (!down_trylock(sema)) |
2485 | return 0; | 2511 | return 0; |
2486 | set_current_state(TASK_INTERRUPTIBLE); | 2512 | if (msleep_interruptible(step)) |
2487 | if (schedule_timeout(step)) | ||
2488 | break; | 2513 | break; |
2489 | } while ((timeout -= step) > 0); | 2514 | } while (--iterations >= 0); |
2490 | 2515 | ||
2491 | return -ETIMEDOUT; | 2516 | return -ETIMEDOUT; |
2492 | } | 2517 | } |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index d7f5c608009c..c14abf743b7c 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -468,21 +468,12 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
468 | uint32_t dwords) | 468 | uint32_t dwords) |
469 | { | 469 | { |
470 | uint32_t i; | 470 | uint32_t i; |
471 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
472 | |||
473 | /* Pause RISC. */ | ||
474 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
475 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
476 | 471 | ||
477 | /* Dword reads to flash. */ | 472 | /* Dword reads to flash. */ |
478 | for (i = 0; i < dwords; i++, faddr++) | 473 | for (i = 0; i < dwords; i++, faddr++) |
479 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 474 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
480 | flash_data_to_access_addr(faddr))); | 475 | flash_data_to_access_addr(faddr))); |
481 | 476 | ||
482 | /* Release RISC pause. */ | ||
483 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
484 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
485 | |||
486 | return dwptr; | 477 | return dwptr; |
487 | } | 478 | } |
488 | 479 | ||
@@ -532,10 +523,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
532 | 523 | ||
533 | ret = QLA_SUCCESS; | 524 | ret = QLA_SUCCESS; |
534 | 525 | ||
535 | /* Pause RISC. */ | ||
536 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
537 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
538 | |||
539 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); | 526 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); |
540 | DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, | 527 | DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, |
541 | ha->host_no, man_id, flash_id)); | 528 | ha->host_no, man_id, flash_id)); |
@@ -599,10 +586,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
599 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 586 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
600 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 587 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
601 | 588 | ||
602 | /* Release RISC pause. */ | ||
603 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
604 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
605 | |||
606 | return ret; | 589 | return ret; |
607 | } | 590 | } |
608 | 591 | ||
@@ -630,11 +613,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
630 | { | 613 | { |
631 | uint32_t i; | 614 | uint32_t i; |
632 | uint32_t *dwptr; | 615 | uint32_t *dwptr; |
633 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
634 | |||
635 | /* Pause RISC. */ | ||
636 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
637 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
638 | 616 | ||
639 | /* Dword reads to flash. */ | 617 | /* Dword reads to flash. */ |
640 | dwptr = (uint32_t *)buf; | 618 | dwptr = (uint32_t *)buf; |
@@ -642,10 +620,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
642 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 620 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
643 | nvram_data_to_access_addr(naddr))); | 621 | nvram_data_to_access_addr(naddr))); |
644 | 622 | ||
645 | /* Release RISC pause. */ | ||
646 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
647 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
648 | |||
649 | return buf; | 623 | return buf; |
650 | } | 624 | } |
651 | 625 | ||
@@ -690,10 +664,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
690 | 664 | ||
691 | ret = QLA_SUCCESS; | 665 | ret = QLA_SUCCESS; |
692 | 666 | ||
693 | /* Pause RISC. */ | ||
694 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
695 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
696 | |||
697 | /* Enable flash write. */ | 667 | /* Enable flash write. */ |
698 | WRT_REG_DWORD(®->ctrl_status, | 668 | WRT_REG_DWORD(®->ctrl_status, |
699 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); | 669 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); |
@@ -728,9 +698,5 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
728 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 698 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
729 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 699 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
730 | 700 | ||
731 | /* Release RISC pause. */ | ||
732 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
733 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
734 | |||
735 | return ret; | 701 | return ret; |
736 | } | 702 | } |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e3cd3618bc54..eae7d6edd531 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -19,9 +19,9 @@ | |||
19 | /* | 19 | /* |
20 | * Driver version | 20 | * Driver version |
21 | */ | 21 | */ |
22 | #define QLA2XXX_VERSION "8.01.00b5-k" | 22 | #define QLA2XXX_VERSION "8.01.00-k" |
23 | 23 | ||
24 | #define QLA_DRIVER_MAJOR_VER 8 | 24 | #define QLA_DRIVER_MAJOR_VER 8 |
25 | #define QLA_DRIVER_MINOR_VER 1 | 25 | #define QLA_DRIVER_MINOR_VER 1 |
26 | #define QLA_DRIVER_PATCH_VER 0 | 26 | #define QLA_DRIVER_PATCH_VER 0 |
27 | #define QLA_DRIVER_BETA_VER 5 | 27 | #define QLA_DRIVER_BETA_VER 0 |
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c new file mode 100644 index 000000000000..f1ea5027865f --- /dev/null +++ b/drivers/scsi/raid_class.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * RAID Attributes | ||
3 | */ | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/list.h> | ||
7 | #include <linux/raid_class.h> | ||
8 | #include <scsi/scsi_device.h> | ||
9 | #include <scsi/scsi_host.h> | ||
10 | |||
11 | #define RAID_NUM_ATTRS 3 | ||
12 | |||
13 | struct raid_internal { | ||
14 | struct raid_template r; | ||
15 | struct raid_function_template *f; | ||
16 | /* The actual attributes */ | ||
17 | struct class_device_attribute private_attrs[RAID_NUM_ATTRS]; | ||
18 | /* The array of null terminated pointers to attributes | ||
19 | * needed by scsi_sysfs.c */ | ||
20 | struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1]; | ||
21 | }; | ||
22 | |||
23 | struct raid_component { | ||
24 | struct list_head node; | ||
25 | struct device *dev; | ||
26 | int num; | ||
27 | }; | ||
28 | |||
29 | #define to_raid_internal(tmpl) container_of(tmpl, struct raid_internal, r) | ||
30 | |||
31 | #define tc_to_raid_internal(tcont) ({ \ | ||
32 | struct raid_template *r = \ | ||
33 | container_of(tcont, struct raid_template, raid_attrs); \ | ||
34 | to_raid_internal(r); \ | ||
35 | }) | ||
36 | |||
37 | #define ac_to_raid_internal(acont) ({ \ | ||
38 | struct transport_container *tc = \ | ||
39 | container_of(acont, struct transport_container, ac); \ | ||
40 | tc_to_raid_internal(tc); \ | ||
41 | }) | ||
42 | |||
43 | #define class_device_to_raid_internal(cdev) ({ \ | ||
44 | struct attribute_container *ac = \ | ||
45 | attribute_container_classdev_to_container(cdev); \ | ||
46 | ac_to_raid_internal(ac); \ | ||
47 | }) | ||
48 | |||
49 | |||
50 | static int raid_match(struct attribute_container *cont, struct device *dev) | ||
51 | { | ||
52 | /* We have to look for every subsystem that could house | ||
53 | * emulated RAID devices, so start with SCSI */ | ||
54 | struct raid_internal *i = ac_to_raid_internal(cont); | ||
55 | |||
56 | if (scsi_is_sdev_device(dev)) { | ||
57 | struct scsi_device *sdev = to_scsi_device(dev); | ||
58 | |||
59 | if (i->f->cookie != sdev->host->hostt) | ||
60 | return 0; | ||
61 | |||
62 | return i->f->is_raid(dev); | ||
63 | } | ||
64 | /* FIXME: look at other subsystems too */ | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int raid_setup(struct transport_container *tc, struct device *dev, | ||
69 | struct class_device *cdev) | ||
70 | { | ||
71 | struct raid_data *rd; | ||
72 | |||
73 | BUG_ON(class_get_devdata(cdev)); | ||
74 | |||
75 | rd = kmalloc(sizeof(*rd), GFP_KERNEL); | ||
76 | if (!rd) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | memset(rd, 0, sizeof(*rd)); | ||
80 | INIT_LIST_HEAD(&rd->component_list); | ||
81 | class_set_devdata(cdev, rd); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int raid_remove(struct transport_container *tc, struct device *dev, | ||
87 | struct class_device *cdev) | ||
88 | { | ||
89 | struct raid_data *rd = class_get_devdata(cdev); | ||
90 | struct raid_component *rc, *next; | ||
91 | class_set_devdata(cdev, NULL); | ||
92 | list_for_each_entry_safe(rc, next, &rd->component_list, node) { | ||
93 | char buf[40]; | ||
94 | snprintf(buf, sizeof(buf), "component-%d", rc->num); | ||
95 | list_del(&rc->node); | ||
96 | sysfs_remove_link(&cdev->kobj, buf); | ||
97 | kfree(rc); | ||
98 | } | ||
99 | kfree(class_get_devdata(cdev)); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static DECLARE_TRANSPORT_CLASS(raid_class, | ||
104 | "raid_devices", | ||
105 | raid_setup, | ||
106 | raid_remove, | ||
107 | NULL); | ||
108 | |||
109 | static struct { | ||
110 | enum raid_state value; | ||
111 | char *name; | ||
112 | } raid_states[] = { | ||
113 | { RAID_ACTIVE, "active" }, | ||
114 | { RAID_DEGRADED, "degraded" }, | ||
115 | { RAID_RESYNCING, "resyncing" }, | ||
116 | { RAID_OFFLINE, "offline" }, | ||
117 | }; | ||
118 | |||
119 | static const char *raid_state_name(enum raid_state state) | ||
120 | { | ||
121 | int i; | ||
122 | char *name = NULL; | ||
123 | |||
124 | for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) { | ||
125 | if (raid_states[i].value == state) { | ||
126 | name = raid_states[i].name; | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | return name; | ||
131 | } | ||
132 | |||
133 | |||
134 | #define raid_attr_show_internal(attr, fmt, var, code) \ | ||
135 | static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \ | ||
136 | { \ | ||
137 | struct raid_data *rd = class_get_devdata(cdev); \ | ||
138 | code \ | ||
139 | return snprintf(buf, 20, #fmt "\n", var); \ | ||
140 | } | ||
141 | |||
142 | #define raid_attr_ro_states(attr, states, code) \ | ||
143 | raid_attr_show_internal(attr, %s, name, \ | ||
144 | const char *name; \ | ||
145 | code \ | ||
146 | name = raid_##states##_name(rd->attr); \ | ||
147 | ) \ | ||
148 | static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL) | ||
149 | |||
150 | |||
151 | #define raid_attr_ro_internal(attr, code) \ | ||
152 | raid_attr_show_internal(attr, %d, rd->attr, code) \ | ||
153 | static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL) | ||
154 | |||
155 | #define ATTR_CODE(attr) \ | ||
156 | struct raid_internal *i = class_device_to_raid_internal(cdev); \ | ||
157 | if (i->f->get_##attr) \ | ||
158 | i->f->get_##attr(cdev->dev); | ||
159 | |||
160 | #define raid_attr_ro(attr) raid_attr_ro_internal(attr, ) | ||
161 | #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr)) | ||
162 | #define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr)) | ||
163 | |||
164 | raid_attr_ro(level); | ||
165 | raid_attr_ro_fn(resync); | ||
166 | raid_attr_ro_state(state); | ||
167 | |||
168 | void raid_component_add(struct raid_template *r,struct device *raid_dev, | ||
169 | struct device *component_dev) | ||
170 | { | ||
171 | struct class_device *cdev = | ||
172 | attribute_container_find_class_device(&r->raid_attrs.ac, | ||
173 | raid_dev); | ||
174 | struct raid_component *rc; | ||
175 | struct raid_data *rd = class_get_devdata(cdev); | ||
176 | char buf[40]; | ||
177 | |||
178 | rc = kmalloc(sizeof(*rc), GFP_KERNEL); | ||
179 | if (!rc) | ||
180 | return; | ||
181 | |||
182 | INIT_LIST_HEAD(&rc->node); | ||
183 | rc->dev = component_dev; | ||
184 | rc->num = rd->component_count++; | ||
185 | |||
186 | snprintf(buf, sizeof(buf), "component-%d", rc->num); | ||
187 | list_add_tail(&rc->node, &rd->component_list); | ||
188 | sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf); | ||
189 | } | ||
190 | EXPORT_SYMBOL(raid_component_add); | ||
191 | |||
192 | struct raid_template * | ||
193 | raid_class_attach(struct raid_function_template *ft) | ||
194 | { | ||
195 | struct raid_internal *i = kmalloc(sizeof(struct raid_internal), | ||
196 | GFP_KERNEL); | ||
197 | int count = 0; | ||
198 | |||
199 | if (unlikely(!i)) | ||
200 | return NULL; | ||
201 | |||
202 | memset(i, 0, sizeof(*i)); | ||
203 | |||
204 | i->f = ft; | ||
205 | |||
206 | i->r.raid_attrs.ac.class = &raid_class.class; | ||
207 | i->r.raid_attrs.ac.match = raid_match; | ||
208 | i->r.raid_attrs.ac.attrs = &i->attrs[0]; | ||
209 | |||
210 | attribute_container_register(&i->r.raid_attrs.ac); | ||
211 | |||
212 | i->attrs[count++] = &class_device_attr_level; | ||
213 | i->attrs[count++] = &class_device_attr_resync; | ||
214 | i->attrs[count++] = &class_device_attr_state; | ||
215 | |||
216 | i->attrs[count] = NULL; | ||
217 | BUG_ON(count > RAID_NUM_ATTRS); | ||
218 | |||
219 | return &i->r; | ||
220 | } | ||
221 | EXPORT_SYMBOL(raid_class_attach); | ||
222 | |||
223 | void | ||
224 | raid_class_release(struct raid_template *r) | ||
225 | { | ||
226 | struct raid_internal *i = to_raid_internal(r); | ||
227 | |||
228 | attribute_container_unregister(&i->r.raid_attrs.ac); | ||
229 | |||
230 | kfree(i); | ||
231 | } | ||
232 | EXPORT_SYMBOL(raid_class_release); | ||
233 | |||
234 | static __init int raid_init(void) | ||
235 | { | ||
236 | return transport_class_register(&raid_class); | ||
237 | } | ||
238 | |||
239 | static __exit void raid_exit(void) | ||
240 | { | ||
241 | transport_class_unregister(&raid_class); | ||
242 | } | ||
243 | |||
244 | MODULE_AUTHOR("James Bottomley"); | ||
245 | MODULE_DESCRIPTION("RAID device class"); | ||
246 | MODULE_LICENSE("GPL"); | ||
247 | |||
248 | module_init(raid_init); | ||
249 | module_exit(raid_exit); | ||
250 | |||
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..07b554affcf2 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 */ |
@@ -191,6 +192,7 @@ static struct { | |||
191 | {"SGI", "RAID5", "*", BLIST_SPARSELUN}, | 192 | {"SGI", "RAID5", "*", BLIST_SPARSELUN}, |
192 | {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, | 193 | {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, |
193 | {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, | 194 | {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, |
195 | {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, | ||
194 | {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, | 196 | {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, |
195 | {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, | 197 | {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, |
196 | {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ | 198 | {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 0fc8b48f052b..895c9452be4c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/kthread.h> | ||
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
24 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
@@ -75,7 +76,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
75 | 76 | ||
76 | scmd->eh_eflags |= eh_flag; | 77 | scmd->eh_eflags |= eh_flag; |
77 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); | 78 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); |
78 | set_bit(SHOST_RECOVERY, &shost->shost_state); | 79 | scsi_host_set_state(shost, SHOST_RECOVERY); |
79 | shost->host_failed++; | 80 | shost->host_failed++; |
80 | scsi_eh_wakeup(shost); | 81 | scsi_eh_wakeup(shost); |
81 | spin_unlock_irqrestore(shost->host_lock, flags); | 82 | spin_unlock_irqrestore(shost->host_lock, flags); |
@@ -115,7 +116,6 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, | |||
115 | 116 | ||
116 | add_timer(&scmd->eh_timeout); | 117 | add_timer(&scmd->eh_timeout); |
117 | } | 118 | } |
118 | EXPORT_SYMBOL(scsi_add_timer); | ||
119 | 119 | ||
120 | /** | 120 | /** |
121 | * scsi_delete_timer - Delete/cancel timer for a given function. | 121 | * scsi_delete_timer - Delete/cancel timer for a given function. |
@@ -143,7 +143,6 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) | |||
143 | 143 | ||
144 | return rtn; | 144 | return rtn; |
145 | } | 145 | } |
146 | EXPORT_SYMBOL(scsi_delete_timer); | ||
147 | 146 | ||
148 | /** | 147 | /** |
149 | * scsi_times_out - Timeout function for normal scsi commands. | 148 | * scsi_times_out - Timeout function for normal scsi commands. |
@@ -197,7 +196,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) | |||
197 | { | 196 | { |
198 | int online; | 197 | int online; |
199 | 198 | ||
200 | wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state))); | 199 | wait_event(sdev->host->host_wait, (sdev->host->shost_state != |
200 | SHOST_RECOVERY)); | ||
201 | 201 | ||
202 | online = scsi_device_online(sdev); | 202 | online = scsi_device_online(sdev); |
203 | 203 | ||
@@ -775,9 +775,11 @@ retry_tur: | |||
775 | __FUNCTION__, scmd, rtn)); | 775 | __FUNCTION__, scmd, rtn)); |
776 | if (rtn == SUCCESS) | 776 | if (rtn == SUCCESS) |
777 | return 0; | 777 | return 0; |
778 | else if (rtn == NEEDS_RETRY) | 778 | else if (rtn == NEEDS_RETRY) { |
779 | if (retry_cnt--) | 779 | if (retry_cnt--) |
780 | goto retry_tur; | 780 | goto retry_tur; |
781 | return 0; | ||
782 | } | ||
781 | return 1; | 783 | return 1; |
782 | } | 784 | } |
783 | 785 | ||
@@ -1458,7 +1460,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1458 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", | 1460 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", |
1459 | __FUNCTION__)); | 1461 | __FUNCTION__)); |
1460 | 1462 | ||
1461 | clear_bit(SHOST_RECOVERY, &shost->shost_state); | 1463 | scsi_host_set_state(shost, SHOST_RUNNING); |
1462 | 1464 | ||
1463 | wake_up(&shost->host_wait); | 1465 | wake_up(&shost->host_wait); |
1464 | 1466 | ||
@@ -1582,16 +1584,8 @@ int scsi_error_handler(void *data) | |||
1582 | int rtn; | 1584 | int rtn; |
1583 | DECLARE_MUTEX_LOCKED(sem); | 1585 | DECLARE_MUTEX_LOCKED(sem); |
1584 | 1586 | ||
1585 | /* | ||
1586 | * Flush resources | ||
1587 | */ | ||
1588 | |||
1589 | daemonize("scsi_eh_%d", shost->host_no); | ||
1590 | |||
1591 | current->flags |= PF_NOFREEZE; | 1587 | current->flags |= PF_NOFREEZE; |
1592 | |||
1593 | shost->eh_wait = &sem; | 1588 | shost->eh_wait = &sem; |
1594 | shost->ehandler = current; | ||
1595 | 1589 | ||
1596 | /* | 1590 | /* |
1597 | * Wake up the thread that created us. | 1591 | * Wake up the thread that created us. |
@@ -1599,8 +1593,6 @@ int scsi_error_handler(void *data) | |||
1599 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" | 1593 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" |
1600 | " scsi_eh_%d\n",shost->host_no)); | 1594 | " scsi_eh_%d\n",shost->host_no)); |
1601 | 1595 | ||
1602 | complete(shost->eh_notify); | ||
1603 | |||
1604 | while (1) { | 1596 | while (1) { |
1605 | /* | 1597 | /* |
1606 | * If we get a signal, it means we are supposed to go | 1598 | * If we get a signal, it means we are supposed to go |
@@ -1621,7 +1613,7 @@ int scsi_error_handler(void *data) | |||
1621 | * semaphores isn't unreasonable. | 1613 | * semaphores isn't unreasonable. |
1622 | */ | 1614 | */ |
1623 | down_interruptible(&sem); | 1615 | down_interruptible(&sem); |
1624 | if (shost->eh_kill) | 1616 | if (kthread_should_stop()) |
1625 | break; | 1617 | break; |
1626 | 1618 | ||
1627 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
@@ -1660,22 +1652,6 @@ int scsi_error_handler(void *data) | |||
1660 | * Make sure that nobody tries to wake us up again. | 1652 | * Make sure that nobody tries to wake us up again. |
1661 | */ | 1653 | */ |
1662 | shost->eh_wait = NULL; | 1654 | shost->eh_wait = NULL; |
1663 | |||
1664 | /* | ||
1665 | * Knock this down too. From this point on, the host is flying | ||
1666 | * without a pilot. If this is because the module is being unloaded, | ||
1667 | * that's fine. If the user sent a signal to this thing, we are | ||
1668 | * potentially in real danger. | ||
1669 | */ | ||
1670 | shost->eh_active = 0; | ||
1671 | shost->ehandler = NULL; | ||
1672 | |||
1673 | /* | ||
1674 | * If anyone is waiting for us to exit (i.e. someone trying to unload | ||
1675 | * a driver), then wake up that process to let them know we are on | ||
1676 | * the way out the door. | ||
1677 | */ | ||
1678 | complete_and_exit(shost->eh_notify, 0); | ||
1679 | return 0; | 1655 | return 0; |
1680 | } | 1656 | } |
1681 | 1657 | ||
@@ -1846,12 +1822,16 @@ EXPORT_SYMBOL(scsi_reset_provider); | |||
1846 | int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, | 1822 | int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, |
1847 | struct scsi_sense_hdr *sshdr) | 1823 | struct scsi_sense_hdr *sshdr) |
1848 | { | 1824 | { |
1849 | if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70) | 1825 | if (!sense_buffer || !sb_len) |
1850 | return 0; | 1826 | return 0; |
1851 | 1827 | ||
1852 | memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); | 1828 | memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); |
1853 | 1829 | ||
1854 | sshdr->response_code = (sense_buffer[0] & 0x7f); | 1830 | sshdr->response_code = (sense_buffer[0] & 0x7f); |
1831 | |||
1832 | if (!scsi_sense_valid(sshdr)) | ||
1833 | return 0; | ||
1834 | |||
1855 | if (sshdr->response_code >= 0x72) { | 1835 | if (sshdr->response_code >= 0x72) { |
1856 | /* | 1836 | /* |
1857 | * descriptor format | 1837 | * descriptor format |
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 7a6b530115ac..b7fddac81347 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -30,20 +30,20 @@ | |||
30 | 30 | ||
31 | #define MAX_BUF PAGE_SIZE | 31 | #define MAX_BUF PAGE_SIZE |
32 | 32 | ||
33 | /* | 33 | /** |
34 | * If we are told to probe a host, we will return 0 if the host is not | 34 | * ioctl_probe -- return host identification |
35 | * present, 1 if the host is present, and will return an identifying | 35 | * @host: host to identify |
36 | * string at *arg, if arg is non null, filling to the length stored at | 36 | * @buffer: userspace buffer for identification |
37 | * (int *) arg | 37 | * |
38 | * Return an identifying string at @buffer, if @buffer is non-NULL, filling | ||
39 | * to the length stored at * (int *) @buffer. | ||
38 | */ | 40 | */ |
39 | |||
40 | static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) | 41 | static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) |
41 | { | 42 | { |
42 | unsigned int len, slen; | 43 | unsigned int len, slen; |
43 | const char *string; | 44 | const char *string; |
44 | int temp = host->hostt->present; | ||
45 | 45 | ||
46 | if (temp && buffer) { | 46 | if (buffer) { |
47 | if (get_user(len, (unsigned int __user *) buffer)) | 47 | if (get_user(len, (unsigned int __user *) buffer)) |
48 | return -EFAULT; | 48 | return -EFAULT; |
49 | 49 | ||
@@ -59,7 +59,7 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) | |||
59 | return -EFAULT; | 59 | return -EFAULT; |
60 | } | 60 | } |
61 | } | 61 | } |
62 | return temp; | 62 | return 1; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* | 65 | /* |
@@ -88,25 +88,18 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) | |||
88 | static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, | 88 | static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, |
89 | int timeout, int retries) | 89 | int timeout, int retries) |
90 | { | 90 | { |
91 | struct scsi_request *sreq; | ||
92 | int result; | 91 | int result; |
93 | struct scsi_sense_hdr sshdr; | 92 | struct scsi_sense_hdr sshdr; |
94 | 93 | ||
95 | SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); | 94 | SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); |
96 | 95 | ||
97 | sreq = scsi_allocate_request(sdev, GFP_KERNEL); | 96 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, |
98 | if (!sreq) { | 97 | &sshdr, timeout, retries); |
99 | printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n"); | ||
100 | return -ENOMEM; | ||
101 | } | ||
102 | |||
103 | sreq->sr_data_direction = DMA_NONE; | ||
104 | scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); | ||
105 | 98 | ||
106 | SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); | 99 | SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); |
107 | 100 | ||
108 | if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && | 101 | if ((driver_byte(result) & DRIVER_SENSE) && |
109 | (scsi_request_normalize_sense(sreq, &sshdr))) { | 102 | (scsi_sense_valid(&sshdr))) { |
110 | switch (sshdr.sense_key) { | 103 | switch (sshdr.sense_key) { |
111 | case ILLEGAL_REQUEST: | 104 | case ILLEGAL_REQUEST: |
112 | if (cmd[0] == ALLOW_MEDIUM_REMOVAL) | 105 | if (cmd[0] == ALLOW_MEDIUM_REMOVAL) |
@@ -125,7 +118,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, | |||
125 | case UNIT_ATTENTION: | 118 | case UNIT_ATTENTION: |
126 | if (sdev->removable) { | 119 | if (sdev->removable) { |
127 | sdev->changed = 1; | 120 | sdev->changed = 1; |
128 | sreq->sr_result = 0; /* This is no longer considered an error */ | 121 | result = 0; /* This is no longer considered an error */ |
129 | break; | 122 | break; |
130 | } | 123 | } |
131 | default: /* Fall through for non-removable media */ | 124 | default: /* Fall through for non-removable media */ |
@@ -135,15 +128,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, | |||
135 | sdev->channel, | 128 | sdev->channel, |
136 | sdev->id, | 129 | sdev->id, |
137 | sdev->lun, | 130 | sdev->lun, |
138 | sreq->sr_result); | 131 | result); |
139 | scsi_print_req_sense(" ", sreq); | 132 | scsi_print_sense_hdr(" ", &sshdr); |
140 | break; | 133 | break; |
141 | } | 134 | } |
142 | } | 135 | } |
143 | 136 | ||
144 | result = sreq->sr_result; | ||
145 | SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); | 137 | SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); |
146 | scsi_release_request(sreq); | ||
147 | return result; | 138 | return result; |
148 | } | 139 | } |
149 | 140 | ||
@@ -208,8 +199,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, | |||
208 | { | 199 | { |
209 | char *buf; | 200 | char *buf; |
210 | unsigned char cmd[MAX_COMMAND_SIZE]; | 201 | unsigned char cmd[MAX_COMMAND_SIZE]; |
202 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | ||
211 | char __user *cmd_in; | 203 | char __user *cmd_in; |
212 | struct scsi_request *sreq; | ||
213 | unsigned char opcode; | 204 | unsigned char opcode; |
214 | unsigned int inlen, outlen, cmdlen; | 205 | unsigned int inlen, outlen, cmdlen; |
215 | unsigned int needed, buf_needed; | 206 | unsigned int needed, buf_needed; |
@@ -321,31 +312,23 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, | |||
321 | break; | 312 | break; |
322 | } | 313 | } |
323 | 314 | ||
324 | sreq = scsi_allocate_request(sdev, GFP_KERNEL); | 315 | result = scsi_execute(sdev, cmd, data_direction, buf, needed, |
325 | if (!sreq) { | 316 | sense, timeout, retries, 0); |
326 | result = -EINTR; | ||
327 | goto error; | ||
328 | } | ||
329 | |||
330 | sreq->sr_data_direction = data_direction; | ||
331 | scsi_wait_req(sreq, cmd, buf, needed, timeout, retries); | ||
332 | 317 | ||
333 | /* | 318 | /* |
334 | * If there was an error condition, pass the info back to the user. | 319 | * If there was an error condition, pass the info back to the user. |
335 | */ | 320 | */ |
336 | result = sreq->sr_result; | ||
337 | if (result) { | 321 | if (result) { |
338 | int sb_len = sizeof(sreq->sr_sense_buffer); | 322 | int sb_len = sizeof(*sense); |
339 | 323 | ||
340 | sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; | 324 | sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; |
341 | if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len)) | 325 | if (copy_to_user(cmd_in, sense, sb_len)) |
342 | result = -EFAULT; | 326 | result = -EFAULT; |
343 | } else { | 327 | } else { |
344 | if (copy_to_user(cmd_in, buf, outlen)) | 328 | if (copy_to_user(cmd_in, buf, outlen)) |
345 | result = -EFAULT; | 329 | result = -EFAULT; |
346 | } | 330 | } |
347 | 331 | ||
348 | scsi_release_request(sreq); | ||
349 | error: | 332 | error: |
350 | kfree(buf); | 333 | kfree(buf); |
351 | return result; | 334 | return result; |
@@ -475,8 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | |||
475 | * error processing, as long as the device was opened | 458 | * error processing, as long as the device was opened |
476 | * non-blocking */ | 459 | * non-blocking */ |
477 | if (filp && filp->f_flags & O_NONBLOCK) { | 460 | if (filp && filp->f_flags & O_NONBLOCK) { |
478 | if (test_bit(SHOST_RECOVERY, | 461 | if (sdev->host->shost_state == SHOST_RECOVERY) |
479 | &sdev->host->shost_state)) | ||
480 | return -ENODEV; | 462 | return -ENODEV; |
481 | } else if (!scsi_block_when_processing_errors(sdev)) | 463 | } else if (!scsi_block_when_processing_errors(sdev)) |
482 | return -ENODEV; | 464 | return -ENODEV; |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7a91ca3d32a6..77f2d444f7e0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -232,23 +232,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd, | |||
232 | } | 232 | } |
233 | EXPORT_SYMBOL(scsi_do_req); | 233 | EXPORT_SYMBOL(scsi_do_req); |
234 | 234 | ||
235 | static void scsi_wait_done(struct scsi_cmnd *cmd) | ||
236 | { | ||
237 | struct request *req = cmd->request; | ||
238 | struct request_queue *q = cmd->device->request_queue; | ||
239 | unsigned long flags; | ||
240 | |||
241 | req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ | ||
242 | |||
243 | spin_lock_irqsave(q->queue_lock, flags); | ||
244 | if (blk_rq_tagged(req)) | ||
245 | blk_queue_end_tag(q, req); | ||
246 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
247 | |||
248 | if (req->waiting) | ||
249 | complete(req->waiting); | ||
250 | } | ||
251 | |||
252 | /* This is the end routine we get to if a command was never attached | 235 | /* This is the end routine we get to if a command was never attached |
253 | * to the request. Simply complete the request without changing | 236 | * to the request. Simply complete the request without changing |
254 | * rq_status; this will cause a DRIVER_ERROR. */ | 237 | * rq_status; this will cause a DRIVER_ERROR. */ |
@@ -263,21 +246,114 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, | |||
263 | unsigned bufflen, int timeout, int retries) | 246 | unsigned bufflen, int timeout, int retries) |
264 | { | 247 | { |
265 | DECLARE_COMPLETION(wait); | 248 | DECLARE_COMPLETION(wait); |
266 | 249 | int write = (sreq->sr_data_direction == DMA_TO_DEVICE); | |
267 | sreq->sr_request->waiting = &wait; | 250 | struct request *req; |
268 | sreq->sr_request->rq_status = RQ_SCSI_BUSY; | 251 | |
269 | sreq->sr_request->end_io = scsi_wait_req_end_io; | 252 | req = blk_get_request(sreq->sr_device->request_queue, write, |
270 | scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done, | 253 | __GFP_WAIT); |
271 | timeout, retries); | 254 | if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req, |
255 | buffer, bufflen, __GFP_WAIT)) { | ||
256 | sreq->sr_result = DRIVER_ERROR << 24; | ||
257 | blk_put_request(req); | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | req->flags |= REQ_NOMERGE; | ||
262 | req->waiting = &wait; | ||
263 | req->end_io = scsi_wait_req_end_io; | ||
264 | req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]); | ||
265 | req->sense = sreq->sr_sense_buffer; | ||
266 | req->sense_len = 0; | ||
267 | memcpy(req->cmd, cmnd, req->cmd_len); | ||
268 | req->timeout = timeout; | ||
269 | req->flags |= REQ_BLOCK_PC; | ||
270 | req->rq_disk = NULL; | ||
271 | blk_insert_request(sreq->sr_device->request_queue, req, | ||
272 | sreq->sr_data_direction == DMA_TO_DEVICE, NULL); | ||
272 | wait_for_completion(&wait); | 273 | wait_for_completion(&wait); |
273 | sreq->sr_request->waiting = NULL; | 274 | sreq->sr_request->waiting = NULL; |
274 | if (sreq->sr_request->rq_status != RQ_SCSI_DONE) | 275 | sreq->sr_result = req->errors; |
276 | if (req->errors) | ||
275 | sreq->sr_result |= (DRIVER_ERROR << 24); | 277 | sreq->sr_result |= (DRIVER_ERROR << 24); |
276 | 278 | ||
277 | __scsi_release_request(sreq); | 279 | blk_put_request(req); |
278 | } | 280 | } |
281 | |||
279 | EXPORT_SYMBOL(scsi_wait_req); | 282 | EXPORT_SYMBOL(scsi_wait_req); |
280 | 283 | ||
284 | /** | ||
285 | * scsi_execute - insert request and wait for the result | ||
286 | * @sdev: scsi device | ||
287 | * @cmd: scsi command | ||
288 | * @data_direction: data direction | ||
289 | * @buffer: data buffer | ||
290 | * @bufflen: len of buffer | ||
291 | * @sense: optional sense buffer | ||
292 | * @timeout: request timeout in seconds | ||
293 | * @retries: number of times to retry request | ||
294 | * @flags: or into request flags; | ||
295 | * | ||
296 | * returns the req->errors value which is the the scsi_cmnd result | ||
297 | * field. | ||
298 | **/ | ||
299 | int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | ||
300 | int data_direction, void *buffer, unsigned bufflen, | ||
301 | unsigned char *sense, int timeout, int retries, int flags) | ||
302 | { | ||
303 | struct request *req; | ||
304 | int write = (data_direction == DMA_TO_DEVICE); | ||
305 | int ret = DRIVER_ERROR << 24; | ||
306 | |||
307 | req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); | ||
308 | |||
309 | if (bufflen && blk_rq_map_kern(sdev->request_queue, req, | ||
310 | buffer, bufflen, __GFP_WAIT)) | ||
311 | goto out; | ||
312 | |||
313 | req->cmd_len = COMMAND_SIZE(cmd[0]); | ||
314 | memcpy(req->cmd, cmd, req->cmd_len); | ||
315 | req->sense = sense; | ||
316 | req->sense_len = 0; | ||
317 | req->timeout = timeout; | ||
318 | req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET; | ||
319 | |||
320 | /* | ||
321 | * head injection *required* here otherwise quiesce won't work | ||
322 | */ | ||
323 | blk_execute_rq(req->q, NULL, req, 1); | ||
324 | |||
325 | ret = req->errors; | ||
326 | out: | ||
327 | blk_put_request(req); | ||
328 | |||
329 | return ret; | ||
330 | } | ||
331 | EXPORT_SYMBOL(scsi_execute); | ||
332 | |||
333 | |||
334 | int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | ||
335 | int data_direction, void *buffer, unsigned bufflen, | ||
336 | struct scsi_sense_hdr *sshdr, int timeout, int retries) | ||
337 | { | ||
338 | char *sense = NULL; | ||
339 | int result; | ||
340 | |||
341 | if (sshdr) { | ||
342 | sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | ||
343 | if (!sense) | ||
344 | return DRIVER_ERROR << 24; | ||
345 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); | ||
346 | } | ||
347 | result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, | ||
348 | sense, timeout, retries, 0); | ||
349 | if (sshdr) | ||
350 | scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); | ||
351 | |||
352 | kfree(sense); | ||
353 | return result; | ||
354 | } | ||
355 | EXPORT_SYMBOL(scsi_execute_req); | ||
356 | |||
281 | /* | 357 | /* |
282 | * Function: scsi_init_cmd_errh() | 358 | * Function: scsi_init_cmd_errh() |
283 | * | 359 | * |
@@ -348,7 +424,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) | |||
348 | 424 | ||
349 | spin_lock_irqsave(shost->host_lock, flags); | 425 | spin_lock_irqsave(shost->host_lock, flags); |
350 | shost->host_busy--; | 426 | shost->host_busy--; |
351 | if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) && | 427 | if (unlikely((shost->shost_state == SHOST_RECOVERY) && |
352 | shost->host_failed)) | 428 | shost->host_failed)) |
353 | scsi_eh_wakeup(shost); | 429 | scsi_eh_wakeup(shost); |
354 | spin_unlock(shost->host_lock); | 430 | spin_unlock(shost->host_lock); |
@@ -851,17 +927,20 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
851 | scsi_requeue_command(q, cmd); | 927 | scsi_requeue_command(q, cmd); |
852 | return; | 928 | return; |
853 | } | 929 | } |
854 | printk(KERN_INFO "Device %s not ready.\n", | 930 | if (!(req->flags & REQ_QUIET)) |
855 | req->rq_disk ? req->rq_disk->disk_name : ""); | 931 | dev_printk(KERN_INFO, |
932 | &cmd->device->sdev_gendev, | ||
933 | "Device not ready.\n"); | ||
856 | cmd = scsi_end_request(cmd, 0, this_count, 1); | 934 | cmd = scsi_end_request(cmd, 0, this_count, 1); |
857 | return; | 935 | return; |
858 | case VOLUME_OVERFLOW: | 936 | case VOLUME_OVERFLOW: |
859 | printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ", | 937 | if (!(req->flags & REQ_QUIET)) { |
860 | cmd->device->host->host_no, | 938 | dev_printk(KERN_INFO, |
861 | (int)cmd->device->channel, | 939 | &cmd->device->sdev_gendev, |
862 | (int)cmd->device->id, (int)cmd->device->lun); | 940 | "Volume overflow, CDB: "); |
863 | __scsi_print_command(cmd->data_cmnd); | 941 | __scsi_print_command(cmd->data_cmnd); |
864 | scsi_print_sense("", cmd); | 942 | scsi_print_sense("", cmd); |
943 | } | ||
865 | cmd = scsi_end_request(cmd, 0, block_bytes, 1); | 944 | cmd = scsi_end_request(cmd, 0, block_bytes, 1); |
866 | return; | 945 | return; |
867 | default: | 946 | default: |
@@ -878,14 +957,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
878 | return; | 957 | return; |
879 | } | 958 | } |
880 | if (result) { | 959 | if (result) { |
881 | printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " | 960 | if (!(req->flags & REQ_QUIET)) { |
882 | "= 0x%x\n", cmd->device->host->host_no, | 961 | dev_printk(KERN_INFO, &cmd->device->sdev_gendev, |
883 | cmd->device->channel, | 962 | "SCSI error: return code = 0x%x\n", result); |
884 | cmd->device->id, | 963 | |
885 | cmd->device->lun, result); | 964 | if (driver_byte(result) & DRIVER_SENSE) |
886 | 965 | scsi_print_sense("", cmd); | |
887 | if (driver_byte(result) & DRIVER_SENSE) | 966 | } |
888 | scsi_print_sense("", cmd); | ||
889 | /* | 967 | /* |
890 | * Mark a single buffer as not uptodate. Queue the remainder. | 968 | * Mark a single buffer as not uptodate. Queue the remainder. |
891 | * We sometimes get this cruft in the event that a medium error | 969 | * We sometimes get this cruft in the event that a medium error |
@@ -1020,6 +1098,12 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, | |||
1020 | return -EOPNOTSUPP; | 1098 | return -EOPNOTSUPP; |
1021 | } | 1099 | } |
1022 | 1100 | ||
1101 | static void scsi_generic_done(struct scsi_cmnd *cmd) | ||
1102 | { | ||
1103 | BUG_ON(!blk_pc_request(cmd->request)); | ||
1104 | scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0); | ||
1105 | } | ||
1106 | |||
1023 | static int scsi_prep_fn(struct request_queue *q, struct request *req) | 1107 | static int scsi_prep_fn(struct request_queue *q, struct request *req) |
1024 | { | 1108 | { |
1025 | struct scsi_device *sdev = q->queuedata; | 1109 | struct scsi_device *sdev = q->queuedata; |
@@ -1061,7 +1145,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1061 | * these two cases differently. We differentiate by looking | 1145 | * these two cases differently. We differentiate by looking |
1062 | * at request->cmd, as this tells us the real story. | 1146 | * at request->cmd, as this tells us the real story. |
1063 | */ | 1147 | */ |
1064 | if (req->flags & REQ_SPECIAL) { | 1148 | if (req->flags & REQ_SPECIAL && req->special) { |
1065 | struct scsi_request *sreq = req->special; | 1149 | struct scsi_request *sreq = req->special; |
1066 | 1150 | ||
1067 | if (sreq->sr_magic == SCSI_REQ_MAGIC) { | 1151 | if (sreq->sr_magic == SCSI_REQ_MAGIC) { |
@@ -1073,7 +1157,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1073 | cmd = req->special; | 1157 | cmd = req->special; |
1074 | } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { | 1158 | } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { |
1075 | 1159 | ||
1076 | if(unlikely(specials_only)) { | 1160 | if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { |
1077 | if(specials_only == SDEV_QUIESCE || | 1161 | if(specials_only == SDEV_QUIESCE || |
1078 | specials_only == SDEV_BLOCK) | 1162 | specials_only == SDEV_BLOCK) |
1079 | return BLKPREP_DEFER; | 1163 | return BLKPREP_DEFER; |
@@ -1142,11 +1226,26 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1142 | /* | 1226 | /* |
1143 | * Initialize the actual SCSI command for this request. | 1227 | * Initialize the actual SCSI command for this request. |
1144 | */ | 1228 | */ |
1145 | drv = *(struct scsi_driver **)req->rq_disk->private_data; | 1229 | if (req->rq_disk) { |
1146 | if (unlikely(!drv->init_command(cmd))) { | 1230 | drv = *(struct scsi_driver **)req->rq_disk->private_data; |
1147 | scsi_release_buffers(cmd); | 1231 | if (unlikely(!drv->init_command(cmd))) { |
1148 | scsi_put_command(cmd); | 1232 | scsi_release_buffers(cmd); |
1149 | return BLKPREP_KILL; | 1233 | scsi_put_command(cmd); |
1234 | return BLKPREP_KILL; | ||
1235 | } | ||
1236 | } else { | ||
1237 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); | ||
1238 | if (rq_data_dir(req) == WRITE) | ||
1239 | cmd->sc_data_direction = DMA_TO_DEVICE; | ||
1240 | else if (req->data_len) | ||
1241 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
1242 | else | ||
1243 | cmd->sc_data_direction = DMA_NONE; | ||
1244 | |||
1245 | cmd->transfersize = req->data_len; | ||
1246 | cmd->allowed = 3; | ||
1247 | cmd->timeout_per_command = req->timeout; | ||
1248 | cmd->done = scsi_generic_done; | ||
1150 | } | 1249 | } |
1151 | } | 1250 | } |
1152 | 1251 | ||
@@ -1207,7 +1306,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, | |||
1207 | struct Scsi_Host *shost, | 1306 | struct Scsi_Host *shost, |
1208 | struct scsi_device *sdev) | 1307 | struct scsi_device *sdev) |
1209 | { | 1308 | { |
1210 | if (test_bit(SHOST_RECOVERY, &shost->shost_state)) | 1309 | if (shost->shost_state == SHOST_RECOVERY) |
1211 | return 0; | 1310 | return 0; |
1212 | if (shost->host_busy == 0 && shost->host_blocked) { | 1311 | if (shost->host_busy == 0 && shost->host_blocked) { |
1213 | /* | 1312 | /* |
@@ -1539,9 +1638,9 @@ void scsi_exit_queue(void) | |||
1539 | } | 1638 | } |
1540 | } | 1639 | } |
1541 | /** | 1640 | /** |
1542 | * __scsi_mode_sense - issue a mode sense, falling back from 10 to | 1641 | * scsi_mode_sense - issue a mode sense, falling back from 10 to |
1543 | * six bytes if necessary. | 1642 | * six bytes if necessary. |
1544 | * @sreq: SCSI request to fill in with the MODE_SENSE | 1643 | * @sdev: SCSI device to be queried |
1545 | * @dbd: set if mode sense will allow block descriptors to be returned | 1644 | * @dbd: set if mode sense will allow block descriptors to be returned |
1546 | * @modepage: mode page being requested | 1645 | * @modepage: mode page being requested |
1547 | * @buffer: request buffer (may not be smaller than eight bytes) | 1646 | * @buffer: request buffer (may not be smaller than eight bytes) |
@@ -1549,26 +1648,34 @@ void scsi_exit_queue(void) | |||
1549 | * @timeout: command timeout | 1648 | * @timeout: command timeout |
1550 | * @retries: number of retries before failing | 1649 | * @retries: number of retries before failing |
1551 | * @data: returns a structure abstracting the mode header data | 1650 | * @data: returns a structure abstracting the mode header data |
1651 | * @sense: place to put sense data (or NULL if no sense to be collected). | ||
1652 | * must be SCSI_SENSE_BUFFERSIZE big. | ||
1552 | * | 1653 | * |
1553 | * Returns zero if unsuccessful, or the header offset (either 4 | 1654 | * Returns zero if unsuccessful, or the header offset (either 4 |
1554 | * or 8 depending on whether a six or ten byte command was | 1655 | * or 8 depending on whether a six or ten byte command was |
1555 | * issued) if successful. | 1656 | * issued) if successful. |
1556 | **/ | 1657 | **/ |
1557 | int | 1658 | int |
1558 | __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, | 1659 | scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, |
1559 | unsigned char *buffer, int len, int timeout, int retries, | 1660 | unsigned char *buffer, int len, int timeout, int retries, |
1560 | struct scsi_mode_data *data) { | 1661 | struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { |
1561 | unsigned char cmd[12]; | 1662 | unsigned char cmd[12]; |
1562 | int use_10_for_ms; | 1663 | int use_10_for_ms; |
1563 | int header_length; | 1664 | int header_length; |
1665 | int result; | ||
1666 | struct scsi_sense_hdr my_sshdr; | ||
1564 | 1667 | ||
1565 | memset(data, 0, sizeof(*data)); | 1668 | memset(data, 0, sizeof(*data)); |
1566 | memset(&cmd[0], 0, 12); | 1669 | memset(&cmd[0], 0, 12); |
1567 | cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ | 1670 | cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ |
1568 | cmd[2] = modepage; | 1671 | cmd[2] = modepage; |
1569 | 1672 | ||
1673 | /* caller might not be interested in sense, but we need it */ | ||
1674 | if (!sshdr) | ||
1675 | sshdr = &my_sshdr; | ||
1676 | |||
1570 | retry: | 1677 | retry: |
1571 | use_10_for_ms = sreq->sr_device->use_10_for_ms; | 1678 | use_10_for_ms = sdev->use_10_for_ms; |
1572 | 1679 | ||
1573 | if (use_10_for_ms) { | 1680 | if (use_10_for_ms) { |
1574 | if (len < 8) | 1681 | if (len < 8) |
@@ -1586,36 +1693,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, | |||
1586 | header_length = 4; | 1693 | header_length = 4; |
1587 | } | 1694 | } |
1588 | 1695 | ||
1589 | sreq->sr_cmd_len = 0; | ||
1590 | memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); | ||
1591 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
1592 | |||
1593 | memset(buffer, 0, len); | 1696 | memset(buffer, 0, len); |
1594 | 1697 | ||
1595 | scsi_wait_req(sreq, cmd, buffer, len, timeout, retries); | 1698 | result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, |
1699 | sshdr, timeout, retries); | ||
1596 | 1700 | ||
1597 | /* This code looks awful: what it's doing is making sure an | 1701 | /* This code looks awful: what it's doing is making sure an |
1598 | * ILLEGAL REQUEST sense return identifies the actual command | 1702 | * ILLEGAL REQUEST sense return identifies the actual command |
1599 | * byte as the problem. MODE_SENSE commands can return | 1703 | * byte as the problem. MODE_SENSE commands can return |
1600 | * ILLEGAL REQUEST if the code page isn't supported */ | 1704 | * ILLEGAL REQUEST if the code page isn't supported */ |
1601 | 1705 | ||
1602 | if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) && | 1706 | if (use_10_for_ms && !scsi_status_is_good(result) && |
1603 | (driver_byte(sreq->sr_result) & DRIVER_SENSE)) { | 1707 | (driver_byte(result) & DRIVER_SENSE)) { |
1604 | struct scsi_sense_hdr sshdr; | 1708 | if (scsi_sense_valid(sshdr)) { |
1605 | 1709 | if ((sshdr->sense_key == ILLEGAL_REQUEST) && | |
1606 | if (scsi_request_normalize_sense(sreq, &sshdr)) { | 1710 | (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { |
1607 | if ((sshdr.sense_key == ILLEGAL_REQUEST) && | ||
1608 | (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { | ||
1609 | /* | 1711 | /* |
1610 | * Invalid command operation code | 1712 | * Invalid command operation code |
1611 | */ | 1713 | */ |
1612 | sreq->sr_device->use_10_for_ms = 0; | 1714 | sdev->use_10_for_ms = 0; |
1613 | goto retry; | 1715 | goto retry; |
1614 | } | 1716 | } |
1615 | } | 1717 | } |
1616 | } | 1718 | } |
1617 | 1719 | ||
1618 | if(scsi_status_is_good(sreq->sr_result)) { | 1720 | if(scsi_status_is_good(result)) { |
1619 | data->header_length = header_length; | 1721 | data->header_length = header_length; |
1620 | if(use_10_for_ms) { | 1722 | if(use_10_for_ms) { |
1621 | data->length = buffer[0]*256 + buffer[1] + 2; | 1723 | data->length = buffer[0]*256 + buffer[1] + 2; |
@@ -1632,73 +1734,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, | |||
1632 | } | 1734 | } |
1633 | } | 1735 | } |
1634 | 1736 | ||
1635 | return sreq->sr_result; | 1737 | return result; |
1636 | } | ||
1637 | EXPORT_SYMBOL(__scsi_mode_sense); | ||
1638 | |||
1639 | /** | ||
1640 | * scsi_mode_sense - issue a mode sense, falling back from 10 to | ||
1641 | * six bytes if necessary. | ||
1642 | * @sdev: scsi device to send command to. | ||
1643 | * @dbd: set if mode sense will disable block descriptors in the return | ||
1644 | * @modepage: mode page being requested | ||
1645 | * @buffer: request buffer (may not be smaller than eight bytes) | ||
1646 | * @len: length of request buffer. | ||
1647 | * @timeout: command timeout | ||
1648 | * @retries: number of retries before failing | ||
1649 | * | ||
1650 | * Returns zero if unsuccessful, or the header offset (either 4 | ||
1651 | * or 8 depending on whether a six or ten byte command was | ||
1652 | * issued) if successful. | ||
1653 | **/ | ||
1654 | int | ||
1655 | scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, | ||
1656 | unsigned char *buffer, int len, int timeout, int retries, | ||
1657 | struct scsi_mode_data *data) | ||
1658 | { | ||
1659 | struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); | ||
1660 | int ret; | ||
1661 | |||
1662 | if (!sreq) | ||
1663 | return -1; | ||
1664 | |||
1665 | ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len, | ||
1666 | timeout, retries, data); | ||
1667 | |||
1668 | scsi_release_request(sreq); | ||
1669 | |||
1670 | return ret; | ||
1671 | } | 1738 | } |
1672 | EXPORT_SYMBOL(scsi_mode_sense); | 1739 | EXPORT_SYMBOL(scsi_mode_sense); |
1673 | 1740 | ||
1674 | int | 1741 | int |
1675 | scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) | 1742 | scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) |
1676 | { | 1743 | { |
1677 | struct scsi_request *sreq; | ||
1678 | char cmd[] = { | 1744 | char cmd[] = { |
1679 | TEST_UNIT_READY, 0, 0, 0, 0, 0, | 1745 | TEST_UNIT_READY, 0, 0, 0, 0, 0, |
1680 | }; | 1746 | }; |
1747 | struct scsi_sense_hdr sshdr; | ||
1681 | int result; | 1748 | int result; |
1682 | 1749 | ||
1683 | sreq = scsi_allocate_request(sdev, GFP_KERNEL); | 1750 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, |
1684 | if (!sreq) | 1751 | timeout, retries); |
1685 | return -ENOMEM; | ||
1686 | |||
1687 | sreq->sr_data_direction = DMA_NONE; | ||
1688 | scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); | ||
1689 | 1752 | ||
1690 | if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) { | 1753 | if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { |
1691 | struct scsi_sense_hdr sshdr; | ||
1692 | 1754 | ||
1693 | if ((scsi_request_normalize_sense(sreq, &sshdr)) && | 1755 | if ((scsi_sense_valid(&sshdr)) && |
1694 | ((sshdr.sense_key == UNIT_ATTENTION) || | 1756 | ((sshdr.sense_key == UNIT_ATTENTION) || |
1695 | (sshdr.sense_key == NOT_READY))) { | 1757 | (sshdr.sense_key == NOT_READY))) { |
1696 | sdev->changed = 1; | 1758 | sdev->changed = 1; |
1697 | sreq->sr_result = 0; | 1759 | result = 0; |
1698 | } | 1760 | } |
1699 | } | 1761 | } |
1700 | result = sreq->sr_result; | ||
1701 | scsi_release_request(sreq); | ||
1702 | return result; | 1762 | return result; |
1703 | } | 1763 | } |
1704 | EXPORT_SYMBOL(scsi_test_unit_ready); | 1764 | EXPORT_SYMBOL(scsi_test_unit_ready); |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index d30d7f4e63ec..ee6de1768e53 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -63,6 +63,9 @@ extern int __init scsi_init_devinfo(void); | |||
63 | extern void scsi_exit_devinfo(void); | 63 | extern void scsi_exit_devinfo(void); |
64 | 64 | ||
65 | /* scsi_error.c */ | 65 | /* scsi_error.c */ |
66 | extern void scsi_add_timer(struct scsi_cmnd *, int, | ||
67 | void (*)(struct scsi_cmnd *)); | ||
68 | extern int scsi_delete_timer(struct scsi_cmnd *); | ||
66 | extern void scsi_times_out(struct scsi_cmnd *cmd); | 69 | extern void scsi_times_out(struct scsi_cmnd *cmd); |
67 | extern int scsi_error_handler(void *host); | 70 | extern int scsi_error_handler(void *host); |
68 | extern int scsi_decide_disposition(struct scsi_cmnd *cmd); | 71 | extern int scsi_decide_disposition(struct scsi_cmnd *cmd); |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 48edd67982a5..19c9a232a754 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout, | |||
111 | 111 | ||
112 | /** | 112 | /** |
113 | * scsi_unlock_floptical - unlock device via a special MODE SENSE command | 113 | * scsi_unlock_floptical - unlock device via a special MODE SENSE command |
114 | * @sreq: used to send the command | 114 | * @sdev: scsi device to send command to |
115 | * @result: area to store the result of the MODE SENSE | 115 | * @result: area to store the result of the MODE SENSE |
116 | * | 116 | * |
117 | * Description: | 117 | * Description: |
118 | * Send a vendor specific MODE SENSE (not a MODE SELECT) command using | 118 | * Send a vendor specific MODE SENSE (not a MODE SELECT) command. |
119 | * @sreq to unlock a device, storing the (unused) results into result. | ||
120 | * Called for BLIST_KEY devices. | 119 | * Called for BLIST_KEY devices. |
121 | **/ | 120 | **/ |
122 | static void scsi_unlock_floptical(struct scsi_request *sreq, | 121 | static void scsi_unlock_floptical(struct scsi_device *sdev, |
123 | unsigned char *result) | 122 | unsigned char *result) |
124 | { | 123 | { |
125 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; | 124 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; |
@@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct scsi_request *sreq, | |||
129 | scsi_cmd[1] = 0; | 128 | scsi_cmd[1] = 0; |
130 | scsi_cmd[2] = 0x2e; | 129 | scsi_cmd[2] = 0x2e; |
131 | scsi_cmd[3] = 0; | 130 | scsi_cmd[3] = 0; |
132 | scsi_cmd[4] = 0x2a; /* size */ | 131 | scsi_cmd[4] = 0x2a; /* size */ |
133 | scsi_cmd[5] = 0; | 132 | scsi_cmd[5] = 0; |
134 | sreq->sr_cmd_len = 0; | 133 | scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, |
135 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 134 | SCSI_TIMEOUT, 3); |
136 | scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3); | ||
137 | } | 135 | } |
138 | 136 | ||
139 | /** | 137 | /** |
@@ -433,26 +431,25 @@ void scsi_target_reap(struct scsi_target *starget) | |||
433 | 431 | ||
434 | /** | 432 | /** |
435 | * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY | 433 | * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY |
436 | * @sreq: used to send the INQUIRY | 434 | * @sdev: scsi_device to probe |
437 | * @inq_result: area to store the INQUIRY result | 435 | * @inq_result: area to store the INQUIRY result |
436 | * @result_len: len of inq_result | ||
438 | * @bflags: store any bflags found here | 437 | * @bflags: store any bflags found here |
439 | * | 438 | * |
440 | * Description: | 439 | * Description: |
441 | * Probe the lun associated with @sreq using a standard SCSI INQUIRY; | 440 | * Probe the lun associated with @req using a standard SCSI INQUIRY; |
442 | * | 441 | * |
443 | * If the INQUIRY is successful, sreq->sr_result is zero and: the | 442 | * If the INQUIRY is successful, zero is returned and the |
444 | * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length | 443 | * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length |
445 | * are copied to the Scsi_Device at @sreq->sr_device (sdev); | 444 | * are copied to the Scsi_Device any flags value is stored in *@bflags. |
446 | * any flags value is stored in *@bflags. | ||
447 | **/ | 445 | **/ |
448 | static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | 446 | static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, |
449 | int *bflags) | 447 | int result_len, int *bflags) |
450 | { | 448 | { |
451 | struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ | ||
452 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; | 449 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; |
453 | int first_inquiry_len, try_inquiry_len, next_inquiry_len; | 450 | int first_inquiry_len, try_inquiry_len, next_inquiry_len; |
454 | int response_len = 0; | 451 | int response_len = 0; |
455 | int pass, count; | 452 | int pass, count, result; |
456 | struct scsi_sense_hdr sshdr; | 453 | struct scsi_sense_hdr sshdr; |
457 | 454 | ||
458 | *bflags = 0; | 455 | *bflags = 0; |
@@ -475,28 +472,26 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
475 | memset(scsi_cmd, 0, 6); | 472 | memset(scsi_cmd, 0, 6); |
476 | scsi_cmd[0] = INQUIRY; | 473 | scsi_cmd[0] = INQUIRY; |
477 | scsi_cmd[4] = (unsigned char) try_inquiry_len; | 474 | scsi_cmd[4] = (unsigned char) try_inquiry_len; |
478 | sreq->sr_cmd_len = 0; | ||
479 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
480 | 475 | ||
481 | memset(inq_result, 0, try_inquiry_len); | 476 | memset(inq_result, 0, try_inquiry_len); |
482 | scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, | 477 | |
483 | try_inquiry_len, | 478 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
484 | HZ/2 + HZ*scsi_inq_timeout, 3); | 479 | inq_result, try_inquiry_len, &sshdr, |
480 | HZ / 2 + HZ * scsi_inq_timeout, 3); | ||
485 | 481 | ||
486 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " | 482 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " |
487 | "with code 0x%x\n", | 483 | "with code 0x%x\n", |
488 | sreq->sr_result ? "failed" : "successful", | 484 | result ? "failed" : "successful", result)); |
489 | sreq->sr_result)); | ||
490 | 485 | ||
491 | if (sreq->sr_result) { | 486 | if (result) { |
492 | /* | 487 | /* |
493 | * not-ready to ready transition [asc/ascq=0x28/0x0] | 488 | * not-ready to ready transition [asc/ascq=0x28/0x0] |
494 | * or power-on, reset [asc/ascq=0x29/0x0], continue. | 489 | * or power-on, reset [asc/ascq=0x29/0x0], continue. |
495 | * INQUIRY should not yield UNIT_ATTENTION | 490 | * INQUIRY should not yield UNIT_ATTENTION |
496 | * but many buggy devices do so anyway. | 491 | * but many buggy devices do so anyway. |
497 | */ | 492 | */ |
498 | if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && | 493 | if ((driver_byte(result) & DRIVER_SENSE) && |
499 | scsi_request_normalize_sense(sreq, &sshdr)) { | 494 | scsi_sense_valid(&sshdr)) { |
500 | if ((sshdr.sense_key == UNIT_ATTENTION) && | 495 | if ((sshdr.sense_key == UNIT_ATTENTION) && |
501 | ((sshdr.asc == 0x28) || | 496 | ((sshdr.asc == 0x28) || |
502 | (sshdr.asc == 0x29)) && | 497 | (sshdr.asc == 0x29)) && |
@@ -507,7 +502,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
507 | break; | 502 | break; |
508 | } | 503 | } |
509 | 504 | ||
510 | if (sreq->sr_result == 0) { | 505 | if (result == 0) { |
511 | response_len = (unsigned char) inq_result[4] + 5; | 506 | response_len = (unsigned char) inq_result[4] + 5; |
512 | if (response_len > 255) | 507 | if (response_len > 255) |
513 | response_len = first_inquiry_len; /* sanity */ | 508 | response_len = first_inquiry_len; /* sanity */ |
@@ -556,8 +551,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
556 | 551 | ||
557 | /* If the last transfer attempt got an error, assume the | 552 | /* If the last transfer attempt got an error, assume the |
558 | * peripheral doesn't exist or is dead. */ | 553 | * peripheral doesn't exist or is dead. */ |
559 | if (sreq->sr_result) | 554 | if (result) |
560 | return; | 555 | return -EIO; |
561 | 556 | ||
562 | /* Don't report any more data than the device says is valid */ | 557 | /* Don't report any more data than the device says is valid */ |
563 | sdev->inquiry_len = min(try_inquiry_len, response_len); | 558 | sdev->inquiry_len = min(try_inquiry_len, response_len); |
@@ -593,7 +588,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
593 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) | 588 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) |
594 | sdev->scsi_level++; | 589 | sdev->scsi_level++; |
595 | 590 | ||
596 | return; | 591 | return 0; |
597 | } | 592 | } |
598 | 593 | ||
599 | /** | 594 | /** |
@@ -800,9 +795,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
800 | void *hostdata) | 795 | void *hostdata) |
801 | { | 796 | { |
802 | struct scsi_device *sdev; | 797 | struct scsi_device *sdev; |
803 | struct scsi_request *sreq; | ||
804 | unsigned char *result; | 798 | unsigned char *result; |
805 | int bflags, res = SCSI_SCAN_NO_RESPONSE; | 799 | int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; |
806 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 800 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
807 | 801 | ||
808 | /* | 802 | /* |
@@ -831,16 +825,13 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
831 | sdev = scsi_alloc_sdev(starget, lun, hostdata); | 825 | sdev = scsi_alloc_sdev(starget, lun, hostdata); |
832 | if (!sdev) | 826 | if (!sdev) |
833 | goto out; | 827 | goto out; |
834 | sreq = scsi_allocate_request(sdev, GFP_ATOMIC); | 828 | |
835 | if (!sreq) | 829 | result = kmalloc(result_len, GFP_ATOMIC | |
836 | goto out_free_sdev; | ||
837 | result = kmalloc(256, GFP_ATOMIC | | ||
838 | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); | 830 | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); |
839 | if (!result) | 831 | if (!result) |
840 | goto out_free_sreq; | 832 | goto out_free_sdev; |
841 | 833 | ||
842 | scsi_probe_lun(sreq, result, &bflags); | 834 | if (scsi_probe_lun(sdev, result, result_len, &bflags)) |
843 | if (sreq->sr_result) | ||
844 | goto out_free_result; | 835 | goto out_free_result; |
845 | 836 | ||
846 | /* | 837 | /* |
@@ -868,7 +859,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
868 | if (res == SCSI_SCAN_LUN_PRESENT) { | 859 | if (res == SCSI_SCAN_LUN_PRESENT) { |
869 | if (bflags & BLIST_KEY) { | 860 | if (bflags & BLIST_KEY) { |
870 | sdev->lockable = 0; | 861 | sdev->lockable = 0; |
871 | scsi_unlock_floptical(sreq, result); | 862 | scsi_unlock_floptical(sdev, result); |
872 | } | 863 | } |
873 | if (bflagsp) | 864 | if (bflagsp) |
874 | *bflagsp = bflags; | 865 | *bflagsp = bflags; |
@@ -876,8 +867,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
876 | 867 | ||
877 | out_free_result: | 868 | out_free_result: |
878 | kfree(result); | 869 | kfree(result); |
879 | out_free_sreq: | ||
880 | scsi_release_request(sreq); | ||
881 | out_free_sdev: | 870 | out_free_sdev: |
882 | if (res == SCSI_SCAN_LUN_PRESENT) { | 871 | if (res == SCSI_SCAN_LUN_PRESENT) { |
883 | if (sdevp) { | 872 | if (sdevp) { |
@@ -1070,8 +1059,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1070 | unsigned int lun; | 1059 | unsigned int lun; |
1071 | unsigned int num_luns; | 1060 | unsigned int num_luns; |
1072 | unsigned int retries; | 1061 | unsigned int retries; |
1062 | int result; | ||
1073 | struct scsi_lun *lunp, *lun_data; | 1063 | struct scsi_lun *lunp, *lun_data; |
1074 | struct scsi_request *sreq; | ||
1075 | u8 *data; | 1064 | u8 *data; |
1076 | struct scsi_sense_hdr sshdr; | 1065 | struct scsi_sense_hdr sshdr; |
1077 | struct scsi_target *starget = scsi_target(sdev); | 1066 | struct scsi_target *starget = scsi_target(sdev); |
@@ -1089,10 +1078,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1089 | if (bflags & BLIST_NOLUN) | 1078 | if (bflags & BLIST_NOLUN) |
1090 | return 0; | 1079 | return 0; |
1091 | 1080 | ||
1092 | sreq = scsi_allocate_request(sdev, GFP_ATOMIC); | ||
1093 | if (!sreq) | ||
1094 | goto out; | ||
1095 | |||
1096 | sprintf(devname, "host %d channel %d id %d", | 1081 | sprintf(devname, "host %d channel %d id %d", |
1097 | sdev->host->host_no, sdev->channel, sdev->id); | 1082 | sdev->host->host_no, sdev->channel, sdev->id); |
1098 | 1083 | ||
@@ -1110,7 +1095,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1110 | lun_data = kmalloc(length, GFP_ATOMIC | | 1095 | lun_data = kmalloc(length, GFP_ATOMIC | |
1111 | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); | 1096 | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); |
1112 | if (!lun_data) | 1097 | if (!lun_data) |
1113 | goto out_release_request; | 1098 | goto out; |
1114 | 1099 | ||
1115 | scsi_cmd[0] = REPORT_LUNS; | 1100 | scsi_cmd[0] = REPORT_LUNS; |
1116 | 1101 | ||
@@ -1129,8 +1114,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1129 | 1114 | ||
1130 | scsi_cmd[10] = 0; /* reserved */ | 1115 | scsi_cmd[10] = 0; /* reserved */ |
1131 | scsi_cmd[11] = 0; /* control */ | 1116 | scsi_cmd[11] = 0; /* control */ |
1132 | sreq->sr_cmd_len = 0; | ||
1133 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
1134 | 1117 | ||
1135 | /* | 1118 | /* |
1136 | * We can get a UNIT ATTENTION, for example a power on/reset, so | 1119 | * We can get a UNIT ATTENTION, for example a power on/reset, so |
@@ -1146,29 +1129,29 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1146 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" | 1129 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" |
1147 | " REPORT LUNS to %s (try %d)\n", devname, | 1130 | " REPORT LUNS to %s (try %d)\n", devname, |
1148 | retries)); | 1131 | retries)); |
1149 | scsi_wait_req(sreq, scsi_cmd, lun_data, length, | 1132 | |
1150 | SCSI_TIMEOUT + 4*HZ, 3); | 1133 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
1134 | lun_data, length, &sshdr, | ||
1135 | SCSI_TIMEOUT + 4 * HZ, 3); | ||
1136 | |||
1151 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" | 1137 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" |
1152 | " %s (try %d) result 0x%x\n", sreq->sr_result | 1138 | " %s (try %d) result 0x%x\n", result |
1153 | ? "failed" : "successful", retries, | 1139 | ? "failed" : "successful", retries, result)); |
1154 | sreq->sr_result)); | 1140 | if (result == 0) |
1155 | if (sreq->sr_result == 0) | ||
1156 | break; | 1141 | break; |
1157 | else if (scsi_request_normalize_sense(sreq, &sshdr)) { | 1142 | else if (scsi_sense_valid(&sshdr)) { |
1158 | if (sshdr.sense_key != UNIT_ATTENTION) | 1143 | if (sshdr.sense_key != UNIT_ATTENTION) |
1159 | break; | 1144 | break; |
1160 | } | 1145 | } |
1161 | } | 1146 | } |
1162 | 1147 | ||
1163 | if (sreq->sr_result) { | 1148 | if (result) { |
1164 | /* | 1149 | /* |
1165 | * The device probably does not support a REPORT LUN command | 1150 | * The device probably does not support a REPORT LUN command |
1166 | */ | 1151 | */ |
1167 | kfree(lun_data); | 1152 | kfree(lun_data); |
1168 | scsi_release_request(sreq); | ||
1169 | return 1; | 1153 | return 1; |
1170 | } | 1154 | } |
1171 | scsi_release_request(sreq); | ||
1172 | 1155 | ||
1173 | /* | 1156 | /* |
1174 | * Get the length from the first four bytes of lun_data. | 1157 | * Get the length from the first four bytes of lun_data. |
@@ -1242,8 +1225,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1242 | kfree(lun_data); | 1225 | kfree(lun_data); |
1243 | return 0; | 1226 | return 0; |
1244 | 1227 | ||
1245 | out_release_request: | ||
1246 | scsi_release_request(sreq); | ||
1247 | out: | 1228 | out: |
1248 | /* | 1229 | /* |
1249 | * We are out of memory, don't try scanning any further. | 1230 | * We are out of memory, don't try scanning any further. |
@@ -1265,9 +1246,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1265 | 1246 | ||
1266 | get_device(&starget->dev); | 1247 | get_device(&starget->dev); |
1267 | down(&shost->scan_mutex); | 1248 | down(&shost->scan_mutex); |
1268 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); | 1249 | if (scsi_host_scan_allowed(shost)) { |
1269 | if (res != SCSI_SCAN_LUN_PRESENT) | 1250 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, |
1270 | sdev = ERR_PTR(-ENODEV); | 1251 | hostdata); |
1252 | if (res != SCSI_SCAN_LUN_PRESENT) | ||
1253 | sdev = ERR_PTR(-ENODEV); | ||
1254 | } | ||
1271 | up(&shost->scan_mutex); | 1255 | up(&shost->scan_mutex); |
1272 | scsi_target_reap(starget); | 1256 | scsi_target_reap(starget); |
1273 | put_device(&starget->dev); | 1257 | put_device(&starget->dev); |
@@ -1417,11 +1401,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1417 | return -EINVAL; | 1401 | return -EINVAL; |
1418 | 1402 | ||
1419 | down(&shost->scan_mutex); | 1403 | down(&shost->scan_mutex); |
1420 | if (channel == SCAN_WILD_CARD) | 1404 | if (scsi_host_scan_allowed(shost)) { |
1421 | for (channel = 0; channel <= shost->max_channel; channel++) | 1405 | if (channel == SCAN_WILD_CARD) |
1406 | for (channel = 0; channel <= shost->max_channel; | ||
1407 | channel++) | ||
1408 | scsi_scan_channel(shost, channel, id, lun, | ||
1409 | rescan); | ||
1410 | else | ||
1422 | scsi_scan_channel(shost, channel, id, lun, rescan); | 1411 | scsi_scan_channel(shost, channel, id, lun, rescan); |
1423 | else | 1412 | } |
1424 | scsi_scan_channel(shost, channel, id, lun, rescan); | ||
1425 | up(&shost->scan_mutex); | 1413 | up(&shost->scan_mutex); |
1426 | 1414 | ||
1427 | return 0; | 1415 | 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..ef577c8c2182 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -28,14 +28,14 @@ | |||
28 | #include "scsi_priv.h" | 28 | #include "scsi_priv.h" |
29 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
30 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
31 | #include <scsi/scsi_request.h> | 31 | #include <scsi/scsi_cmnd.h> |
32 | #include <scsi/scsi_eh.h> | 32 | #include <scsi/scsi_eh.h> |
33 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
34 | #include <scsi/scsi_transport_spi.h> | 34 | #include <scsi/scsi_transport_spi.h> |
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 |
@@ -106,27 +106,31 @@ static int sprint_frac(char *dest, int value, int denom) | |||
106 | return result; | 106 | return result; |
107 | } | 107 | } |
108 | 108 | ||
109 | /* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions | 109 | static int spi_execute(struct scsi_device *sdev, const void *cmd, |
110 | * resulting from (likely) bus and device resets */ | 110 | enum dma_data_direction dir, |
111 | static void spi_wait_req(struct scsi_request *sreq, const void *cmd, | 111 | void *buffer, unsigned bufflen, |
112 | void *buffer, unsigned bufflen) | 112 | struct scsi_sense_hdr *sshdr) |
113 | { | 113 | { |
114 | int i; | 114 | int i, result; |
115 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | ||
115 | 116 | ||
116 | for(i = 0; i < DV_RETRIES; i++) { | 117 | for(i = 0; i < DV_RETRIES; i++) { |
117 | sreq->sr_request->flags |= REQ_FAILFAST; | 118 | result = scsi_execute(sdev, cmd, dir, buffer, bufflen, |
118 | 119 | sense, DV_TIMEOUT, /* retries */ 1, | |
119 | scsi_wait_req(sreq, cmd, buffer, bufflen, | 120 | REQ_FAILFAST); |
120 | DV_TIMEOUT, /* retries */ 1); | 121 | if (result & DRIVER_SENSE) { |
121 | if (sreq->sr_result & DRIVER_SENSE) { | 122 | struct scsi_sense_hdr sshdr_tmp; |
122 | struct scsi_sense_hdr sshdr; | 123 | if (!sshdr) |
123 | 124 | sshdr = &sshdr_tmp; | |
124 | if (scsi_request_normalize_sense(sreq, &sshdr) | 125 | |
125 | && sshdr.sense_key == UNIT_ATTENTION) | 126 | if (scsi_normalize_sense(sense, sizeof(*sense), |
127 | sshdr) | ||
128 | && sshdr->sense_key == UNIT_ATTENTION) | ||
126 | continue; | 129 | continue; |
127 | } | 130 | } |
128 | break; | 131 | break; |
129 | } | 132 | } |
133 | return result; | ||
130 | } | 134 | } |
131 | 135 | ||
132 | static struct { | 136 | static struct { |
@@ -162,7 +166,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name) | |||
162 | return SPI_SIGNAL_UNKNOWN; | 166 | return SPI_SIGNAL_UNKNOWN; |
163 | } | 167 | } |
164 | 168 | ||
165 | static int spi_host_setup(struct device *dev) | 169 | static int spi_host_setup(struct transport_container *tc, struct device *dev, |
170 | struct class_device *cdev) | ||
166 | { | 171 | { |
167 | struct Scsi_Host *shost = dev_to_shost(dev); | 172 | struct Scsi_Host *shost = dev_to_shost(dev); |
168 | 173 | ||
@@ -196,7 +201,9 @@ static int spi_host_match(struct attribute_container *cont, | |||
196 | return &i->t.host_attrs.ac == cont; | 201 | return &i->t.host_attrs.ac == cont; |
197 | } | 202 | } |
198 | 203 | ||
199 | static int spi_device_configure(struct device *dev) | 204 | static int spi_device_configure(struct transport_container *tc, |
205 | struct device *dev, | ||
206 | struct class_device *cdev) | ||
200 | { | 207 | { |
201 | struct scsi_device *sdev = to_scsi_device(dev); | 208 | struct scsi_device *sdev = to_scsi_device(dev); |
202 | struct scsi_target *starget = sdev->sdev_target; | 209 | struct scsi_target *starget = sdev->sdev_target; |
@@ -214,7 +221,9 @@ static int spi_device_configure(struct device *dev) | |||
214 | return 0; | 221 | return 0; |
215 | } | 222 | } |
216 | 223 | ||
217 | static int spi_setup_transport_attrs(struct device *dev) | 224 | static int spi_setup_transport_attrs(struct transport_container *tc, |
225 | struct device *dev, | ||
226 | struct class_device *cdev) | ||
218 | { | 227 | { |
219 | struct scsi_target *starget = to_scsi_target(dev); | 228 | struct scsi_target *starget = to_scsi_target(dev); |
220 | 229 | ||
@@ -231,6 +240,7 @@ static int spi_setup_transport_attrs(struct device *dev) | |||
231 | spi_rd_strm(starget) = 0; | 240 | spi_rd_strm(starget) = 0; |
232 | spi_rti(starget) = 0; | 241 | spi_rti(starget) = 0; |
233 | spi_pcomp_en(starget) = 0; | 242 | spi_pcomp_en(starget) = 0; |
243 | spi_hold_mcs(starget) = 0; | ||
234 | spi_dv_pending(starget) = 0; | 244 | spi_dv_pending(starget) = 0; |
235 | spi_initial_dv(starget) = 0; | 245 | spi_initial_dv(starget) = 0; |
236 | init_MUTEX(&spi_dv_sem(starget)); | 246 | init_MUTEX(&spi_dv_sem(starget)); |
@@ -347,6 +357,7 @@ spi_transport_rd_attr(wr_flow, "%d\n"); | |||
347 | spi_transport_rd_attr(rd_strm, "%d\n"); | 357 | spi_transport_rd_attr(rd_strm, "%d\n"); |
348 | spi_transport_rd_attr(rti, "%d\n"); | 358 | spi_transport_rd_attr(rti, "%d\n"); |
349 | spi_transport_rd_attr(pcomp_en, "%d\n"); | 359 | spi_transport_rd_attr(pcomp_en, "%d\n"); |
360 | spi_transport_rd_attr(hold_mcs, "%d\n"); | ||
350 | 361 | ||
351 | /* we only care about the first child device so we return 1 */ | 362 | /* we only care about the first child device so we return 1 */ |
352 | static int child_iter(struct device *dev, void *data) | 363 | static int child_iter(struct device *dev, void *data) |
@@ -539,13 +550,13 @@ enum spi_compare_returns { | |||
539 | /* This is for read/write Domain Validation: If the device supports | 550 | /* This is for read/write Domain Validation: If the device supports |
540 | * an echo buffer, we do read/write tests to it */ | 551 | * an echo buffer, we do read/write tests to it */ |
541 | static enum spi_compare_returns | 552 | static enum spi_compare_returns |
542 | spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | 553 | spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer, |
543 | u8 *ptr, const int retries) | 554 | u8 *ptr, const int retries) |
544 | { | 555 | { |
545 | struct scsi_device *sdev = sreq->sr_device; | ||
546 | int len = ptr - buffer; | 556 | int len = ptr - buffer; |
547 | int j, k, r; | 557 | int j, k, r, result; |
548 | unsigned int pattern = 0x0000ffff; | 558 | unsigned int pattern = 0x0000ffff; |
559 | struct scsi_sense_hdr sshdr; | ||
549 | 560 | ||
550 | const char spi_write_buffer[] = { | 561 | const char spi_write_buffer[] = { |
551 | WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 | 562 | WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 |
@@ -590,14 +601,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
590 | } | 601 | } |
591 | 602 | ||
592 | for (r = 0; r < retries; r++) { | 603 | for (r = 0; r < retries; r++) { |
593 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | 604 | result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE, |
594 | sreq->sr_data_direction = DMA_TO_DEVICE; | 605 | buffer, len, &sshdr); |
595 | spi_wait_req(sreq, spi_write_buffer, buffer, len); | 606 | if(result || !scsi_device_online(sdev)) { |
596 | if(sreq->sr_result || !scsi_device_online(sdev)) { | ||
597 | struct scsi_sense_hdr sshdr; | ||
598 | 607 | ||
599 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 608 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
600 | if (scsi_request_normalize_sense(sreq, &sshdr) | 609 | if (scsi_sense_valid(&sshdr) |
601 | && sshdr.sense_key == ILLEGAL_REQUEST | 610 | && sshdr.sense_key == ILLEGAL_REQUEST |
602 | /* INVALID FIELD IN CDB */ | 611 | /* INVALID FIELD IN CDB */ |
603 | && sshdr.asc == 0x24 && sshdr.ascq == 0x00) | 612 | && sshdr.asc == 0x24 && sshdr.ascq == 0x00) |
@@ -609,14 +618,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
609 | return SPI_COMPARE_SKIP_TEST; | 618 | return SPI_COMPARE_SKIP_TEST; |
610 | 619 | ||
611 | 620 | ||
612 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); | 621 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result); |
613 | return SPI_COMPARE_FAILURE; | 622 | return SPI_COMPARE_FAILURE; |
614 | } | 623 | } |
615 | 624 | ||
616 | memset(ptr, 0, len); | 625 | memset(ptr, 0, len); |
617 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | 626 | spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE, |
618 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 627 | ptr, len, NULL); |
619 | spi_wait_req(sreq, spi_read_buffer, ptr, len); | ||
620 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 628 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
621 | 629 | ||
622 | if (memcmp(buffer, ptr, len) != 0) | 630 | if (memcmp(buffer, ptr, len) != 0) |
@@ -628,25 +636,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
628 | /* This is for the simplest form of Domain Validation: a read test | 636 | /* This is for the simplest form of Domain Validation: a read test |
629 | * on the inquiry data from the device */ | 637 | * on the inquiry data from the device */ |
630 | static enum spi_compare_returns | 638 | static enum spi_compare_returns |
631 | spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, | 639 | spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer, |
632 | u8 *ptr, const int retries) | 640 | u8 *ptr, const int retries) |
633 | { | 641 | { |
634 | int r; | 642 | int r, result; |
635 | const int len = sreq->sr_device->inquiry_len; | 643 | const int len = sdev->inquiry_len; |
636 | struct scsi_device *sdev = sreq->sr_device; | ||
637 | const char spi_inquiry[] = { | 644 | const char spi_inquiry[] = { |
638 | INQUIRY, 0, 0, 0, len, 0 | 645 | INQUIRY, 0, 0, 0, len, 0 |
639 | }; | 646 | }; |
640 | 647 | ||
641 | for (r = 0; r < retries; r++) { | 648 | for (r = 0; r < retries; r++) { |
642 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | ||
643 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
644 | |||
645 | memset(ptr, 0, len); | 649 | memset(ptr, 0, len); |
646 | 650 | ||
647 | spi_wait_req(sreq, spi_inquiry, ptr, len); | 651 | result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE, |
652 | ptr, len, NULL); | ||
648 | 653 | ||
649 | if(sreq->sr_result || !scsi_device_online(sdev)) { | 654 | if(result || !scsi_device_online(sdev)) { |
650 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 655 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
651 | return SPI_COMPARE_FAILURE; | 656 | return SPI_COMPARE_FAILURE; |
652 | } | 657 | } |
@@ -667,12 +672,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, | |||
667 | } | 672 | } |
668 | 673 | ||
669 | static enum spi_compare_returns | 674 | static enum spi_compare_returns |
670 | spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | 675 | spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr, |
671 | enum spi_compare_returns | 676 | enum spi_compare_returns |
672 | (*compare_fn)(struct scsi_request *, u8 *, u8 *, int)) | 677 | (*compare_fn)(struct scsi_device *, u8 *, u8 *, int)) |
673 | { | 678 | { |
674 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); | 679 | struct spi_internal *i = to_spi_internal(sdev->host->transportt); |
675 | struct scsi_device *sdev = sreq->sr_device; | ||
676 | struct scsi_target *starget = sdev->sdev_target; | 680 | struct scsi_target *starget = sdev->sdev_target; |
677 | int period = 0, prevperiod = 0; | 681 | int period = 0, prevperiod = 0; |
678 | enum spi_compare_returns retval; | 682 | enum spi_compare_returns retval; |
@@ -680,7 +684,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | |||
680 | 684 | ||
681 | for (;;) { | 685 | for (;;) { |
682 | int newperiod; | 686 | int newperiod; |
683 | retval = compare_fn(sreq, buffer, ptr, DV_LOOPS); | 687 | retval = compare_fn(sdev, buffer, ptr, DV_LOOPS); |
684 | 688 | ||
685 | if (retval == SPI_COMPARE_SUCCESS | 689 | if (retval == SPI_COMPARE_SUCCESS |
686 | || retval == SPI_COMPARE_SKIP_TEST) | 690 | || retval == SPI_COMPARE_SKIP_TEST) |
@@ -726,9 +730,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | |||
726 | } | 730 | } |
727 | 731 | ||
728 | static int | 732 | static int |
729 | spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | 733 | spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer) |
730 | { | 734 | { |
731 | int l; | 735 | int l, result; |
732 | 736 | ||
733 | /* first off do a test unit ready. This can error out | 737 | /* first off do a test unit ready. This can error out |
734 | * because of reservations or some other reason. If it | 738 | * because of reservations or some other reason. If it |
@@ -744,18 +748,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
744 | }; | 748 | }; |
745 | 749 | ||
746 | 750 | ||
747 | sreq->sr_cmd_len = 0; | ||
748 | sreq->sr_data_direction = DMA_NONE; | ||
749 | |||
750 | /* We send a set of three TURs to clear any outstanding | 751 | /* We send a set of three TURs to clear any outstanding |
751 | * unit attention conditions if they exist (Otherwise the | 752 | * unit attention conditions if they exist (Otherwise the |
752 | * buffer tests won't be happy). If the TUR still fails | 753 | * buffer tests won't be happy). If the TUR still fails |
753 | * (reservation conflict, device not ready, etc) just | 754 | * (reservation conflict, device not ready, etc) just |
754 | * skip the write tests */ | 755 | * skip the write tests */ |
755 | for (l = 0; ; l++) { | 756 | for (l = 0; ; l++) { |
756 | spi_wait_req(sreq, spi_test_unit_ready, NULL, 0); | 757 | result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE, |
758 | NULL, 0, NULL); | ||
757 | 759 | ||
758 | if(sreq->sr_result) { | 760 | if(result) { |
759 | if(l >= 3) | 761 | if(l >= 3) |
760 | return 0; | 762 | return 0; |
761 | } else { | 763 | } else { |
@@ -764,12 +766,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
764 | } | 766 | } |
765 | } | 767 | } |
766 | 768 | ||
767 | sreq->sr_cmd_len = 0; | 769 | result = spi_execute(sdev, spi_read_buffer_descriptor, |
768 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 770 | DMA_FROM_DEVICE, buffer, 4, NULL); |
769 | |||
770 | spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4); | ||
771 | 771 | ||
772 | if (sreq->sr_result) | 772 | if (result) |
773 | /* Device has no echo buffer */ | 773 | /* Device has no echo buffer */ |
774 | return 0; | 774 | return 0; |
775 | 775 | ||
@@ -777,17 +777,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
777 | } | 777 | } |
778 | 778 | ||
779 | static void | 779 | static void |
780 | spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | 780 | spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) |
781 | { | 781 | { |
782 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); | 782 | struct spi_internal *i = to_spi_internal(sdev->host->transportt); |
783 | struct scsi_device *sdev = sreq->sr_device; | ||
784 | struct scsi_target *starget = sdev->sdev_target; | 783 | struct scsi_target *starget = sdev->sdev_target; |
785 | int len = sdev->inquiry_len; | 784 | int len = sdev->inquiry_len; |
786 | /* first set us up for narrow async */ | 785 | /* first set us up for narrow async */ |
787 | DV_SET(offset, 0); | 786 | DV_SET(offset, 0); |
788 | DV_SET(width, 0); | 787 | DV_SET(width, 0); |
789 | 788 | ||
790 | if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) | 789 | if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) |
791 | != SPI_COMPARE_SUCCESS) { | 790 | != SPI_COMPARE_SUCCESS) { |
792 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); | 791 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); |
793 | /* FIXME: should probably offline the device here? */ | 792 | /* FIXME: should probably offline the device here? */ |
@@ -799,7 +798,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
799 | scsi_device_wide(sdev)) { | 798 | scsi_device_wide(sdev)) { |
800 | i->f->set_width(starget, 1); | 799 | i->f->set_width(starget, 1); |
801 | 800 | ||
802 | if (spi_dv_device_compare_inquiry(sreq, buffer, | 801 | if (spi_dv_device_compare_inquiry(sdev, buffer, |
803 | buffer + len, | 802 | buffer + len, |
804 | DV_LOOPS) | 803 | DV_LOOPS) |
805 | != SPI_COMPARE_SUCCESS) { | 804 | != SPI_COMPARE_SUCCESS) { |
@@ -820,7 +819,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
820 | 819 | ||
821 | len = 0; | 820 | len = 0; |
822 | if (scsi_device_dt(sdev)) | 821 | if (scsi_device_dt(sdev)) |
823 | len = spi_dv_device_get_echo_buffer(sreq, buffer); | 822 | len = spi_dv_device_get_echo_buffer(sdev, buffer); |
824 | 823 | ||
825 | retry: | 824 | retry: |
826 | 825 | ||
@@ -846,7 +845,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
846 | 845 | ||
847 | if (len == 0) { | 846 | if (len == 0) { |
848 | SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); | 847 | SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); |
849 | spi_dv_retrain(sreq, buffer, buffer + len, | 848 | spi_dv_retrain(sdev, buffer, buffer + len, |
850 | spi_dv_device_compare_inquiry); | 849 | spi_dv_device_compare_inquiry); |
851 | return; | 850 | return; |
852 | } | 851 | } |
@@ -856,7 +855,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
856 | len = SPI_MAX_ECHO_BUFFER_SIZE; | 855 | len = SPI_MAX_ECHO_BUFFER_SIZE; |
857 | } | 856 | } |
858 | 857 | ||
859 | if (spi_dv_retrain(sreq, buffer, buffer + len, | 858 | if (spi_dv_retrain(sdev, buffer, buffer + len, |
860 | spi_dv_device_echo_buffer) | 859 | spi_dv_device_echo_buffer) |
861 | == SPI_COMPARE_SKIP_TEST) { | 860 | == SPI_COMPARE_SKIP_TEST) { |
862 | /* OK, the stupid drive can't do a write echo buffer | 861 | /* OK, the stupid drive can't do a write echo buffer |
@@ -879,16 +878,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
879 | void | 878 | void |
880 | spi_dv_device(struct scsi_device *sdev) | 879 | spi_dv_device(struct scsi_device *sdev) |
881 | { | 880 | { |
882 | struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); | ||
883 | struct scsi_target *starget = sdev->sdev_target; | 881 | struct scsi_target *starget = sdev->sdev_target; |
884 | u8 *buffer; | 882 | u8 *buffer; |
885 | const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; | 883 | const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; |
886 | 884 | ||
887 | if (unlikely(!sreq)) | ||
888 | return; | ||
889 | |||
890 | if (unlikely(scsi_device_get(sdev))) | 885 | if (unlikely(scsi_device_get(sdev))) |
891 | goto out_free_req; | 886 | return; |
892 | 887 | ||
893 | buffer = kmalloc(len, GFP_KERNEL); | 888 | buffer = kmalloc(len, GFP_KERNEL); |
894 | 889 | ||
@@ -909,7 +904,7 @@ spi_dv_device(struct scsi_device *sdev) | |||
909 | 904 | ||
910 | SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); | 905 | SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); |
911 | 906 | ||
912 | spi_dv_device_internal(sreq, buffer); | 907 | spi_dv_device_internal(sdev, buffer); |
913 | 908 | ||
914 | SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); | 909 | SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); |
915 | 910 | ||
@@ -924,8 +919,6 @@ spi_dv_device(struct scsi_device *sdev) | |||
924 | kfree(buffer); | 919 | kfree(buffer); |
925 | out_put: | 920 | out_put: |
926 | scsi_device_put(sdev); | 921 | scsi_device_put(sdev); |
927 | out_free_req: | ||
928 | scsi_release_request(sreq); | ||
929 | } | 922 | } |
930 | EXPORT_SYMBOL(spi_dv_device); | 923 | EXPORT_SYMBOL(spi_dv_device); |
931 | 924 | ||
@@ -1028,10 +1021,17 @@ void spi_display_xfer_agreement(struct scsi_target *starget) | |||
1028 | sprint_frac(tmp, picosec, 1000); | 1021 | sprint_frac(tmp, picosec, 1000); |
1029 | 1022 | ||
1030 | dev_info(&starget->dev, | 1023 | dev_info(&starget->dev, |
1031 | "%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n", | 1024 | "%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, | 1025 | scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10, |
1033 | tp->dt ? "DT" : "ST", tp->iu ? " IU" : "", | 1026 | tp->dt ? "DT" : "ST", |
1034 | tp->qas ? " QAS" : "", tmp, tp->offset); | 1027 | tp->iu ? " IU" : "", |
1028 | tp->qas ? " QAS" : "", | ||
1029 | tp->rd_strm ? " RDSTRM" : "", | ||
1030 | tp->rti ? " RTI" : "", | ||
1031 | tp->wr_flow ? " WRFLOW" : "", | ||
1032 | tp->pcomp_en ? " PCOMP" : "", | ||
1033 | tp->hold_mcs ? " HMCS" : "", | ||
1034 | tmp, tp->offset); | ||
1035 | } else { | 1035 | } else { |
1036 | dev_info(&starget->dev, "%sasynchronous.\n", | 1036 | dev_info(&starget->dev, "%sasynchronous.\n", |
1037 | tp->width ? "wide " : ""); | 1037 | tp->width ? "wide " : ""); |
@@ -1073,6 +1073,7 @@ static int spi_device_match(struct attribute_container *cont, | |||
1073 | { | 1073 | { |
1074 | struct scsi_device *sdev; | 1074 | struct scsi_device *sdev; |
1075 | struct Scsi_Host *shost; | 1075 | struct Scsi_Host *shost; |
1076 | struct spi_internal *i; | ||
1076 | 1077 | ||
1077 | if (!scsi_is_sdev_device(dev)) | 1078 | if (!scsi_is_sdev_device(dev)) |
1078 | return 0; | 1079 | return 0; |
@@ -1085,6 +1086,9 @@ static int spi_device_match(struct attribute_container *cont, | |||
1085 | /* Note: this class has no device attributes, so it has | 1086 | /* Note: this class has no device attributes, so it has |
1086 | * no per-HBA allocation and thus we don't need to distinguish | 1087 | * no per-HBA allocation and thus we don't need to distinguish |
1087 | * the attribute containers for the device */ | 1088 | * the attribute containers for the device */ |
1089 | i = to_spi_internal(shost->transportt); | ||
1090 | if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target)) | ||
1091 | return 0; | ||
1088 | return 1; | 1092 | return 1; |
1089 | } | 1093 | } |
1090 | 1094 | ||
@@ -1092,6 +1096,7 @@ static int spi_target_match(struct attribute_container *cont, | |||
1092 | struct device *dev) | 1096 | struct device *dev) |
1093 | { | 1097 | { |
1094 | struct Scsi_Host *shost; | 1098 | struct Scsi_Host *shost; |
1099 | struct scsi_target *starget; | ||
1095 | struct spi_internal *i; | 1100 | struct spi_internal *i; |
1096 | 1101 | ||
1097 | if (!scsi_is_target_device(dev)) | 1102 | if (!scsi_is_target_device(dev)) |
@@ -1103,7 +1108,11 @@ static int spi_target_match(struct attribute_container *cont, | |||
1103 | return 0; | 1108 | return 0; |
1104 | 1109 | ||
1105 | i = to_spi_internal(shost->transportt); | 1110 | i = to_spi_internal(shost->transportt); |
1106 | 1111 | starget = to_scsi_target(dev); | |
1112 | |||
1113 | if (i->f->deny_binding && i->f->deny_binding(starget)) | ||
1114 | return 0; | ||
1115 | |||
1107 | return &i->t.target_attrs.ac == cont; | 1116 | return &i->t.target_attrs.ac == cont; |
1108 | } | 1117 | } |
1109 | 1118 | ||
@@ -1154,6 +1163,7 @@ spi_attach_transport(struct spi_function_template *ft) | |||
1154 | SETUP_ATTRIBUTE(rd_strm); | 1163 | SETUP_ATTRIBUTE(rd_strm); |
1155 | SETUP_ATTRIBUTE(rti); | 1164 | SETUP_ATTRIBUTE(rti); |
1156 | SETUP_ATTRIBUTE(pcomp_en); | 1165 | SETUP_ATTRIBUTE(pcomp_en); |
1166 | SETUP_ATTRIBUTE(hold_mcs); | ||
1157 | 1167 | ||
1158 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS | 1168 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS |
1159 | * this bug will trigger */ | 1169 | * this bug will trigger */ |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0410e1bf109a..de564b386052 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #include <scsi/scsi_eh.h> | 59 | #include <scsi/scsi_eh.h> |
60 | #include <scsi/scsi_host.h> | 60 | #include <scsi/scsi_host.h> |
61 | #include <scsi/scsi_ioctl.h> | 61 | #include <scsi/scsi_ioctl.h> |
62 | #include <scsi/scsi_request.h> | ||
63 | #include <scsi/scsicam.h> | 62 | #include <scsi/scsicam.h> |
64 | 63 | ||
65 | #include "scsi_logging.h" | 64 | #include "scsi_logging.h" |
@@ -125,7 +124,7 @@ static int sd_issue_flush(struct device *, sector_t *); | |||
125 | static void sd_end_flush(request_queue_t *, struct request *); | 124 | static void sd_end_flush(request_queue_t *, struct request *); |
126 | static int sd_prepare_flush(request_queue_t *, struct request *); | 125 | static int sd_prepare_flush(request_queue_t *, struct request *); |
127 | static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, | 126 | static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, |
128 | struct scsi_request *SRpnt, unsigned char *buffer); | 127 | unsigned char *buffer); |
129 | 128 | ||
130 | static struct scsi_driver sd_template = { | 129 | static struct scsi_driver sd_template = { |
131 | .owner = THIS_MODULE, | 130 | .owner = THIS_MODULE, |
@@ -682,19 +681,13 @@ not_present: | |||
682 | 681 | ||
683 | static int sd_sync_cache(struct scsi_device *sdp) | 682 | static int sd_sync_cache(struct scsi_device *sdp) |
684 | { | 683 | { |
685 | struct scsi_request *sreq; | ||
686 | int retries, res; | 684 | int retries, res; |
685 | struct scsi_sense_hdr sshdr; | ||
687 | 686 | ||
688 | if (!scsi_device_online(sdp)) | 687 | if (!scsi_device_online(sdp)) |
689 | return -ENODEV; | 688 | return -ENODEV; |
690 | 689 | ||
691 | sreq = scsi_allocate_request(sdp, GFP_KERNEL); | ||
692 | if (!sreq) { | ||
693 | printk("FAILED\n No memory for request\n"); | ||
694 | return -ENOMEM; | ||
695 | } | ||
696 | 690 | ||
697 | sreq->sr_data_direction = DMA_NONE; | ||
698 | for (retries = 3; retries > 0; --retries) { | 691 | for (retries = 3; retries > 0; --retries) { |
699 | unsigned char cmd[10] = { 0 }; | 692 | unsigned char cmd[10] = { 0 }; |
700 | 693 | ||
@@ -703,22 +696,20 @@ static int sd_sync_cache(struct scsi_device *sdp) | |||
703 | * Leave the rest of the command zero to indicate | 696 | * Leave the rest of the command zero to indicate |
704 | * flush everything. | 697 | * flush everything. |
705 | */ | 698 | */ |
706 | scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); | 699 | res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, |
707 | if (sreq->sr_result == 0) | 700 | SD_TIMEOUT, SD_MAX_RETRIES); |
701 | if (res == 0) | ||
708 | break; | 702 | break; |
709 | } | 703 | } |
710 | 704 | ||
711 | res = sreq->sr_result; | 705 | if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " |
712 | if (res) { | ||
713 | printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " | ||
714 | "host = %d, driver = %02x\n ", | 706 | "host = %d, driver = %02x\n ", |
715 | status_byte(res), msg_byte(res), | 707 | status_byte(res), msg_byte(res), |
716 | host_byte(res), driver_byte(res)); | 708 | host_byte(res), driver_byte(res)); |
717 | if (driver_byte(res) & DRIVER_SENSE) | 709 | if (driver_byte(res) & DRIVER_SENSE) |
718 | scsi_print_req_sense("sd", sreq); | 710 | scsi_print_sense_hdr("sd", &sshdr); |
719 | } | 711 | } |
720 | 712 | ||
721 | scsi_release_request(sreq); | ||
722 | return res; | 713 | return res; |
723 | } | 714 | } |
724 | 715 | ||
@@ -957,22 +948,19 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
957 | scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); | 948 | scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); |
958 | } | 949 | } |
959 | 950 | ||
960 | static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) | 951 | static int media_not_present(struct scsi_disk *sdkp, |
952 | struct scsi_sense_hdr *sshdr) | ||
961 | { | 953 | { |
962 | struct scsi_sense_hdr sshdr; | ||
963 | 954 | ||
964 | if (!srp->sr_result) | 955 | if (!scsi_sense_valid(sshdr)) |
965 | return 0; | ||
966 | if (!(driver_byte(srp->sr_result) & DRIVER_SENSE)) | ||
967 | return 0; | 956 | return 0; |
968 | /* not invoked for commands that could return deferred errors */ | 957 | /* not invoked for commands that could return deferred errors */ |
969 | if (scsi_request_normalize_sense(srp, &sshdr)) { | 958 | if (sshdr->sense_key != NOT_READY && |
970 | if (sshdr.sense_key != NOT_READY && | 959 | sshdr->sense_key != UNIT_ATTENTION) |
971 | sshdr.sense_key != UNIT_ATTENTION) | 960 | return 0; |
972 | return 0; | 961 | if (sshdr->asc != 0x3A) /* medium not present */ |
973 | if (sshdr.asc != 0x3A) /* medium not present */ | 962 | return 0; |
974 | return 0; | 963 | |
975 | } | ||
976 | set_media_not_present(sdkp); | 964 | set_media_not_present(sdkp); |
977 | return 1; | 965 | return 1; |
978 | } | 966 | } |
@@ -981,10 +969,10 @@ static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) | |||
981 | * spinup disk - called only in sd_revalidate_disk() | 969 | * spinup disk - called only in sd_revalidate_disk() |
982 | */ | 970 | */ |
983 | static void | 971 | static void |
984 | sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | 972 | sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) |
985 | struct scsi_request *SRpnt, unsigned char *buffer) { | 973 | { |
986 | unsigned char cmd[10]; | 974 | unsigned char cmd[10]; |
987 | unsigned long spintime_value = 0; | 975 | unsigned long spintime_expire = 0; |
988 | int retries, spintime; | 976 | int retries, spintime; |
989 | unsigned int the_result; | 977 | unsigned int the_result; |
990 | struct scsi_sense_hdr sshdr; | 978 | struct scsi_sense_hdr sshdr; |
@@ -1001,18 +989,13 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | |||
1001 | cmd[0] = TEST_UNIT_READY; | 989 | cmd[0] = TEST_UNIT_READY; |
1002 | memset((void *) &cmd[1], 0, 9); | 990 | memset((void *) &cmd[1], 0, 9); |
1003 | 991 | ||
1004 | SRpnt->sr_cmd_len = 0; | 992 | the_result = scsi_execute_req(sdkp->device, cmd, |
1005 | memset(SRpnt->sr_sense_buffer, 0, | 993 | DMA_NONE, NULL, 0, |
1006 | SCSI_SENSE_BUFFERSIZE); | 994 | &sshdr, SD_TIMEOUT, |
1007 | SRpnt->sr_data_direction = DMA_NONE; | 995 | SD_MAX_RETRIES); |
1008 | 996 | ||
1009 | scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, | ||
1010 | 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES); | ||
1011 | |||
1012 | the_result = SRpnt->sr_result; | ||
1013 | if (the_result) | 997 | if (the_result) |
1014 | sense_valid = scsi_request_normalize_sense( | 998 | sense_valid = scsi_sense_valid(&sshdr); |
1015 | SRpnt, &sshdr); | ||
1016 | retries++; | 999 | retries++; |
1017 | } while (retries < 3 && | 1000 | } while (retries < 3 && |
1018 | (!scsi_status_is_good(the_result) || | 1001 | (!scsi_status_is_good(the_result) || |
@@ -1024,7 +1007,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | |||
1024 | * any media in it, don't bother with any of the rest of | 1007 | * any media in it, don't bother with any of the rest of |
1025 | * this crap. | 1008 | * this crap. |
1026 | */ | 1009 | */ |
1027 | if (media_not_present(sdkp, SRpnt)) | 1010 | if (media_not_present(sdkp, &sshdr)) |
1028 | return; | 1011 | return; |
1029 | 1012 | ||
1030 | if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { | 1013 | if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { |
@@ -1063,33 +1046,42 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | |||
1063 | cmd[1] = 1; /* Return immediately */ | 1046 | cmd[1] = 1; /* Return immediately */ |
1064 | memset((void *) &cmd[2], 0, 8); | 1047 | memset((void *) &cmd[2], 0, 8); |
1065 | cmd[4] = 1; /* Start spin cycle */ | 1048 | cmd[4] = 1; /* Start spin cycle */ |
1066 | SRpnt->sr_cmd_len = 0; | 1049 | scsi_execute_req(sdkp->device, cmd, DMA_NONE, |
1067 | memset(SRpnt->sr_sense_buffer, 0, | 1050 | NULL, 0, &sshdr, |
1068 | SCSI_SENSE_BUFFERSIZE); | 1051 | SD_TIMEOUT, SD_MAX_RETRIES); |
1069 | 1052 | spintime_expire = jiffies + 100 * HZ; | |
1070 | SRpnt->sr_data_direction = DMA_NONE; | 1053 | spintime = 1; |
1071 | scsi_wait_req(SRpnt, (void *)cmd, | ||
1072 | (void *) buffer, 0/*512*/, | ||
1073 | SD_TIMEOUT, SD_MAX_RETRIES); | ||
1074 | spintime_value = jiffies; | ||
1075 | } | 1054 | } |
1076 | spintime = 1; | ||
1077 | /* Wait 1 second for next try */ | 1055 | /* Wait 1 second for next try */ |
1078 | msleep(1000); | 1056 | msleep(1000); |
1079 | printk("."); | 1057 | printk("."); |
1058 | |||
1059 | /* | ||
1060 | * Wait for USB flash devices with slow firmware. | ||
1061 | * Yes, this sense key/ASC combination shouldn't | ||
1062 | * occur here. It's characteristic of these devices. | ||
1063 | */ | ||
1064 | } else if (sense_valid && | ||
1065 | sshdr.sense_key == UNIT_ATTENTION && | ||
1066 | sshdr.asc == 0x28) { | ||
1067 | if (!spintime) { | ||
1068 | spintime_expire = jiffies + 5 * HZ; | ||
1069 | spintime = 1; | ||
1070 | } | ||
1071 | /* Wait 1 second for next try */ | ||
1072 | msleep(1000); | ||
1080 | } else { | 1073 | } else { |
1081 | /* we don't understand the sense code, so it's | 1074 | /* we don't understand the sense code, so it's |
1082 | * probably pointless to loop */ | 1075 | * probably pointless to loop */ |
1083 | if(!spintime) { | 1076 | if(!spintime) { |
1084 | printk(KERN_NOTICE "%s: Unit Not Ready, " | 1077 | printk(KERN_NOTICE "%s: Unit Not Ready, " |
1085 | "sense:\n", diskname); | 1078 | "sense:\n", diskname); |
1086 | scsi_print_req_sense("", SRpnt); | 1079 | scsi_print_sense_hdr("", &sshdr); |
1087 | } | 1080 | } |
1088 | break; | 1081 | break; |
1089 | } | 1082 | } |
1090 | 1083 | ||
1091 | } while (spintime && | 1084 | } while (spintime && time_before_eq(jiffies, spintime_expire)); |
1092 | time_after(spintime_value + 100 * HZ, jiffies)); | ||
1093 | 1085 | ||
1094 | if (spintime) { | 1086 | if (spintime) { |
1095 | if (scsi_status_is_good(the_result)) | 1087 | if (scsi_status_is_good(the_result)) |
@@ -1104,14 +1096,15 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | |||
1104 | */ | 1096 | */ |
1105 | static void | 1097 | static void |
1106 | sd_read_capacity(struct scsi_disk *sdkp, char *diskname, | 1098 | sd_read_capacity(struct scsi_disk *sdkp, char *diskname, |
1107 | struct scsi_request *SRpnt, unsigned char *buffer) { | 1099 | unsigned char *buffer) |
1100 | { | ||
1108 | unsigned char cmd[16]; | 1101 | unsigned char cmd[16]; |
1109 | struct scsi_device *sdp = sdkp->device; | ||
1110 | int the_result, retries; | 1102 | int the_result, retries; |
1111 | int sector_size = 0; | 1103 | int sector_size = 0; |
1112 | int longrc = 0; | 1104 | int longrc = 0; |
1113 | struct scsi_sense_hdr sshdr; | 1105 | struct scsi_sense_hdr sshdr; |
1114 | int sense_valid = 0; | 1106 | int sense_valid = 0; |
1107 | struct scsi_device *sdp = sdkp->device; | ||
1115 | 1108 | ||
1116 | repeat: | 1109 | repeat: |
1117 | retries = 3; | 1110 | retries = 3; |
@@ -1128,20 +1121,15 @@ repeat: | |||
1128 | memset((void *) buffer, 0, 8); | 1121 | memset((void *) buffer, 0, 8); |
1129 | } | 1122 | } |
1130 | 1123 | ||
1131 | SRpnt->sr_cmd_len = 0; | 1124 | the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, |
1132 | memset(SRpnt->sr_sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 1125 | buffer, longrc ? 12 : 8, &sshdr, |
1133 | SRpnt->sr_data_direction = DMA_FROM_DEVICE; | 1126 | SD_TIMEOUT, SD_MAX_RETRIES); |
1134 | |||
1135 | scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, | ||
1136 | longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES); | ||
1137 | 1127 | ||
1138 | if (media_not_present(sdkp, SRpnt)) | 1128 | if (media_not_present(sdkp, &sshdr)) |
1139 | return; | 1129 | return; |
1140 | 1130 | ||
1141 | the_result = SRpnt->sr_result; | ||
1142 | if (the_result) | 1131 | if (the_result) |
1143 | sense_valid = scsi_request_normalize_sense(SRpnt, | 1132 | sense_valid = scsi_sense_valid(&sshdr); |
1144 | &sshdr); | ||
1145 | retries--; | 1133 | retries--; |
1146 | 1134 | ||
1147 | } while (the_result && retries); | 1135 | } while (the_result && retries); |
@@ -1156,7 +1144,7 @@ repeat: | |||
1156 | driver_byte(the_result)); | 1144 | driver_byte(the_result)); |
1157 | 1145 | ||
1158 | if (driver_byte(the_result) & DRIVER_SENSE) | 1146 | if (driver_byte(the_result) & DRIVER_SENSE) |
1159 | scsi_print_req_sense("sd", SRpnt); | 1147 | scsi_print_sense_hdr("sd", &sshdr); |
1160 | else | 1148 | else |
1161 | printk("%s : sense not available. \n", diskname); | 1149 | printk("%s : sense not available. \n", diskname); |
1162 | 1150 | ||
@@ -1296,11 +1284,13 @@ got_data: | |||
1296 | 1284 | ||
1297 | /* called with buffer of length 512 */ | 1285 | /* called with buffer of length 512 */ |
1298 | static inline int | 1286 | static inline int |
1299 | sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, | 1287 | sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage, |
1300 | unsigned char *buffer, int len, struct scsi_mode_data *data) | 1288 | unsigned char *buffer, int len, struct scsi_mode_data *data, |
1289 | struct scsi_sense_hdr *sshdr) | ||
1301 | { | 1290 | { |
1302 | return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len, | 1291 | return scsi_mode_sense(sdp, dbd, modepage, buffer, len, |
1303 | SD_TIMEOUT, SD_MAX_RETRIES, data); | 1292 | SD_TIMEOUT, SD_MAX_RETRIES, data, |
1293 | sshdr); | ||
1304 | } | 1294 | } |
1305 | 1295 | ||
1306 | /* | 1296 | /* |
@@ -1309,25 +1299,27 @@ sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, | |||
1309 | */ | 1299 | */ |
1310 | static void | 1300 | static void |
1311 | sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, | 1301 | sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, |
1312 | struct scsi_request *SRpnt, unsigned char *buffer) { | 1302 | unsigned char *buffer) |
1303 | { | ||
1313 | int res; | 1304 | int res; |
1305 | struct scsi_device *sdp = sdkp->device; | ||
1314 | struct scsi_mode_data data; | 1306 | struct scsi_mode_data data; |
1315 | 1307 | ||
1316 | set_disk_ro(sdkp->disk, 0); | 1308 | set_disk_ro(sdkp->disk, 0); |
1317 | if (sdkp->device->skip_ms_page_3f) { | 1309 | if (sdp->skip_ms_page_3f) { |
1318 | printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname); | 1310 | printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname); |
1319 | return; | 1311 | return; |
1320 | } | 1312 | } |
1321 | 1313 | ||
1322 | if (sdkp->device->use_192_bytes_for_3f) { | 1314 | if (sdp->use_192_bytes_for_3f) { |
1323 | res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data); | 1315 | res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL); |
1324 | } else { | 1316 | } else { |
1325 | /* | 1317 | /* |
1326 | * First attempt: ask for all pages (0x3F), but only 4 bytes. | 1318 | * First attempt: ask for all pages (0x3F), but only 4 bytes. |
1327 | * We have to start carefully: some devices hang if we ask | 1319 | * We have to start carefully: some devices hang if we ask |
1328 | * for more than is available. | 1320 | * for more than is available. |
1329 | */ | 1321 | */ |
1330 | res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data); | 1322 | res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL); |
1331 | 1323 | ||
1332 | /* | 1324 | /* |
1333 | * Second attempt: ask for page 0 When only page 0 is | 1325 | * Second attempt: ask for page 0 When only page 0 is |
@@ -1336,14 +1328,14 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, | |||
1336 | * CDB. | 1328 | * CDB. |
1337 | */ | 1329 | */ |
1338 | if (!scsi_status_is_good(res)) | 1330 | if (!scsi_status_is_good(res)) |
1339 | res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data); | 1331 | res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL); |
1340 | 1332 | ||
1341 | /* | 1333 | /* |
1342 | * Third attempt: ask 255 bytes, as we did earlier. | 1334 | * Third attempt: ask 255 bytes, as we did earlier. |
1343 | */ | 1335 | */ |
1344 | if (!scsi_status_is_good(res)) | 1336 | if (!scsi_status_is_good(res)) |
1345 | res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255, | 1337 | res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255, |
1346 | &data); | 1338 | &data, NULL); |
1347 | } | 1339 | } |
1348 | 1340 | ||
1349 | if (!scsi_status_is_good(res)) { | 1341 | if (!scsi_status_is_good(res)) { |
@@ -1365,19 +1357,20 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, | |||
1365 | */ | 1357 | */ |
1366 | static void | 1358 | static void |
1367 | sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | 1359 | sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, |
1368 | struct scsi_request *SRpnt, unsigned char *buffer) | 1360 | unsigned char *buffer) |
1369 | { | 1361 | { |
1370 | int len = 0, res; | 1362 | int len = 0, res; |
1363 | struct scsi_device *sdp = sdkp->device; | ||
1371 | 1364 | ||
1372 | int dbd; | 1365 | int dbd; |
1373 | int modepage; | 1366 | int modepage; |
1374 | struct scsi_mode_data data; | 1367 | struct scsi_mode_data data; |
1375 | struct scsi_sense_hdr sshdr; | 1368 | struct scsi_sense_hdr sshdr; |
1376 | 1369 | ||
1377 | if (sdkp->device->skip_ms_page_8) | 1370 | if (sdp->skip_ms_page_8) |
1378 | goto defaults; | 1371 | goto defaults; |
1379 | 1372 | ||
1380 | if (sdkp->device->type == TYPE_RBC) { | 1373 | if (sdp->type == TYPE_RBC) { |
1381 | modepage = 6; | 1374 | modepage = 6; |
1382 | dbd = 8; | 1375 | dbd = 8; |
1383 | } else { | 1376 | } else { |
@@ -1386,7 +1379,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1386 | } | 1379 | } |
1387 | 1380 | ||
1388 | /* cautiously ask */ | 1381 | /* cautiously ask */ |
1389 | res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data); | 1382 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); |
1390 | 1383 | ||
1391 | if (!scsi_status_is_good(res)) | 1384 | if (!scsi_status_is_good(res)) |
1392 | goto bad_sense; | 1385 | goto bad_sense; |
@@ -1407,7 +1400,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1407 | len += data.header_length + data.block_descriptor_length; | 1400 | len += data.header_length + data.block_descriptor_length; |
1408 | 1401 | ||
1409 | /* Get the data */ | 1402 | /* Get the data */ |
1410 | res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data); | 1403 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); |
1411 | 1404 | ||
1412 | if (scsi_status_is_good(res)) { | 1405 | if (scsi_status_is_good(res)) { |
1413 | const char *types[] = { | 1406 | const char *types[] = { |
@@ -1439,7 +1432,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1439 | } | 1432 | } |
1440 | 1433 | ||
1441 | bad_sense: | 1434 | bad_sense: |
1442 | if (scsi_request_normalize_sense(SRpnt, &sshdr) && | 1435 | if (scsi_sense_valid(&sshdr) && |
1443 | sshdr.sense_key == ILLEGAL_REQUEST && | 1436 | sshdr.sense_key == ILLEGAL_REQUEST && |
1444 | sshdr.asc == 0x24 && sshdr.ascq == 0x0) | 1437 | sshdr.asc == 0x24 && sshdr.ascq == 0x0) |
1445 | printk(KERN_NOTICE "%s: cache data unavailable\n", | 1438 | printk(KERN_NOTICE "%s: cache data unavailable\n", |
@@ -1464,7 +1457,6 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1464 | { | 1457 | { |
1465 | struct scsi_disk *sdkp = scsi_disk(disk); | 1458 | struct scsi_disk *sdkp = scsi_disk(disk); |
1466 | struct scsi_device *sdp = sdkp->device; | 1459 | struct scsi_device *sdp = sdkp->device; |
1467 | struct scsi_request *sreq; | ||
1468 | unsigned char *buffer; | 1460 | unsigned char *buffer; |
1469 | 1461 | ||
1470 | SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); | 1462 | SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); |
@@ -1476,18 +1468,11 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1476 | if (!scsi_device_online(sdp)) | 1468 | if (!scsi_device_online(sdp)) |
1477 | goto out; | 1469 | goto out; |
1478 | 1470 | ||
1479 | sreq = scsi_allocate_request(sdp, GFP_KERNEL); | ||
1480 | if (!sreq) { | ||
1481 | printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation " | ||
1482 | "failure.\n"); | ||
1483 | goto out; | ||
1484 | } | ||
1485 | |||
1486 | buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA); | 1471 | buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA); |
1487 | if (!buffer) { | 1472 | if (!buffer) { |
1488 | printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation " | 1473 | printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation " |
1489 | "failure.\n"); | 1474 | "failure.\n"); |
1490 | goto out_release_request; | 1475 | goto out; |
1491 | } | 1476 | } |
1492 | 1477 | ||
1493 | /* defaults, until the device tells us otherwise */ | 1478 | /* defaults, until the device tells us otherwise */ |
@@ -1498,25 +1483,23 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1498 | sdkp->WCE = 0; | 1483 | sdkp->WCE = 0; |
1499 | sdkp->RCD = 0; | 1484 | sdkp->RCD = 0; |
1500 | 1485 | ||
1501 | sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer); | 1486 | sd_spinup_disk(sdkp, disk->disk_name); |
1502 | 1487 | ||
1503 | /* | 1488 | /* |
1504 | * Without media there is no reason to ask; moreover, some devices | 1489 | * Without media there is no reason to ask; moreover, some devices |
1505 | * react badly if we do. | 1490 | * react badly if we do. |
1506 | */ | 1491 | */ |
1507 | if (sdkp->media_present) { | 1492 | if (sdkp->media_present) { |
1508 | sd_read_capacity(sdkp, disk->disk_name, sreq, buffer); | 1493 | sd_read_capacity(sdkp, disk->disk_name, buffer); |
1509 | if (sdp->removable) | 1494 | if (sdp->removable) |
1510 | sd_read_write_protect_flag(sdkp, disk->disk_name, | 1495 | sd_read_write_protect_flag(sdkp, disk->disk_name, |
1511 | sreq, buffer); | 1496 | buffer); |
1512 | sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer); | 1497 | sd_read_cache_type(sdkp, disk->disk_name, buffer); |
1513 | } | 1498 | } |
1514 | 1499 | ||
1515 | set_capacity(disk, sdkp->capacity); | 1500 | set_capacity(disk, sdkp->capacity); |
1516 | kfree(buffer); | 1501 | kfree(buffer); |
1517 | 1502 | ||
1518 | out_release_request: | ||
1519 | scsi_release_request(sreq); | ||
1520 | out: | 1503 | out: |
1521 | return 0; | 1504 | return 0; |
1522 | } | 1505 | } |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index e822ca0e97cf..b1b69d738d08 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -61,7 +61,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */ | |||
61 | 61 | ||
62 | #ifdef CONFIG_SCSI_PROC_FS | 62 | #ifdef CONFIG_SCSI_PROC_FS |
63 | #include <linux/proc_fs.h> | 63 | #include <linux/proc_fs.h> |
64 | static char *sg_version_date = "20050328"; | 64 | static char *sg_version_date = "20050901"; |
65 | 65 | ||
66 | static int sg_proc_init(void); | 66 | static int sg_proc_init(void); |
67 | static void sg_proc_cleanup(void); | 67 | static void sg_proc_cleanup(void); |
@@ -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; |
@@ -1795,12 +1794,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, | |||
1795 | unsigned long uaddr, size_t count, int rw, | 1794 | unsigned long uaddr, size_t count, int rw, |
1796 | unsigned long max_pfn) | 1795 | unsigned long max_pfn) |
1797 | { | 1796 | { |
1797 | unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1798 | unsigned long start = uaddr >> PAGE_SHIFT; | ||
1799 | const int nr_pages = end - start; | ||
1798 | int res, i, j; | 1800 | int res, i, j; |
1799 | unsigned int nr_pages; | ||
1800 | struct page **pages; | 1801 | struct page **pages; |
1801 | 1802 | ||
1802 | nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; | ||
1803 | |||
1804 | /* User attempted Overflow! */ | 1803 | /* User attempted Overflow! */ |
1805 | if ((uaddr + count) < uaddr) | 1804 | if ((uaddr + count) < uaddr) |
1806 | return -EINVAL; | 1805 | return -EINVAL; |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 2f259f249522..ce63fc8312dc 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
@@ -50,10 +50,10 @@ | |||
50 | #include <scsi/scsi_dbg.h> | 50 | #include <scsi/scsi_dbg.h> |
51 | #include <scsi/scsi_device.h> | 51 | #include <scsi/scsi_device.h> |
52 | #include <scsi/scsi_driver.h> | 52 | #include <scsi/scsi_driver.h> |
53 | #include <scsi/scsi_cmnd.h> | ||
53 | #include <scsi/scsi_eh.h> | 54 | #include <scsi/scsi_eh.h> |
54 | #include <scsi/scsi_host.h> | 55 | #include <scsi/scsi_host.h> |
55 | #include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */ | 56 | #include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */ |
56 | #include <scsi/scsi_request.h> | ||
57 | 57 | ||
58 | #include "scsi_logging.h" | 58 | #include "scsi_logging.h" |
59 | #include "sr.h" | 59 | #include "sr.h" |
@@ -199,15 +199,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot) | |||
199 | /* check multisession offset etc */ | 199 | /* check multisession offset etc */ |
200 | sr_cd_check(cdi); | 200 | sr_cd_check(cdi); |
201 | 201 | ||
202 | /* | 202 | get_sectorsize(cd); |
203 | * If the disk changed, the capacity will now be different, | ||
204 | * so we force a re-read of this information | ||
205 | * Force 2048 for the sector size so that filesystems won't | ||
206 | * be trying to use something that is too small if the disc | ||
207 | * has changed. | ||
208 | */ | ||
209 | cd->needs_sector_size = 1; | ||
210 | cd->device->sector_size = 2048; | ||
211 | } | 203 | } |
212 | return retval; | 204 | return retval; |
213 | } | 205 | } |
@@ -538,13 +530,6 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose) | |||
538 | if (!scsi_block_when_processing_errors(sdev)) | 530 | if (!scsi_block_when_processing_errors(sdev)) |
539 | goto error_out; | 531 | goto error_out; |
540 | 532 | ||
541 | /* | ||
542 | * If this device did not have media in the drive at boot time, then | ||
543 | * we would have been unable to get the sector size. Check to see if | ||
544 | * this is the case, and try again. | ||
545 | */ | ||
546 | if (cd->needs_sector_size) | ||
547 | get_sectorsize(cd); | ||
548 | return 0; | 533 | return 0; |
549 | 534 | ||
550 | error_out: | 535 | error_out: |
@@ -604,7 +589,6 @@ static int sr_probe(struct device *dev) | |||
604 | cd->driver = &sr_template; | 589 | cd->driver = &sr_template; |
605 | cd->disk = disk; | 590 | cd->disk = disk; |
606 | cd->capacity = 0x1fffff; | 591 | cd->capacity = 0x1fffff; |
607 | cd->needs_sector_size = 1; | ||
608 | cd->device->changed = 1; /* force recheck CD type */ | 592 | cd->device->changed = 1; /* force recheck CD type */ |
609 | cd->use = 1; | 593 | cd->use = 1; |
610 | cd->readcd_known = 0; | 594 | cd->readcd_known = 0; |
@@ -658,43 +642,30 @@ static void get_sectorsize(struct scsi_cd *cd) | |||
658 | unsigned char *buffer; | 642 | unsigned char *buffer; |
659 | int the_result, retries = 3; | 643 | int the_result, retries = 3; |
660 | int sector_size; | 644 | int sector_size; |
661 | struct scsi_request *SRpnt = NULL; | ||
662 | request_queue_t *queue; | 645 | request_queue_t *queue; |
663 | 646 | ||
664 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); | 647 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); |
665 | if (!buffer) | 648 | if (!buffer) |
666 | goto Enomem; | 649 | goto Enomem; |
667 | SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); | ||
668 | if (!SRpnt) | ||
669 | goto Enomem; | ||
670 | 650 | ||
671 | do { | 651 | do { |
672 | cmd[0] = READ_CAPACITY; | 652 | cmd[0] = READ_CAPACITY; |
673 | memset((void *) &cmd[1], 0, 9); | 653 | memset((void *) &cmd[1], 0, 9); |
674 | /* Mark as really busy */ | ||
675 | SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; | ||
676 | SRpnt->sr_cmd_len = 0; | ||
677 | |||
678 | memset(buffer, 0, 8); | 654 | memset(buffer, 0, 8); |
679 | 655 | ||
680 | /* Do the command and wait.. */ | 656 | /* Do the command and wait.. */ |
681 | SRpnt->sr_data_direction = DMA_FROM_DEVICE; | 657 | the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE, |
682 | scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, | 658 | buffer, 8, NULL, SR_TIMEOUT, |
683 | 8, SR_TIMEOUT, MAX_RETRIES); | 659 | MAX_RETRIES); |
684 | 660 | ||
685 | the_result = SRpnt->sr_result; | ||
686 | retries--; | 661 | retries--; |
687 | 662 | ||
688 | } while (the_result && retries); | 663 | } while (the_result && retries); |
689 | 664 | ||
690 | 665 | ||
691 | scsi_release_request(SRpnt); | ||
692 | SRpnt = NULL; | ||
693 | |||
694 | if (the_result) { | 666 | if (the_result) { |
695 | cd->capacity = 0x1fffff; | 667 | cd->capacity = 0x1fffff; |
696 | sector_size = 2048; /* A guess, just in case */ | 668 | sector_size = 2048; /* A guess, just in case */ |
697 | cd->needs_sector_size = 1; | ||
698 | } else { | 669 | } else { |
699 | #if 0 | 670 | #if 0 |
700 | if (cdrom_get_last_written(&cd->cdi, | 671 | if (cdrom_get_last_written(&cd->cdi, |
@@ -727,7 +698,6 @@ static void get_sectorsize(struct scsi_cd *cd) | |||
727 | printk("%s: unsupported sector size %d.\n", | 698 | printk("%s: unsupported sector size %d.\n", |
728 | cd->cdi.name, sector_size); | 699 | cd->cdi.name, sector_size); |
729 | cd->capacity = 0; | 700 | cd->capacity = 0; |
730 | cd->needs_sector_size = 1; | ||
731 | } | 701 | } |
732 | 702 | ||
733 | cd->device->sector_size = sector_size; | 703 | cd->device->sector_size = sector_size; |
@@ -736,7 +706,6 @@ static void get_sectorsize(struct scsi_cd *cd) | |||
736 | * Add this so that we have the ability to correctly gauge | 706 | * Add this so that we have the ability to correctly gauge |
737 | * what the device is capable of. | 707 | * what the device is capable of. |
738 | */ | 708 | */ |
739 | cd->needs_sector_size = 0; | ||
740 | set_capacity(cd->disk, cd->capacity); | 709 | set_capacity(cd->disk, cd->capacity); |
741 | } | 710 | } |
742 | 711 | ||
@@ -748,10 +717,7 @@ out: | |||
748 | 717 | ||
749 | Enomem: | 718 | Enomem: |
750 | cd->capacity = 0x1fffff; | 719 | cd->capacity = 0x1fffff; |
751 | sector_size = 2048; /* A guess, just in case */ | 720 | cd->device->sector_size = 2048; /* A guess, just in case */ |
752 | cd->needs_sector_size = 1; | ||
753 | if (SRpnt) | ||
754 | scsi_release_request(SRpnt); | ||
755 | goto out; | 721 | goto out; |
756 | } | 722 | } |
757 | 723 | ||
@@ -759,8 +725,8 @@ static void get_capabilities(struct scsi_cd *cd) | |||
759 | { | 725 | { |
760 | unsigned char *buffer; | 726 | unsigned char *buffer; |
761 | struct scsi_mode_data data; | 727 | struct scsi_mode_data data; |
762 | struct scsi_request *SRpnt; | ||
763 | unsigned char cmd[MAX_COMMAND_SIZE]; | 728 | unsigned char cmd[MAX_COMMAND_SIZE]; |
729 | struct scsi_sense_hdr sshdr; | ||
764 | unsigned int the_result; | 730 | unsigned int the_result; |
765 | int retries, rc, n; | 731 | int retries, rc, n; |
766 | 732 | ||
@@ -776,19 +742,11 @@ static void get_capabilities(struct scsi_cd *cd) | |||
776 | "" | 742 | "" |
777 | }; | 743 | }; |
778 | 744 | ||
779 | /* allocate a request for the TEST_UNIT_READY */ | ||
780 | SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); | ||
781 | if (!SRpnt) { | ||
782 | printk(KERN_WARNING "(get_capabilities:) Request allocation " | ||
783 | "failure.\n"); | ||
784 | return; | ||
785 | } | ||
786 | 745 | ||
787 | /* allocate transfer buffer */ | 746 | /* allocate transfer buffer */ |
788 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); | 747 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); |
789 | if (!buffer) { | 748 | if (!buffer) { |
790 | printk(KERN_ERR "sr: out of memory.\n"); | 749 | printk(KERN_ERR "sr: out of memory.\n"); |
791 | scsi_release_request(SRpnt); | ||
792 | return; | 750 | return; |
793 | } | 751 | } |
794 | 752 | ||
@@ -800,24 +758,19 @@ static void get_capabilities(struct scsi_cd *cd) | |||
800 | memset((void *)cmd, 0, MAX_COMMAND_SIZE); | 758 | memset((void *)cmd, 0, MAX_COMMAND_SIZE); |
801 | cmd[0] = TEST_UNIT_READY; | 759 | cmd[0] = TEST_UNIT_READY; |
802 | 760 | ||
803 | SRpnt->sr_cmd_len = 0; | 761 | the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL, |
804 | SRpnt->sr_sense_buffer[0] = 0; | 762 | 0, &sshdr, SR_TIMEOUT, |
805 | SRpnt->sr_sense_buffer[2] = 0; | 763 | MAX_RETRIES); |
806 | SRpnt->sr_data_direction = DMA_NONE; | ||
807 | |||
808 | scsi_wait_req (SRpnt, (void *) cmd, buffer, | ||
809 | 0, SR_TIMEOUT, MAX_RETRIES); | ||
810 | 764 | ||
811 | the_result = SRpnt->sr_result; | ||
812 | retries++; | 765 | retries++; |
813 | } while (retries < 5 && | 766 | } while (retries < 5 && |
814 | (!scsi_status_is_good(the_result) || | 767 | (!scsi_status_is_good(the_result) || |
815 | ((driver_byte(the_result) & DRIVER_SENSE) && | 768 | (scsi_sense_valid(&sshdr) && |
816 | SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION))); | 769 | sshdr.sense_key == UNIT_ATTENTION))); |
817 | 770 | ||
818 | /* ask for mode page 0x2a */ | 771 | /* ask for mode page 0x2a */ |
819 | rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, | 772 | rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, |
820 | SR_TIMEOUT, 3, &data); | 773 | SR_TIMEOUT, 3, &data, NULL); |
821 | 774 | ||
822 | if (!scsi_status_is_good(rc)) { | 775 | if (!scsi_status_is_good(rc)) { |
823 | /* failed, drive doesn't have capabilities mode page */ | 776 | /* failed, drive doesn't have capabilities mode page */ |
@@ -825,7 +778,6 @@ static void get_capabilities(struct scsi_cd *cd) | |||
825 | cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | | 778 | cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | |
826 | CDC_DVD | CDC_DVD_RAM | | 779 | CDC_DVD | CDC_DVD_RAM | |
827 | CDC_SELECT_DISC | CDC_SELECT_SPEED); | 780 | CDC_SELECT_DISC | CDC_SELECT_SPEED); |
828 | scsi_release_request(SRpnt); | ||
829 | kfree(buffer); | 781 | kfree(buffer); |
830 | printk("%s: scsi-1 drive\n", cd->cdi.name); | 782 | printk("%s: scsi-1 drive\n", cd->cdi.name); |
831 | return; | 783 | return; |
@@ -885,7 +837,6 @@ static void get_capabilities(struct scsi_cd *cd) | |||
885 | cd->device->writeable = 1; | 837 | cd->device->writeable = 1; |
886 | } | 838 | } |
887 | 839 | ||
888 | scsi_release_request(SRpnt); | ||
889 | kfree(buffer); | 840 | kfree(buffer); |
890 | } | 841 | } |
891 | 842 | ||
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index 0b3178007203..d2bcd99c272f 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h | |||
@@ -33,7 +33,6 @@ typedef struct scsi_cd { | |||
33 | struct scsi_device *device; | 33 | struct scsi_device *device; |
34 | unsigned int vendor; /* vendor code, see sr_vendor.c */ | 34 | unsigned int vendor; /* vendor code, see sr_vendor.c */ |
35 | unsigned long ms_offset; /* for reading multisession-CD's */ | 35 | unsigned long ms_offset; /* for reading multisession-CD's */ |
36 | unsigned needs_sector_size:1; /* needs to get sector size */ | ||
37 | unsigned use:1; /* is this device still supportable */ | 36 | unsigned use:1; /* is this device still supportable */ |
38 | unsigned xa_flag:1; /* CD has XA sectors ? */ | 37 | unsigned xa_flag:1; /* CD has XA sectors ? */ |
39 | unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ | 38 | unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ |
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 82d68fdb1548..6e45ac3c43c5 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <scsi/scsi_eh.h> | 17 | #include <scsi/scsi_eh.h> |
18 | #include <scsi/scsi_host.h> | 18 | #include <scsi/scsi_host.h> |
19 | #include <scsi/scsi_ioctl.h> | 19 | #include <scsi/scsi_ioctl.h> |
20 | #include <scsi/scsi_request.h> | 20 | #include <scsi/scsi_cmnd.h> |
21 | 21 | ||
22 | #include "sr.h" | 22 | #include "sr.h" |
23 | 23 | ||
@@ -84,41 +84,37 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti | |||
84 | 84 | ||
85 | int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) | 85 | int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) |
86 | { | 86 | { |
87 | struct scsi_request *SRpnt; | ||
88 | struct scsi_device *SDev; | 87 | struct scsi_device *SDev; |
89 | struct request *req; | 88 | struct scsi_sense_hdr sshdr; |
90 | int result, err = 0, retries = 0; | 89 | int result, err = 0, retries = 0; |
90 | struct request_sense *sense = cgc->sense; | ||
91 | 91 | ||
92 | SDev = cd->device; | 92 | SDev = cd->device; |
93 | SRpnt = scsi_allocate_request(SDev, GFP_KERNEL); | 93 | |
94 | if (!SRpnt) { | 94 | if (!sense) { |
95 | printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl"); | 95 | sense = kmalloc(sizeof(*sense), GFP_KERNEL); |
96 | err = -ENOMEM; | 96 | if (!sense) { |
97 | goto out; | 97 | err = -ENOMEM; |
98 | } | 98 | goto out; |
99 | SRpnt->sr_data_direction = cgc->data_direction; | 99 | } |
100 | } | ||
100 | 101 | ||
101 | retry: | 102 | retry: |
102 | if (!scsi_block_when_processing_errors(SDev)) { | 103 | if (!scsi_block_when_processing_errors(SDev)) { |
103 | err = -ENODEV; | 104 | err = -ENODEV; |
104 | goto out_free; | 105 | goto out; |
105 | } | 106 | } |
106 | 107 | ||
107 | scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen, | 108 | memset(sense, 0, sizeof(*sense)); |
108 | cgc->timeout, IOCTL_RETRIES); | 109 | result = scsi_execute(SDev, cgc->cmd, cgc->data_direction, |
109 | 110 | cgc->buffer, cgc->buflen, (char *)sense, | |
110 | req = SRpnt->sr_request; | 111 | cgc->timeout, IOCTL_RETRIES, 0); |
111 | if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) { | ||
112 | memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen); | ||
113 | kfree(SRpnt->sr_buffer); | ||
114 | SRpnt->sr_buffer = req->buffer; | ||
115 | } | ||
116 | 112 | ||
117 | result = SRpnt->sr_result; | 113 | scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr); |
118 | 114 | ||
119 | /* Minimal error checking. Ignore cases we know about, and report the rest. */ | 115 | /* Minimal error checking. Ignore cases we know about, and report the rest. */ |
120 | if (driver_byte(result) != 0) { | 116 | if (driver_byte(result) != 0) { |
121 | switch (SRpnt->sr_sense_buffer[2] & 0xf) { | 117 | switch (sshdr.sense_key) { |
122 | case UNIT_ATTENTION: | 118 | case UNIT_ATTENTION: |
123 | SDev->changed = 1; | 119 | SDev->changed = 1; |
124 | if (!cgc->quiet) | 120 | if (!cgc->quiet) |
@@ -128,8 +124,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) | |||
128 | err = -ENOMEDIUM; | 124 | err = -ENOMEDIUM; |
129 | break; | 125 | break; |
130 | case NOT_READY: /* This happens if there is no disc in drive */ | 126 | case NOT_READY: /* This happens if there is no disc in drive */ |
131 | if (SRpnt->sr_sense_buffer[12] == 0x04 && | 127 | if (sshdr.asc == 0x04 && |
132 | SRpnt->sr_sense_buffer[13] == 0x01) { | 128 | sshdr.ascq == 0x01) { |
133 | /* sense: Logical unit is in process of becoming ready */ | 129 | /* sense: Logical unit is in process of becoming ready */ |
134 | if (!cgc->quiet) | 130 | if (!cgc->quiet) |
135 | printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); | 131 | printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); |
@@ -146,37 +142,33 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) | |||
146 | if (!cgc->quiet) | 142 | if (!cgc->quiet) |
147 | printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); | 143 | printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); |
148 | #ifdef DEBUG | 144 | #ifdef DEBUG |
149 | scsi_print_req_sense("sr", SRpnt); | 145 | scsi_print_sense_hdr("sr", &sshdr); |
150 | #endif | 146 | #endif |
151 | err = -ENOMEDIUM; | 147 | err = -ENOMEDIUM; |
152 | break; | 148 | break; |
153 | case ILLEGAL_REQUEST: | 149 | case ILLEGAL_REQUEST: |
154 | err = -EIO; | 150 | err = -EIO; |
155 | if (SRpnt->sr_sense_buffer[12] == 0x20 && | 151 | if (sshdr.asc == 0x20 && |
156 | SRpnt->sr_sense_buffer[13] == 0x00) | 152 | sshdr.ascq == 0x00) |
157 | /* sense: Invalid command operation code */ | 153 | /* sense: Invalid command operation code */ |
158 | err = -EDRIVE_CANT_DO_THIS; | 154 | err = -EDRIVE_CANT_DO_THIS; |
159 | #ifdef DEBUG | 155 | #ifdef DEBUG |
160 | __scsi_print_command(cgc->cmd); | 156 | __scsi_print_command(cgc->cmd); |
161 | scsi_print_req_sense("sr", SRpnt); | 157 | scsi_print_sense_hdr("sr", &sshdr); |
162 | #endif | 158 | #endif |
163 | break; | 159 | break; |
164 | default: | 160 | default: |
165 | printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); | 161 | printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); |
166 | __scsi_print_command(cgc->cmd); | 162 | __scsi_print_command(cgc->cmd); |
167 | scsi_print_req_sense("sr", SRpnt); | 163 | scsi_print_sense_hdr("sr", &sshdr); |
168 | err = -EIO; | 164 | err = -EIO; |
169 | } | 165 | } |
170 | } | 166 | } |
171 | 167 | ||
172 | if (cgc->sense) | ||
173 | memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense)); | ||
174 | |||
175 | /* Wake up a process waiting for device */ | 168 | /* Wake up a process waiting for device */ |
176 | out_free: | ||
177 | scsi_release_request(SRpnt); | ||
178 | SRpnt = NULL; | ||
179 | out: | 169 | out: |
170 | if (!cgc->sense) | ||
171 | kfree(sense); | ||
180 | cgc->stat = err; | 172 | cgc->stat = err; |
181 | return err; | 173 | return err; |
182 | } | 174 | } |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0a7839db5752..a93308ae9736 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 = "20050830"; |
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); |
@@ -4348,12 +4440,12 @@ static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pag | |||
4348 | static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, | 4440 | static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, |
4349 | unsigned long uaddr, size_t count, int rw) | 4441 | unsigned long uaddr, size_t count, int rw) |
4350 | { | 4442 | { |
4443 | unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
4444 | unsigned long start = uaddr >> PAGE_SHIFT; | ||
4445 | const int nr_pages = end - start; | ||
4351 | int res, i, j; | 4446 | int res, i, j; |
4352 | unsigned int nr_pages; | ||
4353 | struct page **pages; | 4447 | struct page **pages; |
4354 | 4448 | ||
4355 | nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; | ||
4356 | |||
4357 | /* User attempted Overflow! */ | 4449 | /* User attempted Overflow! */ |
4358 | if ((uaddr + count) < uaddr) | 4450 | if ((uaddr + count) < uaddr) |
4359 | return -EINVAL; | 4451 | return -EINVAL; |
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 */ |