diff options
-rw-r--r-- | drivers/scsi/advansys.c | 12273 |
1 files changed, 6043 insertions, 6230 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 0303fc7dacd3..4f047cc87c66 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -878,7 +878,6 @@ typedef struct asceep_config { | |||
878 | #define ASC_1000_ID0W_FIX 0x00C1 | 878 | #define ASC_1000_ID0W_FIX 0x00C1 |
879 | #define ASC_1000_ID1B 0x25 | 879 | #define ASC_1000_ID1B 0x25 |
880 | #define ASC_EISA_REV_IOP_MASK (0x0C83) | 880 | #define ASC_EISA_REV_IOP_MASK (0x0C83) |
881 | #define ASC_EISA_PID_IOP_MASK (0x0C80) | ||
882 | #define ASC_EISA_CFG_IOP_MASK (0x0C86) | 881 | #define ASC_EISA_CFG_IOP_MASK (0x0C86) |
883 | #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000) | 882 | #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000) |
884 | #define INS_HALTINT (ushort)0x6281 | 883 | #define INS_HALTINT (ushort)0x6281 |
@@ -903,10 +902,10 @@ typedef struct asc_mc_saved { | |||
903 | #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B) | 902 | #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B) |
904 | #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val) | 903 | #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val) |
905 | #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val) | 904 | #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val) |
906 | #define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)); | 905 | #define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)) |
907 | #define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)); | 906 | #define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)) |
908 | #define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data); | 907 | #define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data) |
909 | #define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)); | 908 | #define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)) |
910 | #define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ]) | 909 | #define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ]) |
911 | #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE) | 910 | #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE) |
912 | #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD) | 911 | #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD) |
@@ -962,83 +961,6 @@ typedef struct asc_mc_saved { | |||
962 | #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID) | 961 | #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID) |
963 | #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data) | 962 | #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data) |
964 | 963 | ||
965 | static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); | ||
966 | static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); | ||
967 | static void AscWaitEEPRead(void); | ||
968 | static void AscWaitEEPWrite(void); | ||
969 | static ushort AscReadEEPWord(PortAddr, uchar); | ||
970 | static ushort AscWriteEEPWord(PortAddr, uchar, ushort); | ||
971 | static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); | ||
972 | static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); | ||
973 | static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); | ||
974 | static int AscStartChip(PortAddr); | ||
975 | static int AscStopChip(PortAddr); | ||
976 | static void AscSetChipIH(PortAddr, ushort); | ||
977 | static int AscIsChipHalted(PortAddr); | ||
978 | static void AscAckInterrupt(PortAddr); | ||
979 | static void AscDisableInterrupt(PortAddr); | ||
980 | static void AscEnableInterrupt(PortAddr); | ||
981 | static void AscSetBank(PortAddr, uchar); | ||
982 | static int AscResetChipAndScsiBus(ASC_DVC_VAR *); | ||
983 | #ifdef CONFIG_ISA | ||
984 | static uchar AscGetIsaDmaSpeed(PortAddr); | ||
985 | #endif /* CONFIG_ISA */ | ||
986 | static uchar AscReadLramByte(PortAddr, ushort); | ||
987 | static ushort AscReadLramWord(PortAddr, ushort); | ||
988 | #if CC_VERY_LONG_SG_LIST | ||
989 | static ASC_DCNT AscReadLramDWord(PortAddr, ushort); | ||
990 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
991 | static void AscWriteLramWord(PortAddr, ushort, ushort); | ||
992 | static void AscWriteLramByte(PortAddr, ushort, uchar); | ||
993 | static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int); | ||
994 | static void AscMemWordSetLram(PortAddr, ushort, ushort, int); | ||
995 | static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int); | ||
996 | static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int); | ||
997 | static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int); | ||
998 | static ushort AscInitAscDvcVar(ASC_DVC_VAR *); | ||
999 | static ushort AscInitFromEEP(ASC_DVC_VAR *); | ||
1000 | static ushort AscInitMicroCodeVar(ASC_DVC_VAR *); | ||
1001 | static int AscTestExternalLram(ASC_DVC_VAR *); | ||
1002 | static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar); | ||
1003 | static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar); | ||
1004 | static void AscSetChipSDTR(PortAddr, uchar, uchar); | ||
1005 | static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar); | ||
1006 | static uchar AscAllocFreeQueue(PortAddr, uchar); | ||
1007 | static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); | ||
1008 | static int AscHostReqRiscHalt(PortAddr); | ||
1009 | static int AscStopQueueExe(PortAddr); | ||
1010 | static int AscSendScsiQueue(ASC_DVC_VAR *, | ||
1011 | ASC_SCSI_Q *scsiq, uchar n_q_required); | ||
1012 | static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); | ||
1013 | static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); | ||
1014 | static int AscSetChipSynRegAtID(PortAddr, uchar, uchar); | ||
1015 | static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); | ||
1016 | static ushort AscInitLram(ASC_DVC_VAR *); | ||
1017 | static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort); | ||
1018 | static int AscIsrChipHalted(ASC_DVC_VAR *); | ||
1019 | static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, | ||
1020 | ASC_QDONE_INFO *, ASC_DCNT); | ||
1021 | static int AscIsrQDone(ASC_DVC_VAR *); | ||
1022 | #ifdef CONFIG_ISA | ||
1023 | static ushort AscGetEisaChipCfg(PortAddr); | ||
1024 | #endif /* CONFIG_ISA */ | ||
1025 | static uchar AscGetChipScsiCtrl(PortAddr); | ||
1026 | static uchar AscGetChipVersion(PortAddr, ushort); | ||
1027 | static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort); | ||
1028 | static void AscToggleIRQAct(PortAddr); | ||
1029 | static void DvcPutScsiQ(PortAddr, ushort, uchar *, int); | ||
1030 | static void DvcGetQinfo(PortAddr, ushort, uchar *, int); | ||
1031 | static ushort AscInitAsc1000Driver(ASC_DVC_VAR *); | ||
1032 | static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *); | ||
1033 | static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *); | ||
1034 | static int AscISR(ASC_DVC_VAR *); | ||
1035 | static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar); | ||
1036 | static int AscSgListToQueue(int); | ||
1037 | #ifdef CONFIG_ISA | ||
1038 | static void AscEnableIsaDma(uchar); | ||
1039 | #endif /* CONFIG_ISA */ | ||
1040 | static const char *advansys_info(struct Scsi_Host *shost); | ||
1041 | |||
1042 | #define ADV_LIB_VERSION_MAJOR 5 | 964 | #define ADV_LIB_VERSION_MAJOR 5 |
1043 | #define ADV_LIB_VERSION_MINOR 14 | 965 | #define ADV_LIB_VERSION_MINOR 14 |
1044 | 966 | ||
@@ -2109,36 +2031,6 @@ typedef struct adv_scsi_req_q { | |||
2109 | 2031 | ||
2110 | #define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ | 2032 | #define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ |
2111 | 2033 | ||
2112 | static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, | ||
2113 | uchar *, ASC_SDCNT *, int); | ||
2114 | |||
2115 | /* | ||
2116 | * Adv Library functions available to drivers. | ||
2117 | */ | ||
2118 | static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); | ||
2119 | static int AdvISR(ADV_DVC_VAR *); | ||
2120 | static int AdvInitAsc3550Driver(ADV_DVC_VAR *); | ||
2121 | static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *); | ||
2122 | static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *); | ||
2123 | static int AdvResetChipAndSB(ADV_DVC_VAR *); | ||
2124 | static int AdvResetSB(ADV_DVC_VAR *asc_dvc); | ||
2125 | |||
2126 | /* | ||
2127 | * Internal Adv Library functions. | ||
2128 | */ | ||
2129 | static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT); | ||
2130 | static int AdvInitFrom3550EEP(ADV_DVC_VAR *); | ||
2131 | static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *); | ||
2132 | static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *); | ||
2133 | static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); | ||
2134 | static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); | ||
2135 | static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); | ||
2136 | static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); | ||
2137 | static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); | ||
2138 | static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); | ||
2139 | static void AdvWaitEEPCmd(AdvPortAddr); | ||
2140 | static ushort AdvReadEEPWord(AdvPortAddr, int); | ||
2141 | |||
2142 | /* Read byte from a register. */ | 2034 | /* Read byte from a register. */ |
2143 | #define AdvReadByteRegister(iop_base, reg_off) \ | 2035 | #define AdvReadByteRegister(iop_base, reg_off) \ |
2144 | (ADV_MEM_READB((iop_base) + (reg_off))) | 2036 | (ADV_MEM_READB((iop_base) + (reg_off))) |
@@ -2676,1717 +2568,489 @@ static ASC_SG_HEAD asc_sg_head = { 0 }; | |||
2676 | 2568 | ||
2677 | #ifdef ADVANSYS_DEBUG | 2569 | #ifdef ADVANSYS_DEBUG |
2678 | static int asc_dbglvl = 3; | 2570 | static int asc_dbglvl = 3; |
2679 | #endif /* ADVANSYS_DEBUG */ | ||
2680 | |||
2681 | static int advansys_slave_configure(struct scsi_device *); | ||
2682 | static int asc_execute_scsi_cmnd(struct scsi_cmnd *); | ||
2683 | static int asc_build_req(asc_board_t *, struct scsi_cmnd *); | ||
2684 | static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); | ||
2685 | static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); | ||
2686 | #ifdef CONFIG_PROC_FS | ||
2687 | static int asc_proc_copy(off_t, off_t, char *, int, char *, int); | ||
2688 | static int asc_prt_board_devices(struct Scsi_Host *, char *, int); | ||
2689 | static int asc_prt_adv_bios(struct Scsi_Host *, char *, int); | ||
2690 | static int asc_get_eeprom_string(ushort *serialnum, uchar *cp); | ||
2691 | static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); | ||
2692 | static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); | ||
2693 | static int asc_prt_driver_conf(struct Scsi_Host *, char *, int); | ||
2694 | static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); | ||
2695 | static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); | ||
2696 | static int asc_prt_line(char *, int, char *fmt, ...); | ||
2697 | #endif /* CONFIG_PROC_FS */ | ||
2698 | 2571 | ||
2699 | /* Statistics function prototypes. */ | ||
2700 | #ifdef ADVANSYS_STATS | ||
2701 | #ifdef CONFIG_PROC_FS | ||
2702 | static int asc_prt_board_stats(struct Scsi_Host *, char *, int); | ||
2703 | #endif /* CONFIG_PROC_FS */ | ||
2704 | #endif /* ADVANSYS_STATS */ | ||
2705 | |||
2706 | /* Debug function prototypes. */ | ||
2707 | #ifdef ADVANSYS_DEBUG | ||
2708 | static void asc_prt_scsi_host(struct Scsi_Host *); | ||
2709 | static void asc_prt_scsi_cmnd(struct scsi_cmnd *); | ||
2710 | static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); | ||
2711 | static void asc_prt_asc_dvc_var(ASC_DVC_VAR *); | ||
2712 | static void asc_prt_asc_scsi_q(ASC_SCSI_Q *); | ||
2713 | static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); | ||
2714 | static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); | ||
2715 | static void asc_prt_adv_dvc_var(ADV_DVC_VAR *); | ||
2716 | static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); | ||
2717 | static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); | ||
2718 | static void asc_prt_hex(char *f, uchar *, int); | ||
2719 | #endif /* ADVANSYS_DEBUG */ | ||
2720 | |||
2721 | #ifdef CONFIG_PROC_FS | ||
2722 | /* | 2572 | /* |
2723 | * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...} | 2573 | * asc_prt_scsi_host() |
2724 | * | ||
2725 | * *buffer: I/O buffer | ||
2726 | * **start: if inout == FALSE pointer into buffer where user read should start | ||
2727 | * offset: current offset into a /proc/scsi/advansys/[0...] file | ||
2728 | * length: length of buffer | ||
2729 | * hostno: Scsi_Host host_no | ||
2730 | * inout: TRUE - user is writing; FALSE - user is reading | ||
2731 | * | ||
2732 | * Return the number of bytes read from or written to a | ||
2733 | * /proc/scsi/advansys/[0...] file. | ||
2734 | * | ||
2735 | * Note: This function uses the per board buffer 'prtbuf' which is | ||
2736 | * allocated when the board is initialized in advansys_detect(). The | ||
2737 | * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is | ||
2738 | * used to write to the buffer. The way asc_proc_copy() is written | ||
2739 | * if 'prtbuf' is too small it will not be overwritten. Instead the | ||
2740 | * user just won't get all the available statistics. | ||
2741 | */ | 2574 | */ |
2742 | static int | 2575 | static void asc_prt_scsi_host(struct Scsi_Host *s) |
2743 | advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | ||
2744 | off_t offset, int length, int inout) | ||
2745 | { | 2576 | { |
2746 | asc_board_t *boardp; | 2577 | asc_board_t *boardp; |
2747 | char *cp; | ||
2748 | int cplen; | ||
2749 | int cnt; | ||
2750 | int totcnt; | ||
2751 | int leftlen; | ||
2752 | char *curbuf; | ||
2753 | off_t advoffset; | ||
2754 | |||
2755 | ASC_DBG(1, "advansys_proc_info: begin\n"); | ||
2756 | |||
2757 | /* | ||
2758 | * User write not supported. | ||
2759 | */ | ||
2760 | if (inout == TRUE) { | ||
2761 | return (-ENOSYS); | ||
2762 | } | ||
2763 | |||
2764 | /* | ||
2765 | * User read of /proc/scsi/advansys/[0...] file. | ||
2766 | */ | ||
2767 | |||
2768 | boardp = ASC_BOARDP(shost); | ||
2769 | |||
2770 | /* Copy read data starting at the beginning of the buffer. */ | ||
2771 | *start = buffer; | ||
2772 | curbuf = buffer; | ||
2773 | advoffset = 0; | ||
2774 | totcnt = 0; | ||
2775 | leftlen = length; | ||
2776 | |||
2777 | /* | ||
2778 | * Get board configuration information. | ||
2779 | * | ||
2780 | * advansys_info() returns the board string from its own static buffer. | ||
2781 | */ | ||
2782 | cp = (char *)advansys_info(shost); | ||
2783 | strcat(cp, "\n"); | ||
2784 | cplen = strlen(cp); | ||
2785 | /* Copy board information. */ | ||
2786 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
2787 | totcnt += cnt; | ||
2788 | leftlen -= cnt; | ||
2789 | if (leftlen == 0) { | ||
2790 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2791 | return totcnt; | ||
2792 | } | ||
2793 | advoffset += cplen; | ||
2794 | curbuf += cnt; | ||
2795 | 2578 | ||
2796 | /* | 2579 | boardp = ASC_BOARDP(s); |
2797 | * Display Wide Board BIOS Information. | ||
2798 | */ | ||
2799 | if (ASC_WIDE_BOARD(boardp)) { | ||
2800 | cp = boardp->prtbuf; | ||
2801 | cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE); | ||
2802 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
2803 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, | ||
2804 | cplen); | ||
2805 | totcnt += cnt; | ||
2806 | leftlen -= cnt; | ||
2807 | if (leftlen == 0) { | ||
2808 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2809 | return totcnt; | ||
2810 | } | ||
2811 | advoffset += cplen; | ||
2812 | curbuf += cnt; | ||
2813 | } | ||
2814 | 2580 | ||
2815 | /* | 2581 | printk("Scsi_Host at addr 0x%lx\n", (ulong)s); |
2816 | * Display driver information for each device attached to the board. | 2582 | printk(" host_busy %u, host_no %d, last_reset %d,\n", |
2817 | */ | 2583 | s->host_busy, s->host_no, (unsigned)s->last_reset); |
2818 | cp = boardp->prtbuf; | ||
2819 | cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE); | ||
2820 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
2821 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
2822 | totcnt += cnt; | ||
2823 | leftlen -= cnt; | ||
2824 | if (leftlen == 0) { | ||
2825 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2826 | return totcnt; | ||
2827 | } | ||
2828 | advoffset += cplen; | ||
2829 | curbuf += cnt; | ||
2830 | 2584 | ||
2831 | /* | 2585 | printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n", |
2832 | * Display EEPROM configuration for the board. | 2586 | (ulong)s->base, (ulong)s->io_port, s->irq); |
2833 | */ | ||
2834 | cp = boardp->prtbuf; | ||
2835 | if (ASC_NARROW_BOARD(boardp)) { | ||
2836 | cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); | ||
2837 | } else { | ||
2838 | cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); | ||
2839 | } | ||
2840 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
2841 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
2842 | totcnt += cnt; | ||
2843 | leftlen -= cnt; | ||
2844 | if (leftlen == 0) { | ||
2845 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2846 | return totcnt; | ||
2847 | } | ||
2848 | advoffset += cplen; | ||
2849 | curbuf += cnt; | ||
2850 | 2587 | ||
2851 | /* | 2588 | printk(" dma_channel %d, this_id %d, can_queue %d,\n", |
2852 | * Display driver configuration and information for the board. | 2589 | s->dma_channel, s->this_id, s->can_queue); |
2853 | */ | ||
2854 | cp = boardp->prtbuf; | ||
2855 | cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE); | ||
2856 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
2857 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
2858 | totcnt += cnt; | ||
2859 | leftlen -= cnt; | ||
2860 | if (leftlen == 0) { | ||
2861 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2862 | return totcnt; | ||
2863 | } | ||
2864 | advoffset += cplen; | ||
2865 | curbuf += cnt; | ||
2866 | 2590 | ||
2867 | #ifdef ADVANSYS_STATS | 2591 | printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", |
2868 | /* | 2592 | s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); |
2869 | * Display driver statistics for the board. | ||
2870 | */ | ||
2871 | cp = boardp->prtbuf; | ||
2872 | cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE); | ||
2873 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
2874 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
2875 | totcnt += cnt; | ||
2876 | leftlen -= cnt; | ||
2877 | if (leftlen == 0) { | ||
2878 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2879 | return totcnt; | ||
2880 | } | ||
2881 | advoffset += cplen; | ||
2882 | curbuf += cnt; | ||
2883 | #endif /* ADVANSYS_STATS */ | ||
2884 | 2593 | ||
2885 | /* | ||
2886 | * Display Asc Library dynamic configuration information | ||
2887 | * for the board. | ||
2888 | */ | ||
2889 | cp = boardp->prtbuf; | ||
2890 | if (ASC_NARROW_BOARD(boardp)) { | 2594 | if (ASC_NARROW_BOARD(boardp)) { |
2891 | cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE); | 2595 | asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); |
2596 | asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); | ||
2892 | } else { | 2597 | } else { |
2893 | cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE); | 2598 | asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); |
2894 | } | 2599 | asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); |
2895 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
2896 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
2897 | totcnt += cnt; | ||
2898 | leftlen -= cnt; | ||
2899 | if (leftlen == 0) { | ||
2900 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2901 | return totcnt; | ||
2902 | } | 2600 | } |
2903 | advoffset += cplen; | ||
2904 | curbuf += cnt; | ||
2905 | |||
2906 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
2907 | |||
2908 | return totcnt; | ||
2909 | } | 2601 | } |
2910 | #endif /* CONFIG_PROC_FS */ | ||
2911 | 2602 | ||
2912 | /* | 2603 | /* |
2913 | * advansys_info() | 2604 | * asc_prt_scsi_cmnd() |
2914 | * | ||
2915 | * Return suitable for printing on the console with the argument | ||
2916 | * adapter's configuration information. | ||
2917 | * | ||
2918 | * Note: The information line should not exceed ASC_INFO_SIZE bytes, | ||
2919 | * otherwise the static 'info' array will be overrun. | ||
2920 | */ | 2605 | */ |
2921 | static const char *advansys_info(struct Scsi_Host *shost) | 2606 | static void asc_prt_scsi_cmnd(struct scsi_cmnd *s) |
2922 | { | ||
2923 | static char info[ASC_INFO_SIZE]; | ||
2924 | asc_board_t *boardp; | ||
2925 | ASC_DVC_VAR *asc_dvc_varp; | ||
2926 | ADV_DVC_VAR *adv_dvc_varp; | ||
2927 | char *busname; | ||
2928 | char *widename = NULL; | ||
2929 | |||
2930 | boardp = ASC_BOARDP(shost); | ||
2931 | if (ASC_NARROW_BOARD(boardp)) { | ||
2932 | asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; | ||
2933 | ASC_DBG(1, "advansys_info: begin\n"); | ||
2934 | if (asc_dvc_varp->bus_type & ASC_IS_ISA) { | ||
2935 | if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == | ||
2936 | ASC_IS_ISAPNP) { | ||
2937 | busname = "ISA PnP"; | ||
2938 | } else { | ||
2939 | busname = "ISA"; | ||
2940 | } | ||
2941 | sprintf(info, | ||
2942 | "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", | ||
2943 | ASC_VERSION, busname, | ||
2944 | (ulong)shost->io_port, | ||
2945 | (ulong)shost->io_port + ASC_IOADR_GAP - 1, | ||
2946 | shost->irq, shost->dma_channel); | ||
2947 | } else { | ||
2948 | if (asc_dvc_varp->bus_type & ASC_IS_VL) { | ||
2949 | busname = "VL"; | ||
2950 | } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { | ||
2951 | busname = "EISA"; | ||
2952 | } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { | ||
2953 | if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) | ||
2954 | == ASC_IS_PCI_ULTRA) { | ||
2955 | busname = "PCI Ultra"; | ||
2956 | } else { | ||
2957 | busname = "PCI"; | ||
2958 | } | ||
2959 | } else { | ||
2960 | busname = "?"; | ||
2961 | ASC_PRINT2("advansys_info: board %d: unknown " | ||
2962 | "bus type %d\n", boardp->id, | ||
2963 | asc_dvc_varp->bus_type); | ||
2964 | } | ||
2965 | sprintf(info, | ||
2966 | "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", | ||
2967 | ASC_VERSION, busname, (ulong)shost->io_port, | ||
2968 | (ulong)shost->io_port + ASC_IOADR_GAP - 1, | ||
2969 | shost->irq); | ||
2970 | } | ||
2971 | } else { | ||
2972 | /* | ||
2973 | * Wide Adapter Information | ||
2974 | * | ||
2975 | * Memory-mapped I/O is used instead of I/O space to access | ||
2976 | * the adapter, but display the I/O Port range. The Memory | ||
2977 | * I/O address is displayed through the driver /proc file. | ||
2978 | */ | ||
2979 | adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; | ||
2980 | if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { | ||
2981 | widename = "Ultra-Wide"; | ||
2982 | } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { | ||
2983 | widename = "Ultra2-Wide"; | ||
2984 | } else { | ||
2985 | widename = "Ultra3-Wide"; | ||
2986 | } | ||
2987 | sprintf(info, | ||
2988 | "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", | ||
2989 | ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base, | ||
2990 | (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq); | ||
2991 | } | ||
2992 | BUG_ON(strlen(info) >= ASC_INFO_SIZE); | ||
2993 | ASC_DBG(1, "advansys_info: end\n"); | ||
2994 | return info; | ||
2995 | } | ||
2996 | |||
2997 | static void asc_scsi_done(struct scsi_cmnd *scp) | ||
2998 | { | 2607 | { |
2999 | struct asc_board *boardp = ASC_BOARDP(scp->device->host); | 2608 | printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s); |
3000 | 2609 | ||
3001 | if (scp->use_sg) | 2610 | printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", |
3002 | dma_unmap_sg(boardp->dev, | 2611 | (ulong)s->device->host, (ulong)s->device, s->device->id, |
3003 | (struct scatterlist *)scp->request_buffer, | 2612 | s->device->lun, s->device->channel); |
3004 | scp->use_sg, scp->sc_data_direction); | ||
3005 | else if (scp->request_bufflen) | ||
3006 | dma_unmap_single(boardp->dev, scp->SCp.dma_handle, | ||
3007 | scp->request_bufflen, scp->sc_data_direction); | ||
3008 | 2613 | ||
3009 | ASC_STATS(scp->device->host, done); | 2614 | asc_prt_hex(" CDB", s->cmnd, s->cmd_len); |
3010 | 2615 | ||
3011 | scp->scsi_done(scp); | 2616 | printk("sc_data_direction %u, resid %d\n", |
3012 | } | 2617 | s->sc_data_direction, s->resid); |
3013 | 2618 | ||
3014 | /* | 2619 | printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len); |
3015 | * advansys_queuecommand() - interrupt-driven I/O entrypoint. | ||
3016 | * | ||
3017 | * This function always returns 0. Command return status is saved | ||
3018 | * in the 'scp' result field. | ||
3019 | */ | ||
3020 | static int | ||
3021 | advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) | ||
3022 | { | ||
3023 | struct Scsi_Host *shost = scp->device->host; | ||
3024 | asc_board_t *boardp = ASC_BOARDP(shost); | ||
3025 | unsigned long flags; | ||
3026 | int asc_res, result = 0; | ||
3027 | 2620 | ||
3028 | ASC_STATS(shost, queuecommand); | 2621 | printk(" serial_number 0x%x, retries %d, allowed %d\n", |
3029 | scp->scsi_done = done; | 2622 | (unsigned)s->serial_number, s->retries, s->allowed); |
3030 | 2623 | ||
3031 | /* | 2624 | printk(" timeout_per_command %d\n", s->timeout_per_command); |
3032 | * host_lock taken by mid-level prior to call, but need | ||
3033 | * to protect against own ISR | ||
3034 | */ | ||
3035 | spin_lock_irqsave(&boardp->lock, flags); | ||
3036 | asc_res = asc_execute_scsi_cmnd(scp); | ||
3037 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
3038 | 2625 | ||
3039 | switch (asc_res) { | 2626 | printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n", |
3040 | case ASC_NOERROR: | 2627 | s->scsi_done, s->done, s->host_scribble, s->result); |
3041 | break; | ||
3042 | case ASC_BUSY: | ||
3043 | result = SCSI_MLQUEUE_HOST_BUSY; | ||
3044 | break; | ||
3045 | case ASC_ERROR: | ||
3046 | default: | ||
3047 | asc_scsi_done(scp); | ||
3048 | break; | ||
3049 | } | ||
3050 | 2628 | ||
3051 | return result; | 2629 | printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid); |
3052 | } | 2630 | } |
3053 | 2631 | ||
3054 | /* | 2632 | /* |
3055 | * advansys_reset() | 2633 | * asc_prt_asc_dvc_var() |
3056 | * | ||
3057 | * Reset the bus associated with the command 'scp'. | ||
3058 | * | ||
3059 | * This function runs its own thread. Interrupts must be blocked but | ||
3060 | * sleeping is allowed and no locking other than for host structures is | ||
3061 | * required. Returns SUCCESS or FAILED. | ||
3062 | */ | 2634 | */ |
3063 | static int advansys_reset(struct scsi_cmnd *scp) | 2635 | static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) |
3064 | { | 2636 | { |
3065 | struct Scsi_Host *shost; | 2637 | printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); |
3066 | asc_board_t *boardp; | ||
3067 | ASC_DVC_VAR *asc_dvc_varp; | ||
3068 | ADV_DVC_VAR *adv_dvc_varp; | ||
3069 | ulong flags; | ||
3070 | int status; | ||
3071 | int ret = SUCCESS; | ||
3072 | |||
3073 | ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp); | ||
3074 | |||
3075 | #ifdef ADVANSYS_STATS | ||
3076 | if (scp->device->host != NULL) { | ||
3077 | ASC_STATS(scp->device->host, reset); | ||
3078 | } | ||
3079 | #endif /* ADVANSYS_STATS */ | ||
3080 | |||
3081 | if ((shost = scp->device->host) == NULL) { | ||
3082 | scp->result = HOST_BYTE(DID_ERROR); | ||
3083 | return FAILED; | ||
3084 | } | ||
3085 | |||
3086 | boardp = ASC_BOARDP(shost); | ||
3087 | |||
3088 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", | ||
3089 | boardp->id); | ||
3090 | /* | ||
3091 | * Check for re-entrancy. | ||
3092 | */ | ||
3093 | spin_lock_irqsave(&boardp->lock, flags); | ||
3094 | if (boardp->flags & ASC_HOST_IN_RESET) { | ||
3095 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
3096 | return FAILED; | ||
3097 | } | ||
3098 | boardp->flags |= ASC_HOST_IN_RESET; | ||
3099 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
3100 | |||
3101 | if (ASC_NARROW_BOARD(boardp)) { | ||
3102 | /* | ||
3103 | * Narrow Board | ||
3104 | */ | ||
3105 | asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; | ||
3106 | |||
3107 | /* | ||
3108 | * Reset the chip and SCSI bus. | ||
3109 | */ | ||
3110 | ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); | ||
3111 | status = AscInitAsc1000Driver(asc_dvc_varp); | ||
3112 | |||
3113 | /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ | ||
3114 | if (asc_dvc_varp->err_code) { | ||
3115 | ASC_PRINT2("advansys_reset: board %d: SCSI bus reset " | ||
3116 | "error: 0x%x\n", boardp->id, | ||
3117 | asc_dvc_varp->err_code); | ||
3118 | ret = FAILED; | ||
3119 | } else if (status) { | ||
3120 | ASC_PRINT2("advansys_reset: board %d: SCSI bus reset " | ||
3121 | "warning: 0x%x\n", boardp->id, status); | ||
3122 | } else { | ||
3123 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset " | ||
3124 | "successful.\n", boardp->id); | ||
3125 | } | ||
3126 | |||
3127 | ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); | ||
3128 | spin_lock_irqsave(&boardp->lock, flags); | ||
3129 | |||
3130 | } else { | ||
3131 | /* | ||
3132 | * Wide Board | ||
3133 | * | ||
3134 | * If the suggest reset bus flags are set, then reset the bus. | ||
3135 | * Otherwise only reset the device. | ||
3136 | */ | ||
3137 | adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; | ||
3138 | 2638 | ||
3139 | /* | 2639 | printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl " |
3140 | * Reset the target's SCSI bus. | 2640 | "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); |
3141 | */ | ||
3142 | ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); | ||
3143 | switch (AdvResetChipAndSB(adv_dvc_varp)) { | ||
3144 | case ASC_TRUE: | ||
3145 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset " | ||
3146 | "successful.\n", boardp->id); | ||
3147 | break; | ||
3148 | case ASC_FALSE: | ||
3149 | default: | ||
3150 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset " | ||
3151 | "error.\n", boardp->id); | ||
3152 | ret = FAILED; | ||
3153 | break; | ||
3154 | } | ||
3155 | spin_lock_irqsave(&boardp->lock, flags); | ||
3156 | (void)AdvISR(adv_dvc_varp); | ||
3157 | } | ||
3158 | /* Board lock is held. */ | ||
3159 | 2641 | ||
3160 | /* Save the time of the most recently completed reset. */ | 2642 | printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type, |
3161 | boardp->last_reset = jiffies; | 2643 | (unsigned)h->init_sdtr); |
3162 | 2644 | ||
3163 | /* Clear reset flag. */ | 2645 | printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, " |
3164 | boardp->flags &= ~ASC_HOST_IN_RESET; | 2646 | "chip_no 0x%x,\n", (unsigned)h->sdtr_done, |
3165 | spin_unlock_irqrestore(&boardp->lock, flags); | 2647 | (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready, |
2648 | (unsigned)h->chip_no); | ||
3166 | 2649 | ||
3167 | ASC_DBG1(1, "advansys_reset: ret %d\n", ret); | 2650 | printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait " |
2651 | "%u,\n", (unsigned)h->queue_full_or_busy, | ||
2652 | (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait); | ||
3168 | 2653 | ||
3169 | return ret; | 2654 | printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, " |
3170 | } | 2655 | "in_critical_cnt %u,\n", (unsigned)h->is_in_int, |
2656 | (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng, | ||
2657 | (unsigned)h->in_critical_cnt); | ||
3171 | 2658 | ||
3172 | /* | 2659 | printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, " |
3173 | * advansys_biosparam() | 2660 | "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage, |
3174 | * | 2661 | (unsigned)h->init_state, (unsigned)h->no_scam, |
3175 | * Translate disk drive geometry if the "BIOS greater than 1 GB" | 2662 | (unsigned)h->pci_fix_asyn_xfer); |
3176 | * support is enabled for a drive. | ||
3177 | * | ||
3178 | * ip (information pointer) is an int array with the following definition: | ||
3179 | * ip[0]: heads | ||
3180 | * ip[1]: sectors | ||
3181 | * ip[2]: cylinders | ||
3182 | */ | ||
3183 | static int | ||
3184 | advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, | ||
3185 | sector_t capacity, int ip[]) | ||
3186 | { | ||
3187 | asc_board_t *boardp; | ||
3188 | 2663 | ||
3189 | ASC_DBG(1, "advansys_biosparam: begin\n"); | 2664 | printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no); |
3190 | ASC_STATS(sdev->host, biosparam); | ||
3191 | boardp = ASC_BOARDP(sdev->host); | ||
3192 | if (ASC_NARROW_BOARD(boardp)) { | ||
3193 | if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & | ||
3194 | ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { | ||
3195 | ip[0] = 255; | ||
3196 | ip[1] = 63; | ||
3197 | } else { | ||
3198 | ip[0] = 64; | ||
3199 | ip[1] = 32; | ||
3200 | } | ||
3201 | } else { | ||
3202 | if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & | ||
3203 | BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { | ||
3204 | ip[0] = 255; | ||
3205 | ip[1] = 63; | ||
3206 | } else { | ||
3207 | ip[0] = 64; | ||
3208 | ip[1] = 32; | ||
3209 | } | ||
3210 | } | ||
3211 | ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); | ||
3212 | ASC_DBG(1, "advansys_biosparam: end\n"); | ||
3213 | return 0; | ||
3214 | } | 2665 | } |
3215 | 2666 | ||
3216 | static struct scsi_host_template advansys_template = { | ||
3217 | .proc_name = DRV_NAME, | ||
3218 | #ifdef CONFIG_PROC_FS | ||
3219 | .proc_info = advansys_proc_info, | ||
3220 | #endif | ||
3221 | .name = DRV_NAME, | ||
3222 | .info = advansys_info, | ||
3223 | .queuecommand = advansys_queuecommand, | ||
3224 | .eh_bus_reset_handler = advansys_reset, | ||
3225 | .bios_param = advansys_biosparam, | ||
3226 | .slave_configure = advansys_slave_configure, | ||
3227 | /* | ||
3228 | * Because the driver may control an ISA adapter 'unchecked_isa_dma' | ||
3229 | * must be set. The flag will be cleared in advansys_board_found | ||
3230 | * for non-ISA adapters. | ||
3231 | */ | ||
3232 | .unchecked_isa_dma = 1, | ||
3233 | /* | ||
3234 | * All adapters controlled by this driver are capable of large | ||
3235 | * scatter-gather lists. According to the mid-level SCSI documentation | ||
3236 | * this obviates any performance gain provided by setting | ||
3237 | * 'use_clustering'. But empirically while CPU utilization is increased | ||
3238 | * by enabling clustering, I/O throughput increases as well. | ||
3239 | */ | ||
3240 | .use_clustering = ENABLE_CLUSTERING, | ||
3241 | }; | ||
3242 | |||
3243 | /* | 2667 | /* |
3244 | * First-level interrupt handler. | 2668 | * asc_prt_asc_dvc_cfg() |
3245 | * | ||
3246 | * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host. | ||
3247 | */ | 2669 | */ |
3248 | static irqreturn_t advansys_interrupt(int irq, void *dev_id) | 2670 | static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) |
3249 | { | ||
3250 | unsigned long flags; | ||
3251 | struct Scsi_Host *shost = dev_id; | ||
3252 | asc_board_t *boardp = ASC_BOARDP(shost); | ||
3253 | irqreturn_t result = IRQ_NONE; | ||
3254 | |||
3255 | ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp); | ||
3256 | spin_lock_irqsave(&boardp->lock, flags); | ||
3257 | if (ASC_NARROW_BOARD(boardp)) { | ||
3258 | if (AscIsIntPending(shost->io_port)) { | ||
3259 | result = IRQ_HANDLED; | ||
3260 | ASC_STATS(shost, interrupt); | ||
3261 | ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); | ||
3262 | AscISR(&boardp->dvc_var.asc_dvc_var); | ||
3263 | } | ||
3264 | } else { | ||
3265 | ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); | ||
3266 | if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { | ||
3267 | result = IRQ_HANDLED; | ||
3268 | ASC_STATS(shost, interrupt); | ||
3269 | } | ||
3270 | } | ||
3271 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
3272 | |||
3273 | ASC_DBG(1, "advansys_interrupt: end\n"); | ||
3274 | return result; | ||
3275 | } | ||
3276 | |||
3277 | static void | ||
3278 | advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc) | ||
3279 | { | 2671 | { |
3280 | ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id; | 2672 | printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); |
3281 | ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng; | ||
3282 | |||
3283 | if (sdev->lun == 0) { | ||
3284 | ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr; | ||
3285 | if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) { | ||
3286 | asc_dvc->init_sdtr |= tid_bit; | ||
3287 | } else { | ||
3288 | asc_dvc->init_sdtr &= ~tid_bit; | ||
3289 | } | ||
3290 | |||
3291 | if (orig_init_sdtr != asc_dvc->init_sdtr) | ||
3292 | AscAsyncFix(asc_dvc, sdev); | ||
3293 | } | ||
3294 | |||
3295 | if (sdev->tagged_supported) { | ||
3296 | if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) { | ||
3297 | if (sdev->lun == 0) { | ||
3298 | asc_dvc->cfg->can_tagged_qng |= tid_bit; | ||
3299 | asc_dvc->use_tagged_qng |= tid_bit; | ||
3300 | } | ||
3301 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, | ||
3302 | asc_dvc->max_dvc_qng[sdev->id]); | ||
3303 | } | ||
3304 | } else { | ||
3305 | if (sdev->lun == 0) { | ||
3306 | asc_dvc->cfg->can_tagged_qng &= ~tid_bit; | ||
3307 | asc_dvc->use_tagged_qng &= ~tid_bit; | ||
3308 | } | ||
3309 | scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); | ||
3310 | } | ||
3311 | |||
3312 | if ((sdev->lun == 0) && | ||
3313 | (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) { | ||
3314 | AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, | ||
3315 | asc_dvc->cfg->disc_enable); | ||
3316 | AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, | ||
3317 | asc_dvc->use_tagged_qng); | ||
3318 | AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, | ||
3319 | asc_dvc->cfg->can_tagged_qng); | ||
3320 | 2673 | ||
3321 | asc_dvc->max_dvc_qng[sdev->id] = | 2674 | printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", |
3322 | asc_dvc->cfg->max_tag_qng[sdev->id]; | 2675 | h->can_tagged_qng, h->cmd_qng_enabled); |
3323 | AscWriteLramByte(asc_dvc->iop_base, | 2676 | printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n", |
3324 | (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id), | 2677 | h->disc_enable, h->sdtr_enable); |
3325 | asc_dvc->max_dvc_qng[sdev->id]); | ||
3326 | } | ||
3327 | } | ||
3328 | 2678 | ||
3329 | /* | 2679 | printk |
3330 | * Wide Transfers | 2680 | (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", |
3331 | * | 2681 | h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, |
3332 | * If the EEPROM enabled WDTR for the device and the device supports wide | 2682 | h->chip_version); |
3333 | * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and | ||
3334 | * write the new value to the microcode. | ||
3335 | */ | ||
3336 | static void | ||
3337 | advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask) | ||
3338 | { | ||
3339 | unsigned short cfg_word; | ||
3340 | AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); | ||
3341 | if ((cfg_word & tidmask) != 0) | ||
3342 | return; | ||
3343 | 2683 | ||
3344 | cfg_word |= tidmask; | 2684 | printk |
3345 | AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); | 2685 | (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", |
2686 | to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, | ||
2687 | h->mcode_date); | ||
3346 | 2688 | ||
3347 | /* | 2689 | printk(" mcode_version %d, overrun_buf 0x%lx\n", |
3348 | * Clear the microcode SDTR and WDTR negotiation done indicators for | 2690 | h->mcode_version, (ulong)h->overrun_buf); |
3349 | * the target to cause it to negotiate with the new setting set above. | ||
3350 | * WDTR when accepted causes the target to enter asynchronous mode, so | ||
3351 | * SDTR must be negotiated. | ||
3352 | */ | ||
3353 | AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
3354 | cfg_word &= ~tidmask; | ||
3355 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
3356 | AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); | ||
3357 | cfg_word &= ~tidmask; | ||
3358 | AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); | ||
3359 | } | 2691 | } |
3360 | 2692 | ||
3361 | /* | 2693 | /* |
3362 | * Synchronous Transfers | 2694 | * asc_prt_asc_scsi_q() |
3363 | * | ||
3364 | * If the EEPROM enabled SDTR for the device and the device | ||
3365 | * supports synchronous transfers, then turn on the device's | ||
3366 | * 'sdtr_able' bit. Write the new value to the microcode. | ||
3367 | */ | 2695 | */ |
3368 | static void | 2696 | static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) |
3369 | advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask) | ||
3370 | { | 2697 | { |
3371 | unsigned short cfg_word; | 2698 | ASC_SG_HEAD *sgp; |
3372 | AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); | 2699 | int i; |
3373 | if ((cfg_word & tidmask) != 0) | ||
3374 | return; | ||
3375 | |||
3376 | cfg_word |= tidmask; | ||
3377 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); | ||
3378 | |||
3379 | /* | ||
3380 | * Clear the microcode "SDTR negotiation" done indicator for the | ||
3381 | * target to cause it to negotiate with the new setting set above. | ||
3382 | */ | ||
3383 | AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
3384 | cfg_word &= ~tidmask; | ||
3385 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
3386 | } | ||
3387 | 2700 | ||
3388 | /* | 2701 | printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); |
3389 | * PPR (Parallel Protocol Request) Capable | ||
3390 | * | ||
3391 | * If the device supports DT mode, then it must be PPR capable. | ||
3392 | * The PPR message will be used in place of the SDTR and WDTR | ||
3393 | * messages to negotiate synchronous speed and offset, transfer | ||
3394 | * width, and protocol options. | ||
3395 | */ | ||
3396 | static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc, | ||
3397 | AdvPortAddr iop_base, unsigned short tidmask) | ||
3398 | { | ||
3399 | AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able); | ||
3400 | adv_dvc->ppr_able |= tidmask; | ||
3401 | AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able); | ||
3402 | } | ||
3403 | 2702 | ||
3404 | static void | 2703 | printk |
3405 | advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc) | 2704 | (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", |
3406 | { | 2705 | q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr, |
3407 | AdvPortAddr iop_base = adv_dvc->iop_base; | 2706 | q->q2.tag_code); |
3408 | unsigned short tidmask = 1 << sdev->id; | ||
3409 | 2707 | ||
3410 | if (sdev->lun == 0) { | 2708 | printk |
3411 | /* | 2709 | (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", |
3412 | * Handle WDTR, SDTR, and Tag Queuing. If the feature | 2710 | (ulong)le32_to_cpu(q->q1.data_addr), |
3413 | * is enabled in the EEPROM and the device supports the | 2711 | (ulong)le32_to_cpu(q->q1.data_cnt), |
3414 | * feature, then enable it in the microcode. | 2712 | (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); |
3415 | */ | ||
3416 | 2713 | ||
3417 | if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr) | 2714 | printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", |
3418 | advansys_wide_enable_wdtr(iop_base, tidmask); | 2715 | (ulong)q->cdbptr, q->q2.cdb_len, |
3419 | if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr) | 2716 | (ulong)q->sg_head, q->q1.sg_queue_cnt); |
3420 | advansys_wide_enable_sdtr(iop_base, tidmask); | ||
3421 | if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr) | ||
3422 | advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask); | ||
3423 | 2717 | ||
3424 | /* | 2718 | if (q->sg_head) { |
3425 | * Tag Queuing is disabled for the BIOS which runs in polled | 2719 | sgp = q->sg_head; |
3426 | * mode and would see no benefit from Tag Queuing. Also by | 2720 | printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp); |
3427 | * disabling Tag Queuing in the BIOS devices with Tag Queuing | 2721 | printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, |
3428 | * bugs will at least work with the BIOS. | 2722 | sgp->queue_cnt); |
3429 | */ | 2723 | for (i = 0; i < sgp->entry_cnt; i++) { |
3430 | if ((adv_dvc->tagqng_able & tidmask) && | 2724 | printk(" [%u]: addr 0x%lx, bytes %lu\n", |
3431 | sdev->tagged_supported) { | 2725 | i, (ulong)le32_to_cpu(sgp->sg_list[i].addr), |
3432 | unsigned short cfg_word; | 2726 | (ulong)le32_to_cpu(sgp->sg_list[i].bytes)); |
3433 | AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); | ||
3434 | cfg_word |= tidmask; | ||
3435 | AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, | ||
3436 | cfg_word); | ||
3437 | AdvWriteByteLram(iop_base, | ||
3438 | ASC_MC_NUMBER_OF_MAX_CMD + sdev->id, | ||
3439 | adv_dvc->max_dvc_qng); | ||
3440 | } | 2727 | } |
3441 | } | ||
3442 | 2728 | ||
3443 | if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) { | ||
3444 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, | ||
3445 | adv_dvc->max_dvc_qng); | ||
3446 | } else { | ||
3447 | scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); | ||
3448 | } | 2729 | } |
3449 | } | 2730 | } |
3450 | 2731 | ||
3451 | /* | 2732 | /* |
3452 | * Set the number of commands to queue per device for the | 2733 | * asc_prt_asc_qdone_info() |
3453 | * specified host adapter. | ||
3454 | */ | 2734 | */ |
3455 | static int advansys_slave_configure(struct scsi_device *sdev) | 2735 | static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) |
3456 | { | 2736 | { |
3457 | asc_board_t *boardp = ASC_BOARDP(sdev->host); | 2737 | printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q); |
3458 | boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; | 2738 | printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", |
3459 | 2739 | (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, | |
3460 | /* | 2740 | q->d2.tag_code); |
3461 | * Save a pointer to the sdev and set its initial/maximum | 2741 | printk |
3462 | * queue depth. Only save the pointer for a lun0 dev though. | 2742 | (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", |
3463 | */ | 2743 | q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); |
3464 | if (sdev->lun == 0) | ||
3465 | boardp->device[sdev->id] = sdev; | ||
3466 | |||
3467 | if (ASC_NARROW_BOARD(boardp)) | ||
3468 | advansys_narrow_slave_configure(sdev, | ||
3469 | &boardp->dvc_var.asc_dvc_var); | ||
3470 | else | ||
3471 | advansys_wide_slave_configure(sdev, | ||
3472 | &boardp->dvc_var.adv_dvc_var); | ||
3473 | |||
3474 | return 0; | ||
3475 | } | 2744 | } |
3476 | 2745 | ||
3477 | /* | 2746 | /* |
3478 | * Execute a single 'Scsi_Cmnd'. | 2747 | * asc_prt_adv_dvc_var() |
3479 | * | ||
3480 | * The function 'done' is called when the request has been completed. | ||
3481 | * | ||
3482 | * Scsi_Cmnd: | ||
3483 | * | ||
3484 | * host - board controlling device | ||
3485 | * device - device to send command | ||
3486 | * target - target of device | ||
3487 | * lun - lun of device | ||
3488 | * cmd_len - length of SCSI CDB | ||
3489 | * cmnd - buffer for SCSI 8, 10, or 12 byte CDB | ||
3490 | * use_sg - if non-zero indicates scatter-gather request with use_sg elements | ||
3491 | * | ||
3492 | * if (use_sg == 0) { | ||
3493 | * request_buffer - buffer address for request | ||
3494 | * request_bufflen - length of request buffer | ||
3495 | * } else { | ||
3496 | * request_buffer - pointer to scatterlist structure | ||
3497 | * } | ||
3498 | * | ||
3499 | * sense_buffer - sense command buffer | ||
3500 | * | ||
3501 | * result (4 bytes of an int): | ||
3502 | * Byte Meaning | ||
3503 | * 0 SCSI Status Byte Code | ||
3504 | * 1 SCSI One Byte Message Code | ||
3505 | * 2 Host Error Code | ||
3506 | * 3 Mid-Level Error Code | ||
3507 | * | ||
3508 | * host driver fields: | ||
3509 | * SCp - Scsi_Pointer used for command processing status | ||
3510 | * scsi_done - used to save caller's done function | ||
3511 | * host_scribble - used for pointer to another struct scsi_cmnd | ||
3512 | * | ||
3513 | * If this function returns ASC_NOERROR the request will be completed | ||
3514 | * from the interrupt handler. | ||
3515 | * | ||
3516 | * If this function returns ASC_ERROR the host error code has been set, | ||
3517 | * and the called must call asc_scsi_done. | ||
3518 | * | 2748 | * |
3519 | * If ASC_BUSY is returned the request will be returned to the midlayer | 2749 | * Display an ADV_DVC_VAR structure. |
3520 | * and re-tried later. | ||
3521 | */ | 2750 | */ |
3522 | static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | 2751 | static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) |
3523 | { | 2752 | { |
3524 | asc_board_t *boardp; | 2753 | printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); |
3525 | ASC_DVC_VAR *asc_dvc_varp; | ||
3526 | ADV_DVC_VAR *adv_dvc_varp; | ||
3527 | ADV_SCSI_REQ_Q *adv_scsiqp; | ||
3528 | struct scsi_device *device; | ||
3529 | int ret; | ||
3530 | |||
3531 | ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", | ||
3532 | (ulong)scp, (ulong)scp->scsi_done); | ||
3533 | |||
3534 | boardp = ASC_BOARDP(scp->device->host); | ||
3535 | device = boardp->device[scp->device->id]; | ||
3536 | 2754 | ||
3537 | if (ASC_NARROW_BOARD(boardp)) { | 2755 | printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", |
3538 | /* | 2756 | (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); |
3539 | * Build and execute Narrow Board request. | ||
3540 | */ | ||
3541 | 2757 | ||
3542 | asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; | 2758 | printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", |
2759 | (ulong)h->isr_callback, (unsigned)h->sdtr_able, | ||
2760 | (unsigned)h->wdtr_able); | ||
3543 | 2761 | ||
3544 | /* | 2762 | printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", |
3545 | * Build Asc Library request structure using the | 2763 | (unsigned)h->start_motor, |
3546 | * global structures 'asc_scsi_req' and 'asc_sg_head'. | 2764 | (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no); |
3547 | * | ||
3548 | * If an error is returned, then the request has been | ||
3549 | * queued on the board done queue. It will be completed | ||
3550 | * by the caller. | ||
3551 | * | ||
3552 | * asc_build_req() can not return ASC_BUSY. | ||
3553 | */ | ||
3554 | if (asc_build_req(boardp, scp) == ASC_ERROR) { | ||
3555 | ASC_STATS(scp->device->host, build_error); | ||
3556 | return ASC_ERROR; | ||
3557 | } | ||
3558 | 2765 | ||
3559 | switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { | 2766 | printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", |
3560 | case ASC_NOERROR: | 2767 | (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng, |
3561 | ASC_STATS(scp->device->host, exe_noerror); | 2768 | (ulong)h->carr_freelist); |
3562 | /* | ||
3563 | * Increment monotonically increasing per device | ||
3564 | * successful request counter. Wrapping doesn't matter. | ||
3565 | */ | ||
3566 | boardp->reqcnt[scp->device->id]++; | ||
3567 | ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), " | ||
3568 | "ASC_NOERROR\n"); | ||
3569 | break; | ||
3570 | case ASC_BUSY: | ||
3571 | ASC_STATS(scp->device->host, exe_busy); | ||
3572 | break; | ||
3573 | case ASC_ERROR: | ||
3574 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
3575 | "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", | ||
3576 | boardp->id, asc_dvc_varp->err_code); | ||
3577 | ASC_STATS(scp->device->host, exe_error); | ||
3578 | scp->result = HOST_BYTE(DID_ERROR); | ||
3579 | break; | ||
3580 | default: | ||
3581 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
3582 | "AscExeScsiQueue() unknown, err_code 0x%x\n", | ||
3583 | boardp->id, asc_dvc_varp->err_code); | ||
3584 | ASC_STATS(scp->device->host, exe_unknown); | ||
3585 | scp->result = HOST_BYTE(DID_ERROR); | ||
3586 | break; | ||
3587 | } | ||
3588 | } else { | ||
3589 | /* | ||
3590 | * Build and execute Wide Board request. | ||
3591 | */ | ||
3592 | adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; | ||
3593 | 2769 | ||
3594 | /* | 2770 | printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", |
3595 | * Build and get a pointer to an Adv Library request structure. | 2771 | (ulong)h->icq_sp, (ulong)h->irq_sp); |
3596 | * | ||
3597 | * If the request is successfully built then send it below, | ||
3598 | * otherwise return with an error. | ||
3599 | */ | ||
3600 | switch (adv_build_req(boardp, scp, &adv_scsiqp)) { | ||
3601 | case ASC_NOERROR: | ||
3602 | ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req " | ||
3603 | "ASC_NOERROR\n"); | ||
3604 | break; | ||
3605 | case ASC_BUSY: | ||
3606 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " | ||
3607 | "ASC_BUSY\n"); | ||
3608 | /* | ||
3609 | * The asc_stats fields 'adv_build_noreq' and | ||
3610 | * 'adv_build_nosg' count wide board busy conditions. | ||
3611 | * They are updated in adv_build_req and | ||
3612 | * adv_get_sglist, respectively. | ||
3613 | */ | ||
3614 | return ASC_BUSY; | ||
3615 | case ASC_ERROR: | ||
3616 | default: | ||
3617 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " | ||
3618 | "ASC_ERROR\n"); | ||
3619 | ASC_STATS(scp->device->host, build_error); | ||
3620 | return ASC_ERROR; | ||
3621 | } | ||
3622 | 2772 | ||
3623 | switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { | 2773 | printk(" no_scam 0x%x, tagqng_able 0x%x\n", |
3624 | case ASC_NOERROR: | 2774 | (unsigned)h->no_scam, (unsigned)h->tagqng_able); |
3625 | ASC_STATS(scp->device->host, exe_noerror); | ||
3626 | /* | ||
3627 | * Increment monotonically increasing per device | ||
3628 | * successful request counter. Wrapping doesn't matter. | ||
3629 | */ | ||
3630 | boardp->reqcnt[scp->device->id]++; | ||
3631 | ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), " | ||
3632 | "ASC_NOERROR\n"); | ||
3633 | break; | ||
3634 | case ASC_BUSY: | ||
3635 | ASC_STATS(scp->device->host, exe_busy); | ||
3636 | break; | ||
3637 | case ASC_ERROR: | ||
3638 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
3639 | "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", | ||
3640 | boardp->id, adv_dvc_varp->err_code); | ||
3641 | ASC_STATS(scp->device->host, exe_error); | ||
3642 | scp->result = HOST_BYTE(DID_ERROR); | ||
3643 | break; | ||
3644 | default: | ||
3645 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
3646 | "AdvExeScsiQueue() unknown, err_code 0x%x\n", | ||
3647 | boardp->id, adv_dvc_varp->err_code); | ||
3648 | ASC_STATS(scp->device->host, exe_unknown); | ||
3649 | scp->result = HOST_BYTE(DID_ERROR); | ||
3650 | break; | ||
3651 | } | ||
3652 | } | ||
3653 | 2775 | ||
3654 | ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); | 2776 | printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", |
3655 | return ret; | 2777 | (unsigned)h->chip_scsi_id, (ulong)h->cfg); |
3656 | } | 2778 | } |
3657 | 2779 | ||
3658 | /* | 2780 | /* |
3659 | * Build a request structure for the Asc Library (Narrow Board). | 2781 | * asc_prt_adv_dvc_cfg() |
3660 | * | ||
3661 | * The global structures 'asc_scsi_q' and 'asc_sg_head' are | ||
3662 | * used to build the request. | ||
3663 | * | 2782 | * |
3664 | * If an error occurs, then return ASC_ERROR. | 2783 | * Display an ADV_DVC_CFG structure. |
3665 | */ | 2784 | */ |
3666 | static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | 2785 | static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) |
3667 | { | 2786 | { |
3668 | /* | 2787 | printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h); |
3669 | * Mutually exclusive access is required to 'asc_scsi_q' and | ||
3670 | * 'asc_sg_head' until after the request is started. | ||
3671 | */ | ||
3672 | memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); | ||
3673 | |||
3674 | /* | ||
3675 | * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. | ||
3676 | */ | ||
3677 | asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); | ||
3678 | |||
3679 | /* | ||
3680 | * Build the ASC_SCSI_Q request. | ||
3681 | */ | ||
3682 | asc_scsi_q.cdbptr = &scp->cmnd[0]; | ||
3683 | asc_scsi_q.q2.cdb_len = scp->cmd_len; | ||
3684 | asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); | ||
3685 | asc_scsi_q.q1.target_lun = scp->device->lun; | ||
3686 | asc_scsi_q.q2.target_ix = | ||
3687 | ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); | ||
3688 | asc_scsi_q.q1.sense_addr = | ||
3689 | cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); | ||
3690 | asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); | ||
3691 | |||
3692 | /* | ||
3693 | * If there are any outstanding requests for the current target, | ||
3694 | * then every 255th request send an ORDERED request. This heuristic | ||
3695 | * tries to retain the benefit of request sorting while preventing | ||
3696 | * request starvation. 255 is the max number of tags or pending commands | ||
3697 | * a device may have outstanding. | ||
3698 | * | ||
3699 | * The request count is incremented below for every successfully | ||
3700 | * started request. | ||
3701 | * | ||
3702 | */ | ||
3703 | if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && | ||
3704 | (boardp->reqcnt[scp->device->id] % 255) == 0) { | ||
3705 | asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; | ||
3706 | } else { | ||
3707 | asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; | ||
3708 | } | ||
3709 | |||
3710 | /* | ||
3711 | * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather | ||
3712 | * buffer command. | ||
3713 | */ | ||
3714 | if (scp->use_sg == 0) { | ||
3715 | /* | ||
3716 | * CDB request of single contiguous buffer. | ||
3717 | */ | ||
3718 | ASC_STATS(scp->device->host, cont_cnt); | ||
3719 | scp->SCp.dma_handle = scp->request_bufflen ? | ||
3720 | dma_map_single(boardp->dev, scp->request_buffer, | ||
3721 | scp->request_bufflen, | ||
3722 | scp->sc_data_direction) : 0; | ||
3723 | asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); | ||
3724 | asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); | ||
3725 | ASC_STATS_ADD(scp->device->host, cont_xfer, | ||
3726 | ASC_CEILING(scp->request_bufflen, 512)); | ||
3727 | asc_scsi_q.q1.sg_queue_cnt = 0; | ||
3728 | asc_scsi_q.sg_head = NULL; | ||
3729 | } else { | ||
3730 | /* | ||
3731 | * CDB scatter-gather request list. | ||
3732 | */ | ||
3733 | int sgcnt; | ||
3734 | int use_sg; | ||
3735 | struct scatterlist *slp; | ||
3736 | |||
3737 | slp = (struct scatterlist *)scp->request_buffer; | ||
3738 | use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg, | ||
3739 | scp->sc_data_direction); | ||
3740 | |||
3741 | if (use_sg > scp->device->host->sg_tablesize) { | ||
3742 | ASC_PRINT3("asc_build_req: board %d: use_sg %d > " | ||
3743 | "sg_tablesize %d\n", boardp->id, use_sg, | ||
3744 | scp->device->host->sg_tablesize); | ||
3745 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, | ||
3746 | scp->sc_data_direction); | ||
3747 | scp->result = HOST_BYTE(DID_ERROR); | ||
3748 | return ASC_ERROR; | ||
3749 | } | ||
3750 | |||
3751 | ASC_STATS(scp->device->host, sg_cnt); | ||
3752 | |||
3753 | /* | ||
3754 | * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q | ||
3755 | * structure to point to it. | ||
3756 | */ | ||
3757 | memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); | ||
3758 | 2788 | ||
3759 | asc_scsi_q.q1.cntl |= QC_SG_HEAD; | 2789 | printk(" disc_enable 0x%x, termination 0x%x\n", |
3760 | asc_scsi_q.sg_head = &asc_sg_head; | 2790 | h->disc_enable, h->termination); |
3761 | asc_scsi_q.q1.data_cnt = 0; | ||
3762 | asc_scsi_q.q1.data_addr = 0; | ||
3763 | /* This is a byte value, otherwise it would need to be swapped. */ | ||
3764 | asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; | ||
3765 | ASC_STATS_ADD(scp->device->host, sg_elem, | ||
3766 | asc_sg_head.entry_cnt); | ||
3767 | 2791 | ||
3768 | /* | 2792 | printk(" chip_version 0x%x, mcode_date 0x%x\n", |
3769 | * Convert scatter-gather list into ASC_SG_HEAD list. | 2793 | h->chip_version, h->mcode_date); |
3770 | */ | ||
3771 | for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { | ||
3772 | asc_sg_head.sg_list[sgcnt].addr = | ||
3773 | cpu_to_le32(sg_dma_address(slp)); | ||
3774 | asc_sg_head.sg_list[sgcnt].bytes = | ||
3775 | cpu_to_le32(sg_dma_len(slp)); | ||
3776 | ASC_STATS_ADD(scp->device->host, sg_xfer, | ||
3777 | ASC_CEILING(sg_dma_len(slp), 512)); | ||
3778 | } | ||
3779 | } | ||
3780 | 2794 | ||
3781 | ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); | 2795 | printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", |
3782 | ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); | 2796 | h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); |
3783 | 2797 | ||
3784 | return ASC_NOERROR; | 2798 | printk(" control_flag 0x%x\n", h->control_flag); |
3785 | } | 2799 | } |
3786 | 2800 | ||
3787 | /* | 2801 | /* |
3788 | * Build a request structure for the Adv Library (Wide Board). | 2802 | * asc_prt_adv_scsi_req_q() |
3789 | * | ||
3790 | * If an adv_req_t can not be allocated to issue the request, | ||
3791 | * then return ASC_BUSY. If an error occurs, then return ASC_ERROR. | ||
3792 | * | 2803 | * |
3793 | * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the | 2804 | * Display an ADV_SCSI_REQ_Q structure. |
3794 | * microcode for DMA addresses or math operations are byte swapped | ||
3795 | * to little-endian order. | ||
3796 | */ | 2805 | */ |
3797 | static int | 2806 | static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) |
3798 | adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, | ||
3799 | ADV_SCSI_REQ_Q **adv_scsiqpp) | ||
3800 | { | 2807 | { |
3801 | adv_req_t *reqp; | 2808 | int sg_blk_cnt; |
3802 | ADV_SCSI_REQ_Q *scsiqp; | 2809 | struct asc_sg_block *sg_ptr; |
3803 | int i; | ||
3804 | int ret; | ||
3805 | |||
3806 | /* | ||
3807 | * Allocate an adv_req_t structure from the board to execute | ||
3808 | * the command. | ||
3809 | */ | ||
3810 | if (boardp->adv_reqp == NULL) { | ||
3811 | ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); | ||
3812 | ASC_STATS(scp->device->host, adv_build_noreq); | ||
3813 | return ASC_BUSY; | ||
3814 | } else { | ||
3815 | reqp = boardp->adv_reqp; | ||
3816 | boardp->adv_reqp = reqp->next_reqp; | ||
3817 | reqp->next_reqp = NULL; | ||
3818 | } | ||
3819 | |||
3820 | /* | ||
3821 | * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. | ||
3822 | */ | ||
3823 | scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); | ||
3824 | |||
3825 | /* | ||
3826 | * Initialize the structure. | ||
3827 | */ | ||
3828 | scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; | ||
3829 | |||
3830 | /* | ||
3831 | * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. | ||
3832 | */ | ||
3833 | scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); | ||
3834 | |||
3835 | /* | ||
3836 | * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. | ||
3837 | */ | ||
3838 | reqp->cmndp = scp; | ||
3839 | |||
3840 | /* | ||
3841 | * Build the ADV_SCSI_REQ_Q request. | ||
3842 | */ | ||
3843 | |||
3844 | /* Set CDB length and copy it to the request structure. */ | ||
3845 | scsiqp->cdb_len = scp->cmd_len; | ||
3846 | /* Copy first 12 CDB bytes to cdb[]. */ | ||
3847 | for (i = 0; i < scp->cmd_len && i < 12; i++) { | ||
3848 | scsiqp->cdb[i] = scp->cmnd[i]; | ||
3849 | } | ||
3850 | /* Copy last 4 CDB bytes, if present, to cdb16[]. */ | ||
3851 | for (; i < scp->cmd_len; i++) { | ||
3852 | scsiqp->cdb16[i - 12] = scp->cmnd[i]; | ||
3853 | } | ||
3854 | |||
3855 | scsiqp->target_id = scp->device->id; | ||
3856 | scsiqp->target_lun = scp->device->lun; | ||
3857 | |||
3858 | scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); | ||
3859 | scsiqp->sense_len = sizeof(scp->sense_buffer); | ||
3860 | 2810 | ||
3861 | /* | 2811 | printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); |
3862 | * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather | ||
3863 | * buffer command. | ||
3864 | */ | ||
3865 | 2812 | ||
3866 | scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); | 2813 | printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", |
3867 | scsiqp->vdata_addr = scp->request_buffer; | 2814 | q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag); |
3868 | scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); | ||
3869 | 2815 | ||
3870 | if (scp->use_sg == 0) { | 2816 | printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", |
3871 | /* | 2817 | q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr); |
3872 | * CDB request of single contiguous buffer. | ||
3873 | */ | ||
3874 | reqp->sgblkp = NULL; | ||
3875 | scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); | ||
3876 | if (scp->request_bufflen) { | ||
3877 | scsiqp->vdata_addr = scp->request_buffer; | ||
3878 | scp->SCp.dma_handle = | ||
3879 | dma_map_single(boardp->dev, scp->request_buffer, | ||
3880 | scp->request_bufflen, | ||
3881 | scp->sc_data_direction); | ||
3882 | } else { | ||
3883 | scsiqp->vdata_addr = NULL; | ||
3884 | scp->SCp.dma_handle = 0; | ||
3885 | } | ||
3886 | scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); | ||
3887 | scsiqp->sg_list_ptr = NULL; | ||
3888 | scsiqp->sg_real_addr = 0; | ||
3889 | ASC_STATS(scp->device->host, cont_cnt); | ||
3890 | ASC_STATS_ADD(scp->device->host, cont_xfer, | ||
3891 | ASC_CEILING(scp->request_bufflen, 512)); | ||
3892 | } else { | ||
3893 | /* | ||
3894 | * CDB scatter-gather request list. | ||
3895 | */ | ||
3896 | struct scatterlist *slp; | ||
3897 | int use_sg; | ||
3898 | 2818 | ||
3899 | slp = (struct scatterlist *)scp->request_buffer; | 2819 | printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", |
3900 | use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg, | 2820 | (ulong)le32_to_cpu(q->data_cnt), |
3901 | scp->sc_data_direction); | 2821 | (ulong)le32_to_cpu(q->sense_addr), q->sense_len); |
3902 | 2822 | ||
3903 | if (use_sg > ADV_MAX_SG_LIST) { | 2823 | printk |
3904 | ASC_PRINT3("adv_build_req: board %d: use_sg %d > " | 2824 | (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", |
3905 | "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg, | 2825 | q->cdb_len, q->done_status, q->host_status, q->scsi_status); |
3906 | scp->device->host->sg_tablesize); | ||
3907 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, | ||
3908 | scp->sc_data_direction); | ||
3909 | scp->result = HOST_BYTE(DID_ERROR); | ||
3910 | 2826 | ||
3911 | /* | 2827 | printk(" sg_working_ix 0x%x, target_cmd %u\n", |
3912 | * Free the 'adv_req_t' structure by adding it back | 2828 | q->sg_working_ix, q->target_cmd); |
3913 | * to the board free list. | ||
3914 | */ | ||
3915 | reqp->next_reqp = boardp->adv_reqp; | ||
3916 | boardp->adv_reqp = reqp; | ||
3917 | 2829 | ||
3918 | return ASC_ERROR; | 2830 | printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", |
3919 | } | 2831 | (ulong)le32_to_cpu(q->scsiq_rptr), |
2832 | (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr); | ||
3920 | 2833 | ||
3921 | ret = adv_get_sglist(boardp, reqp, scp, use_sg); | 2834 | /* Display the request's ADV_SG_BLOCK structures. */ |
3922 | if (ret != ADV_SUCCESS) { | 2835 | if (q->sg_list_ptr != NULL) { |
2836 | sg_blk_cnt = 0; | ||
2837 | while (1) { | ||
3923 | /* | 2838 | /* |
3924 | * Free the adv_req_t structure by adding it back to | 2839 | * 'sg_ptr' is a physical address. Convert it to a virtual |
3925 | * the board free list. | 2840 | * address by indexing 'sg_blk_cnt' into the virtual address |
2841 | * array 'sg_list_ptr'. | ||
2842 | * | ||
2843 | * XXX - Assumes all SG physical blocks are virtually contiguous. | ||
3926 | */ | 2844 | */ |
3927 | reqp->next_reqp = boardp->adv_reqp; | 2845 | sg_ptr = |
3928 | boardp->adv_reqp = reqp; | 2846 | &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]); |
3929 | 2847 | asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); | |
3930 | return ret; | 2848 | if (sg_ptr->sg_ptr == 0) { |
2849 | break; | ||
2850 | } | ||
2851 | sg_blk_cnt++; | ||
3931 | } | 2852 | } |
3932 | |||
3933 | ASC_STATS(scp->device->host, sg_cnt); | ||
3934 | ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); | ||
3935 | } | 2853 | } |
3936 | |||
3937 | ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); | ||
3938 | ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); | ||
3939 | |||
3940 | *adv_scsiqpp = scsiqp; | ||
3941 | |||
3942 | return ASC_NOERROR; | ||
3943 | } | 2854 | } |
3944 | 2855 | ||
3945 | /* | 2856 | /* |
3946 | * Build scatter-gather list for Adv Library (Wide Board). | 2857 | * asc_prt_adv_sgblock() |
3947 | * | ||
3948 | * Additional ADV_SG_BLOCK structures will need to be allocated | ||
3949 | * if the total number of scatter-gather elements exceeds | ||
3950 | * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are | ||
3951 | * assumed to be physically contiguous. | ||
3952 | * | 2858 | * |
3953 | * Return: | 2859 | * Display an ADV_SG_BLOCK structure. |
3954 | * ADV_SUCCESS(1) - SG List successfully created | ||
3955 | * ADV_ERROR(-1) - SG List creation failed | ||
3956 | */ | 2860 | */ |
3957 | static int | 2861 | static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) |
3958 | adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, | ||
3959 | int use_sg) | ||
3960 | { | 2862 | { |
3961 | adv_sgblk_t *sgblkp; | ||
3962 | ADV_SCSI_REQ_Q *scsiqp; | ||
3963 | struct scatterlist *slp; | ||
3964 | int sg_elem_cnt; | ||
3965 | ADV_SG_BLOCK *sg_block, *prev_sg_block; | ||
3966 | ADV_PADDR sg_block_paddr; | ||
3967 | int i; | 2863 | int i; |
3968 | 2864 | ||
3969 | scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); | 2865 | printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", |
3970 | slp = (struct scatterlist *)scp->request_buffer; | 2866 | (ulong)b, sgblockno); |
3971 | sg_elem_cnt = use_sg; | 2867 | printk(" sg_cnt %u, sg_ptr 0x%lx\n", |
3972 | prev_sg_block = NULL; | 2868 | b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr)); |
3973 | reqp->sgblkp = NULL; | 2869 | BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK); |
3974 | 2870 | if (b->sg_ptr != 0) | |
3975 | for (;;) { | 2871 | BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK); |
3976 | /* | 2872 | for (i = 0; i < b->sg_cnt; i++) { |
3977 | * Allocate a 'adv_sgblk_t' structure from the board free | 2873 | printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", |
3978 | * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK | 2874 | i, (ulong)b->sg_list[i].sg_addr, |
3979 | * (15) scatter-gather elements. | 2875 | (ulong)b->sg_list[i].sg_count); |
3980 | */ | ||
3981 | if ((sgblkp = boardp->adv_sgblkp) == NULL) { | ||
3982 | ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); | ||
3983 | ASC_STATS(scp->device->host, adv_build_nosg); | ||
3984 | |||
3985 | /* | ||
3986 | * Allocation failed. Free 'adv_sgblk_t' structures | ||
3987 | * already allocated for the request. | ||
3988 | */ | ||
3989 | while ((sgblkp = reqp->sgblkp) != NULL) { | ||
3990 | /* Remove 'sgblkp' from the request list. */ | ||
3991 | reqp->sgblkp = sgblkp->next_sgblkp; | ||
3992 | |||
3993 | /* Add 'sgblkp' to the board free list. */ | ||
3994 | sgblkp->next_sgblkp = boardp->adv_sgblkp; | ||
3995 | boardp->adv_sgblkp = sgblkp; | ||
3996 | } | ||
3997 | return ASC_BUSY; | ||
3998 | } | ||
3999 | |||
4000 | /* Complete 'adv_sgblk_t' board allocation. */ | ||
4001 | boardp->adv_sgblkp = sgblkp->next_sgblkp; | ||
4002 | sgblkp->next_sgblkp = NULL; | ||
4003 | |||
4004 | /* | ||
4005 | * Get 8 byte aligned virtual and physical addresses | ||
4006 | * for the allocated ADV_SG_BLOCK structure. | ||
4007 | */ | ||
4008 | sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block); | ||
4009 | sg_block_paddr = virt_to_bus(sg_block); | ||
4010 | |||
4011 | /* | ||
4012 | * Check if this is the first 'adv_sgblk_t' for the | ||
4013 | * request. | ||
4014 | */ | ||
4015 | if (reqp->sgblkp == NULL) { | ||
4016 | /* Request's first scatter-gather block. */ | ||
4017 | reqp->sgblkp = sgblkp; | ||
4018 | |||
4019 | /* | ||
4020 | * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical | ||
4021 | * address pointers. | ||
4022 | */ | ||
4023 | scsiqp->sg_list_ptr = sg_block; | ||
4024 | scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr); | ||
4025 | } else { | ||
4026 | /* Request's second or later scatter-gather block. */ | ||
4027 | sgblkp->next_sgblkp = reqp->sgblkp; | ||
4028 | reqp->sgblkp = sgblkp; | ||
4029 | |||
4030 | /* | ||
4031 | * Point the previous ADV_SG_BLOCK structure to | ||
4032 | * the newly allocated ADV_SG_BLOCK structure. | ||
4033 | */ | ||
4034 | prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr); | ||
4035 | } | ||
4036 | |||
4037 | for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { | ||
4038 | sg_block->sg_list[i].sg_addr = | ||
4039 | cpu_to_le32(sg_dma_address(slp)); | ||
4040 | sg_block->sg_list[i].sg_count = | ||
4041 | cpu_to_le32(sg_dma_len(slp)); | ||
4042 | ASC_STATS_ADD(scp->device->host, sg_xfer, | ||
4043 | ASC_CEILING(sg_dma_len(slp), 512)); | ||
4044 | |||
4045 | if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ | ||
4046 | sg_block->sg_cnt = i + 1; | ||
4047 | sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ | ||
4048 | return ADV_SUCCESS; | ||
4049 | } | ||
4050 | slp++; | ||
4051 | } | ||
4052 | sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; | ||
4053 | prev_sg_block = sg_block; | ||
4054 | } | 2876 | } |
4055 | } | 2877 | } |
4056 | 2878 | ||
4057 | /* | 2879 | /* |
4058 | * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). | 2880 | * asc_prt_hex() |
4059 | * | 2881 | * |
4060 | * Interrupt callback function for the Narrow SCSI Asc Library. | 2882 | * Print hexadecimal output in 4 byte groupings 32 bytes |
2883 | * or 8 double-words per line. | ||
4061 | */ | 2884 | */ |
4062 | static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) | 2885 | static void asc_prt_hex(char *f, uchar *s, int l) |
4063 | { | 2886 | { |
4064 | asc_board_t *boardp; | 2887 | int i; |
4065 | struct scsi_cmnd *scp; | 2888 | int j; |
4066 | struct Scsi_Host *shost; | 2889 | int k; |
4067 | 2890 | int m; | |
4068 | ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", | ||
4069 | (ulong)asc_dvc_varp, (ulong)qdonep); | ||
4070 | ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); | ||
4071 | |||
4072 | /* | ||
4073 | * Get the struct scsi_cmnd structure and Scsi_Host structure for the | ||
4074 | * command that has been completed. | ||
4075 | */ | ||
4076 | scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); | ||
4077 | ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp); | ||
4078 | |||
4079 | if (scp == NULL) { | ||
4080 | ASC_PRINT("asc_isr_callback: scp is NULL\n"); | ||
4081 | return; | ||
4082 | } | ||
4083 | ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); | ||
4084 | |||
4085 | shost = scp->device->host; | ||
4086 | ASC_STATS(shost, callback); | ||
4087 | ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); | ||
4088 | 2891 | ||
4089 | boardp = ASC_BOARDP(shost); | 2892 | printk("%s: (%d bytes)\n", f, l); |
4090 | BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var); | ||
4091 | 2893 | ||
4092 | /* | 2894 | for (i = 0; i < l; i += 32) { |
4093 | * 'qdonep' contains the command's ending status. | ||
4094 | */ | ||
4095 | switch (qdonep->d3.done_stat) { | ||
4096 | case QD_NO_ERROR: | ||
4097 | ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); | ||
4098 | scp->result = 0; | ||
4099 | 2895 | ||
4100 | /* | 2896 | /* Display a maximum of 8 double-words per line. */ |
4101 | * Check for an underrun condition. | 2897 | if ((k = (l - i) / 4) >= 8) { |
4102 | * | 2898 | k = 8; |
4103 | * If there was no error and an underrun condition, then | 2899 | m = 0; |
4104 | * return the number of underrun bytes. | 2900 | } else { |
4105 | */ | 2901 | m = (l - i) % 4; |
4106 | if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && | ||
4107 | qdonep->remain_bytes <= scp->request_bufflen) { | ||
4108 | ASC_DBG1(1, | ||
4109 | "asc_isr_callback: underrun condition %u bytes\n", | ||
4110 | (unsigned)qdonep->remain_bytes); | ||
4111 | scp->resid = qdonep->remain_bytes; | ||
4112 | } | 2902 | } |
4113 | break; | ||
4114 | 2903 | ||
4115 | case QD_WITH_ERROR: | 2904 | for (j = 0; j < k; j++) { |
4116 | ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); | 2905 | printk(" %2.2X%2.2X%2.2X%2.2X", |
4117 | switch (qdonep->d3.host_stat) { | 2906 | (unsigned)s[i + (j * 4)], |
4118 | case QHSTA_NO_ERROR: | 2907 | (unsigned)s[i + (j * 4) + 1], |
4119 | if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { | 2908 | (unsigned)s[i + (j * 4) + 2], |
4120 | ASC_DBG(2, | 2909 | (unsigned)s[i + (j * 4) + 3]); |
4121 | "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); | 2910 | } |
4122 | ASC_DBG_PRT_SENSE(2, scp->sense_buffer, | ||
4123 | sizeof(scp->sense_buffer)); | ||
4124 | /* | ||
4125 | * Note: The 'status_byte()' macro used by | ||
4126 | * target drivers defined in scsi.h shifts the | ||
4127 | * status byte returned by host drivers right | ||
4128 | * by 1 bit. This is why target drivers also | ||
4129 | * use right shifted status byte definitions. | ||
4130 | * For instance target drivers use | ||
4131 | * CHECK_CONDITION, defined to 0x1, instead of | ||
4132 | * the SCSI defined check condition value of | ||
4133 | * 0x2. Host drivers are supposed to return | ||
4134 | * the status byte as it is defined by SCSI. | ||
4135 | */ | ||
4136 | scp->result = DRIVER_BYTE(DRIVER_SENSE) | | ||
4137 | STATUS_BYTE(qdonep->d3.scsi_stat); | ||
4138 | } else { | ||
4139 | scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); | ||
4140 | } | ||
4141 | break; | ||
4142 | 2911 | ||
2912 | switch (m) { | ||
2913 | case 0: | ||
4143 | default: | 2914 | default: |
4144 | /* QHSTA error occurred */ | 2915 | break; |
4145 | ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", | 2916 | case 1: |
4146 | qdonep->d3.host_stat); | 2917 | printk(" %2.2X", (unsigned)s[i + (j * 4)]); |
4147 | scp->result = HOST_BYTE(DID_BAD_TARGET); | 2918 | break; |
2919 | case 2: | ||
2920 | printk(" %2.2X%2.2X", | ||
2921 | (unsigned)s[i + (j * 4)], | ||
2922 | (unsigned)s[i + (j * 4) + 1]); | ||
2923 | break; | ||
2924 | case 3: | ||
2925 | printk(" %2.2X%2.2X%2.2X", | ||
2926 | (unsigned)s[i + (j * 4) + 1], | ||
2927 | (unsigned)s[i + (j * 4) + 2], | ||
2928 | (unsigned)s[i + (j * 4) + 3]); | ||
4148 | break; | 2929 | break; |
4149 | } | 2930 | } |
4150 | break; | ||
4151 | |||
4152 | case QD_ABORTED_BY_HOST: | ||
4153 | ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); | ||
4154 | scp->result = | ||
4155 | HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3. | ||
4156 | scsi_msg) | | ||
4157 | STATUS_BYTE(qdonep->d3.scsi_stat); | ||
4158 | break; | ||
4159 | |||
4160 | default: | ||
4161 | ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", | ||
4162 | qdonep->d3.done_stat); | ||
4163 | scp->result = | ||
4164 | HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3. | ||
4165 | scsi_msg) | | ||
4166 | STATUS_BYTE(qdonep->d3.scsi_stat); | ||
4167 | break; | ||
4168 | } | ||
4169 | 2931 | ||
4170 | /* | 2932 | printk("\n"); |
4171 | * If the 'init_tidmask' bit isn't already set for the target and the | ||
4172 | * current request finished normally, then set the bit for the target | ||
4173 | * to indicate that a device is present. | ||
4174 | */ | ||
4175 | if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && | ||
4176 | qdonep->d3.done_stat == QD_NO_ERROR && | ||
4177 | qdonep->d3.host_stat == QHSTA_NO_ERROR) { | ||
4178 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); | ||
4179 | } | 2933 | } |
4180 | |||
4181 | asc_scsi_done(scp); | ||
4182 | |||
4183 | return; | ||
4184 | } | 2934 | } |
2935 | #endif /* ADVANSYS_DEBUG */ | ||
4185 | 2936 | ||
4186 | /* | 2937 | /* |
4187 | * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR(). | 2938 | * advansys_info() |
4188 | * | 2939 | * |
4189 | * Callback function for the Wide SCSI Adv Library. | 2940 | * Return suitable for printing on the console with the argument |
2941 | * adapter's configuration information. | ||
2942 | * | ||
2943 | * Note: The information line should not exceed ASC_INFO_SIZE bytes, | ||
2944 | * otherwise the static 'info' array will be overrun. | ||
4190 | */ | 2945 | */ |
4191 | static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) | 2946 | static const char *advansys_info(struct Scsi_Host *shost) |
4192 | { | 2947 | { |
2948 | static char info[ASC_INFO_SIZE]; | ||
4193 | asc_board_t *boardp; | 2949 | asc_board_t *boardp; |
4194 | adv_req_t *reqp; | 2950 | ASC_DVC_VAR *asc_dvc_varp; |
4195 | adv_sgblk_t *sgblkp; | 2951 | ADV_DVC_VAR *adv_dvc_varp; |
4196 | struct scsi_cmnd *scp; | 2952 | char *busname; |
4197 | struct Scsi_Host *shost; | 2953 | char *widename = NULL; |
4198 | ADV_DCNT resid_cnt; | ||
4199 | |||
4200 | ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", | ||
4201 | (ulong)adv_dvc_varp, (ulong)scsiqp); | ||
4202 | ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); | ||
4203 | |||
4204 | /* | ||
4205 | * Get the adv_req_t structure for the command that has been | ||
4206 | * completed. The adv_req_t structure actually contains the | ||
4207 | * completed ADV_SCSI_REQ_Q structure. | ||
4208 | */ | ||
4209 | reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr); | ||
4210 | ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp); | ||
4211 | if (reqp == NULL) { | ||
4212 | ASC_PRINT("adv_isr_callback: reqp is NULL\n"); | ||
4213 | return; | ||
4214 | } | ||
4215 | |||
4216 | /* | ||
4217 | * Get the struct scsi_cmnd structure and Scsi_Host structure for the | ||
4218 | * command that has been completed. | ||
4219 | * | ||
4220 | * Note: The adv_req_t request structure and adv_sgblk_t structure, | ||
4221 | * if any, are dropped, because a board structure pointer can not be | ||
4222 | * determined. | ||
4223 | */ | ||
4224 | scp = reqp->cmndp; | ||
4225 | ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp); | ||
4226 | if (scp == NULL) { | ||
4227 | ASC_PRINT | ||
4228 | ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); | ||
4229 | return; | ||
4230 | } | ||
4231 | ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); | ||
4232 | |||
4233 | shost = scp->device->host; | ||
4234 | ASC_STATS(shost, callback); | ||
4235 | ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); | ||
4236 | 2954 | ||
4237 | boardp = ASC_BOARDP(shost); | 2955 | boardp = ASC_BOARDP(shost); |
4238 | BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var); | 2956 | if (ASC_NARROW_BOARD(boardp)) { |
4239 | 2957 | asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; | |
4240 | /* | 2958 | ASC_DBG(1, "advansys_info: begin\n"); |
4241 | * 'done_status' contains the command's ending status. | 2959 | if (asc_dvc_varp->bus_type & ASC_IS_ISA) { |
4242 | */ | 2960 | if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == |
4243 | switch (scsiqp->done_status) { | 2961 | ASC_IS_ISAPNP) { |
4244 | case QD_NO_ERROR: | 2962 | busname = "ISA PnP"; |
4245 | ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); | 2963 | } else { |
4246 | scp->result = 0; | 2964 | busname = "ISA"; |
4247 | 2965 | } | |
2966 | sprintf(info, | ||
2967 | "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", | ||
2968 | ASC_VERSION, busname, | ||
2969 | (ulong)shost->io_port, | ||
2970 | (ulong)shost->io_port + ASC_IOADR_GAP - 1, | ||
2971 | shost->irq, shost->dma_channel); | ||
2972 | } else { | ||
2973 | if (asc_dvc_varp->bus_type & ASC_IS_VL) { | ||
2974 | busname = "VL"; | ||
2975 | } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { | ||
2976 | busname = "EISA"; | ||
2977 | } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { | ||
2978 | if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) | ||
2979 | == ASC_IS_PCI_ULTRA) { | ||
2980 | busname = "PCI Ultra"; | ||
2981 | } else { | ||
2982 | busname = "PCI"; | ||
2983 | } | ||
2984 | } else { | ||
2985 | busname = "?"; | ||
2986 | ASC_PRINT2("advansys_info: board %d: unknown " | ||
2987 | "bus type %d\n", boardp->id, | ||
2988 | asc_dvc_varp->bus_type); | ||
2989 | } | ||
2990 | sprintf(info, | ||
2991 | "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", | ||
2992 | ASC_VERSION, busname, (ulong)shost->io_port, | ||
2993 | (ulong)shost->io_port + ASC_IOADR_GAP - 1, | ||
2994 | shost->irq); | ||
2995 | } | ||
2996 | } else { | ||
4248 | /* | 2997 | /* |
4249 | * Check for an underrun condition. | 2998 | * Wide Adapter Information |
4250 | * | 2999 | * |
4251 | * If there was no error and an underrun condition, then | 3000 | * Memory-mapped I/O is used instead of I/O space to access |
4252 | * then return the number of underrun bytes. | 3001 | * the adapter, but display the I/O Port range. The Memory |
3002 | * I/O address is displayed through the driver /proc file. | ||
4253 | */ | 3003 | */ |
4254 | resid_cnt = le32_to_cpu(scsiqp->data_cnt); | 3004 | adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; |
4255 | if (scp->request_bufflen != 0 && resid_cnt != 0 && | 3005 | if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { |
4256 | resid_cnt <= scp->request_bufflen) { | 3006 | widename = "Ultra-Wide"; |
4257 | ASC_DBG1(1, | 3007 | } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { |
4258 | "adv_isr_callback: underrun condition %lu bytes\n", | 3008 | widename = "Ultra2-Wide"; |
4259 | (ulong)resid_cnt); | 3009 | } else { |
4260 | scp->resid = resid_cnt; | 3010 | widename = "Ultra3-Wide"; |
4261 | } | ||
4262 | break; | ||
4263 | |||
4264 | case QD_WITH_ERROR: | ||
4265 | ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); | ||
4266 | switch (scsiqp->host_status) { | ||
4267 | case QHSTA_NO_ERROR: | ||
4268 | if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { | ||
4269 | ASC_DBG(2, | ||
4270 | "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); | ||
4271 | ASC_DBG_PRT_SENSE(2, scp->sense_buffer, | ||
4272 | sizeof(scp->sense_buffer)); | ||
4273 | /* | ||
4274 | * Note: The 'status_byte()' macro used by | ||
4275 | * target drivers defined in scsi.h shifts the | ||
4276 | * status byte returned by host drivers right | ||
4277 | * by 1 bit. This is why target drivers also | ||
4278 | * use right shifted status byte definitions. | ||
4279 | * For instance target drivers use | ||
4280 | * CHECK_CONDITION, defined to 0x1, instead of | ||
4281 | * the SCSI defined check condition value of | ||
4282 | * 0x2. Host drivers are supposed to return | ||
4283 | * the status byte as it is defined by SCSI. | ||
4284 | */ | ||
4285 | scp->result = DRIVER_BYTE(DRIVER_SENSE) | | ||
4286 | STATUS_BYTE(scsiqp->scsi_status); | ||
4287 | } else { | ||
4288 | scp->result = STATUS_BYTE(scsiqp->scsi_status); | ||
4289 | } | ||
4290 | break; | ||
4291 | |||
4292 | default: | ||
4293 | /* Some other QHSTA error occurred. */ | ||
4294 | ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", | ||
4295 | scsiqp->host_status); | ||
4296 | scp->result = HOST_BYTE(DID_BAD_TARGET); | ||
4297 | break; | ||
4298 | } | 3011 | } |
4299 | break; | 3012 | sprintf(info, |
4300 | 3013 | "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", | |
4301 | case QD_ABORTED_BY_HOST: | 3014 | ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base, |
4302 | ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); | 3015 | (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq); |
4303 | scp->result = | ||
4304 | HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); | ||
4305 | break; | ||
4306 | |||
4307 | default: | ||
4308 | ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", | ||
4309 | scsiqp->done_status); | ||
4310 | scp->result = | ||
4311 | HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); | ||
4312 | break; | ||
4313 | } | ||
4314 | |||
4315 | /* | ||
4316 | * If the 'init_tidmask' bit isn't already set for the target and the | ||
4317 | * current request finished normally, then set the bit for the target | ||
4318 | * to indicate that a device is present. | ||
4319 | */ | ||
4320 | if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && | ||
4321 | scsiqp->done_status == QD_NO_ERROR && | ||
4322 | scsiqp->host_status == QHSTA_NO_ERROR) { | ||
4323 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); | ||
4324 | } | ||
4325 | |||
4326 | asc_scsi_done(scp); | ||
4327 | |||
4328 | /* | ||
4329 | * Free all 'adv_sgblk_t' structures allocated for the request. | ||
4330 | */ | ||
4331 | while ((sgblkp = reqp->sgblkp) != NULL) { | ||
4332 | /* Remove 'sgblkp' from the request list. */ | ||
4333 | reqp->sgblkp = sgblkp->next_sgblkp; | ||
4334 | |||
4335 | /* Add 'sgblkp' to the board free list. */ | ||
4336 | sgblkp->next_sgblkp = boardp->adv_sgblkp; | ||
4337 | boardp->adv_sgblkp = sgblkp; | ||
4338 | } | 3016 | } |
4339 | 3017 | BUG_ON(strlen(info) >= ASC_INFO_SIZE); | |
4340 | /* | 3018 | ASC_DBG(1, "advansys_info: end\n"); |
4341 | * Free the adv_req_t structure used with the command by adding | 3019 | return info; |
4342 | * it back to the board free list. | ||
4343 | */ | ||
4344 | reqp->next_reqp = boardp->adv_reqp; | ||
4345 | boardp->adv_reqp = reqp; | ||
4346 | |||
4347 | ASC_DBG(1, "adv_isr_callback: done\n"); | ||
4348 | |||
4349 | return; | ||
4350 | } | 3020 | } |
4351 | 3021 | ||
3022 | #ifdef CONFIG_PROC_FS | ||
4352 | /* | 3023 | /* |
4353 | * adv_async_callback() - Adv Library asynchronous event callback function. | 3024 | * asc_prt_line() |
3025 | * | ||
3026 | * If 'cp' is NULL print to the console, otherwise print to a buffer. | ||
3027 | * | ||
3028 | * Return 0 if printing to the console, otherwise return the number of | ||
3029 | * bytes written to the buffer. | ||
3030 | * | ||
3031 | * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack | ||
3032 | * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. | ||
4354 | */ | 3033 | */ |
4355 | static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) | 3034 | static int asc_prt_line(char *buf, int buflen, char *fmt, ...) |
4356 | { | 3035 | { |
4357 | switch (code) { | 3036 | va_list args; |
4358 | case ADV_ASYNC_SCSI_BUS_RESET_DET: | 3037 | int ret; |
4359 | /* | 3038 | char s[ASC_PRTLINE_SIZE]; |
4360 | * The firmware detected a SCSI Bus reset. | ||
4361 | */ | ||
4362 | ASC_DBG(0, | ||
4363 | "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); | ||
4364 | break; | ||
4365 | |||
4366 | case ADV_ASYNC_RDMA_FAILURE: | ||
4367 | /* | ||
4368 | * Handle RDMA failure by resetting the SCSI Bus and | ||
4369 | * possibly the chip if it is unresponsive. Log the error | ||
4370 | * with a unique code. | ||
4371 | */ | ||
4372 | ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); | ||
4373 | AdvResetChipAndSB(adv_dvc_varp); | ||
4374 | break; | ||
4375 | |||
4376 | case ADV_HOST_SCSI_BUS_RESET: | ||
4377 | /* | ||
4378 | * Host generated SCSI bus reset occurred. | ||
4379 | */ | ||
4380 | ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); | ||
4381 | break; | ||
4382 | 3039 | ||
4383 | default: | 3040 | va_start(args, fmt); |
4384 | ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); | 3041 | ret = vsprintf(s, fmt, args); |
4385 | break; | 3042 | BUG_ON(ret >= ASC_PRTLINE_SIZE); |
3043 | if (buf == NULL) { | ||
3044 | (void)printk(s); | ||
3045 | ret = 0; | ||
3046 | } else { | ||
3047 | ret = min(buflen, ret); | ||
3048 | memcpy(buf, s, ret); | ||
4386 | } | 3049 | } |
3050 | va_end(args); | ||
3051 | return ret; | ||
4387 | } | 3052 | } |
4388 | 3053 | ||
4389 | #ifdef CONFIG_PROC_FS | ||
4390 | /* | 3054 | /* |
4391 | * asc_prt_board_devices() | 3055 | * asc_prt_board_devices() |
4392 | * | 3056 | * |
@@ -5548,159 +4212,7 @@ asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, | |||
5548 | return cnt; | 4212 | return cnt; |
5549 | } | 4213 | } |
5550 | 4214 | ||
5551 | /* | ||
5552 | * asc_prt_line() | ||
5553 | * | ||
5554 | * If 'cp' is NULL print to the console, otherwise print to a buffer. | ||
5555 | * | ||
5556 | * Return 0 if printing to the console, otherwise return the number of | ||
5557 | * bytes written to the buffer. | ||
5558 | * | ||
5559 | * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack | ||
5560 | * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. | ||
5561 | */ | ||
5562 | static int asc_prt_line(char *buf, int buflen, char *fmt, ...) | ||
5563 | { | ||
5564 | va_list args; | ||
5565 | int ret; | ||
5566 | char s[ASC_PRTLINE_SIZE]; | ||
5567 | |||
5568 | va_start(args, fmt); | ||
5569 | ret = vsprintf(s, fmt, args); | ||
5570 | BUG_ON(ret >= ASC_PRTLINE_SIZE); | ||
5571 | if (buf == NULL) { | ||
5572 | (void)printk(s); | ||
5573 | ret = 0; | ||
5574 | } else { | ||
5575 | ret = min(buflen, ret); | ||
5576 | memcpy(buf, s, ret); | ||
5577 | } | ||
5578 | va_end(args); | ||
5579 | return ret; | ||
5580 | } | ||
5581 | #endif /* CONFIG_PROC_FS */ | ||
5582 | |||
5583 | /* | ||
5584 | * void | ||
5585 | * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) | ||
5586 | * | ||
5587 | * Calling/Exit State: | ||
5588 | * none | ||
5589 | * | ||
5590 | * Description: | ||
5591 | * Output an ASC_SCSI_Q structure to the chip | ||
5592 | */ | ||
5593 | static void | ||
5594 | DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) | ||
5595 | { | ||
5596 | int i; | ||
5597 | |||
5598 | ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); | ||
5599 | AscSetChipLramAddr(iop_base, s_addr); | ||
5600 | for (i = 0; i < 2 * words; i += 2) { | ||
5601 | if (i == 4 || i == 20) { | ||
5602 | continue; | ||
5603 | } | ||
5604 | outpw(iop_base + IOP_RAM_DATA, | ||
5605 | ((ushort)outbuf[i + 1] << 8) | outbuf[i]); | ||
5606 | } | ||
5607 | } | ||
5608 | |||
5609 | /* | ||
5610 | * void | ||
5611 | * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) | ||
5612 | * | ||
5613 | * Calling/Exit State: | ||
5614 | * none | ||
5615 | * | ||
5616 | * Description: | ||
5617 | * Input an ASC_QDONE_INFO structure from the chip | ||
5618 | */ | ||
5619 | static void | ||
5620 | DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) | ||
5621 | { | ||
5622 | int i; | ||
5623 | ushort word; | ||
5624 | |||
5625 | AscSetChipLramAddr(iop_base, s_addr); | ||
5626 | for (i = 0; i < 2 * words; i += 2) { | ||
5627 | if (i == 10) { | ||
5628 | continue; | ||
5629 | } | ||
5630 | word = inpw(iop_base + IOP_RAM_DATA); | ||
5631 | inbuf[i] = word & 0xff; | ||
5632 | inbuf[i + 1] = (word >> 8) & 0xff; | ||
5633 | } | ||
5634 | ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); | ||
5635 | } | ||
5636 | |||
5637 | /* | ||
5638 | * Return the BIOS address of the adapter at the specified | ||
5639 | * I/O port and with the specified bus type. | ||
5640 | */ | ||
5641 | static unsigned short __devinit | ||
5642 | AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type) | ||
5643 | { | ||
5644 | unsigned short cfg_lsw; | ||
5645 | unsigned short bios_addr; | ||
5646 | |||
5647 | /* | ||
5648 | * The PCI BIOS is re-located by the motherboard BIOS. Because | ||
5649 | * of this the driver can not determine where a PCI BIOS is | ||
5650 | * loaded and executes. | ||
5651 | */ | ||
5652 | if (bus_type & ASC_IS_PCI) | ||
5653 | return 0; | ||
5654 | |||
5655 | #ifdef CONFIG_ISA | ||
5656 | if ((bus_type & ASC_IS_EISA) != 0) { | ||
5657 | cfg_lsw = AscGetEisaChipCfg(iop_base); | ||
5658 | cfg_lsw &= 0x000F; | ||
5659 | bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE; | ||
5660 | return bios_addr; | ||
5661 | } | ||
5662 | #endif /* CONFIG_ISA */ | ||
5663 | |||
5664 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
5665 | |||
5666 | /* | ||
5667 | * ISA PnP uses the top bit as the 32K BIOS flag | ||
5668 | */ | ||
5669 | if (bus_type == ASC_IS_ISAPNP) | ||
5670 | cfg_lsw &= 0x7FFF; | ||
5671 | bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE; | ||
5672 | return bios_addr; | ||
5673 | } | ||
5674 | |||
5675 | /* | ||
5676 | * DvcGetPhyAddr() | ||
5677 | * | ||
5678 | * Return the physical address of 'vaddr' and set '*lenp' to the | ||
5679 | * number of physically contiguous bytes that follow 'vaddr'. | ||
5680 | * 'flag' indicates the type of structure whose physical address | ||
5681 | * is being translated. | ||
5682 | * | ||
5683 | * Note: Because Linux currently doesn't page the kernel and all | ||
5684 | * kernel buffers are physically contiguous, leave '*lenp' unchanged. | ||
5685 | */ | ||
5686 | ADV_PADDR | ||
5687 | DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, | ||
5688 | uchar *vaddr, ADV_SDCNT *lenp, int flag) | ||
5689 | { | ||
5690 | ADV_PADDR paddr; | ||
5691 | |||
5692 | paddr = virt_to_bus(vaddr); | ||
5693 | |||
5694 | ASC_DBG4(4, | ||
5695 | "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", | ||
5696 | (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp), | ||
5697 | (ulong)paddr); | ||
5698 | |||
5699 | return paddr; | ||
5700 | } | ||
5701 | |||
5702 | #ifdef ADVANSYS_STATS | 4215 | #ifdef ADVANSYS_STATS |
5703 | #ifdef CONFIG_PROC_FS | ||
5704 | /* | 4216 | /* |
5705 | * asc_prt_board_stats() | 4217 | * asc_prt_board_stats() |
5706 | * | 4218 | * |
@@ -5803,420 +4315,543 @@ static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen) | |||
5803 | 4315 | ||
5804 | return totlen; | 4316 | return totlen; |
5805 | } | 4317 | } |
5806 | #endif /* CONFIG_PROC_FS */ | ||
5807 | #endif /* ADVANSYS_STATS */ | 4318 | #endif /* ADVANSYS_STATS */ |
5808 | 4319 | ||
5809 | #ifdef ADVANSYS_DEBUG | ||
5810 | /* | 4320 | /* |
5811 | * asc_prt_scsi_host() | 4321 | * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...} |
4322 | * | ||
4323 | * *buffer: I/O buffer | ||
4324 | * **start: if inout == FALSE pointer into buffer where user read should start | ||
4325 | * offset: current offset into a /proc/scsi/advansys/[0...] file | ||
4326 | * length: length of buffer | ||
4327 | * hostno: Scsi_Host host_no | ||
4328 | * inout: TRUE - user is writing; FALSE - user is reading | ||
4329 | * | ||
4330 | * Return the number of bytes read from or written to a | ||
4331 | * /proc/scsi/advansys/[0...] file. | ||
4332 | * | ||
4333 | * Note: This function uses the per board buffer 'prtbuf' which is | ||
4334 | * allocated when the board is initialized in advansys_detect(). The | ||
4335 | * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is | ||
4336 | * used to write to the buffer. The way asc_proc_copy() is written | ||
4337 | * if 'prtbuf' is too small it will not be overwritten. Instead the | ||
4338 | * user just won't get all the available statistics. | ||
5812 | */ | 4339 | */ |
5813 | static void asc_prt_scsi_host(struct Scsi_Host *s) | 4340 | static int |
4341 | advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | ||
4342 | off_t offset, int length, int inout) | ||
5814 | { | 4343 | { |
5815 | asc_board_t *boardp; | 4344 | asc_board_t *boardp; |
4345 | char *cp; | ||
4346 | int cplen; | ||
4347 | int cnt; | ||
4348 | int totcnt; | ||
4349 | int leftlen; | ||
4350 | char *curbuf; | ||
4351 | off_t advoffset; | ||
5816 | 4352 | ||
5817 | boardp = ASC_BOARDP(s); | 4353 | ASC_DBG(1, "advansys_proc_info: begin\n"); |
5818 | 4354 | ||
5819 | printk("Scsi_Host at addr 0x%lx\n", (ulong)s); | 4355 | /* |
5820 | printk(" host_busy %u, host_no %d, last_reset %d,\n", | 4356 | * User write not supported. |
5821 | s->host_busy, s->host_no, (unsigned)s->last_reset); | 4357 | */ |
4358 | if (inout == TRUE) { | ||
4359 | return (-ENOSYS); | ||
4360 | } | ||
5822 | 4361 | ||
5823 | printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n", | 4362 | /* |
5824 | (ulong)s->base, (ulong)s->io_port, s->irq); | 4363 | * User read of /proc/scsi/advansys/[0...] file. |
4364 | */ | ||
5825 | 4365 | ||
5826 | printk(" dma_channel %d, this_id %d, can_queue %d,\n", | 4366 | boardp = ASC_BOARDP(shost); |
5827 | s->dma_channel, s->this_id, s->can_queue); | ||
5828 | 4367 | ||
5829 | printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", | 4368 | /* Copy read data starting at the beginning of the buffer. */ |
5830 | s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); | 4369 | *start = buffer; |
4370 | curbuf = buffer; | ||
4371 | advoffset = 0; | ||
4372 | totcnt = 0; | ||
4373 | leftlen = length; | ||
5831 | 4374 | ||
5832 | if (ASC_NARROW_BOARD(boardp)) { | 4375 | /* |
5833 | asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); | 4376 | * Get board configuration information. |
5834 | asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); | 4377 | * |
5835 | } else { | 4378 | * advansys_info() returns the board string from its own static buffer. |
5836 | asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); | 4379 | */ |
5837 | asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); | 4380 | cp = (char *)advansys_info(shost); |
4381 | strcat(cp, "\n"); | ||
4382 | cplen = strlen(cp); | ||
4383 | /* Copy board information. */ | ||
4384 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
4385 | totcnt += cnt; | ||
4386 | leftlen -= cnt; | ||
4387 | if (leftlen == 0) { | ||
4388 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4389 | return totcnt; | ||
5838 | } | 4390 | } |
5839 | } | 4391 | advoffset += cplen; |
5840 | 4392 | curbuf += cnt; | |
5841 | /* | ||
5842 | * asc_prt_scsi_cmnd() | ||
5843 | */ | ||
5844 | static void asc_prt_scsi_cmnd(struct scsi_cmnd *s) | ||
5845 | { | ||
5846 | printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s); | ||
5847 | 4393 | ||
5848 | printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", | 4394 | /* |
5849 | (ulong)s->device->host, (ulong)s->device, s->device->id, | 4395 | * Display Wide Board BIOS Information. |
5850 | s->device->lun, s->device->channel); | 4396 | */ |
4397 | if (ASC_WIDE_BOARD(boardp)) { | ||
4398 | cp = boardp->prtbuf; | ||
4399 | cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE); | ||
4400 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
4401 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, | ||
4402 | cplen); | ||
4403 | totcnt += cnt; | ||
4404 | leftlen -= cnt; | ||
4405 | if (leftlen == 0) { | ||
4406 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4407 | return totcnt; | ||
4408 | } | ||
4409 | advoffset += cplen; | ||
4410 | curbuf += cnt; | ||
4411 | } | ||
5851 | 4412 | ||
5852 | asc_prt_hex(" CDB", s->cmnd, s->cmd_len); | 4413 | /* |
4414 | * Display driver information for each device attached to the board. | ||
4415 | */ | ||
4416 | cp = boardp->prtbuf; | ||
4417 | cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE); | ||
4418 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
4419 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
4420 | totcnt += cnt; | ||
4421 | leftlen -= cnt; | ||
4422 | if (leftlen == 0) { | ||
4423 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4424 | return totcnt; | ||
4425 | } | ||
4426 | advoffset += cplen; | ||
4427 | curbuf += cnt; | ||
5853 | 4428 | ||
5854 | printk("sc_data_direction %u, resid %d\n", | 4429 | /* |
5855 | s->sc_data_direction, s->resid); | 4430 | * Display EEPROM configuration for the board. |
4431 | */ | ||
4432 | cp = boardp->prtbuf; | ||
4433 | if (ASC_NARROW_BOARD(boardp)) { | ||
4434 | cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); | ||
4435 | } else { | ||
4436 | cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); | ||
4437 | } | ||
4438 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
4439 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
4440 | totcnt += cnt; | ||
4441 | leftlen -= cnt; | ||
4442 | if (leftlen == 0) { | ||
4443 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4444 | return totcnt; | ||
4445 | } | ||
4446 | advoffset += cplen; | ||
4447 | curbuf += cnt; | ||
5856 | 4448 | ||
5857 | printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len); | 4449 | /* |
4450 | * Display driver configuration and information for the board. | ||
4451 | */ | ||
4452 | cp = boardp->prtbuf; | ||
4453 | cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE); | ||
4454 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
4455 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
4456 | totcnt += cnt; | ||
4457 | leftlen -= cnt; | ||
4458 | if (leftlen == 0) { | ||
4459 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4460 | return totcnt; | ||
4461 | } | ||
4462 | advoffset += cplen; | ||
4463 | curbuf += cnt; | ||
5858 | 4464 | ||
5859 | printk(" serial_number 0x%x, retries %d, allowed %d\n", | 4465 | #ifdef ADVANSYS_STATS |
5860 | (unsigned)s->serial_number, s->retries, s->allowed); | 4466 | /* |
4467 | * Display driver statistics for the board. | ||
4468 | */ | ||
4469 | cp = boardp->prtbuf; | ||
4470 | cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE); | ||
4471 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
4472 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
4473 | totcnt += cnt; | ||
4474 | leftlen -= cnt; | ||
4475 | if (leftlen == 0) { | ||
4476 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4477 | return totcnt; | ||
4478 | } | ||
4479 | advoffset += cplen; | ||
4480 | curbuf += cnt; | ||
4481 | #endif /* ADVANSYS_STATS */ | ||
5861 | 4482 | ||
5862 | printk(" timeout_per_command %d\n", s->timeout_per_command); | 4483 | /* |
4484 | * Display Asc Library dynamic configuration information | ||
4485 | * for the board. | ||
4486 | */ | ||
4487 | cp = boardp->prtbuf; | ||
4488 | if (ASC_NARROW_BOARD(boardp)) { | ||
4489 | cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE); | ||
4490 | } else { | ||
4491 | cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE); | ||
4492 | } | ||
4493 | BUG_ON(cplen >= ASC_PRTBUF_SIZE); | ||
4494 | cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); | ||
4495 | totcnt += cnt; | ||
4496 | leftlen -= cnt; | ||
4497 | if (leftlen == 0) { | ||
4498 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); | ||
4499 | return totcnt; | ||
4500 | } | ||
4501 | advoffset += cplen; | ||
4502 | curbuf += cnt; | ||
5863 | 4503 | ||
5864 | printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n", | 4504 | ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); |
5865 | s->scsi_done, s->done, s->host_scribble, s->result); | ||
5866 | 4505 | ||
5867 | printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid); | 4506 | return totcnt; |
5868 | } | 4507 | } |
4508 | #endif /* CONFIG_PROC_FS */ | ||
5869 | 4509 | ||
5870 | /* | 4510 | static void asc_scsi_done(struct scsi_cmnd *scp) |
5871 | * asc_prt_asc_dvc_var() | ||
5872 | */ | ||
5873 | static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) | ||
5874 | { | 4511 | { |
5875 | printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); | 4512 | struct asc_board *boardp = ASC_BOARDP(scp->device->host); |
5876 | |||
5877 | printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl " | ||
5878 | "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); | ||
5879 | |||
5880 | printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type, | ||
5881 | (unsigned)h->init_sdtr); | ||
5882 | 4513 | ||
5883 | printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, " | 4514 | if (scp->use_sg) |
5884 | "chip_no 0x%x,\n", (unsigned)h->sdtr_done, | 4515 | dma_unmap_sg(boardp->dev, |
5885 | (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready, | 4516 | (struct scatterlist *)scp->request_buffer, |
5886 | (unsigned)h->chip_no); | 4517 | scp->use_sg, scp->sc_data_direction); |
4518 | else if (scp->request_bufflen) | ||
4519 | dma_unmap_single(boardp->dev, scp->SCp.dma_handle, | ||
4520 | scp->request_bufflen, scp->sc_data_direction); | ||
5887 | 4521 | ||
5888 | printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait " | 4522 | ASC_STATS(scp->device->host, done); |
5889 | "%u,\n", (unsigned)h->queue_full_or_busy, | ||
5890 | (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait); | ||
5891 | 4523 | ||
5892 | printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, " | 4524 | scp->scsi_done(scp); |
5893 | "in_critical_cnt %u,\n", (unsigned)h->is_in_int, | 4525 | } |
5894 | (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng, | ||
5895 | (unsigned)h->in_critical_cnt); | ||
5896 | 4526 | ||
5897 | printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, " | 4527 | static void AscSetBank(PortAddr iop_base, uchar bank) |
5898 | "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage, | 4528 | { |
5899 | (unsigned)h->init_state, (unsigned)h->no_scam, | 4529 | uchar val; |
5900 | (unsigned)h->pci_fix_asyn_xfer); | ||
5901 | 4530 | ||
5902 | printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no); | 4531 | val = AscGetChipControl(iop_base) & |
4532 | (~ | ||
4533 | (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | | ||
4534 | CC_CHIP_RESET)); | ||
4535 | if (bank == 1) { | ||
4536 | val |= CC_BANK_ONE; | ||
4537 | } else if (bank == 2) { | ||
4538 | val |= CC_DIAG | CC_BANK_ONE; | ||
4539 | } else { | ||
4540 | val &= ~CC_BANK_ONE; | ||
4541 | } | ||
4542 | AscSetChipControl(iop_base, val); | ||
4543 | return; | ||
5903 | } | 4544 | } |
5904 | 4545 | ||
5905 | /* | 4546 | static void AscSetChipIH(PortAddr iop_base, ushort ins_code) |
5906 | * asc_prt_asc_dvc_cfg() | ||
5907 | */ | ||
5908 | static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) | ||
5909 | { | 4547 | { |
5910 | printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); | 4548 | AscSetBank(iop_base, 1); |
5911 | 4549 | AscWriteChipIH(iop_base, ins_code); | |
5912 | printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", | 4550 | AscSetBank(iop_base, 0); |
5913 | h->can_tagged_qng, h->cmd_qng_enabled); | 4551 | return; |
5914 | printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n", | 4552 | } |
5915 | h->disc_enable, h->sdtr_enable); | ||
5916 | 4553 | ||
5917 | printk | 4554 | static int AscStartChip(PortAddr iop_base) |
5918 | (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", | 4555 | { |
5919 | h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, | 4556 | AscSetChipControl(iop_base, 0); |
5920 | h->chip_version); | 4557 | if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { |
4558 | return (0); | ||
4559 | } | ||
4560 | return (1); | ||
4561 | } | ||
5921 | 4562 | ||
5922 | printk | 4563 | static int AscStopChip(PortAddr iop_base) |
5923 | (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", | 4564 | { |
5924 | to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, | 4565 | uchar cc_val; |
5925 | h->mcode_date); | ||
5926 | 4566 | ||
5927 | printk(" mcode_version %d, overrun_buf 0x%lx\n", | 4567 | cc_val = |
5928 | h->mcode_version, (ulong)h->overrun_buf); | 4568 | AscGetChipControl(iop_base) & |
4569 | (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); | ||
4570 | AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT)); | ||
4571 | AscSetChipIH(iop_base, INS_HALT); | ||
4572 | AscSetChipIH(iop_base, INS_RFLAG_WTM); | ||
4573 | if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { | ||
4574 | return (0); | ||
4575 | } | ||
4576 | return (1); | ||
5929 | } | 4577 | } |
5930 | 4578 | ||
5931 | /* | 4579 | static int AscIsChipHalted(PortAddr iop_base) |
5932 | * asc_prt_asc_scsi_q() | ||
5933 | */ | ||
5934 | static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) | ||
5935 | { | 4580 | { |
5936 | ASC_SG_HEAD *sgp; | 4581 | if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { |
5937 | int i; | 4582 | if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { |
5938 | 4583 | return (1); | |
5939 | printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); | 4584 | } |
4585 | } | ||
4586 | return (0); | ||
4587 | } | ||
5940 | 4588 | ||
5941 | printk | 4589 | static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) |
5942 | (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", | 4590 | { |
5943 | q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr, | 4591 | PortAddr iop_base; |
5944 | q->q2.tag_code); | 4592 | int i = 10; |
5945 | 4593 | ||
5946 | printk | 4594 | iop_base = asc_dvc->iop_base; |
5947 | (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", | 4595 | while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) |
5948 | (ulong)le32_to_cpu(q->q1.data_addr), | 4596 | && (i-- > 0)) { |
5949 | (ulong)le32_to_cpu(q->q1.data_cnt), | 4597 | mdelay(100); |
5950 | (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); | 4598 | } |
4599 | AscStopChip(iop_base); | ||
4600 | AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); | ||
4601 | udelay(60); | ||
4602 | AscSetChipIH(iop_base, INS_RFLAG_WTM); | ||
4603 | AscSetChipIH(iop_base, INS_HALT); | ||
4604 | AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); | ||
4605 | AscSetChipControl(iop_base, CC_HALT); | ||
4606 | mdelay(200); | ||
4607 | AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); | ||
4608 | AscSetChipStatus(iop_base, 0); | ||
4609 | return (AscIsChipHalted(iop_base)); | ||
4610 | } | ||
5951 | 4611 | ||
5952 | printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", | 4612 | static int AscFindSignature(PortAddr iop_base) |
5953 | (ulong)q->cdbptr, q->q2.cdb_len, | 4613 | { |
5954 | (ulong)q->sg_head, q->q1.sg_queue_cnt); | 4614 | ushort sig_word; |
5955 | 4615 | ||
5956 | if (q->sg_head) { | 4616 | ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", |
5957 | sgp = q->sg_head; | 4617 | iop_base, AscGetChipSignatureByte(iop_base)); |
5958 | printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp); | 4618 | if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) { |
5959 | printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, | 4619 | ASC_DBG2(1, |
5960 | sgp->queue_cnt); | 4620 | "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", |
5961 | for (i = 0; i < sgp->entry_cnt; i++) { | 4621 | iop_base, AscGetChipSignatureWord(iop_base)); |
5962 | printk(" [%u]: addr 0x%lx, bytes %lu\n", | 4622 | sig_word = AscGetChipSignatureWord(iop_base); |
5963 | i, (ulong)le32_to_cpu(sgp->sg_list[i].addr), | 4623 | if ((sig_word == (ushort)ASC_1000_ID0W) || |
5964 | (ulong)le32_to_cpu(sgp->sg_list[i].bytes)); | 4624 | (sig_word == (ushort)ASC_1000_ID0W_FIX)) { |
4625 | return (1); | ||
5965 | } | 4626 | } |
5966 | |||
5967 | } | 4627 | } |
4628 | return (0); | ||
5968 | } | 4629 | } |
5969 | 4630 | ||
5970 | /* | 4631 | static void AscEnableInterrupt(PortAddr iop_base) |
5971 | * asc_prt_asc_qdone_info() | ||
5972 | */ | ||
5973 | static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) | ||
5974 | { | 4632 | { |
5975 | printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q); | 4633 | ushort cfg; |
5976 | printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", | 4634 | |
5977 | (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, | 4635 | cfg = AscGetChipCfgLsw(iop_base); |
5978 | q->d2.tag_code); | 4636 | AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); |
5979 | printk | 4637 | return; |
5980 | (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", | ||
5981 | q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); | ||
5982 | } | 4638 | } |
5983 | 4639 | ||
5984 | /* | 4640 | static void AscDisableInterrupt(PortAddr iop_base) |
5985 | * asc_prt_adv_dvc_var() | ||
5986 | * | ||
5987 | * Display an ADV_DVC_VAR structure. | ||
5988 | */ | ||
5989 | static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) | ||
5990 | { | 4641 | { |
5991 | printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); | 4642 | ushort cfg; |
5992 | 4643 | ||
5993 | printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", | 4644 | cfg = AscGetChipCfgLsw(iop_base); |
5994 | (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); | 4645 | AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); |
4646 | return; | ||
4647 | } | ||
5995 | 4648 | ||
5996 | printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", | 4649 | static uchar AscReadLramByte(PortAddr iop_base, ushort addr) |
5997 | (ulong)h->isr_callback, (unsigned)h->sdtr_able, | 4650 | { |
5998 | (unsigned)h->wdtr_able); | 4651 | unsigned char byte_data; |
4652 | unsigned short word_data; | ||
5999 | 4653 | ||
6000 | printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", | 4654 | if (isodd_word(addr)) { |
6001 | (unsigned)h->start_motor, | 4655 | AscSetChipLramAddr(iop_base, addr - 1); |
6002 | (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no); | 4656 | word_data = AscGetChipLramData(iop_base); |
4657 | byte_data = (word_data >> 8) & 0xFF; | ||
4658 | } else { | ||
4659 | AscSetChipLramAddr(iop_base, addr); | ||
4660 | word_data = AscGetChipLramData(iop_base); | ||
4661 | byte_data = word_data & 0xFF; | ||
4662 | } | ||
4663 | return byte_data; | ||
4664 | } | ||
6003 | 4665 | ||
6004 | printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", | 4666 | static ushort AscReadLramWord(PortAddr iop_base, ushort addr) |
6005 | (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng, | 4667 | { |
6006 | (ulong)h->carr_freelist); | 4668 | ushort word_data; |
6007 | 4669 | ||
6008 | printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", | 4670 | AscSetChipLramAddr(iop_base, addr); |
6009 | (ulong)h->icq_sp, (ulong)h->irq_sp); | 4671 | word_data = AscGetChipLramData(iop_base); |
4672 | return (word_data); | ||
4673 | } | ||
6010 | 4674 | ||
6011 | printk(" no_scam 0x%x, tagqng_able 0x%x\n", | 4675 | #if CC_VERY_LONG_SG_LIST |
6012 | (unsigned)h->no_scam, (unsigned)h->tagqng_able); | 4676 | static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) |
4677 | { | ||
4678 | ushort val_low, val_high; | ||
4679 | ASC_DCNT dword_data; | ||
6013 | 4680 | ||
6014 | printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", | 4681 | AscSetChipLramAddr(iop_base, addr); |
6015 | (unsigned)h->chip_scsi_id, (ulong)h->cfg); | 4682 | val_low = AscGetChipLramData(iop_base); |
4683 | val_high = AscGetChipLramData(iop_base); | ||
4684 | dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; | ||
4685 | return (dword_data); | ||
6016 | } | 4686 | } |
4687 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
6017 | 4688 | ||
6018 | /* | 4689 | static void |
6019 | * asc_prt_adv_dvc_cfg() | 4690 | AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) |
6020 | * | ||
6021 | * Display an ADV_DVC_CFG structure. | ||
6022 | */ | ||
6023 | static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) | ||
6024 | { | 4691 | { |
6025 | printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h); | 4692 | int i; |
6026 | 4693 | ||
6027 | printk(" disc_enable 0x%x, termination 0x%x\n", | 4694 | AscSetChipLramAddr(iop_base, s_addr); |
6028 | h->disc_enable, h->termination); | 4695 | for (i = 0; i < words; i++) { |
4696 | AscSetChipLramData(iop_base, set_wval); | ||
4697 | } | ||
4698 | } | ||
6029 | 4699 | ||
6030 | printk(" chip_version 0x%x, mcode_date 0x%x\n", | 4700 | static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) |
6031 | h->chip_version, h->mcode_date); | 4701 | { |
4702 | AscSetChipLramAddr(iop_base, addr); | ||
4703 | AscSetChipLramData(iop_base, word_val); | ||
4704 | return; | ||
4705 | } | ||
6032 | 4706 | ||
6033 | printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", | 4707 | static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) |
6034 | h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); | 4708 | { |
4709 | ushort word_data; | ||
6035 | 4710 | ||
6036 | printk(" control_flag 0x%x\n", h->control_flag); | 4711 | if (isodd_word(addr)) { |
4712 | addr--; | ||
4713 | word_data = AscReadLramWord(iop_base, addr); | ||
4714 | word_data &= 0x00FF; | ||
4715 | word_data |= (((ushort)byte_val << 8) & 0xFF00); | ||
4716 | } else { | ||
4717 | word_data = AscReadLramWord(iop_base, addr); | ||
4718 | word_data &= 0xFF00; | ||
4719 | word_data |= ((ushort)byte_val & 0x00FF); | ||
4720 | } | ||
4721 | AscWriteLramWord(iop_base, addr, word_data); | ||
4722 | return; | ||
6037 | } | 4723 | } |
6038 | 4724 | ||
6039 | /* | 4725 | /* |
6040 | * asc_prt_adv_scsi_req_q() | 4726 | * Copy 2 bytes to LRAM. |
6041 | * | 4727 | * |
6042 | * Display an ADV_SCSI_REQ_Q structure. | 4728 | * The source data is assumed to be in little-endian order in memory |
4729 | * and is maintained in little-endian order when written to LRAM. | ||
6043 | */ | 4730 | */ |
6044 | static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) | 4731 | static void |
4732 | AscMemWordCopyPtrToLram(PortAddr iop_base, | ||
4733 | ushort s_addr, uchar *s_buffer, int words) | ||
6045 | { | 4734 | { |
6046 | int sg_blk_cnt; | 4735 | int i; |
6047 | struct asc_sg_block *sg_ptr; | ||
6048 | |||
6049 | printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); | ||
6050 | |||
6051 | printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", | ||
6052 | q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag); | ||
6053 | |||
6054 | printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", | ||
6055 | q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr); | ||
6056 | |||
6057 | printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", | ||
6058 | (ulong)le32_to_cpu(q->data_cnt), | ||
6059 | (ulong)le32_to_cpu(q->sense_addr), q->sense_len); | ||
6060 | |||
6061 | printk | ||
6062 | (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", | ||
6063 | q->cdb_len, q->done_status, q->host_status, q->scsi_status); | ||
6064 | |||
6065 | printk(" sg_working_ix 0x%x, target_cmd %u\n", | ||
6066 | q->sg_working_ix, q->target_cmd); | ||
6067 | |||
6068 | printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", | ||
6069 | (ulong)le32_to_cpu(q->scsiq_rptr), | ||
6070 | (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr); | ||
6071 | 4736 | ||
6072 | /* Display the request's ADV_SG_BLOCK structures. */ | 4737 | AscSetChipLramAddr(iop_base, s_addr); |
6073 | if (q->sg_list_ptr != NULL) { | 4738 | for (i = 0; i < 2 * words; i += 2) { |
6074 | sg_blk_cnt = 0; | 4739 | /* |
6075 | while (1) { | 4740 | * On a little-endian system the second argument below |
6076 | /* | 4741 | * produces a little-endian ushort which is written to |
6077 | * 'sg_ptr' is a physical address. Convert it to a virtual | 4742 | * LRAM in little-endian order. On a big-endian system |
6078 | * address by indexing 'sg_blk_cnt' into the virtual address | 4743 | * the second argument produces a big-endian ushort which |
6079 | * array 'sg_list_ptr'. | 4744 | * is "transparently" byte-swapped by outpw() and written |
6080 | * | 4745 | * in little-endian order to LRAM. |
6081 | * XXX - Assumes all SG physical blocks are virtually contiguous. | 4746 | */ |
6082 | */ | 4747 | outpw(iop_base + IOP_RAM_DATA, |
6083 | sg_ptr = | 4748 | ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); |
6084 | &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]); | ||
6085 | asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); | ||
6086 | if (sg_ptr->sg_ptr == 0) { | ||
6087 | break; | ||
6088 | } | ||
6089 | sg_blk_cnt++; | ||
6090 | } | ||
6091 | } | 4749 | } |
4750 | return; | ||
6092 | } | 4751 | } |
6093 | 4752 | ||
6094 | /* | 4753 | /* |
6095 | * asc_prt_adv_sgblock() | 4754 | * Copy 4 bytes to LRAM. |
6096 | * | 4755 | * |
6097 | * Display an ADV_SG_BLOCK structure. | 4756 | * The source data is assumed to be in little-endian order in memory |
4757 | * and is maintained in little-endian order when writen to LRAM. | ||
6098 | */ | 4758 | */ |
6099 | static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) | 4759 | static void |
4760 | AscMemDWordCopyPtrToLram(PortAddr iop_base, | ||
4761 | ushort s_addr, uchar *s_buffer, int dwords) | ||
6100 | { | 4762 | { |
6101 | int i; | 4763 | int i; |
6102 | 4764 | ||
6103 | printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", | 4765 | AscSetChipLramAddr(iop_base, s_addr); |
6104 | (ulong)b, sgblockno); | 4766 | for (i = 0; i < 4 * dwords; i += 4) { |
6105 | printk(" sg_cnt %u, sg_ptr 0x%lx\n", | 4767 | outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ |
6106 | b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr)); | 4768 | outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ |
6107 | BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK); | ||
6108 | if (b->sg_ptr != 0) | ||
6109 | BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK); | ||
6110 | for (i = 0; i < b->sg_cnt; i++) { | ||
6111 | printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", | ||
6112 | i, (ulong)b->sg_list[i].sg_addr, | ||
6113 | (ulong)b->sg_list[i].sg_count); | ||
6114 | } | 4769 | } |
4770 | return; | ||
6115 | } | 4771 | } |
6116 | 4772 | ||
6117 | /* | 4773 | /* |
6118 | * asc_prt_hex() | 4774 | * Copy 2 bytes from LRAM. |
6119 | * | 4775 | * |
6120 | * Print hexadecimal output in 4 byte groupings 32 bytes | 4776 | * The source data is assumed to be in little-endian order in LRAM |
6121 | * or 8 double-words per line. | 4777 | * and is maintained in little-endian order when written to memory. |
6122 | */ | 4778 | */ |
6123 | static void asc_prt_hex(char *f, uchar *s, int l) | 4779 | static void |
4780 | AscMemWordCopyPtrFromLram(PortAddr iop_base, | ||
4781 | ushort s_addr, uchar *d_buffer, int words) | ||
6124 | { | 4782 | { |
6125 | int i; | 4783 | int i; |
6126 | int j; | 4784 | ushort word; |
6127 | int k; | ||
6128 | int m; | ||
6129 | |||
6130 | printk("%s: (%d bytes)\n", f, l); | ||
6131 | |||
6132 | for (i = 0; i < l; i += 32) { | ||
6133 | |||
6134 | /* Display a maximum of 8 double-words per line. */ | ||
6135 | if ((k = (l - i) / 4) >= 8) { | ||
6136 | k = 8; | ||
6137 | m = 0; | ||
6138 | } else { | ||
6139 | m = (l - i) % 4; | ||
6140 | } | ||
6141 | |||
6142 | for (j = 0; j < k; j++) { | ||
6143 | printk(" %2.2X%2.2X%2.2X%2.2X", | ||
6144 | (unsigned)s[i + (j * 4)], | ||
6145 | (unsigned)s[i + (j * 4) + 1], | ||
6146 | (unsigned)s[i + (j * 4) + 2], | ||
6147 | (unsigned)s[i + (j * 4) + 3]); | ||
6148 | } | ||
6149 | |||
6150 | switch (m) { | ||
6151 | case 0: | ||
6152 | default: | ||
6153 | break; | ||
6154 | case 1: | ||
6155 | printk(" %2.2X", (unsigned)s[i + (j * 4)]); | ||
6156 | break; | ||
6157 | case 2: | ||
6158 | printk(" %2.2X%2.2X", | ||
6159 | (unsigned)s[i + (j * 4)], | ||
6160 | (unsigned)s[i + (j * 4) + 1]); | ||
6161 | break; | ||
6162 | case 3: | ||
6163 | printk(" %2.2X%2.2X%2.2X", | ||
6164 | (unsigned)s[i + (j * 4) + 1], | ||
6165 | (unsigned)s[i + (j * 4) + 2], | ||
6166 | (unsigned)s[i + (j * 4) + 3]); | ||
6167 | break; | ||
6168 | } | ||
6169 | 4785 | ||
6170 | printk("\n"); | 4786 | AscSetChipLramAddr(iop_base, s_addr); |
4787 | for (i = 0; i < 2 * words; i += 2) { | ||
4788 | word = inpw(iop_base + IOP_RAM_DATA); | ||
4789 | d_buffer[i] = word & 0xff; | ||
4790 | d_buffer[i + 1] = (word >> 8) & 0xff; | ||
6171 | } | 4791 | } |
6172 | } | 4792 | return; |
6173 | #endif /* ADVANSYS_DEBUG */ | ||
6174 | |||
6175 | static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base) | ||
6176 | { | ||
6177 | PortAddr eisa_cfg_iop; | ||
6178 | |||
6179 | eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | | ||
6180 | (PortAddr) (ASC_EISA_CFG_IOP_MASK); | ||
6181 | return (inpw(eisa_cfg_iop)); | ||
6182 | } | 4793 | } |
6183 | 4794 | ||
6184 | static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) | 4795 | static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) |
6185 | { | 4796 | { |
6186 | ushort cfg_lsw; | 4797 | ASC_DCNT sum; |
4798 | int i; | ||
6187 | 4799 | ||
6188 | if (AscGetChipScsiID(iop_base) == new_host_id) { | 4800 | sum = 0L; |
6189 | return (new_host_id); | 4801 | for (i = 0; i < words; i++, s_addr += 2) { |
4802 | sum += AscReadLramWord(iop_base, s_addr); | ||
6190 | } | 4803 | } |
6191 | cfg_lsw = AscGetChipCfgLsw(iop_base); | 4804 | return (sum); |
6192 | cfg_lsw &= 0xF8FF; | ||
6193 | cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8); | ||
6194 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
6195 | return (AscGetChipScsiID(iop_base)); | ||
6196 | } | 4805 | } |
6197 | 4806 | ||
6198 | static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base) | 4807 | static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) |
6199 | { | 4808 | { |
6200 | unsigned char sc; | 4809 | uchar i; |
6201 | 4810 | ushort s_addr; | |
6202 | AscSetBank(iop_base, 1); | 4811 | PortAddr iop_base; |
6203 | sc = inp(iop_base + IOP_REG_SC); | 4812 | ushort warn_code; |
6204 | AscSetBank(iop_base, 0); | ||
6205 | return sc; | ||
6206 | } | ||
6207 | 4813 | ||
6208 | static unsigned char __devinit | 4814 | iop_base = asc_dvc->iop_base; |
6209 | AscGetChipVersion(PortAddr iop_base, unsigned short bus_type) | 4815 | warn_code = 0; |
6210 | { | 4816 | AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, |
6211 | if (bus_type & ASC_IS_EISA) { | 4817 | (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) * |
6212 | PortAddr eisa_iop; | 4818 | 64) >> 1)); |
6213 | unsigned char revision; | 4819 | i = ASC_MIN_ACTIVE_QNO; |
6214 | eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | | 4820 | s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; |
6215 | (PortAddr) ASC_EISA_REV_IOP_MASK; | 4821 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), |
6216 | revision = inp(eisa_iop); | 4822 | (uchar)(i + 1)); |
6217 | return ASC_CHIP_MIN_VER_EISA - 1 + revision; | 4823 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), |
4824 | (uchar)(asc_dvc->max_total_qng)); | ||
4825 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), | ||
4826 | (uchar)i); | ||
4827 | i++; | ||
4828 | s_addr += ASC_QBLK_SIZE; | ||
4829 | for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { | ||
4830 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), | ||
4831 | (uchar)(i + 1)); | ||
4832 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), | ||
4833 | (uchar)(i - 1)); | ||
4834 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), | ||
4835 | (uchar)i); | ||
6218 | } | 4836 | } |
6219 | return AscGetChipVerNo(iop_base); | 4837 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), |
4838 | (uchar)ASC_QLINK_END); | ||
4839 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), | ||
4840 | (uchar)(asc_dvc->max_total_qng - 1)); | ||
4841 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), | ||
4842 | (uchar)asc_dvc->max_total_qng); | ||
4843 | i++; | ||
4844 | s_addr += ASC_QBLK_SIZE; | ||
4845 | for (; i <= (uchar)(asc_dvc->max_total_qng + 3); | ||
4846 | i++, s_addr += ASC_QBLK_SIZE) { | ||
4847 | AscWriteLramByte(iop_base, | ||
4848 | (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i); | ||
4849 | AscWriteLramByte(iop_base, | ||
4850 | (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i); | ||
4851 | AscWriteLramByte(iop_base, | ||
4852 | (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i); | ||
4853 | } | ||
4854 | return warn_code; | ||
6220 | } | 4855 | } |
6221 | 4856 | ||
6222 | static ASC_DCNT | 4857 | static ASC_DCNT |
@@ -6247,865 +4882,6 @@ AscLoadMicroCode(PortAddr iop_base, | |||
6247 | return (chksum); | 4882 | return (chksum); |
6248 | } | 4883 | } |
6249 | 4884 | ||
6250 | static int AscFindSignature(PortAddr iop_base) | ||
6251 | { | ||
6252 | ushort sig_word; | ||
6253 | |||
6254 | ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", | ||
6255 | iop_base, AscGetChipSignatureByte(iop_base)); | ||
6256 | if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) { | ||
6257 | ASC_DBG2(1, | ||
6258 | "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", | ||
6259 | iop_base, AscGetChipSignatureWord(iop_base)); | ||
6260 | sig_word = AscGetChipSignatureWord(iop_base); | ||
6261 | if ((sig_word == (ushort)ASC_1000_ID0W) || | ||
6262 | (sig_word == (ushort)ASC_1000_ID0W_FIX)) { | ||
6263 | return (1); | ||
6264 | } | ||
6265 | } | ||
6266 | return (0); | ||
6267 | } | ||
6268 | |||
6269 | static void __devinit AscToggleIRQAct(PortAddr iop_base) | ||
6270 | { | ||
6271 | AscSetChipStatus(iop_base, CIW_IRQ_ACT); | ||
6272 | AscSetChipStatus(iop_base, 0); | ||
6273 | return; | ||
6274 | } | ||
6275 | |||
6276 | static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type) | ||
6277 | { | ||
6278 | ushort cfg_lsw; | ||
6279 | uchar chip_irq; | ||
6280 | |||
6281 | if ((bus_type & ASC_IS_EISA) != 0) { | ||
6282 | cfg_lsw = AscGetEisaChipCfg(iop_base); | ||
6283 | chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10); | ||
6284 | if ((chip_irq == 13) || (chip_irq > 15)) { | ||
6285 | return (0); | ||
6286 | } | ||
6287 | return (chip_irq); | ||
6288 | } | ||
6289 | if ((bus_type & ASC_IS_VL) != 0) { | ||
6290 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
6291 | chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07)); | ||
6292 | if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) { | ||
6293 | return (0); | ||
6294 | } | ||
6295 | return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1))); | ||
6296 | } | ||
6297 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
6298 | chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03)); | ||
6299 | if (chip_irq == 3) | ||
6300 | chip_irq += (uchar)2; | ||
6301 | return ((uchar)(chip_irq + ASC_MIN_IRQ_NO)); | ||
6302 | } | ||
6303 | |||
6304 | static uchar __devinit | ||
6305 | AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type) | ||
6306 | { | ||
6307 | ushort cfg_lsw; | ||
6308 | |||
6309 | if ((bus_type & ASC_IS_VL) != 0) { | ||
6310 | if (irq_no != 0) { | ||
6311 | if ((irq_no < ASC_MIN_IRQ_NO) | ||
6312 | || (irq_no > ASC_MAX_IRQ_NO)) { | ||
6313 | irq_no = 0; | ||
6314 | } else { | ||
6315 | irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1)); | ||
6316 | } | ||
6317 | } | ||
6318 | cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3); | ||
6319 | cfg_lsw |= (ushort)0x0010; | ||
6320 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
6321 | AscToggleIRQAct(iop_base); | ||
6322 | cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0); | ||
6323 | cfg_lsw |= (ushort)((irq_no & 0x07) << 2); | ||
6324 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
6325 | AscToggleIRQAct(iop_base); | ||
6326 | return (AscGetChipIRQ(iop_base, bus_type)); | ||
6327 | } | ||
6328 | if ((bus_type & (ASC_IS_ISA)) != 0) { | ||
6329 | if (irq_no == 15) | ||
6330 | irq_no -= (uchar)2; | ||
6331 | irq_no -= (uchar)ASC_MIN_IRQ_NO; | ||
6332 | cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3); | ||
6333 | cfg_lsw |= (ushort)((irq_no & 0x03) << 2); | ||
6334 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
6335 | return (AscGetChipIRQ(iop_base, bus_type)); | ||
6336 | } | ||
6337 | return (0); | ||
6338 | } | ||
6339 | |||
6340 | #ifdef CONFIG_ISA | ||
6341 | static void __devinit AscEnableIsaDma(uchar dma_channel) | ||
6342 | { | ||
6343 | if (dma_channel < 4) { | ||
6344 | outp(0x000B, (ushort)(0xC0 | dma_channel)); | ||
6345 | outp(0x000A, dma_channel); | ||
6346 | } else if (dma_channel < 8) { | ||
6347 | outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4))); | ||
6348 | outp(0x00D4, (ushort)(dma_channel - 4)); | ||
6349 | } | ||
6350 | return; | ||
6351 | } | ||
6352 | #endif /* CONFIG_ISA */ | ||
6353 | |||
6354 | static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) | ||
6355 | { | ||
6356 | EXT_MSG ext_msg; | ||
6357 | EXT_MSG out_msg; | ||
6358 | ushort halt_q_addr; | ||
6359 | int sdtr_accept; | ||
6360 | ushort int_halt_code; | ||
6361 | ASC_SCSI_BIT_ID_TYPE scsi_busy; | ||
6362 | ASC_SCSI_BIT_ID_TYPE target_id; | ||
6363 | PortAddr iop_base; | ||
6364 | uchar tag_code; | ||
6365 | uchar q_status; | ||
6366 | uchar halt_qp; | ||
6367 | uchar sdtr_data; | ||
6368 | uchar target_ix; | ||
6369 | uchar q_cntl, tid_no; | ||
6370 | uchar cur_dvc_qng; | ||
6371 | uchar asyn_sdtr; | ||
6372 | uchar scsi_status; | ||
6373 | asc_board_t *boardp; | ||
6374 | |||
6375 | BUG_ON(!asc_dvc->drv_ptr); | ||
6376 | boardp = asc_dvc->drv_ptr; | ||
6377 | |||
6378 | iop_base = asc_dvc->iop_base; | ||
6379 | int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); | ||
6380 | |||
6381 | halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); | ||
6382 | halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); | ||
6383 | target_ix = AscReadLramByte(iop_base, | ||
6384 | (ushort)(halt_q_addr + | ||
6385 | (ushort)ASC_SCSIQ_B_TARGET_IX)); | ||
6386 | q_cntl = AscReadLramByte(iop_base, | ||
6387 | (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL)); | ||
6388 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
6389 | target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no); | ||
6390 | if (asc_dvc->pci_fix_asyn_xfer & target_id) { | ||
6391 | asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; | ||
6392 | } else { | ||
6393 | asyn_sdtr = 0; | ||
6394 | } | ||
6395 | if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { | ||
6396 | if (asc_dvc->pci_fix_asyn_xfer & target_id) { | ||
6397 | AscSetChipSDTR(iop_base, 0, tid_no); | ||
6398 | boardp->sdtr_data[tid_no] = 0; | ||
6399 | } | ||
6400 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6401 | return (0); | ||
6402 | } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { | ||
6403 | if (asc_dvc->pci_fix_asyn_xfer & target_id) { | ||
6404 | AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); | ||
6405 | boardp->sdtr_data[tid_no] = asyn_sdtr; | ||
6406 | } | ||
6407 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6408 | return (0); | ||
6409 | } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { | ||
6410 | AscMemWordCopyPtrFromLram(iop_base, | ||
6411 | ASCV_MSGIN_BEG, | ||
6412 | (uchar *)&ext_msg, | ||
6413 | sizeof(EXT_MSG) >> 1); | ||
6414 | |||
6415 | if (ext_msg.msg_type == EXTENDED_MESSAGE && | ||
6416 | ext_msg.msg_req == EXTENDED_SDTR && | ||
6417 | ext_msg.msg_len == MS_SDTR_LEN) { | ||
6418 | sdtr_accept = TRUE; | ||
6419 | if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { | ||
6420 | |||
6421 | sdtr_accept = FALSE; | ||
6422 | ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; | ||
6423 | } | ||
6424 | if ((ext_msg.xfer_period < | ||
6425 | asc_dvc->sdtr_period_tbl[asc_dvc-> | ||
6426 | host_init_sdtr_index]) | ||
6427 | || (ext_msg.xfer_period > | ||
6428 | asc_dvc->sdtr_period_tbl[asc_dvc-> | ||
6429 | max_sdtr_index])) { | ||
6430 | sdtr_accept = FALSE; | ||
6431 | ext_msg.xfer_period = | ||
6432 | asc_dvc->sdtr_period_tbl[asc_dvc-> | ||
6433 | host_init_sdtr_index]; | ||
6434 | } | ||
6435 | if (sdtr_accept) { | ||
6436 | sdtr_data = | ||
6437 | AscCalSDTRData(asc_dvc, ext_msg.xfer_period, | ||
6438 | ext_msg.req_ack_offset); | ||
6439 | if ((sdtr_data == 0xFF)) { | ||
6440 | |||
6441 | q_cntl |= QC_MSG_OUT; | ||
6442 | asc_dvc->init_sdtr &= ~target_id; | ||
6443 | asc_dvc->sdtr_done &= ~target_id; | ||
6444 | AscSetChipSDTR(iop_base, asyn_sdtr, | ||
6445 | tid_no); | ||
6446 | boardp->sdtr_data[tid_no] = asyn_sdtr; | ||
6447 | } | ||
6448 | } | ||
6449 | if (ext_msg.req_ack_offset == 0) { | ||
6450 | |||
6451 | q_cntl &= ~QC_MSG_OUT; | ||
6452 | asc_dvc->init_sdtr &= ~target_id; | ||
6453 | asc_dvc->sdtr_done &= ~target_id; | ||
6454 | AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); | ||
6455 | } else { | ||
6456 | if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { | ||
6457 | |||
6458 | q_cntl &= ~QC_MSG_OUT; | ||
6459 | asc_dvc->sdtr_done |= target_id; | ||
6460 | asc_dvc->init_sdtr |= target_id; | ||
6461 | asc_dvc->pci_fix_asyn_xfer &= | ||
6462 | ~target_id; | ||
6463 | sdtr_data = | ||
6464 | AscCalSDTRData(asc_dvc, | ||
6465 | ext_msg.xfer_period, | ||
6466 | ext_msg. | ||
6467 | req_ack_offset); | ||
6468 | AscSetChipSDTR(iop_base, sdtr_data, | ||
6469 | tid_no); | ||
6470 | boardp->sdtr_data[tid_no] = sdtr_data; | ||
6471 | } else { | ||
6472 | |||
6473 | q_cntl |= QC_MSG_OUT; | ||
6474 | AscMsgOutSDTR(asc_dvc, | ||
6475 | ext_msg.xfer_period, | ||
6476 | ext_msg.req_ack_offset); | ||
6477 | asc_dvc->pci_fix_asyn_xfer &= | ||
6478 | ~target_id; | ||
6479 | sdtr_data = | ||
6480 | AscCalSDTRData(asc_dvc, | ||
6481 | ext_msg.xfer_period, | ||
6482 | ext_msg. | ||
6483 | req_ack_offset); | ||
6484 | AscSetChipSDTR(iop_base, sdtr_data, | ||
6485 | tid_no); | ||
6486 | boardp->sdtr_data[tid_no] = sdtr_data; | ||
6487 | asc_dvc->sdtr_done |= target_id; | ||
6488 | asc_dvc->init_sdtr |= target_id; | ||
6489 | } | ||
6490 | } | ||
6491 | |||
6492 | AscWriteLramByte(iop_base, | ||
6493 | (ushort)(halt_q_addr + | ||
6494 | (ushort)ASC_SCSIQ_B_CNTL), | ||
6495 | q_cntl); | ||
6496 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6497 | return (0); | ||
6498 | } else if (ext_msg.msg_type == EXTENDED_MESSAGE && | ||
6499 | ext_msg.msg_req == EXTENDED_WDTR && | ||
6500 | ext_msg.msg_len == MS_WDTR_LEN) { | ||
6501 | |||
6502 | ext_msg.wdtr_width = 0; | ||
6503 | AscMemWordCopyPtrToLram(iop_base, | ||
6504 | ASCV_MSGOUT_BEG, | ||
6505 | (uchar *)&ext_msg, | ||
6506 | sizeof(EXT_MSG) >> 1); | ||
6507 | q_cntl |= QC_MSG_OUT; | ||
6508 | AscWriteLramByte(iop_base, | ||
6509 | (ushort)(halt_q_addr + | ||
6510 | (ushort)ASC_SCSIQ_B_CNTL), | ||
6511 | q_cntl); | ||
6512 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6513 | return (0); | ||
6514 | } else { | ||
6515 | |||
6516 | ext_msg.msg_type = MESSAGE_REJECT; | ||
6517 | AscMemWordCopyPtrToLram(iop_base, | ||
6518 | ASCV_MSGOUT_BEG, | ||
6519 | (uchar *)&ext_msg, | ||
6520 | sizeof(EXT_MSG) >> 1); | ||
6521 | q_cntl |= QC_MSG_OUT; | ||
6522 | AscWriteLramByte(iop_base, | ||
6523 | (ushort)(halt_q_addr + | ||
6524 | (ushort)ASC_SCSIQ_B_CNTL), | ||
6525 | q_cntl); | ||
6526 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6527 | return (0); | ||
6528 | } | ||
6529 | } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { | ||
6530 | |||
6531 | q_cntl |= QC_REQ_SENSE; | ||
6532 | |||
6533 | if ((asc_dvc->init_sdtr & target_id) != 0) { | ||
6534 | |||
6535 | asc_dvc->sdtr_done &= ~target_id; | ||
6536 | |||
6537 | sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); | ||
6538 | q_cntl |= QC_MSG_OUT; | ||
6539 | AscMsgOutSDTR(asc_dvc, | ||
6540 | asc_dvc-> | ||
6541 | sdtr_period_tbl[(sdtr_data >> 4) & | ||
6542 | (uchar)(asc_dvc-> | ||
6543 | max_sdtr_index - | ||
6544 | 1)], | ||
6545 | (uchar)(sdtr_data & (uchar) | ||
6546 | ASC_SYN_MAX_OFFSET)); | ||
6547 | } | ||
6548 | |||
6549 | AscWriteLramByte(iop_base, | ||
6550 | (ushort)(halt_q_addr + | ||
6551 | (ushort)ASC_SCSIQ_B_CNTL), q_cntl); | ||
6552 | |||
6553 | tag_code = AscReadLramByte(iop_base, | ||
6554 | (ushort)(halt_q_addr + (ushort) | ||
6555 | ASC_SCSIQ_B_TAG_CODE)); | ||
6556 | tag_code &= 0xDC; | ||
6557 | if ((asc_dvc->pci_fix_asyn_xfer & target_id) | ||
6558 | && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) | ||
6559 | ) { | ||
6560 | |||
6561 | tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT | ||
6562 | | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); | ||
6563 | |||
6564 | } | ||
6565 | AscWriteLramByte(iop_base, | ||
6566 | (ushort)(halt_q_addr + | ||
6567 | (ushort)ASC_SCSIQ_B_TAG_CODE), | ||
6568 | tag_code); | ||
6569 | |||
6570 | q_status = AscReadLramByte(iop_base, | ||
6571 | (ushort)(halt_q_addr + (ushort) | ||
6572 | ASC_SCSIQ_B_STATUS)); | ||
6573 | q_status |= (QS_READY | QS_BUSY); | ||
6574 | AscWriteLramByte(iop_base, | ||
6575 | (ushort)(halt_q_addr + | ||
6576 | (ushort)ASC_SCSIQ_B_STATUS), | ||
6577 | q_status); | ||
6578 | |||
6579 | scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B); | ||
6580 | scsi_busy &= ~target_id; | ||
6581 | AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy); | ||
6582 | |||
6583 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6584 | return (0); | ||
6585 | } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { | ||
6586 | |||
6587 | AscMemWordCopyPtrFromLram(iop_base, | ||
6588 | ASCV_MSGOUT_BEG, | ||
6589 | (uchar *)&out_msg, | ||
6590 | sizeof(EXT_MSG) >> 1); | ||
6591 | |||
6592 | if ((out_msg.msg_type == EXTENDED_MESSAGE) && | ||
6593 | (out_msg.msg_len == MS_SDTR_LEN) && | ||
6594 | (out_msg.msg_req == EXTENDED_SDTR)) { | ||
6595 | |||
6596 | asc_dvc->init_sdtr &= ~target_id; | ||
6597 | asc_dvc->sdtr_done &= ~target_id; | ||
6598 | AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); | ||
6599 | boardp->sdtr_data[tid_no] = asyn_sdtr; | ||
6600 | } | ||
6601 | q_cntl &= ~QC_MSG_OUT; | ||
6602 | AscWriteLramByte(iop_base, | ||
6603 | (ushort)(halt_q_addr + | ||
6604 | (ushort)ASC_SCSIQ_B_CNTL), q_cntl); | ||
6605 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6606 | return (0); | ||
6607 | } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { | ||
6608 | |||
6609 | scsi_status = AscReadLramByte(iop_base, | ||
6610 | (ushort)((ushort)halt_q_addr + | ||
6611 | (ushort) | ||
6612 | ASC_SCSIQ_SCSI_STATUS)); | ||
6613 | cur_dvc_qng = | ||
6614 | AscReadLramByte(iop_base, | ||
6615 | (ushort)((ushort)ASC_QADR_BEG + | ||
6616 | (ushort)target_ix)); | ||
6617 | if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) { | ||
6618 | |||
6619 | scsi_busy = AscReadLramByte(iop_base, | ||
6620 | (ushort)ASCV_SCSIBUSY_B); | ||
6621 | scsi_busy |= target_id; | ||
6622 | AscWriteLramByte(iop_base, | ||
6623 | (ushort)ASCV_SCSIBUSY_B, scsi_busy); | ||
6624 | asc_dvc->queue_full_or_busy |= target_id; | ||
6625 | |||
6626 | if (scsi_status == SAM_STAT_TASK_SET_FULL) { | ||
6627 | if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { | ||
6628 | cur_dvc_qng -= 1; | ||
6629 | asc_dvc->max_dvc_qng[tid_no] = | ||
6630 | cur_dvc_qng; | ||
6631 | |||
6632 | AscWriteLramByte(iop_base, | ||
6633 | (ushort)((ushort) | ||
6634 | ASCV_MAX_DVC_QNG_BEG | ||
6635 | + (ushort) | ||
6636 | tid_no), | ||
6637 | cur_dvc_qng); | ||
6638 | |||
6639 | /* | ||
6640 | * Set the device queue depth to the | ||
6641 | * number of active requests when the | ||
6642 | * QUEUE FULL condition was encountered. | ||
6643 | */ | ||
6644 | boardp->queue_full |= target_id; | ||
6645 | boardp->queue_full_cnt[tid_no] = | ||
6646 | cur_dvc_qng; | ||
6647 | } | ||
6648 | } | ||
6649 | } | ||
6650 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6651 | return (0); | ||
6652 | } | ||
6653 | #if CC_VERY_LONG_SG_LIST | ||
6654 | else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) { | ||
6655 | uchar q_no; | ||
6656 | ushort q_addr; | ||
6657 | uchar sg_wk_q_no; | ||
6658 | uchar first_sg_wk_q_no; | ||
6659 | ASC_SCSI_Q *scsiq; /* Ptr to driver request. */ | ||
6660 | ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */ | ||
6661 | ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */ | ||
6662 | ushort sg_list_dwords; | ||
6663 | ushort sg_entry_cnt; | ||
6664 | uchar next_qp; | ||
6665 | int i; | ||
6666 | |||
6667 | q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP); | ||
6668 | if (q_no == ASC_QLINK_END) | ||
6669 | return 0; | ||
6670 | |||
6671 | q_addr = ASC_QNO_TO_QADDR(q_no); | ||
6672 | |||
6673 | /* | ||
6674 | * Convert the request's SRB pointer to a host ASC_SCSI_REQ | ||
6675 | * structure pointer using a macro provided by the driver. | ||
6676 | * The ASC_SCSI_REQ pointer provides a pointer to the | ||
6677 | * host ASC_SG_HEAD structure. | ||
6678 | */ | ||
6679 | /* Read request's SRB pointer. */ | ||
6680 | scsiq = (ASC_SCSI_Q *) | ||
6681 | ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base, | ||
6682 | (ushort) | ||
6683 | (q_addr + | ||
6684 | ASC_SCSIQ_D_SRBPTR)))); | ||
6685 | |||
6686 | /* | ||
6687 | * Get request's first and working SG queue. | ||
6688 | */ | ||
6689 | sg_wk_q_no = AscReadLramByte(iop_base, | ||
6690 | (ushort)(q_addr + | ||
6691 | ASC_SCSIQ_B_SG_WK_QP)); | ||
6692 | |||
6693 | first_sg_wk_q_no = AscReadLramByte(iop_base, | ||
6694 | (ushort)(q_addr + | ||
6695 | ASC_SCSIQ_B_FIRST_SG_WK_QP)); | ||
6696 | |||
6697 | /* | ||
6698 | * Reset request's working SG queue back to the | ||
6699 | * first SG queue. | ||
6700 | */ | ||
6701 | AscWriteLramByte(iop_base, | ||
6702 | (ushort)(q_addr + | ||
6703 | (ushort)ASC_SCSIQ_B_SG_WK_QP), | ||
6704 | first_sg_wk_q_no); | ||
6705 | |||
6706 | sg_head = scsiq->sg_head; | ||
6707 | |||
6708 | /* | ||
6709 | * Set sg_entry_cnt to the number of SG elements | ||
6710 | * that will be completed on this interrupt. | ||
6711 | * | ||
6712 | * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1 | ||
6713 | * SG elements. The data_cnt and data_addr fields which | ||
6714 | * add 1 to the SG element capacity are not used when | ||
6715 | * restarting SG handling after a halt. | ||
6716 | */ | ||
6717 | if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) { | ||
6718 | sg_entry_cnt = ASC_MAX_SG_LIST - 1; | ||
6719 | |||
6720 | /* | ||
6721 | * Keep track of remaining number of SG elements that | ||
6722 | * will need to be handled on the next interrupt. | ||
6723 | */ | ||
6724 | scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); | ||
6725 | } else { | ||
6726 | sg_entry_cnt = scsiq->remain_sg_entry_cnt; | ||
6727 | scsiq->remain_sg_entry_cnt = 0; | ||
6728 | } | ||
6729 | |||
6730 | /* | ||
6731 | * Copy SG elements into the list of allocated SG queues. | ||
6732 | * | ||
6733 | * Last index completed is saved in scsiq->next_sg_index. | ||
6734 | */ | ||
6735 | next_qp = first_sg_wk_q_no; | ||
6736 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
6737 | scsi_sg_q.sg_head_qp = q_no; | ||
6738 | scsi_sg_q.cntl = QCSG_SG_XFER_LIST; | ||
6739 | for (i = 0; i < sg_head->queue_cnt; i++) { | ||
6740 | scsi_sg_q.seq_no = i + 1; | ||
6741 | if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { | ||
6742 | sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); | ||
6743 | sg_entry_cnt -= ASC_SG_LIST_PER_Q; | ||
6744 | /* | ||
6745 | * After very first SG queue RISC FW uses next | ||
6746 | * SG queue first element then checks sg_list_cnt | ||
6747 | * against zero and then decrements, so set | ||
6748 | * sg_list_cnt 1 less than number of SG elements | ||
6749 | * in each SG queue. | ||
6750 | */ | ||
6751 | scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; | ||
6752 | scsi_sg_q.sg_cur_list_cnt = | ||
6753 | ASC_SG_LIST_PER_Q - 1; | ||
6754 | } else { | ||
6755 | /* | ||
6756 | * This is the last SG queue in the list of | ||
6757 | * allocated SG queues. If there are more | ||
6758 | * SG elements than will fit in the allocated | ||
6759 | * queues, then set the QCSG_SG_XFER_MORE flag. | ||
6760 | */ | ||
6761 | if (scsiq->remain_sg_entry_cnt != 0) { | ||
6762 | scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; | ||
6763 | } else { | ||
6764 | scsi_sg_q.cntl |= QCSG_SG_XFER_END; | ||
6765 | } | ||
6766 | /* equals sg_entry_cnt * 2 */ | ||
6767 | sg_list_dwords = sg_entry_cnt << 1; | ||
6768 | scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; | ||
6769 | scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; | ||
6770 | sg_entry_cnt = 0; | ||
6771 | } | ||
6772 | |||
6773 | scsi_sg_q.q_no = next_qp; | ||
6774 | AscMemWordCopyPtrToLram(iop_base, | ||
6775 | q_addr + ASC_SCSIQ_SGHD_CPY_BEG, | ||
6776 | (uchar *)&scsi_sg_q, | ||
6777 | sizeof(ASC_SG_LIST_Q) >> 1); | ||
6778 | |||
6779 | AscMemDWordCopyPtrToLram(iop_base, | ||
6780 | q_addr + ASC_SGQ_LIST_BEG, | ||
6781 | (uchar *)&sg_head-> | ||
6782 | sg_list[scsiq->next_sg_index], | ||
6783 | sg_list_dwords); | ||
6784 | |||
6785 | scsiq->next_sg_index += ASC_SG_LIST_PER_Q; | ||
6786 | |||
6787 | /* | ||
6788 | * If the just completed SG queue contained the | ||
6789 | * last SG element, then no more SG queues need | ||
6790 | * to be written. | ||
6791 | */ | ||
6792 | if (scsi_sg_q.cntl & QCSG_SG_XFER_END) { | ||
6793 | break; | ||
6794 | } | ||
6795 | |||
6796 | next_qp = AscReadLramByte(iop_base, | ||
6797 | (ushort)(q_addr + | ||
6798 | ASC_SCSIQ_B_FWD)); | ||
6799 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
6800 | } | ||
6801 | |||
6802 | /* | ||
6803 | * Clear the halt condition so the RISC will be restarted | ||
6804 | * after the return. | ||
6805 | */ | ||
6806 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
6807 | return (0); | ||
6808 | } | ||
6809 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
6810 | return (0); | ||
6811 | } | ||
6812 | |||
6813 | static uchar | ||
6814 | _AscCopyLramScsiDoneQ(PortAddr iop_base, | ||
6815 | ushort q_addr, | ||
6816 | ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count) | ||
6817 | { | ||
6818 | ushort _val; | ||
6819 | uchar sg_queue_cnt; | ||
6820 | |||
6821 | DvcGetQinfo(iop_base, | ||
6822 | q_addr + ASC_SCSIQ_DONE_INFO_BEG, | ||
6823 | (uchar *)scsiq, | ||
6824 | (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2); | ||
6825 | |||
6826 | _val = AscReadLramWord(iop_base, | ||
6827 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS)); | ||
6828 | scsiq->q_status = (uchar)_val; | ||
6829 | scsiq->q_no = (uchar)(_val >> 8); | ||
6830 | _val = AscReadLramWord(iop_base, | ||
6831 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL)); | ||
6832 | scsiq->cntl = (uchar)_val; | ||
6833 | sg_queue_cnt = (uchar)(_val >> 8); | ||
6834 | _val = AscReadLramWord(iop_base, | ||
6835 | (ushort)(q_addr + | ||
6836 | (ushort)ASC_SCSIQ_B_SENSE_LEN)); | ||
6837 | scsiq->sense_len = (uchar)_val; | ||
6838 | scsiq->extra_bytes = (uchar)(_val >> 8); | ||
6839 | |||
6840 | /* | ||
6841 | * Read high word of remain bytes from alternate location. | ||
6842 | */ | ||
6843 | scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base, | ||
6844 | (ushort)(q_addr + | ||
6845 | (ushort) | ||
6846 | ASC_SCSIQ_W_ALT_DC1))) | ||
6847 | << 16); | ||
6848 | /* | ||
6849 | * Read low word of remain bytes from original location. | ||
6850 | */ | ||
6851 | scsiq->remain_bytes += AscReadLramWord(iop_base, | ||
6852 | (ushort)(q_addr + (ushort) | ||
6853 | ASC_SCSIQ_DW_REMAIN_XFER_CNT)); | ||
6854 | |||
6855 | scsiq->remain_bytes &= max_dma_count; | ||
6856 | return (sg_queue_cnt); | ||
6857 | } | ||
6858 | |||
6859 | static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) | ||
6860 | { | ||
6861 | uchar next_qp; | ||
6862 | uchar n_q_used; | ||
6863 | uchar sg_list_qp; | ||
6864 | uchar sg_queue_cnt; | ||
6865 | uchar q_cnt; | ||
6866 | uchar done_q_tail; | ||
6867 | uchar tid_no; | ||
6868 | ASC_SCSI_BIT_ID_TYPE scsi_busy; | ||
6869 | ASC_SCSI_BIT_ID_TYPE target_id; | ||
6870 | PortAddr iop_base; | ||
6871 | ushort q_addr; | ||
6872 | ushort sg_q_addr; | ||
6873 | uchar cur_target_qng; | ||
6874 | ASC_QDONE_INFO scsiq_buf; | ||
6875 | ASC_QDONE_INFO *scsiq; | ||
6876 | int false_overrun; | ||
6877 | |||
6878 | iop_base = asc_dvc->iop_base; | ||
6879 | n_q_used = 1; | ||
6880 | scsiq = (ASC_QDONE_INFO *)&scsiq_buf; | ||
6881 | done_q_tail = (uchar)AscGetVarDoneQTail(iop_base); | ||
6882 | q_addr = ASC_QNO_TO_QADDR(done_q_tail); | ||
6883 | next_qp = AscReadLramByte(iop_base, | ||
6884 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD)); | ||
6885 | if (next_qp != ASC_QLINK_END) { | ||
6886 | AscPutVarDoneQTail(iop_base, next_qp); | ||
6887 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
6888 | sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, | ||
6889 | asc_dvc->max_dma_count); | ||
6890 | AscWriteLramByte(iop_base, | ||
6891 | (ushort)(q_addr + | ||
6892 | (ushort)ASC_SCSIQ_B_STATUS), | ||
6893 | (uchar)(scsiq-> | ||
6894 | q_status & (uchar)~(QS_READY | | ||
6895 | QS_ABORTED))); | ||
6896 | tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); | ||
6897 | target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); | ||
6898 | if ((scsiq->cntl & QC_SG_HEAD) != 0) { | ||
6899 | sg_q_addr = q_addr; | ||
6900 | sg_list_qp = next_qp; | ||
6901 | for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { | ||
6902 | sg_list_qp = AscReadLramByte(iop_base, | ||
6903 | (ushort)(sg_q_addr | ||
6904 | + (ushort) | ||
6905 | ASC_SCSIQ_B_FWD)); | ||
6906 | sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); | ||
6907 | if (sg_list_qp == ASC_QLINK_END) { | ||
6908 | AscSetLibErrorCode(asc_dvc, | ||
6909 | ASCQ_ERR_SG_Q_LINKS); | ||
6910 | scsiq->d3.done_stat = QD_WITH_ERROR; | ||
6911 | scsiq->d3.host_stat = | ||
6912 | QHSTA_D_QDONE_SG_LIST_CORRUPTED; | ||
6913 | goto FATAL_ERR_QDONE; | ||
6914 | } | ||
6915 | AscWriteLramByte(iop_base, | ||
6916 | (ushort)(sg_q_addr + (ushort) | ||
6917 | ASC_SCSIQ_B_STATUS), | ||
6918 | QS_FREE); | ||
6919 | } | ||
6920 | n_q_used = sg_queue_cnt + 1; | ||
6921 | AscPutVarDoneQTail(iop_base, sg_list_qp); | ||
6922 | } | ||
6923 | if (asc_dvc->queue_full_or_busy & target_id) { | ||
6924 | cur_target_qng = AscReadLramByte(iop_base, | ||
6925 | (ushort)((ushort) | ||
6926 | ASC_QADR_BEG | ||
6927 | + (ushort) | ||
6928 | scsiq->d2. | ||
6929 | target_ix)); | ||
6930 | if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { | ||
6931 | scsi_busy = AscReadLramByte(iop_base, (ushort) | ||
6932 | ASCV_SCSIBUSY_B); | ||
6933 | scsi_busy &= ~target_id; | ||
6934 | AscWriteLramByte(iop_base, | ||
6935 | (ushort)ASCV_SCSIBUSY_B, | ||
6936 | scsi_busy); | ||
6937 | asc_dvc->queue_full_or_busy &= ~target_id; | ||
6938 | } | ||
6939 | } | ||
6940 | if (asc_dvc->cur_total_qng >= n_q_used) { | ||
6941 | asc_dvc->cur_total_qng -= n_q_used; | ||
6942 | if (asc_dvc->cur_dvc_qng[tid_no] != 0) { | ||
6943 | asc_dvc->cur_dvc_qng[tid_no]--; | ||
6944 | } | ||
6945 | } else { | ||
6946 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); | ||
6947 | scsiq->d3.done_stat = QD_WITH_ERROR; | ||
6948 | goto FATAL_ERR_QDONE; | ||
6949 | } | ||
6950 | if ((scsiq->d2.srb_ptr == 0UL) || | ||
6951 | ((scsiq->q_status & QS_ABORTED) != 0)) { | ||
6952 | return (0x11); | ||
6953 | } else if (scsiq->q_status == QS_DONE) { | ||
6954 | false_overrun = FALSE; | ||
6955 | if (scsiq->extra_bytes != 0) { | ||
6956 | scsiq->remain_bytes += | ||
6957 | (ADV_DCNT)scsiq->extra_bytes; | ||
6958 | } | ||
6959 | if (scsiq->d3.done_stat == QD_WITH_ERROR) { | ||
6960 | if (scsiq->d3.host_stat == | ||
6961 | QHSTA_M_DATA_OVER_RUN) { | ||
6962 | if ((scsiq-> | ||
6963 | cntl & (QC_DATA_IN | QC_DATA_OUT)) | ||
6964 | == 0) { | ||
6965 | scsiq->d3.done_stat = | ||
6966 | QD_NO_ERROR; | ||
6967 | scsiq->d3.host_stat = | ||
6968 | QHSTA_NO_ERROR; | ||
6969 | } else if (false_overrun) { | ||
6970 | scsiq->d3.done_stat = | ||
6971 | QD_NO_ERROR; | ||
6972 | scsiq->d3.host_stat = | ||
6973 | QHSTA_NO_ERROR; | ||
6974 | } | ||
6975 | } else if (scsiq->d3.host_stat == | ||
6976 | QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { | ||
6977 | AscStopChip(iop_base); | ||
6978 | AscSetChipControl(iop_base, | ||
6979 | (uchar)(CC_SCSI_RESET | ||
6980 | | CC_HALT)); | ||
6981 | udelay(60); | ||
6982 | AscSetChipControl(iop_base, CC_HALT); | ||
6983 | AscSetChipStatus(iop_base, | ||
6984 | CIW_CLR_SCSI_RESET_INT); | ||
6985 | AscSetChipStatus(iop_base, 0); | ||
6986 | AscSetChipControl(iop_base, 0); | ||
6987 | } | ||
6988 | } | ||
6989 | if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { | ||
6990 | asc_isr_callback(asc_dvc, scsiq); | ||
6991 | } else { | ||
6992 | if ((AscReadLramByte(iop_base, | ||
6993 | (ushort)(q_addr + (ushort) | ||
6994 | ASC_SCSIQ_CDB_BEG)) | ||
6995 | == START_STOP)) { | ||
6996 | asc_dvc->unit_not_ready &= ~target_id; | ||
6997 | if (scsiq->d3.done_stat != QD_NO_ERROR) { | ||
6998 | asc_dvc->start_motor &= | ||
6999 | ~target_id; | ||
7000 | } | ||
7001 | } | ||
7002 | } | ||
7003 | return (1); | ||
7004 | } else { | ||
7005 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); | ||
7006 | FATAL_ERR_QDONE: | ||
7007 | if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { | ||
7008 | asc_isr_callback(asc_dvc, scsiq); | ||
7009 | } | ||
7010 | return (0x80); | ||
7011 | } | ||
7012 | } | ||
7013 | return (0); | ||
7014 | } | ||
7015 | |||
7016 | static int AscISR(ASC_DVC_VAR *asc_dvc) | ||
7017 | { | ||
7018 | ASC_CS_TYPE chipstat; | ||
7019 | PortAddr iop_base; | ||
7020 | ushort saved_ram_addr; | ||
7021 | uchar ctrl_reg; | ||
7022 | uchar saved_ctrl_reg; | ||
7023 | int int_pending; | ||
7024 | int status; | ||
7025 | uchar host_flag; | ||
7026 | |||
7027 | iop_base = asc_dvc->iop_base; | ||
7028 | int_pending = FALSE; | ||
7029 | |||
7030 | if (AscIsIntPending(iop_base) == 0) { | ||
7031 | return int_pending; | ||
7032 | } | ||
7033 | |||
7034 | if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) { | ||
7035 | return (ERR); | ||
7036 | } | ||
7037 | if (asc_dvc->in_critical_cnt != 0) { | ||
7038 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); | ||
7039 | return (ERR); | ||
7040 | } | ||
7041 | if (asc_dvc->is_in_int) { | ||
7042 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); | ||
7043 | return (ERR); | ||
7044 | } | ||
7045 | asc_dvc->is_in_int = TRUE; | ||
7046 | ctrl_reg = AscGetChipControl(iop_base); | ||
7047 | saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | | ||
7048 | CC_SINGLE_STEP | CC_DIAG | CC_TEST)); | ||
7049 | chipstat = AscGetChipStatus(iop_base); | ||
7050 | if (chipstat & CSW_SCSI_RESET_LATCH) { | ||
7051 | if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { | ||
7052 | int i = 10; | ||
7053 | int_pending = TRUE; | ||
7054 | asc_dvc->sdtr_done = 0; | ||
7055 | saved_ctrl_reg &= (uchar)(~CC_HALT); | ||
7056 | while ((AscGetChipStatus(iop_base) & | ||
7057 | CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) { | ||
7058 | mdelay(100); | ||
7059 | } | ||
7060 | AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); | ||
7061 | AscSetChipControl(iop_base, CC_HALT); | ||
7062 | AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); | ||
7063 | AscSetChipStatus(iop_base, 0); | ||
7064 | chipstat = AscGetChipStatus(iop_base); | ||
7065 | } | ||
7066 | } | ||
7067 | saved_ram_addr = AscGetChipLramAddr(iop_base); | ||
7068 | host_flag = AscReadLramByte(iop_base, | ||
7069 | ASCV_HOST_FLAG_B) & | ||
7070 | (uchar)(~ASC_HOST_FLAG_IN_ISR); | ||
7071 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, | ||
7072 | (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR)); | ||
7073 | if ((chipstat & CSW_INT_PENDING) | ||
7074 | || (int_pending) | ||
7075 | ) { | ||
7076 | AscAckInterrupt(iop_base); | ||
7077 | int_pending = TRUE; | ||
7078 | if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) { | ||
7079 | if (AscIsrChipHalted(asc_dvc) == ERR) { | ||
7080 | goto ISR_REPORT_QDONE_FATAL_ERROR; | ||
7081 | } else { | ||
7082 | saved_ctrl_reg &= (uchar)(~CC_HALT); | ||
7083 | } | ||
7084 | } else { | ||
7085 | ISR_REPORT_QDONE_FATAL_ERROR: | ||
7086 | if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { | ||
7087 | while (((status = | ||
7088 | AscIsrQDone(asc_dvc)) & 0x01) != 0) { | ||
7089 | } | ||
7090 | } else { | ||
7091 | do { | ||
7092 | if ((status = | ||
7093 | AscIsrQDone(asc_dvc)) == 1) { | ||
7094 | break; | ||
7095 | } | ||
7096 | } while (status == 0x11); | ||
7097 | } | ||
7098 | if ((status & 0x80) != 0) | ||
7099 | int_pending = ERR; | ||
7100 | } | ||
7101 | } | ||
7102 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); | ||
7103 | AscSetChipLramAddr(iop_base, saved_ram_addr); | ||
7104 | AscSetChipControl(iop_base, saved_ctrl_reg); | ||
7105 | asc_dvc->is_in_int = FALSE; | ||
7106 | return (int_pending); | ||
7107 | } | ||
7108 | |||
7109 | /* Microcode buffer is kept after initialization for error recovery. */ | 4885 | /* Microcode buffer is kept after initialization for error recovery. */ |
7110 | static uchar _asc_mcode_buf[] = { | 4886 | static uchar _asc_mcode_buf[] = { |
7111 | 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 4887 | 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -7302,1977 +5078,9 @@ static uchar _asc_mcode_buf[] = { | |||
7302 | 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84, | 5078 | 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84, |
7303 | }; | 5079 | }; |
7304 | 5080 | ||
7305 | static ushort _asc_mcode_size = sizeof(_asc_mcode_buf); | 5081 | static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf); |
7306 | static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; | 5082 | static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; |
7307 | 5083 | ||
7308 | #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 | ||
7309 | static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { | ||
7310 | INQUIRY, | ||
7311 | REQUEST_SENSE, | ||
7312 | READ_CAPACITY, | ||
7313 | READ_TOC, | ||
7314 | MODE_SELECT, | ||
7315 | MODE_SENSE, | ||
7316 | MODE_SELECT_10, | ||
7317 | MODE_SENSE_10, | ||
7318 | 0xFF, | ||
7319 | 0xFF, | ||
7320 | 0xFF, | ||
7321 | 0xFF, | ||
7322 | 0xFF, | ||
7323 | 0xFF, | ||
7324 | 0xFF, | ||
7325 | 0xFF | ||
7326 | }; | ||
7327 | |||
7328 | static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) | ||
7329 | { | ||
7330 | PortAddr iop_base; | ||
7331 | int sta; | ||
7332 | int n_q_required; | ||
7333 | int disable_syn_offset_one_fix; | ||
7334 | int i; | ||
7335 | ASC_PADDR addr; | ||
7336 | ushort sg_entry_cnt = 0; | ||
7337 | ushort sg_entry_cnt_minus_one = 0; | ||
7338 | uchar target_ix; | ||
7339 | uchar tid_no; | ||
7340 | uchar sdtr_data; | ||
7341 | uchar extra_bytes; | ||
7342 | uchar scsi_cmd; | ||
7343 | uchar disable_cmd; | ||
7344 | ASC_SG_HEAD *sg_head; | ||
7345 | ASC_DCNT data_cnt; | ||
7346 | |||
7347 | iop_base = asc_dvc->iop_base; | ||
7348 | sg_head = scsiq->sg_head; | ||
7349 | if (asc_dvc->err_code != 0) | ||
7350 | return (ERR); | ||
7351 | scsiq->q1.q_no = 0; | ||
7352 | if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { | ||
7353 | scsiq->q1.extra_bytes = 0; | ||
7354 | } | ||
7355 | sta = 0; | ||
7356 | target_ix = scsiq->q2.target_ix; | ||
7357 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
7358 | n_q_required = 1; | ||
7359 | if (scsiq->cdbptr[0] == REQUEST_SENSE) { | ||
7360 | if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { | ||
7361 | asc_dvc->sdtr_done &= ~scsiq->q1.target_id; | ||
7362 | sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); | ||
7363 | AscMsgOutSDTR(asc_dvc, | ||
7364 | asc_dvc-> | ||
7365 | sdtr_period_tbl[(sdtr_data >> 4) & | ||
7366 | (uchar)(asc_dvc-> | ||
7367 | max_sdtr_index - | ||
7368 | 1)], | ||
7369 | (uchar)(sdtr_data & (uchar) | ||
7370 | ASC_SYN_MAX_OFFSET)); | ||
7371 | scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); | ||
7372 | } | ||
7373 | } | ||
7374 | if (asc_dvc->in_critical_cnt != 0) { | ||
7375 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); | ||
7376 | return (ERR); | ||
7377 | } | ||
7378 | asc_dvc->in_critical_cnt++; | ||
7379 | if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { | ||
7380 | if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { | ||
7381 | asc_dvc->in_critical_cnt--; | ||
7382 | return (ERR); | ||
7383 | } | ||
7384 | #if !CC_VERY_LONG_SG_LIST | ||
7385 | if (sg_entry_cnt > ASC_MAX_SG_LIST) { | ||
7386 | asc_dvc->in_critical_cnt--; | ||
7387 | return (ERR); | ||
7388 | } | ||
7389 | #endif /* !CC_VERY_LONG_SG_LIST */ | ||
7390 | if (sg_entry_cnt == 1) { | ||
7391 | scsiq->q1.data_addr = | ||
7392 | (ADV_PADDR)sg_head->sg_list[0].addr; | ||
7393 | scsiq->q1.data_cnt = | ||
7394 | (ADV_DCNT)sg_head->sg_list[0].bytes; | ||
7395 | scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); | ||
7396 | } | ||
7397 | sg_entry_cnt_minus_one = sg_entry_cnt - 1; | ||
7398 | } | ||
7399 | scsi_cmd = scsiq->cdbptr[0]; | ||
7400 | disable_syn_offset_one_fix = FALSE; | ||
7401 | if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && | ||
7402 | !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { | ||
7403 | if (scsiq->q1.cntl & QC_SG_HEAD) { | ||
7404 | data_cnt = 0; | ||
7405 | for (i = 0; i < sg_entry_cnt; i++) { | ||
7406 | data_cnt += | ||
7407 | (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i]. | ||
7408 | bytes); | ||
7409 | } | ||
7410 | } else { | ||
7411 | data_cnt = le32_to_cpu(scsiq->q1.data_cnt); | ||
7412 | } | ||
7413 | if (data_cnt != 0UL) { | ||
7414 | if (data_cnt < 512UL) { | ||
7415 | disable_syn_offset_one_fix = TRUE; | ||
7416 | } else { | ||
7417 | for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; | ||
7418 | i++) { | ||
7419 | disable_cmd = | ||
7420 | _syn_offset_one_disable_cmd[i]; | ||
7421 | if (disable_cmd == 0xFF) { | ||
7422 | break; | ||
7423 | } | ||
7424 | if (scsi_cmd == disable_cmd) { | ||
7425 | disable_syn_offset_one_fix = | ||
7426 | TRUE; | ||
7427 | break; | ||
7428 | } | ||
7429 | } | ||
7430 | } | ||
7431 | } | ||
7432 | } | ||
7433 | if (disable_syn_offset_one_fix) { | ||
7434 | scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; | ||
7435 | scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | | ||
7436 | ASC_TAG_FLAG_DISABLE_DISCONNECT); | ||
7437 | } else { | ||
7438 | scsiq->q2.tag_code &= 0x27; | ||
7439 | } | ||
7440 | if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { | ||
7441 | if (asc_dvc->bug_fix_cntl) { | ||
7442 | if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { | ||
7443 | if ((scsi_cmd == READ_6) || | ||
7444 | (scsi_cmd == READ_10)) { | ||
7445 | addr = | ||
7446 | (ADV_PADDR)le32_to_cpu(sg_head-> | ||
7447 | sg_list | ||
7448 | [sg_entry_cnt_minus_one]. | ||
7449 | addr) + | ||
7450 | (ADV_DCNT)le32_to_cpu(sg_head-> | ||
7451 | sg_list | ||
7452 | [sg_entry_cnt_minus_one]. | ||
7453 | bytes); | ||
7454 | extra_bytes = | ||
7455 | (uchar)((ushort)addr & 0x0003); | ||
7456 | if ((extra_bytes != 0) | ||
7457 | && | ||
7458 | ((scsiq->q2. | ||
7459 | tag_code & | ||
7460 | ASC_TAG_FLAG_EXTRA_BYTES) | ||
7461 | == 0)) { | ||
7462 | scsiq->q2.tag_code |= | ||
7463 | ASC_TAG_FLAG_EXTRA_BYTES; | ||
7464 | scsiq->q1.extra_bytes = | ||
7465 | extra_bytes; | ||
7466 | data_cnt = | ||
7467 | le32_to_cpu(sg_head-> | ||
7468 | sg_list | ||
7469 | [sg_entry_cnt_minus_one]. | ||
7470 | bytes); | ||
7471 | data_cnt -= | ||
7472 | (ASC_DCNT) extra_bytes; | ||
7473 | sg_head-> | ||
7474 | sg_list | ||
7475 | [sg_entry_cnt_minus_one]. | ||
7476 | bytes = | ||
7477 | cpu_to_le32(data_cnt); | ||
7478 | } | ||
7479 | } | ||
7480 | } | ||
7481 | } | ||
7482 | sg_head->entry_to_copy = sg_head->entry_cnt; | ||
7483 | #if CC_VERY_LONG_SG_LIST | ||
7484 | /* | ||
7485 | * Set the sg_entry_cnt to the maximum possible. The rest of | ||
7486 | * the SG elements will be copied when the RISC completes the | ||
7487 | * SG elements that fit and halts. | ||
7488 | */ | ||
7489 | if (sg_entry_cnt > ASC_MAX_SG_LIST) { | ||
7490 | sg_entry_cnt = ASC_MAX_SG_LIST; | ||
7491 | } | ||
7492 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
7493 | n_q_required = AscSgListToQueue(sg_entry_cnt); | ||
7494 | if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= | ||
7495 | (uint) n_q_required) | ||
7496 | || ((scsiq->q1.cntl & QC_URGENT) != 0)) { | ||
7497 | if ((sta = | ||
7498 | AscSendScsiQueue(asc_dvc, scsiq, | ||
7499 | n_q_required)) == 1) { | ||
7500 | asc_dvc->in_critical_cnt--; | ||
7501 | return (sta); | ||
7502 | } | ||
7503 | } | ||
7504 | } else { | ||
7505 | if (asc_dvc->bug_fix_cntl) { | ||
7506 | if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { | ||
7507 | if ((scsi_cmd == READ_6) || | ||
7508 | (scsi_cmd == READ_10)) { | ||
7509 | addr = | ||
7510 | le32_to_cpu(scsiq->q1.data_addr) + | ||
7511 | le32_to_cpu(scsiq->q1.data_cnt); | ||
7512 | extra_bytes = | ||
7513 | (uchar)((ushort)addr & 0x0003); | ||
7514 | if ((extra_bytes != 0) | ||
7515 | && | ||
7516 | ((scsiq->q2. | ||
7517 | tag_code & | ||
7518 | ASC_TAG_FLAG_EXTRA_BYTES) | ||
7519 | == 0)) { | ||
7520 | data_cnt = | ||
7521 | le32_to_cpu(scsiq->q1. | ||
7522 | data_cnt); | ||
7523 | if (((ushort)data_cnt & 0x01FF) | ||
7524 | == 0) { | ||
7525 | scsiq->q2.tag_code |= | ||
7526 | ASC_TAG_FLAG_EXTRA_BYTES; | ||
7527 | data_cnt -= (ASC_DCNT) | ||
7528 | extra_bytes; | ||
7529 | scsiq->q1.data_cnt = | ||
7530 | cpu_to_le32 | ||
7531 | (data_cnt); | ||
7532 | scsiq->q1.extra_bytes = | ||
7533 | extra_bytes; | ||
7534 | } | ||
7535 | } | ||
7536 | } | ||
7537 | } | ||
7538 | } | ||
7539 | n_q_required = 1; | ||
7540 | if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || | ||
7541 | ((scsiq->q1.cntl & QC_URGENT) != 0)) { | ||
7542 | if ((sta = AscSendScsiQueue(asc_dvc, scsiq, | ||
7543 | n_q_required)) == 1) { | ||
7544 | asc_dvc->in_critical_cnt--; | ||
7545 | return (sta); | ||
7546 | } | ||
7547 | } | ||
7548 | } | ||
7549 | asc_dvc->in_critical_cnt--; | ||
7550 | return (sta); | ||
7551 | } | ||
7552 | |||
7553 | static int | ||
7554 | AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) | ||
7555 | { | ||
7556 | PortAddr iop_base; | ||
7557 | uchar free_q_head; | ||
7558 | uchar next_qp; | ||
7559 | uchar tid_no; | ||
7560 | uchar target_ix; | ||
7561 | int sta; | ||
7562 | |||
7563 | iop_base = asc_dvc->iop_base; | ||
7564 | target_ix = scsiq->q2.target_ix; | ||
7565 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
7566 | sta = 0; | ||
7567 | free_q_head = (uchar)AscGetVarFreeQHead(iop_base); | ||
7568 | if (n_q_required > 1) { | ||
7569 | next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head, | ||
7570 | (uchar)n_q_required); | ||
7571 | if (next_qp != ASC_QLINK_END) { | ||
7572 | asc_dvc->last_q_shortage = 0; | ||
7573 | scsiq->sg_head->queue_cnt = n_q_required - 1; | ||
7574 | scsiq->q1.q_no = free_q_head; | ||
7575 | sta = AscPutReadySgListQueue(asc_dvc, scsiq, | ||
7576 | free_q_head); | ||
7577 | } | ||
7578 | } else if (n_q_required == 1) { | ||
7579 | next_qp = AscAllocFreeQueue(iop_base, free_q_head); | ||
7580 | if (next_qp != ASC_QLINK_END) { | ||
7581 | scsiq->q1.q_no = free_q_head; | ||
7582 | sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head); | ||
7583 | } | ||
7584 | } | ||
7585 | if (sta == 1) { | ||
7586 | AscPutVarFreeQHead(iop_base, next_qp); | ||
7587 | asc_dvc->cur_total_qng += (uchar)(n_q_required); | ||
7588 | asc_dvc->cur_dvc_qng[tid_no]++; | ||
7589 | } | ||
7590 | return sta; | ||
7591 | } | ||
7592 | |||
7593 | static int AscSgListToQueue(int sg_list) | ||
7594 | { | ||
7595 | int n_sg_list_qs; | ||
7596 | |||
7597 | n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); | ||
7598 | if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) | ||
7599 | n_sg_list_qs++; | ||
7600 | return (n_sg_list_qs + 1); | ||
7601 | } | ||
7602 | |||
7603 | static uint | ||
7604 | AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) | ||
7605 | { | ||
7606 | uint cur_used_qs; | ||
7607 | uint cur_free_qs; | ||
7608 | ASC_SCSI_BIT_ID_TYPE target_id; | ||
7609 | uchar tid_no; | ||
7610 | |||
7611 | target_id = ASC_TIX_TO_TARGET_ID(target_ix); | ||
7612 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
7613 | if ((asc_dvc->unit_not_ready & target_id) || | ||
7614 | (asc_dvc->queue_full_or_busy & target_id)) { | ||
7615 | return (0); | ||
7616 | } | ||
7617 | if (n_qs == 1) { | ||
7618 | cur_used_qs = (uint) asc_dvc->cur_total_qng + | ||
7619 | (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q; | ||
7620 | } else { | ||
7621 | cur_used_qs = (uint) asc_dvc->cur_total_qng + | ||
7622 | (uint) ASC_MIN_FREE_Q; | ||
7623 | } | ||
7624 | if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { | ||
7625 | cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; | ||
7626 | if (asc_dvc->cur_dvc_qng[tid_no] >= | ||
7627 | asc_dvc->max_dvc_qng[tid_no]) { | ||
7628 | return (0); | ||
7629 | } | ||
7630 | return (cur_free_qs); | ||
7631 | } | ||
7632 | if (n_qs > 1) { | ||
7633 | if ((n_qs > asc_dvc->last_q_shortage) | ||
7634 | && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { | ||
7635 | asc_dvc->last_q_shortage = n_qs; | ||
7636 | } | ||
7637 | } | ||
7638 | return (0); | ||
7639 | } | ||
7640 | |||
7641 | static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) | ||
7642 | { | ||
7643 | ushort q_addr; | ||
7644 | uchar tid_no; | ||
7645 | uchar sdtr_data; | ||
7646 | uchar syn_period_ix; | ||
7647 | uchar syn_offset; | ||
7648 | PortAddr iop_base; | ||
7649 | |||
7650 | iop_base = asc_dvc->iop_base; | ||
7651 | if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && | ||
7652 | ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { | ||
7653 | tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); | ||
7654 | sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); | ||
7655 | syn_period_ix = | ||
7656 | (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); | ||
7657 | syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; | ||
7658 | AscMsgOutSDTR(asc_dvc, | ||
7659 | asc_dvc->sdtr_period_tbl[syn_period_ix], | ||
7660 | syn_offset); | ||
7661 | scsiq->q1.cntl |= QC_MSG_OUT; | ||
7662 | } | ||
7663 | q_addr = ASC_QNO_TO_QADDR(q_no); | ||
7664 | if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { | ||
7665 | scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; | ||
7666 | } | ||
7667 | scsiq->q1.status = QS_FREE; | ||
7668 | AscMemWordCopyPtrToLram(iop_base, | ||
7669 | q_addr + ASC_SCSIQ_CDB_BEG, | ||
7670 | (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1); | ||
7671 | |||
7672 | DvcPutScsiQ(iop_base, | ||
7673 | q_addr + ASC_SCSIQ_CPY_BEG, | ||
7674 | (uchar *)&scsiq->q1.cntl, | ||
7675 | ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); | ||
7676 | AscWriteLramWord(iop_base, | ||
7677 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), | ||
7678 | (ushort)(((ushort)scsiq->q1. | ||
7679 | q_no << 8) | (ushort)QS_READY)); | ||
7680 | return (1); | ||
7681 | } | ||
7682 | |||
7683 | static int | ||
7684 | AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) | ||
7685 | { | ||
7686 | int sta; | ||
7687 | int i; | ||
7688 | ASC_SG_HEAD *sg_head; | ||
7689 | ASC_SG_LIST_Q scsi_sg_q; | ||
7690 | ASC_DCNT saved_data_addr; | ||
7691 | ASC_DCNT saved_data_cnt; | ||
7692 | PortAddr iop_base; | ||
7693 | ushort sg_list_dwords; | ||
7694 | ushort sg_index; | ||
7695 | ushort sg_entry_cnt; | ||
7696 | ushort q_addr; | ||
7697 | uchar next_qp; | ||
7698 | |||
7699 | iop_base = asc_dvc->iop_base; | ||
7700 | sg_head = scsiq->sg_head; | ||
7701 | saved_data_addr = scsiq->q1.data_addr; | ||
7702 | saved_data_cnt = scsiq->q1.data_cnt; | ||
7703 | scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; | ||
7704 | scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; | ||
7705 | #if CC_VERY_LONG_SG_LIST | ||
7706 | /* | ||
7707 | * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST | ||
7708 | * then not all SG elements will fit in the allocated queues. | ||
7709 | * The rest of the SG elements will be copied when the RISC | ||
7710 | * completes the SG elements that fit and halts. | ||
7711 | */ | ||
7712 | if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { | ||
7713 | /* | ||
7714 | * Set sg_entry_cnt to be the number of SG elements that | ||
7715 | * will fit in the allocated SG queues. It is minus 1, because | ||
7716 | * the first SG element is handled above. ASC_MAX_SG_LIST is | ||
7717 | * already inflated by 1 to account for this. For example it | ||
7718 | * may be 50 which is 1 + 7 queues * 7 SG elements. | ||
7719 | */ | ||
7720 | sg_entry_cnt = ASC_MAX_SG_LIST - 1; | ||
7721 | |||
7722 | /* | ||
7723 | * Keep track of remaining number of SG elements that will | ||
7724 | * need to be handled from a_isr.c. | ||
7725 | */ | ||
7726 | scsiq->remain_sg_entry_cnt = | ||
7727 | sg_head->entry_cnt - ASC_MAX_SG_LIST; | ||
7728 | } else { | ||
7729 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
7730 | /* | ||
7731 | * Set sg_entry_cnt to be the number of SG elements that | ||
7732 | * will fit in the allocated SG queues. It is minus 1, because | ||
7733 | * the first SG element is handled above. | ||
7734 | */ | ||
7735 | sg_entry_cnt = sg_head->entry_cnt - 1; | ||
7736 | #if CC_VERY_LONG_SG_LIST | ||
7737 | } | ||
7738 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
7739 | if (sg_entry_cnt != 0) { | ||
7740 | scsiq->q1.cntl |= QC_SG_HEAD; | ||
7741 | q_addr = ASC_QNO_TO_QADDR(q_no); | ||
7742 | sg_index = 1; | ||
7743 | scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; | ||
7744 | scsi_sg_q.sg_head_qp = q_no; | ||
7745 | scsi_sg_q.cntl = QCSG_SG_XFER_LIST; | ||
7746 | for (i = 0; i < sg_head->queue_cnt; i++) { | ||
7747 | scsi_sg_q.seq_no = i + 1; | ||
7748 | if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { | ||
7749 | sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); | ||
7750 | sg_entry_cnt -= ASC_SG_LIST_PER_Q; | ||
7751 | if (i == 0) { | ||
7752 | scsi_sg_q.sg_list_cnt = | ||
7753 | ASC_SG_LIST_PER_Q; | ||
7754 | scsi_sg_q.sg_cur_list_cnt = | ||
7755 | ASC_SG_LIST_PER_Q; | ||
7756 | } else { | ||
7757 | scsi_sg_q.sg_list_cnt = | ||
7758 | ASC_SG_LIST_PER_Q - 1; | ||
7759 | scsi_sg_q.sg_cur_list_cnt = | ||
7760 | ASC_SG_LIST_PER_Q - 1; | ||
7761 | } | ||
7762 | } else { | ||
7763 | #if CC_VERY_LONG_SG_LIST | ||
7764 | /* | ||
7765 | * This is the last SG queue in the list of | ||
7766 | * allocated SG queues. If there are more | ||
7767 | * SG elements than will fit in the allocated | ||
7768 | * queues, then set the QCSG_SG_XFER_MORE flag. | ||
7769 | */ | ||
7770 | if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { | ||
7771 | scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; | ||
7772 | } else { | ||
7773 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
7774 | scsi_sg_q.cntl |= QCSG_SG_XFER_END; | ||
7775 | #if CC_VERY_LONG_SG_LIST | ||
7776 | } | ||
7777 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
7778 | sg_list_dwords = sg_entry_cnt << 1; | ||
7779 | if (i == 0) { | ||
7780 | scsi_sg_q.sg_list_cnt = sg_entry_cnt; | ||
7781 | scsi_sg_q.sg_cur_list_cnt = | ||
7782 | sg_entry_cnt; | ||
7783 | } else { | ||
7784 | scsi_sg_q.sg_list_cnt = | ||
7785 | sg_entry_cnt - 1; | ||
7786 | scsi_sg_q.sg_cur_list_cnt = | ||
7787 | sg_entry_cnt - 1; | ||
7788 | } | ||
7789 | sg_entry_cnt = 0; | ||
7790 | } | ||
7791 | next_qp = AscReadLramByte(iop_base, | ||
7792 | (ushort)(q_addr + | ||
7793 | ASC_SCSIQ_B_FWD)); | ||
7794 | scsi_sg_q.q_no = next_qp; | ||
7795 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
7796 | AscMemWordCopyPtrToLram(iop_base, | ||
7797 | q_addr + ASC_SCSIQ_SGHD_CPY_BEG, | ||
7798 | (uchar *)&scsi_sg_q, | ||
7799 | sizeof(ASC_SG_LIST_Q) >> 1); | ||
7800 | AscMemDWordCopyPtrToLram(iop_base, | ||
7801 | q_addr + ASC_SGQ_LIST_BEG, | ||
7802 | (uchar *)&sg_head-> | ||
7803 | sg_list[sg_index], | ||
7804 | sg_list_dwords); | ||
7805 | sg_index += ASC_SG_LIST_PER_Q; | ||
7806 | scsiq->next_sg_index = sg_index; | ||
7807 | } | ||
7808 | } else { | ||
7809 | scsiq->q1.cntl &= ~QC_SG_HEAD; | ||
7810 | } | ||
7811 | sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); | ||
7812 | scsiq->q1.data_addr = saved_data_addr; | ||
7813 | scsiq->q1.data_cnt = saved_data_cnt; | ||
7814 | return (sta); | ||
7815 | } | ||
7816 | |||
7817 | static int | ||
7818 | AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) | ||
7819 | { | ||
7820 | int sta = FALSE; | ||
7821 | |||
7822 | if (AscHostReqRiscHalt(iop_base)) { | ||
7823 | sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); | ||
7824 | AscStartChip(iop_base); | ||
7825 | return (sta); | ||
7826 | } | ||
7827 | return (sta); | ||
7828 | } | ||
7829 | |||
7830 | static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) | ||
7831 | { | ||
7832 | ASC_SCSI_BIT_ID_TYPE org_id; | ||
7833 | int i; | ||
7834 | int sta = TRUE; | ||
7835 | |||
7836 | AscSetBank(iop_base, 1); | ||
7837 | org_id = AscReadChipDvcID(iop_base); | ||
7838 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
7839 | if (org_id == (0x01 << i)) | ||
7840 | break; | ||
7841 | } | ||
7842 | org_id = (ASC_SCSI_BIT_ID_TYPE) i; | ||
7843 | AscWriteChipDvcID(iop_base, id); | ||
7844 | if (AscReadChipDvcID(iop_base) == (0x01 << id)) { | ||
7845 | AscSetBank(iop_base, 0); | ||
7846 | AscSetChipSyn(iop_base, sdtr_data); | ||
7847 | if (AscGetChipSyn(iop_base) != sdtr_data) { | ||
7848 | sta = FALSE; | ||
7849 | } | ||
7850 | } else { | ||
7851 | sta = FALSE; | ||
7852 | } | ||
7853 | AscSetBank(iop_base, 1); | ||
7854 | AscWriteChipDvcID(iop_base, org_id); | ||
7855 | AscSetBank(iop_base, 0); | ||
7856 | return (sta); | ||
7857 | } | ||
7858 | |||
7859 | static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) | ||
7860 | { | ||
7861 | uchar i; | ||
7862 | ushort s_addr; | ||
7863 | PortAddr iop_base; | ||
7864 | ushort warn_code; | ||
7865 | |||
7866 | iop_base = asc_dvc->iop_base; | ||
7867 | warn_code = 0; | ||
7868 | AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, | ||
7869 | (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) * | ||
7870 | 64) >> 1) | ||
7871 | ); | ||
7872 | i = ASC_MIN_ACTIVE_QNO; | ||
7873 | s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; | ||
7874 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), | ||
7875 | (uchar)(i + 1)); | ||
7876 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), | ||
7877 | (uchar)(asc_dvc->max_total_qng)); | ||
7878 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), | ||
7879 | (uchar)i); | ||
7880 | i++; | ||
7881 | s_addr += ASC_QBLK_SIZE; | ||
7882 | for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { | ||
7883 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), | ||
7884 | (uchar)(i + 1)); | ||
7885 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), | ||
7886 | (uchar)(i - 1)); | ||
7887 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), | ||
7888 | (uchar)i); | ||
7889 | } | ||
7890 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), | ||
7891 | (uchar)ASC_QLINK_END); | ||
7892 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), | ||
7893 | (uchar)(asc_dvc->max_total_qng - 1)); | ||
7894 | AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), | ||
7895 | (uchar)asc_dvc->max_total_qng); | ||
7896 | i++; | ||
7897 | s_addr += ASC_QBLK_SIZE; | ||
7898 | for (; i <= (uchar)(asc_dvc->max_total_qng + 3); | ||
7899 | i++, s_addr += ASC_QBLK_SIZE) { | ||
7900 | AscWriteLramByte(iop_base, | ||
7901 | (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i); | ||
7902 | AscWriteLramByte(iop_base, | ||
7903 | (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i); | ||
7904 | AscWriteLramByte(iop_base, | ||
7905 | (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i); | ||
7906 | } | ||
7907 | return (warn_code); | ||
7908 | } | ||
7909 | |||
7910 | static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) | ||
7911 | { | ||
7912 | PortAddr iop_base; | ||
7913 | int i; | ||
7914 | ushort lram_addr; | ||
7915 | |||
7916 | iop_base = asc_dvc->iop_base; | ||
7917 | AscPutRiscVarFreeQHead(iop_base, 1); | ||
7918 | AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); | ||
7919 | AscPutVarFreeQHead(iop_base, 1); | ||
7920 | AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); | ||
7921 | AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, | ||
7922 | (uchar)((int)asc_dvc->max_total_qng + 1)); | ||
7923 | AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, | ||
7924 | (uchar)((int)asc_dvc->max_total_qng + 2)); | ||
7925 | AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B, | ||
7926 | asc_dvc->max_total_qng); | ||
7927 | AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); | ||
7928 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
7929 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); | ||
7930 | AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); | ||
7931 | AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); | ||
7932 | AscPutQDoneInProgress(iop_base, 0); | ||
7933 | lram_addr = ASC_QADR_BEG; | ||
7934 | for (i = 0; i < 32; i++, lram_addr += 2) { | ||
7935 | AscWriteLramWord(iop_base, lram_addr, 0); | ||
7936 | } | ||
7937 | } | ||
7938 | |||
7939 | static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code) | ||
7940 | { | ||
7941 | if (asc_dvc->err_code == 0) { | ||
7942 | asc_dvc->err_code = err_code; | ||
7943 | AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, | ||
7944 | err_code); | ||
7945 | } | ||
7946 | return (err_code); | ||
7947 | } | ||
7948 | |||
7949 | static uchar | ||
7950 | AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) | ||
7951 | { | ||
7952 | EXT_MSG sdtr_buf; | ||
7953 | uchar sdtr_period_index; | ||
7954 | PortAddr iop_base; | ||
7955 | |||
7956 | iop_base = asc_dvc->iop_base; | ||
7957 | sdtr_buf.msg_type = EXTENDED_MESSAGE; | ||
7958 | sdtr_buf.msg_len = MS_SDTR_LEN; | ||
7959 | sdtr_buf.msg_req = EXTENDED_SDTR; | ||
7960 | sdtr_buf.xfer_period = sdtr_period; | ||
7961 | sdtr_offset &= ASC_SYN_MAX_OFFSET; | ||
7962 | sdtr_buf.req_ack_offset = sdtr_offset; | ||
7963 | if ((sdtr_period_index = | ||
7964 | AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= | ||
7965 | asc_dvc->max_sdtr_index) { | ||
7966 | AscMemWordCopyPtrToLram(iop_base, | ||
7967 | ASCV_MSGOUT_BEG, | ||
7968 | (uchar *)&sdtr_buf, | ||
7969 | sizeof(EXT_MSG) >> 1); | ||
7970 | return ((sdtr_period_index << 4) | sdtr_offset); | ||
7971 | } else { | ||
7972 | |||
7973 | sdtr_buf.req_ack_offset = 0; | ||
7974 | AscMemWordCopyPtrToLram(iop_base, | ||
7975 | ASCV_MSGOUT_BEG, | ||
7976 | (uchar *)&sdtr_buf, | ||
7977 | sizeof(EXT_MSG) >> 1); | ||
7978 | return (0); | ||
7979 | } | ||
7980 | } | ||
7981 | |||
7982 | static uchar | ||
7983 | AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) | ||
7984 | { | ||
7985 | uchar byte; | ||
7986 | uchar sdtr_period_ix; | ||
7987 | |||
7988 | sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); | ||
7989 | if ((sdtr_period_ix > asc_dvc->max_sdtr_index) | ||
7990 | ) { | ||
7991 | return (0xFF); | ||
7992 | } | ||
7993 | byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); | ||
7994 | return (byte); | ||
7995 | } | ||
7996 | |||
7997 | static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no) | ||
7998 | { | ||
7999 | AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); | ||
8000 | AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); | ||
8001 | return; | ||
8002 | } | ||
8003 | |||
8004 | static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) | ||
8005 | { | ||
8006 | uchar *period_table; | ||
8007 | int max_index; | ||
8008 | int min_index; | ||
8009 | int i; | ||
8010 | |||
8011 | period_table = asc_dvc->sdtr_period_tbl; | ||
8012 | max_index = (int)asc_dvc->max_sdtr_index; | ||
8013 | min_index = (int)asc_dvc->host_init_sdtr_index; | ||
8014 | if ((syn_time <= period_table[max_index])) { | ||
8015 | for (i = min_index; i < (max_index - 1); i++) { | ||
8016 | if (syn_time <= period_table[i]) { | ||
8017 | return ((uchar)i); | ||
8018 | } | ||
8019 | } | ||
8020 | return ((uchar)max_index); | ||
8021 | } else { | ||
8022 | return ((uchar)(max_index + 1)); | ||
8023 | } | ||
8024 | } | ||
8025 | |||
8026 | static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) | ||
8027 | { | ||
8028 | ushort q_addr; | ||
8029 | uchar next_qp; | ||
8030 | uchar q_status; | ||
8031 | |||
8032 | q_addr = ASC_QNO_TO_QADDR(free_q_head); | ||
8033 | q_status = (uchar)AscReadLramByte(iop_base, | ||
8034 | (ushort)(q_addr + | ||
8035 | ASC_SCSIQ_B_STATUS)); | ||
8036 | next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD)); | ||
8037 | if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { | ||
8038 | return (next_qp); | ||
8039 | } | ||
8040 | return (ASC_QLINK_END); | ||
8041 | } | ||
8042 | |||
8043 | static uchar | ||
8044 | AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) | ||
8045 | { | ||
8046 | uchar i; | ||
8047 | |||
8048 | for (i = 0; i < n_free_q; i++) { | ||
8049 | if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) | ||
8050 | == ASC_QLINK_END) { | ||
8051 | return (ASC_QLINK_END); | ||
8052 | } | ||
8053 | } | ||
8054 | return (free_q_head); | ||
8055 | } | ||
8056 | |||
8057 | static int AscHostReqRiscHalt(PortAddr iop_base) | ||
8058 | { | ||
8059 | int count = 0; | ||
8060 | int sta = 0; | ||
8061 | uchar saved_stop_code; | ||
8062 | |||
8063 | if (AscIsChipHalted(iop_base)) | ||
8064 | return (1); | ||
8065 | saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); | ||
8066 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, | ||
8067 | ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP); | ||
8068 | do { | ||
8069 | if (AscIsChipHalted(iop_base)) { | ||
8070 | sta = 1; | ||
8071 | break; | ||
8072 | } | ||
8073 | mdelay(100); | ||
8074 | } while (count++ < 20); | ||
8075 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); | ||
8076 | return (sta); | ||
8077 | } | ||
8078 | |||
8079 | static int AscStopQueueExe(PortAddr iop_base) | ||
8080 | { | ||
8081 | int count = 0; | ||
8082 | |||
8083 | if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { | ||
8084 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, | ||
8085 | ASC_STOP_REQ_RISC_STOP); | ||
8086 | do { | ||
8087 | if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & | ||
8088 | ASC_STOP_ACK_RISC_STOP) { | ||
8089 | return (1); | ||
8090 | } | ||
8091 | mdelay(100); | ||
8092 | } while (count++ < 20); | ||
8093 | } | ||
8094 | return (0); | ||
8095 | } | ||
8096 | |||
8097 | static int AscStartChip(PortAddr iop_base) | ||
8098 | { | ||
8099 | AscSetChipControl(iop_base, 0); | ||
8100 | if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { | ||
8101 | return (0); | ||
8102 | } | ||
8103 | return (1); | ||
8104 | } | ||
8105 | |||
8106 | static int AscStopChip(PortAddr iop_base) | ||
8107 | { | ||
8108 | uchar cc_val; | ||
8109 | |||
8110 | cc_val = | ||
8111 | AscGetChipControl(iop_base) & | ||
8112 | (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); | ||
8113 | AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT)); | ||
8114 | AscSetChipIH(iop_base, INS_HALT); | ||
8115 | AscSetChipIH(iop_base, INS_RFLAG_WTM); | ||
8116 | if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { | ||
8117 | return (0); | ||
8118 | } | ||
8119 | return (1); | ||
8120 | } | ||
8121 | |||
8122 | static int AscIsChipHalted(PortAddr iop_base) | ||
8123 | { | ||
8124 | if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { | ||
8125 | if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { | ||
8126 | return (1); | ||
8127 | } | ||
8128 | } | ||
8129 | return (0); | ||
8130 | } | ||
8131 | |||
8132 | static void AscSetChipIH(PortAddr iop_base, ushort ins_code) | ||
8133 | { | ||
8134 | AscSetBank(iop_base, 1); | ||
8135 | AscWriteChipIH(iop_base, ins_code); | ||
8136 | AscSetBank(iop_base, 0); | ||
8137 | return; | ||
8138 | } | ||
8139 | |||
8140 | static void AscAckInterrupt(PortAddr iop_base) | ||
8141 | { | ||
8142 | uchar host_flag; | ||
8143 | uchar risc_flag; | ||
8144 | ushort loop; | ||
8145 | |||
8146 | loop = 0; | ||
8147 | do { | ||
8148 | risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); | ||
8149 | if (loop++ > 0x7FFF) { | ||
8150 | break; | ||
8151 | } | ||
8152 | } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); | ||
8153 | host_flag = | ||
8154 | AscReadLramByte(iop_base, | ||
8155 | ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); | ||
8156 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, | ||
8157 | (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT)); | ||
8158 | AscSetChipStatus(iop_base, CIW_INT_ACK); | ||
8159 | loop = 0; | ||
8160 | while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { | ||
8161 | AscSetChipStatus(iop_base, CIW_INT_ACK); | ||
8162 | if (loop++ > 3) { | ||
8163 | break; | ||
8164 | } | ||
8165 | } | ||
8166 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); | ||
8167 | return; | ||
8168 | } | ||
8169 | |||
8170 | static void AscDisableInterrupt(PortAddr iop_base) | ||
8171 | { | ||
8172 | ushort cfg; | ||
8173 | |||
8174 | cfg = AscGetChipCfgLsw(iop_base); | ||
8175 | AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); | ||
8176 | return; | ||
8177 | } | ||
8178 | |||
8179 | static void AscEnableInterrupt(PortAddr iop_base) | ||
8180 | { | ||
8181 | ushort cfg; | ||
8182 | |||
8183 | cfg = AscGetChipCfgLsw(iop_base); | ||
8184 | AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); | ||
8185 | return; | ||
8186 | } | ||
8187 | |||
8188 | static void AscSetBank(PortAddr iop_base, uchar bank) | ||
8189 | { | ||
8190 | uchar val; | ||
8191 | |||
8192 | val = AscGetChipControl(iop_base) & | ||
8193 | (~ | ||
8194 | (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | | ||
8195 | CC_CHIP_RESET)); | ||
8196 | if (bank == 1) { | ||
8197 | val |= CC_BANK_ONE; | ||
8198 | } else if (bank == 2) { | ||
8199 | val |= CC_DIAG | CC_BANK_ONE; | ||
8200 | } else { | ||
8201 | val &= ~CC_BANK_ONE; | ||
8202 | } | ||
8203 | AscSetChipControl(iop_base, val); | ||
8204 | return; | ||
8205 | } | ||
8206 | |||
8207 | static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) | ||
8208 | { | ||
8209 | PortAddr iop_base; | ||
8210 | int i = 10; | ||
8211 | |||
8212 | iop_base = asc_dvc->iop_base; | ||
8213 | while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) | ||
8214 | && (i-- > 0)) { | ||
8215 | mdelay(100); | ||
8216 | } | ||
8217 | AscStopChip(iop_base); | ||
8218 | AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); | ||
8219 | udelay(60); | ||
8220 | AscSetChipIH(iop_base, INS_RFLAG_WTM); | ||
8221 | AscSetChipIH(iop_base, INS_HALT); | ||
8222 | AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); | ||
8223 | AscSetChipControl(iop_base, CC_HALT); | ||
8224 | mdelay(200); | ||
8225 | AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); | ||
8226 | AscSetChipStatus(iop_base, 0); | ||
8227 | return (AscIsChipHalted(iop_base)); | ||
8228 | } | ||
8229 | |||
8230 | static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type) | ||
8231 | { | ||
8232 | if (bus_type & ASC_IS_ISA) | ||
8233 | return ASC_MAX_ISA_DMA_COUNT; | ||
8234 | else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) | ||
8235 | return ASC_MAX_VL_DMA_COUNT; | ||
8236 | return ASC_MAX_PCI_DMA_COUNT; | ||
8237 | } | ||
8238 | |||
8239 | #ifdef CONFIG_ISA | ||
8240 | static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base) | ||
8241 | { | ||
8242 | ushort channel; | ||
8243 | |||
8244 | channel = AscGetChipCfgLsw(iop_base) & 0x0003; | ||
8245 | if (channel == 0x03) | ||
8246 | return (0); | ||
8247 | else if (channel == 0x00) | ||
8248 | return (7); | ||
8249 | return (channel + 4); | ||
8250 | } | ||
8251 | |||
8252 | static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) | ||
8253 | { | ||
8254 | ushort cfg_lsw; | ||
8255 | uchar value; | ||
8256 | |||
8257 | if ((dma_channel >= 5) && (dma_channel <= 7)) { | ||
8258 | if (dma_channel == 7) | ||
8259 | value = 0x00; | ||
8260 | else | ||
8261 | value = dma_channel - 4; | ||
8262 | cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; | ||
8263 | cfg_lsw |= value; | ||
8264 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
8265 | return (AscGetIsaDmaChannel(iop_base)); | ||
8266 | } | ||
8267 | return (0); | ||
8268 | } | ||
8269 | |||
8270 | static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value) | ||
8271 | { | ||
8272 | speed_value &= 0x07; | ||
8273 | AscSetBank(iop_base, 1); | ||
8274 | AscWriteChipDmaSpeed(iop_base, speed_value); | ||
8275 | AscSetBank(iop_base, 0); | ||
8276 | return (AscGetIsaDmaSpeed(iop_base)); | ||
8277 | } | ||
8278 | |||
8279 | static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base) | ||
8280 | { | ||
8281 | uchar speed_value; | ||
8282 | |||
8283 | AscSetBank(iop_base, 1); | ||
8284 | speed_value = AscReadChipDmaSpeed(iop_base); | ||
8285 | speed_value &= 0x07; | ||
8286 | AscSetBank(iop_base, 0); | ||
8287 | return (speed_value); | ||
8288 | } | ||
8289 | #endif /* CONFIG_ISA */ | ||
8290 | |||
8291 | static int __devinit AscInitGetConfig(asc_board_t *boardp) | ||
8292 | { | ||
8293 | ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; | ||
8294 | unsigned short warn_code = 0; | ||
8295 | |||
8296 | asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; | ||
8297 | if (asc_dvc->err_code != 0) | ||
8298 | return asc_dvc->err_code; | ||
8299 | |||
8300 | if (AscFindSignature(asc_dvc->iop_base)) { | ||
8301 | warn_code |= AscInitAscDvcVar(asc_dvc); | ||
8302 | warn_code |= AscInitFromEEP(asc_dvc); | ||
8303 | asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; | ||
8304 | if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) | ||
8305 | asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; | ||
8306 | } else { | ||
8307 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; | ||
8308 | } | ||
8309 | |||
8310 | switch (warn_code) { | ||
8311 | case 0: /* No error */ | ||
8312 | break; | ||
8313 | case ASC_WARN_IO_PORT_ROTATE: | ||
8314 | ASC_PRINT1("AscInitGetConfig: board %d: I/O port address " | ||
8315 | "modified\n", boardp->id); | ||
8316 | break; | ||
8317 | case ASC_WARN_AUTO_CONFIG: | ||
8318 | ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment " | ||
8319 | "switch enabled\n", boardp->id); | ||
8320 | break; | ||
8321 | case ASC_WARN_EEPROM_CHKSUM: | ||
8322 | ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum " | ||
8323 | "error\n", boardp->id); | ||
8324 | break; | ||
8325 | case ASC_WARN_IRQ_MODIFIED: | ||
8326 | ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n", | ||
8327 | boardp->id); | ||
8328 | break; | ||
8329 | case ASC_WARN_CMD_QNG_CONFLICT: | ||
8330 | ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled " | ||
8331 | "w/o disconnects\n", boardp->id); | ||
8332 | break; | ||
8333 | default: | ||
8334 | ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: " | ||
8335 | "0x%x\n", boardp->id, warn_code); | ||
8336 | break; | ||
8337 | } | ||
8338 | |||
8339 | if (asc_dvc->err_code != 0) { | ||
8340 | ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, " | ||
8341 | "err_code 0x%x\n", boardp->id, asc_dvc->init_state, | ||
8342 | asc_dvc->err_code); | ||
8343 | } | ||
8344 | |||
8345 | return asc_dvc->err_code; | ||
8346 | } | ||
8347 | |||
8348 | static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp) | ||
8349 | { | ||
8350 | ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; | ||
8351 | PortAddr iop_base = asc_dvc->iop_base; | ||
8352 | unsigned short cfg_msw; | ||
8353 | unsigned short warn_code = 0; | ||
8354 | |||
8355 | asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; | ||
8356 | if (asc_dvc->err_code != 0) | ||
8357 | return asc_dvc->err_code; | ||
8358 | if (!AscFindSignature(asc_dvc->iop_base)) { | ||
8359 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; | ||
8360 | return asc_dvc->err_code; | ||
8361 | } | ||
8362 | |||
8363 | cfg_msw = AscGetChipCfgMsw(iop_base); | ||
8364 | if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { | ||
8365 | cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; | ||
8366 | warn_code |= ASC_WARN_CFG_MSW_RECOVER; | ||
8367 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
8368 | } | ||
8369 | if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != | ||
8370 | asc_dvc->cfg->cmd_qng_enabled) { | ||
8371 | asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; | ||
8372 | warn_code |= ASC_WARN_CMD_QNG_CONFLICT; | ||
8373 | } | ||
8374 | if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { | ||
8375 | warn_code |= ASC_WARN_AUTO_CONFIG; | ||
8376 | } | ||
8377 | if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { | ||
8378 | if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) | ||
8379 | != asc_dvc->irq_no) { | ||
8380 | asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; | ||
8381 | } | ||
8382 | } | ||
8383 | #ifdef CONFIG_PCI | ||
8384 | if (asc_dvc->bus_type & ASC_IS_PCI) { | ||
8385 | cfg_msw &= 0xFFC0; | ||
8386 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
8387 | if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { | ||
8388 | } else { | ||
8389 | if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) || | ||
8390 | (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) { | ||
8391 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; | ||
8392 | asc_dvc->bug_fix_cntl |= | ||
8393 | ASC_BUG_FIX_ASYN_USE_SYN; | ||
8394 | } | ||
8395 | } | ||
8396 | } else | ||
8397 | #endif /* CONFIG_PCI */ | ||
8398 | if (asc_dvc->bus_type == ASC_IS_ISAPNP) { | ||
8399 | if (AscGetChipVersion(iop_base, asc_dvc->bus_type) | ||
8400 | == ASC_CHIP_VER_ASYN_BUG) { | ||
8401 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; | ||
8402 | } | ||
8403 | } | ||
8404 | if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != | ||
8405 | asc_dvc->cfg->chip_scsi_id) { | ||
8406 | asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; | ||
8407 | } | ||
8408 | #ifdef CONFIG_ISA | ||
8409 | if (asc_dvc->bus_type & ASC_IS_ISA) { | ||
8410 | AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); | ||
8411 | AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); | ||
8412 | } | ||
8413 | #endif /* CONFIG_ISA */ | ||
8414 | |||
8415 | asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; | ||
8416 | |||
8417 | switch (warn_code) { | ||
8418 | case 0: /* No error. */ | ||
8419 | break; | ||
8420 | case ASC_WARN_IO_PORT_ROTATE: | ||
8421 | ASC_PRINT1("AscInitSetConfig: board %d: I/O port address " | ||
8422 | "modified\n", boardp->id); | ||
8423 | break; | ||
8424 | case ASC_WARN_AUTO_CONFIG: | ||
8425 | ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment " | ||
8426 | "switch enabled\n", boardp->id); | ||
8427 | break; | ||
8428 | case ASC_WARN_EEPROM_CHKSUM: | ||
8429 | ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum " | ||
8430 | "error\n", boardp->id); | ||
8431 | break; | ||
8432 | case ASC_WARN_IRQ_MODIFIED: | ||
8433 | ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n", | ||
8434 | boardp->id); | ||
8435 | break; | ||
8436 | case ASC_WARN_CMD_QNG_CONFLICT: | ||
8437 | ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o " | ||
8438 | "disconnects\n", | ||
8439 | boardp->id); | ||
8440 | break; | ||
8441 | default: | ||
8442 | ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: " | ||
8443 | "0x%x\n", boardp->id, warn_code); | ||
8444 | break; | ||
8445 | } | ||
8446 | |||
8447 | if (asc_dvc->err_code != 0) { | ||
8448 | ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, " | ||
8449 | "err_code 0x%x\n", boardp->id, asc_dvc->init_state, | ||
8450 | asc_dvc->err_code); | ||
8451 | } | ||
8452 | |||
8453 | return asc_dvc->err_code; | ||
8454 | } | ||
8455 | |||
8456 | static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) | ||
8457 | { | ||
8458 | ushort warn_code; | ||
8459 | PortAddr iop_base; | ||
8460 | |||
8461 | iop_base = asc_dvc->iop_base; | ||
8462 | warn_code = 0; | ||
8463 | if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && | ||
8464 | !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { | ||
8465 | AscResetChipAndScsiBus(asc_dvc); | ||
8466 | mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ | ||
8467 | } | ||
8468 | asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; | ||
8469 | if (asc_dvc->err_code != 0) | ||
8470 | return (UW_ERR); | ||
8471 | if (!AscFindSignature(asc_dvc->iop_base)) { | ||
8472 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; | ||
8473 | return (warn_code); | ||
8474 | } | ||
8475 | AscDisableInterrupt(iop_base); | ||
8476 | warn_code |= AscInitLram(asc_dvc); | ||
8477 | if (asc_dvc->err_code != 0) | ||
8478 | return (UW_ERR); | ||
8479 | ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", | ||
8480 | (ulong)_asc_mcode_chksum); | ||
8481 | if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, | ||
8482 | _asc_mcode_size) != _asc_mcode_chksum) { | ||
8483 | asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; | ||
8484 | return (warn_code); | ||
8485 | } | ||
8486 | warn_code |= AscInitMicroCodeVar(asc_dvc); | ||
8487 | asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; | ||
8488 | AscEnableInterrupt(iop_base); | ||
8489 | return (warn_code); | ||
8490 | } | ||
8491 | |||
8492 | static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) | ||
8493 | { | ||
8494 | int i; | ||
8495 | PortAddr iop_base; | ||
8496 | ushort warn_code; | ||
8497 | uchar chip_version; | ||
8498 | |||
8499 | iop_base = asc_dvc->iop_base; | ||
8500 | warn_code = 0; | ||
8501 | asc_dvc->err_code = 0; | ||
8502 | if ((asc_dvc->bus_type & | ||
8503 | (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { | ||
8504 | asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; | ||
8505 | } | ||
8506 | AscSetChipControl(iop_base, CC_HALT); | ||
8507 | AscSetChipStatus(iop_base, 0); | ||
8508 | asc_dvc->bug_fix_cntl = 0; | ||
8509 | asc_dvc->pci_fix_asyn_xfer = 0; | ||
8510 | asc_dvc->pci_fix_asyn_xfer_always = 0; | ||
8511 | /* asc_dvc->init_state initalized in AscInitGetConfig(). */ | ||
8512 | asc_dvc->sdtr_done = 0; | ||
8513 | asc_dvc->cur_total_qng = 0; | ||
8514 | asc_dvc->is_in_int = 0; | ||
8515 | asc_dvc->in_critical_cnt = 0; | ||
8516 | asc_dvc->last_q_shortage = 0; | ||
8517 | asc_dvc->use_tagged_qng = 0; | ||
8518 | asc_dvc->no_scam = 0; | ||
8519 | asc_dvc->unit_not_ready = 0; | ||
8520 | asc_dvc->queue_full_or_busy = 0; | ||
8521 | asc_dvc->redo_scam = 0; | ||
8522 | asc_dvc->res2 = 0; | ||
8523 | asc_dvc->host_init_sdtr_index = 0; | ||
8524 | asc_dvc->cfg->can_tagged_qng = 0; | ||
8525 | asc_dvc->cfg->cmd_qng_enabled = 0; | ||
8526 | asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; | ||
8527 | asc_dvc->init_sdtr = 0; | ||
8528 | asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; | ||
8529 | asc_dvc->scsi_reset_wait = 3; | ||
8530 | asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; | ||
8531 | asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); | ||
8532 | asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; | ||
8533 | asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; | ||
8534 | asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; | ||
8535 | asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; | ||
8536 | asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | | ||
8537 | ASC_LIB_VERSION_MINOR; | ||
8538 | chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); | ||
8539 | asc_dvc->cfg->chip_version = chip_version; | ||
8540 | asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; | ||
8541 | asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; | ||
8542 | asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; | ||
8543 | asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; | ||
8544 | asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; | ||
8545 | asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; | ||
8546 | asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; | ||
8547 | asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; | ||
8548 | asc_dvc->max_sdtr_index = 7; | ||
8549 | if ((asc_dvc->bus_type & ASC_IS_PCI) && | ||
8550 | (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { | ||
8551 | asc_dvc->bus_type = ASC_IS_PCI_ULTRA; | ||
8552 | asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; | ||
8553 | asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; | ||
8554 | asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; | ||
8555 | asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; | ||
8556 | asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; | ||
8557 | asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; | ||
8558 | asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; | ||
8559 | asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; | ||
8560 | asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; | ||
8561 | asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; | ||
8562 | asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; | ||
8563 | asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; | ||
8564 | asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; | ||
8565 | asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; | ||
8566 | asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; | ||
8567 | asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; | ||
8568 | asc_dvc->max_sdtr_index = 15; | ||
8569 | if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) { | ||
8570 | AscSetExtraControl(iop_base, | ||
8571 | (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); | ||
8572 | } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { | ||
8573 | AscSetExtraControl(iop_base, | ||
8574 | (SEC_ACTIVE_NEGATE | | ||
8575 | SEC_ENABLE_FILTER)); | ||
8576 | } | ||
8577 | } | ||
8578 | if (asc_dvc->bus_type == ASC_IS_PCI) { | ||
8579 | AscSetExtraControl(iop_base, | ||
8580 | (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); | ||
8581 | } | ||
8582 | |||
8583 | asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; | ||
8584 | #ifdef CONFIG_ISA | ||
8585 | if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { | ||
8586 | if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) { | ||
8587 | AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); | ||
8588 | asc_dvc->bus_type = ASC_IS_ISAPNP; | ||
8589 | } | ||
8590 | asc_dvc->cfg->isa_dma_channel = | ||
8591 | (uchar)AscGetIsaDmaChannel(iop_base); | ||
8592 | } | ||
8593 | #endif /* CONFIG_ISA */ | ||
8594 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
8595 | asc_dvc->cur_dvc_qng[i] = 0; | ||
8596 | asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; | ||
8597 | asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L; | ||
8598 | asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L; | ||
8599 | asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; | ||
8600 | } | ||
8601 | return (warn_code); | ||
8602 | } | ||
8603 | |||
8604 | static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc) | ||
8605 | { | ||
8606 | ASCEEP_CONFIG eep_config_buf; | ||
8607 | ASCEEP_CONFIG *eep_config; | ||
8608 | PortAddr iop_base; | ||
8609 | ushort chksum; | ||
8610 | ushort warn_code; | ||
8611 | ushort cfg_msw, cfg_lsw; | ||
8612 | int i; | ||
8613 | int write_eep = 0; | ||
8614 | |||
8615 | iop_base = asc_dvc->iop_base; | ||
8616 | warn_code = 0; | ||
8617 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); | ||
8618 | AscStopQueueExe(iop_base); | ||
8619 | if ((AscStopChip(iop_base) == FALSE) || | ||
8620 | (AscGetChipScsiCtrl(iop_base) != 0)) { | ||
8621 | asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; | ||
8622 | AscResetChipAndScsiBus(asc_dvc); | ||
8623 | mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ | ||
8624 | } | ||
8625 | if (AscIsChipHalted(iop_base) == FALSE) { | ||
8626 | asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; | ||
8627 | return (warn_code); | ||
8628 | } | ||
8629 | AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); | ||
8630 | if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { | ||
8631 | asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; | ||
8632 | return (warn_code); | ||
8633 | } | ||
8634 | eep_config = (ASCEEP_CONFIG *)&eep_config_buf; | ||
8635 | cfg_msw = AscGetChipCfgMsw(iop_base); | ||
8636 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
8637 | if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { | ||
8638 | cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; | ||
8639 | warn_code |= ASC_WARN_CFG_MSW_RECOVER; | ||
8640 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
8641 | } | ||
8642 | chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); | ||
8643 | ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); | ||
8644 | if (chksum == 0) { | ||
8645 | chksum = 0xaa55; | ||
8646 | } | ||
8647 | if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { | ||
8648 | warn_code |= ASC_WARN_AUTO_CONFIG; | ||
8649 | if (asc_dvc->cfg->chip_version == 3) { | ||
8650 | if (eep_config->cfg_lsw != cfg_lsw) { | ||
8651 | warn_code |= ASC_WARN_EEPROM_RECOVER; | ||
8652 | eep_config->cfg_lsw = | ||
8653 | AscGetChipCfgLsw(iop_base); | ||
8654 | } | ||
8655 | if (eep_config->cfg_msw != cfg_msw) { | ||
8656 | warn_code |= ASC_WARN_EEPROM_RECOVER; | ||
8657 | eep_config->cfg_msw = | ||
8658 | AscGetChipCfgMsw(iop_base); | ||
8659 | } | ||
8660 | } | ||
8661 | } | ||
8662 | eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; | ||
8663 | eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; | ||
8664 | ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", | ||
8665 | eep_config->chksum); | ||
8666 | if (chksum != eep_config->chksum) { | ||
8667 | if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == | ||
8668 | ASC_CHIP_VER_PCI_ULTRA_3050) { | ||
8669 | ASC_DBG(1, | ||
8670 | "AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); | ||
8671 | eep_config->init_sdtr = 0xFF; | ||
8672 | eep_config->disc_enable = 0xFF; | ||
8673 | eep_config->start_motor = 0xFF; | ||
8674 | eep_config->use_cmd_qng = 0; | ||
8675 | eep_config->max_total_qng = 0xF0; | ||
8676 | eep_config->max_tag_qng = 0x20; | ||
8677 | eep_config->cntl = 0xBFFF; | ||
8678 | ASC_EEP_SET_CHIP_ID(eep_config, 7); | ||
8679 | eep_config->no_scam = 0; | ||
8680 | eep_config->adapter_info[0] = 0; | ||
8681 | eep_config->adapter_info[1] = 0; | ||
8682 | eep_config->adapter_info[2] = 0; | ||
8683 | eep_config->adapter_info[3] = 0; | ||
8684 | eep_config->adapter_info[4] = 0; | ||
8685 | /* Indicate EEPROM-less board. */ | ||
8686 | eep_config->adapter_info[5] = 0xBB; | ||
8687 | } else { | ||
8688 | ASC_PRINT | ||
8689 | ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); | ||
8690 | write_eep = 1; | ||
8691 | warn_code |= ASC_WARN_EEPROM_CHKSUM; | ||
8692 | } | ||
8693 | } | ||
8694 | asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; | ||
8695 | asc_dvc->cfg->disc_enable = eep_config->disc_enable; | ||
8696 | asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; | ||
8697 | asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); | ||
8698 | asc_dvc->start_motor = eep_config->start_motor; | ||
8699 | asc_dvc->dvc_cntl = eep_config->cntl; | ||
8700 | asc_dvc->no_scam = eep_config->no_scam; | ||
8701 | asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; | ||
8702 | asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; | ||
8703 | asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; | ||
8704 | asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; | ||
8705 | asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; | ||
8706 | asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; | ||
8707 | if (!AscTestExternalLram(asc_dvc)) { | ||
8708 | if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == | ||
8709 | ASC_IS_PCI_ULTRA)) { | ||
8710 | eep_config->max_total_qng = | ||
8711 | ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; | ||
8712 | eep_config->max_tag_qng = | ||
8713 | ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; | ||
8714 | } else { | ||
8715 | eep_config->cfg_msw |= 0x0800; | ||
8716 | cfg_msw |= 0x0800; | ||
8717 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
8718 | eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; | ||
8719 | eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; | ||
8720 | } | ||
8721 | } else { | ||
8722 | } | ||
8723 | if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { | ||
8724 | eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; | ||
8725 | } | ||
8726 | if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { | ||
8727 | eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; | ||
8728 | } | ||
8729 | if (eep_config->max_tag_qng > eep_config->max_total_qng) { | ||
8730 | eep_config->max_tag_qng = eep_config->max_total_qng; | ||
8731 | } | ||
8732 | if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { | ||
8733 | eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; | ||
8734 | } | ||
8735 | asc_dvc->max_total_qng = eep_config->max_total_qng; | ||
8736 | if ((eep_config->use_cmd_qng & eep_config->disc_enable) != | ||
8737 | eep_config->use_cmd_qng) { | ||
8738 | eep_config->disc_enable = eep_config->use_cmd_qng; | ||
8739 | warn_code |= ASC_WARN_CMD_QNG_CONFLICT; | ||
8740 | } | ||
8741 | if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { | ||
8742 | asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); | ||
8743 | } | ||
8744 | ASC_EEP_SET_CHIP_ID(eep_config, | ||
8745 | ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); | ||
8746 | asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); | ||
8747 | if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && | ||
8748 | !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { | ||
8749 | asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; | ||
8750 | } | ||
8751 | |||
8752 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
8753 | asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; | ||
8754 | asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; | ||
8755 | asc_dvc->cfg->sdtr_period_offset[i] = | ||
8756 | (uchar)(ASC_DEF_SDTR_OFFSET | | ||
8757 | (asc_dvc->host_init_sdtr_index << 4)); | ||
8758 | } | ||
8759 | eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); | ||
8760 | if (write_eep) { | ||
8761 | if ((i = | ||
8762 | AscSetEEPConfig(iop_base, eep_config, | ||
8763 | asc_dvc->bus_type)) != 0) { | ||
8764 | ASC_PRINT1 | ||
8765 | ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", | ||
8766 | i); | ||
8767 | } else { | ||
8768 | ASC_PRINT | ||
8769 | ("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); | ||
8770 | } | ||
8771 | } | ||
8772 | return (warn_code); | ||
8773 | } | ||
8774 | |||
8775 | static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) | ||
8776 | { | ||
8777 | int i; | ||
8778 | ushort warn_code; | ||
8779 | PortAddr iop_base; | ||
8780 | ASC_PADDR phy_addr; | ||
8781 | ASC_DCNT phy_size; | ||
8782 | |||
8783 | iop_base = asc_dvc->iop_base; | ||
8784 | warn_code = 0; | ||
8785 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
8786 | AscPutMCodeInitSDTRAtID(iop_base, i, | ||
8787 | asc_dvc->cfg->sdtr_period_offset[i] | ||
8788 | ); | ||
8789 | } | ||
8790 | |||
8791 | AscInitQLinkVar(asc_dvc); | ||
8792 | AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, | ||
8793 | asc_dvc->cfg->disc_enable); | ||
8794 | AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, | ||
8795 | ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); | ||
8796 | |||
8797 | /* Align overrun buffer on an 8 byte boundary. */ | ||
8798 | phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); | ||
8799 | phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); | ||
8800 | AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, | ||
8801 | (uchar *)&phy_addr, 1); | ||
8802 | phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); | ||
8803 | AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, | ||
8804 | (uchar *)&phy_size, 1); | ||
8805 | |||
8806 | asc_dvc->cfg->mcode_date = | ||
8807 | AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W); | ||
8808 | asc_dvc->cfg->mcode_version = | ||
8809 | AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W); | ||
8810 | |||
8811 | AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); | ||
8812 | if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { | ||
8813 | asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; | ||
8814 | return (warn_code); | ||
8815 | } | ||
8816 | if (AscStartChip(iop_base) != 1) { | ||
8817 | asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; | ||
8818 | return (warn_code); | ||
8819 | } | ||
8820 | |||
8821 | return (warn_code); | ||
8822 | } | ||
8823 | |||
8824 | static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc) | ||
8825 | { | ||
8826 | PortAddr iop_base; | ||
8827 | ushort q_addr; | ||
8828 | ushort saved_word; | ||
8829 | int sta; | ||
8830 | |||
8831 | iop_base = asc_dvc->iop_base; | ||
8832 | sta = 0; | ||
8833 | q_addr = ASC_QNO_TO_QADDR(241); | ||
8834 | saved_word = AscReadLramWord(iop_base, q_addr); | ||
8835 | AscSetChipLramAddr(iop_base, q_addr); | ||
8836 | AscSetChipLramData(iop_base, 0x55AA); | ||
8837 | mdelay(10); | ||
8838 | AscSetChipLramAddr(iop_base, q_addr); | ||
8839 | if (AscGetChipLramData(iop_base) == 0x55AA) { | ||
8840 | sta = 1; | ||
8841 | AscWriteLramWord(iop_base, q_addr, saved_word); | ||
8842 | } | ||
8843 | return (sta); | ||
8844 | } | ||
8845 | |||
8846 | static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) | ||
8847 | { | ||
8848 | uchar read_back; | ||
8849 | int retry; | ||
8850 | |||
8851 | retry = 0; | ||
8852 | while (TRUE) { | ||
8853 | AscSetChipEEPCmd(iop_base, cmd_reg); | ||
8854 | mdelay(1); | ||
8855 | read_back = AscGetChipEEPCmd(iop_base); | ||
8856 | if (read_back == cmd_reg) { | ||
8857 | return (1); | ||
8858 | } | ||
8859 | if (retry++ > ASC_EEP_MAX_RETRY) { | ||
8860 | return (0); | ||
8861 | } | ||
8862 | } | ||
8863 | } | ||
8864 | |||
8865 | static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) | ||
8866 | { | ||
8867 | ushort read_back; | ||
8868 | int retry; | ||
8869 | |||
8870 | retry = 0; | ||
8871 | while (TRUE) { | ||
8872 | AscSetChipEEPData(iop_base, data_reg); | ||
8873 | mdelay(1); | ||
8874 | read_back = AscGetChipEEPData(iop_base); | ||
8875 | if (read_back == data_reg) { | ||
8876 | return (1); | ||
8877 | } | ||
8878 | if (retry++ > ASC_EEP_MAX_RETRY) { | ||
8879 | return (0); | ||
8880 | } | ||
8881 | } | ||
8882 | } | ||
8883 | |||
8884 | static void __devinit AscWaitEEPRead(void) | ||
8885 | { | ||
8886 | mdelay(1); | ||
8887 | return; | ||
8888 | } | ||
8889 | |||
8890 | static void __devinit AscWaitEEPWrite(void) | ||
8891 | { | ||
8892 | mdelay(20); | ||
8893 | return; | ||
8894 | } | ||
8895 | |||
8896 | static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr) | ||
8897 | { | ||
8898 | ushort read_wval; | ||
8899 | uchar cmd_reg; | ||
8900 | |||
8901 | AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); | ||
8902 | AscWaitEEPRead(); | ||
8903 | cmd_reg = addr | ASC_EEP_CMD_READ; | ||
8904 | AscWriteEEPCmdReg(iop_base, cmd_reg); | ||
8905 | AscWaitEEPRead(); | ||
8906 | read_wval = AscGetChipEEPData(iop_base); | ||
8907 | AscWaitEEPRead(); | ||
8908 | return (read_wval); | ||
8909 | } | ||
8910 | |||
8911 | static ushort __devinit | ||
8912 | AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) | ||
8913 | { | ||
8914 | ushort read_wval; | ||
8915 | |||
8916 | read_wval = AscReadEEPWord(iop_base, addr); | ||
8917 | if (read_wval != word_val) { | ||
8918 | AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); | ||
8919 | AscWaitEEPRead(); | ||
8920 | AscWriteEEPDataReg(iop_base, word_val); | ||
8921 | AscWaitEEPRead(); | ||
8922 | AscWriteEEPCmdReg(iop_base, | ||
8923 | (uchar)((uchar)ASC_EEP_CMD_WRITE | addr)); | ||
8924 | AscWaitEEPWrite(); | ||
8925 | AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); | ||
8926 | AscWaitEEPRead(); | ||
8927 | return (AscReadEEPWord(iop_base, addr)); | ||
8928 | } | ||
8929 | return (read_wval); | ||
8930 | } | ||
8931 | |||
8932 | static ushort __devinit | ||
8933 | AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) | ||
8934 | { | ||
8935 | ushort wval; | ||
8936 | ushort sum; | ||
8937 | ushort *wbuf; | ||
8938 | int cfg_beg; | ||
8939 | int cfg_end; | ||
8940 | int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; | ||
8941 | int s_addr; | ||
8942 | |||
8943 | wbuf = (ushort *)cfg_buf; | ||
8944 | sum = 0; | ||
8945 | /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ | ||
8946 | for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { | ||
8947 | *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
8948 | sum += *wbuf; | ||
8949 | } | ||
8950 | if (bus_type & ASC_IS_VL) { | ||
8951 | cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; | ||
8952 | cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; | ||
8953 | } else { | ||
8954 | cfg_beg = ASC_EEP_DVC_CFG_BEG; | ||
8955 | cfg_end = ASC_EEP_MAX_DVC_ADDR; | ||
8956 | } | ||
8957 | for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { | ||
8958 | wval = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
8959 | if (s_addr <= uchar_end_in_config) { | ||
8960 | /* | ||
8961 | * Swap all char fields - must unswap bytes already swapped | ||
8962 | * by AscReadEEPWord(). | ||
8963 | */ | ||
8964 | *wbuf = le16_to_cpu(wval); | ||
8965 | } else { | ||
8966 | /* Don't swap word field at the end - cntl field. */ | ||
8967 | *wbuf = wval; | ||
8968 | } | ||
8969 | sum += wval; /* Checksum treats all EEPROM data as words. */ | ||
8970 | } | ||
8971 | /* | ||
8972 | * Read the checksum word which will be compared against 'sum' | ||
8973 | * by the caller. Word field already swapped. | ||
8974 | */ | ||
8975 | *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
8976 | return (sum); | ||
8977 | } | ||
8978 | |||
8979 | static int __devinit | ||
8980 | AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) | ||
8981 | { | ||
8982 | int n_error; | ||
8983 | ushort *wbuf; | ||
8984 | ushort word; | ||
8985 | ushort sum; | ||
8986 | int s_addr; | ||
8987 | int cfg_beg; | ||
8988 | int cfg_end; | ||
8989 | int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; | ||
8990 | |||
8991 | wbuf = (ushort *)cfg_buf; | ||
8992 | n_error = 0; | ||
8993 | sum = 0; | ||
8994 | /* Write two config words; AscWriteEEPWord() will swap bytes. */ | ||
8995 | for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { | ||
8996 | sum += *wbuf; | ||
8997 | if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { | ||
8998 | n_error++; | ||
8999 | } | ||
9000 | } | ||
9001 | if (bus_type & ASC_IS_VL) { | ||
9002 | cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; | ||
9003 | cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; | ||
9004 | } else { | ||
9005 | cfg_beg = ASC_EEP_DVC_CFG_BEG; | ||
9006 | cfg_end = ASC_EEP_MAX_DVC_ADDR; | ||
9007 | } | ||
9008 | for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { | ||
9009 | if (s_addr <= uchar_end_in_config) { | ||
9010 | /* | ||
9011 | * This is a char field. Swap char fields before they are | ||
9012 | * swapped again by AscWriteEEPWord(). | ||
9013 | */ | ||
9014 | word = cpu_to_le16(*wbuf); | ||
9015 | if (word != | ||
9016 | AscWriteEEPWord(iop_base, (uchar)s_addr, word)) { | ||
9017 | n_error++; | ||
9018 | } | ||
9019 | } else { | ||
9020 | /* Don't swap word field at the end - cntl field. */ | ||
9021 | if (*wbuf != | ||
9022 | AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { | ||
9023 | n_error++; | ||
9024 | } | ||
9025 | } | ||
9026 | sum += *wbuf; /* Checksum calculated from word values. */ | ||
9027 | } | ||
9028 | /* Write checksum word. It will be swapped by AscWriteEEPWord(). */ | ||
9029 | *wbuf = sum; | ||
9030 | if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) { | ||
9031 | n_error++; | ||
9032 | } | ||
9033 | |||
9034 | /* Read EEPROM back again. */ | ||
9035 | wbuf = (ushort *)cfg_buf; | ||
9036 | /* | ||
9037 | * Read two config words; Byte-swapping done by AscReadEEPWord(). | ||
9038 | */ | ||
9039 | for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { | ||
9040 | if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) { | ||
9041 | n_error++; | ||
9042 | } | ||
9043 | } | ||
9044 | if (bus_type & ASC_IS_VL) { | ||
9045 | cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; | ||
9046 | cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; | ||
9047 | } else { | ||
9048 | cfg_beg = ASC_EEP_DVC_CFG_BEG; | ||
9049 | cfg_end = ASC_EEP_MAX_DVC_ADDR; | ||
9050 | } | ||
9051 | for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { | ||
9052 | if (s_addr <= uchar_end_in_config) { | ||
9053 | /* | ||
9054 | * Swap all char fields. Must unswap bytes already swapped | ||
9055 | * by AscReadEEPWord(). | ||
9056 | */ | ||
9057 | word = | ||
9058 | le16_to_cpu(AscReadEEPWord | ||
9059 | (iop_base, (uchar)s_addr)); | ||
9060 | } else { | ||
9061 | /* Don't swap word field at the end - cntl field. */ | ||
9062 | word = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
9063 | } | ||
9064 | if (*wbuf != word) { | ||
9065 | n_error++; | ||
9066 | } | ||
9067 | } | ||
9068 | /* Read checksum; Byte swapping not needed. */ | ||
9069 | if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) { | ||
9070 | n_error++; | ||
9071 | } | ||
9072 | return (n_error); | ||
9073 | } | ||
9074 | |||
9075 | static int __devinit | ||
9076 | AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) | ||
9077 | { | ||
9078 | int retry; | ||
9079 | int n_error; | ||
9080 | |||
9081 | retry = 0; | ||
9082 | while (TRUE) { | ||
9083 | if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, | ||
9084 | bus_type)) == 0) { | ||
9085 | break; | ||
9086 | } | ||
9087 | if (++retry > ASC_EEP_MAX_RETRY) { | ||
9088 | break; | ||
9089 | } | ||
9090 | } | ||
9091 | return (n_error); | ||
9092 | } | ||
9093 | |||
9094 | static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev) | ||
9095 | { | ||
9096 | char type = sdev->type; | ||
9097 | ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id; | ||
9098 | |||
9099 | if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN)) | ||
9100 | return; | ||
9101 | if (asc_dvc->init_sdtr & tid_bits) | ||
9102 | return; | ||
9103 | |||
9104 | if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0)) | ||
9105 | asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; | ||
9106 | |||
9107 | asc_dvc->pci_fix_asyn_xfer |= tid_bits; | ||
9108 | if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) || | ||
9109 | (type == TYPE_ROM) || (type == TYPE_TAPE)) | ||
9110 | asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; | ||
9111 | |||
9112 | if (asc_dvc->pci_fix_asyn_xfer & tid_bits) | ||
9113 | AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id, | ||
9114 | ASYN_SDTR_DATA_FIX_PCI_REV_AB); | ||
9115 | } | ||
9116 | |||
9117 | static uchar AscReadLramByte(PortAddr iop_base, ushort addr) | ||
9118 | { | ||
9119 | uchar byte_data; | ||
9120 | ushort word_data; | ||
9121 | |||
9122 | if (isodd_word(addr)) { | ||
9123 | AscSetChipLramAddr(iop_base, addr - 1); | ||
9124 | word_data = AscGetChipLramData(iop_base); | ||
9125 | byte_data = (uchar)((word_data >> 8) & 0xFF); | ||
9126 | } else { | ||
9127 | AscSetChipLramAddr(iop_base, addr); | ||
9128 | word_data = AscGetChipLramData(iop_base); | ||
9129 | byte_data = (uchar)(word_data & 0xFF); | ||
9130 | } | ||
9131 | return (byte_data); | ||
9132 | } | ||
9133 | |||
9134 | static ushort AscReadLramWord(PortAddr iop_base, ushort addr) | ||
9135 | { | ||
9136 | ushort word_data; | ||
9137 | |||
9138 | AscSetChipLramAddr(iop_base, addr); | ||
9139 | word_data = AscGetChipLramData(iop_base); | ||
9140 | return (word_data); | ||
9141 | } | ||
9142 | |||
9143 | #if CC_VERY_LONG_SG_LIST | ||
9144 | static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) | ||
9145 | { | ||
9146 | ushort val_low, val_high; | ||
9147 | ASC_DCNT dword_data; | ||
9148 | |||
9149 | AscSetChipLramAddr(iop_base, addr); | ||
9150 | val_low = AscGetChipLramData(iop_base); | ||
9151 | val_high = AscGetChipLramData(iop_base); | ||
9152 | dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; | ||
9153 | return (dword_data); | ||
9154 | } | ||
9155 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
9156 | |||
9157 | static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) | ||
9158 | { | ||
9159 | AscSetChipLramAddr(iop_base, addr); | ||
9160 | AscSetChipLramData(iop_base, word_val); | ||
9161 | return; | ||
9162 | } | ||
9163 | |||
9164 | static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) | ||
9165 | { | ||
9166 | ushort word_data; | ||
9167 | |||
9168 | if (isodd_word(addr)) { | ||
9169 | addr--; | ||
9170 | word_data = AscReadLramWord(iop_base, addr); | ||
9171 | word_data &= 0x00FF; | ||
9172 | word_data |= (((ushort)byte_val << 8) & 0xFF00); | ||
9173 | } else { | ||
9174 | word_data = AscReadLramWord(iop_base, addr); | ||
9175 | word_data &= 0xFF00; | ||
9176 | word_data |= ((ushort)byte_val & 0x00FF); | ||
9177 | } | ||
9178 | AscWriteLramWord(iop_base, addr, word_data); | ||
9179 | return; | ||
9180 | } | ||
9181 | |||
9182 | /* | ||
9183 | * Copy 2 bytes to LRAM. | ||
9184 | * | ||
9185 | * The source data is assumed to be in little-endian order in memory | ||
9186 | * and is maintained in little-endian order when written to LRAM. | ||
9187 | */ | ||
9188 | static void | ||
9189 | AscMemWordCopyPtrToLram(PortAddr iop_base, | ||
9190 | ushort s_addr, uchar *s_buffer, int words) | ||
9191 | { | ||
9192 | int i; | ||
9193 | |||
9194 | AscSetChipLramAddr(iop_base, s_addr); | ||
9195 | for (i = 0; i < 2 * words; i += 2) { | ||
9196 | /* | ||
9197 | * On a little-endian system the second argument below | ||
9198 | * produces a little-endian ushort which is written to | ||
9199 | * LRAM in little-endian order. On a big-endian system | ||
9200 | * the second argument produces a big-endian ushort which | ||
9201 | * is "transparently" byte-swapped by outpw() and written | ||
9202 | * in little-endian order to LRAM. | ||
9203 | */ | ||
9204 | outpw(iop_base + IOP_RAM_DATA, | ||
9205 | ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); | ||
9206 | } | ||
9207 | return; | ||
9208 | } | ||
9209 | |||
9210 | /* | ||
9211 | * Copy 4 bytes to LRAM. | ||
9212 | * | ||
9213 | * The source data is assumed to be in little-endian order in memory | ||
9214 | * and is maintained in little-endian order when writen to LRAM. | ||
9215 | */ | ||
9216 | static void | ||
9217 | AscMemDWordCopyPtrToLram(PortAddr iop_base, | ||
9218 | ushort s_addr, uchar *s_buffer, int dwords) | ||
9219 | { | ||
9220 | int i; | ||
9221 | |||
9222 | AscSetChipLramAddr(iop_base, s_addr); | ||
9223 | for (i = 0; i < 4 * dwords; i += 4) { | ||
9224 | outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ | ||
9225 | outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ | ||
9226 | } | ||
9227 | return; | ||
9228 | } | ||
9229 | |||
9230 | /* | ||
9231 | * Copy 2 bytes from LRAM. | ||
9232 | * | ||
9233 | * The source data is assumed to be in little-endian order in LRAM | ||
9234 | * and is maintained in little-endian order when written to memory. | ||
9235 | */ | ||
9236 | static void | ||
9237 | AscMemWordCopyPtrFromLram(PortAddr iop_base, | ||
9238 | ushort s_addr, uchar *d_buffer, int words) | ||
9239 | { | ||
9240 | int i; | ||
9241 | ushort word; | ||
9242 | |||
9243 | AscSetChipLramAddr(iop_base, s_addr); | ||
9244 | for (i = 0; i < 2 * words; i += 2) { | ||
9245 | word = inpw(iop_base + IOP_RAM_DATA); | ||
9246 | d_buffer[i] = word & 0xff; | ||
9247 | d_buffer[i + 1] = (word >> 8) & 0xff; | ||
9248 | } | ||
9249 | return; | ||
9250 | } | ||
9251 | |||
9252 | static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) | ||
9253 | { | ||
9254 | ASC_DCNT sum; | ||
9255 | int i; | ||
9256 | |||
9257 | sum = 0L; | ||
9258 | for (i = 0; i < words; i++, s_addr += 2) { | ||
9259 | sum += AscReadLramWord(iop_base, s_addr); | ||
9260 | } | ||
9261 | return (sum); | ||
9262 | } | ||
9263 | |||
9264 | static void | ||
9265 | AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) | ||
9266 | { | ||
9267 | int i; | ||
9268 | |||
9269 | AscSetChipLramAddr(iop_base, s_addr); | ||
9270 | for (i = 0; i < words; i++) { | ||
9271 | AscSetChipLramData(iop_base, set_wval); | ||
9272 | } | ||
9273 | return; | ||
9274 | } | ||
9275 | |||
9276 | /* Microcode buffer is kept after initialization for error recovery. */ | 5084 | /* Microcode buffer is kept after initialization for error recovery. */ |
9277 | static unsigned char _adv_asc3550_buf[] = { | 5085 | static unsigned char _adv_asc3550_buf[] = { |
9278 | 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc, | 5086 | 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc, |
@@ -10686,451 +6494,213 @@ static unsigned char _adv_asc38C1600_buf[] = { | |||
10686 | static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */ | 6494 | static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */ |
10687 | static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */ | 6495 | static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */ |
10688 | 6496 | ||
10689 | /* | 6497 | static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) |
10690 | * EEPROM Configuration. | 6498 | { |
10691 | * | 6499 | PortAddr iop_base; |
10692 | * All drivers should use this structure to set the default EEPROM | 6500 | int i; |
10693 | * configuration. The BIOS now uses this structure when it is built. | 6501 | ushort lram_addr; |
10694 | * Additional structure information can be found in a_condor.h where | ||
10695 | * the structure is defined. | ||
10696 | * | ||
10697 | * The *_Field_IsChar structs are needed to correct for endianness. | ||
10698 | * These values are read from the board 16 bits at a time directly | ||
10699 | * into the structs. Because some fields are char, the values will be | ||
10700 | * in the wrong order. The *_Field_IsChar tells when to flip the | ||
10701 | * bytes. Data read and written to PCI memory is automatically swapped | ||
10702 | * on big-endian platforms so char fields read as words are actually being | ||
10703 | * unswapped on big-endian platforms. | ||
10704 | */ | ||
10705 | static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = { | ||
10706 | ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ | ||
10707 | 0x0000, /* cfg_msw */ | ||
10708 | 0xFFFF, /* disc_enable */ | ||
10709 | 0xFFFF, /* wdtr_able */ | ||
10710 | 0xFFFF, /* sdtr_able */ | ||
10711 | 0xFFFF, /* start_motor */ | ||
10712 | 0xFFFF, /* tagqng_able */ | ||
10713 | 0xFFFF, /* bios_scan */ | ||
10714 | 0, /* scam_tolerant */ | ||
10715 | 7, /* adapter_scsi_id */ | ||
10716 | 0, /* bios_boot_delay */ | ||
10717 | 3, /* scsi_reset_delay */ | ||
10718 | 0, /* bios_id_lun */ | ||
10719 | 0, /* termination */ | ||
10720 | 0, /* reserved1 */ | ||
10721 | 0xFFE7, /* bios_ctrl */ | ||
10722 | 0xFFFF, /* ultra_able */ | ||
10723 | 0, /* reserved2 */ | ||
10724 | ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ | ||
10725 | ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ | ||
10726 | 0, /* dvc_cntl */ | ||
10727 | 0, /* bug_fix */ | ||
10728 | 0, /* serial_number_word1 */ | ||
10729 | 0, /* serial_number_word2 */ | ||
10730 | 0, /* serial_number_word3 */ | ||
10731 | 0, /* check_sum */ | ||
10732 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
10733 | , /* oem_name[16] */ | ||
10734 | 0, /* dvc_err_code */ | ||
10735 | 0, /* adv_err_code */ | ||
10736 | 0, /* adv_err_addr */ | ||
10737 | 0, /* saved_dvc_err_code */ | ||
10738 | 0, /* saved_adv_err_code */ | ||
10739 | 0, /* saved_adv_err_addr */ | ||
10740 | 0 /* num_of_err */ | ||
10741 | }; | ||
10742 | 6502 | ||
10743 | static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = { | 6503 | iop_base = asc_dvc->iop_base; |
10744 | 0, /* cfg_lsw */ | 6504 | AscPutRiscVarFreeQHead(iop_base, 1); |
10745 | 0, /* cfg_msw */ | 6505 | AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); |
10746 | 0, /* -disc_enable */ | 6506 | AscPutVarFreeQHead(iop_base, 1); |
10747 | 0, /* wdtr_able */ | 6507 | AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); |
10748 | 0, /* sdtr_able */ | 6508 | AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, |
10749 | 0, /* start_motor */ | 6509 | (uchar)((int)asc_dvc->max_total_qng + 1)); |
10750 | 0, /* tagqng_able */ | 6510 | AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, |
10751 | 0, /* bios_scan */ | 6511 | (uchar)((int)asc_dvc->max_total_qng + 2)); |
10752 | 0, /* scam_tolerant */ | 6512 | AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B, |
10753 | 1, /* adapter_scsi_id */ | 6513 | asc_dvc->max_total_qng); |
10754 | 1, /* bios_boot_delay */ | 6514 | AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); |
10755 | 1, /* scsi_reset_delay */ | 6515 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); |
10756 | 1, /* bios_id_lun */ | 6516 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); |
10757 | 1, /* termination */ | 6517 | AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); |
10758 | 1, /* reserved1 */ | 6518 | AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); |
10759 | 0, /* bios_ctrl */ | 6519 | AscPutQDoneInProgress(iop_base, 0); |
10760 | 0, /* ultra_able */ | 6520 | lram_addr = ASC_QADR_BEG; |
10761 | 0, /* reserved2 */ | 6521 | for (i = 0; i < 32; i++, lram_addr += 2) { |
10762 | 1, /* max_host_qng */ | 6522 | AscWriteLramWord(iop_base, lram_addr, 0); |
10763 | 1, /* max_dvc_qng */ | 6523 | } |
10764 | 0, /* dvc_cntl */ | 6524 | } |
10765 | 0, /* bug_fix */ | ||
10766 | 0, /* serial_number_word1 */ | ||
10767 | 0, /* serial_number_word2 */ | ||
10768 | 0, /* serial_number_word3 */ | ||
10769 | 0, /* check_sum */ | ||
10770 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
10771 | , /* oem_name[16] */ | ||
10772 | 0, /* dvc_err_code */ | ||
10773 | 0, /* adv_err_code */ | ||
10774 | 0, /* adv_err_addr */ | ||
10775 | 0, /* saved_dvc_err_code */ | ||
10776 | 0, /* saved_adv_err_code */ | ||
10777 | 0, /* saved_adv_err_addr */ | ||
10778 | 0 /* num_of_err */ | ||
10779 | }; | ||
10780 | 6525 | ||
10781 | static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = { | 6526 | static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) |
10782 | ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ | 6527 | { |
10783 | 0x0000, /* 01 cfg_msw */ | 6528 | int i; |
10784 | 0xFFFF, /* 02 disc_enable */ | 6529 | ushort warn_code; |
10785 | 0xFFFF, /* 03 wdtr_able */ | 6530 | PortAddr iop_base; |
10786 | 0x4444, /* 04 sdtr_speed1 */ | 6531 | ASC_PADDR phy_addr; |
10787 | 0xFFFF, /* 05 start_motor */ | 6532 | ASC_DCNT phy_size; |
10788 | 0xFFFF, /* 06 tagqng_able */ | ||
10789 | 0xFFFF, /* 07 bios_scan */ | ||
10790 | 0, /* 08 scam_tolerant */ | ||
10791 | 7, /* 09 adapter_scsi_id */ | ||
10792 | 0, /* bios_boot_delay */ | ||
10793 | 3, /* 10 scsi_reset_delay */ | ||
10794 | 0, /* bios_id_lun */ | ||
10795 | 0, /* 11 termination_se */ | ||
10796 | 0, /* termination_lvd */ | ||
10797 | 0xFFE7, /* 12 bios_ctrl */ | ||
10798 | 0x4444, /* 13 sdtr_speed2 */ | ||
10799 | 0x4444, /* 14 sdtr_speed3 */ | ||
10800 | ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ | ||
10801 | ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ | ||
10802 | 0, /* 16 dvc_cntl */ | ||
10803 | 0x4444, /* 17 sdtr_speed4 */ | ||
10804 | 0, /* 18 serial_number_word1 */ | ||
10805 | 0, /* 19 serial_number_word2 */ | ||
10806 | 0, /* 20 serial_number_word3 */ | ||
10807 | 0, /* 21 check_sum */ | ||
10808 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
10809 | , /* 22-29 oem_name[16] */ | ||
10810 | 0, /* 30 dvc_err_code */ | ||
10811 | 0, /* 31 adv_err_code */ | ||
10812 | 0, /* 32 adv_err_addr */ | ||
10813 | 0, /* 33 saved_dvc_err_code */ | ||
10814 | 0, /* 34 saved_adv_err_code */ | ||
10815 | 0, /* 35 saved_adv_err_addr */ | ||
10816 | 0, /* 36 reserved */ | ||
10817 | 0, /* 37 reserved */ | ||
10818 | 0, /* 38 reserved */ | ||
10819 | 0, /* 39 reserved */ | ||
10820 | 0, /* 40 reserved */ | ||
10821 | 0, /* 41 reserved */ | ||
10822 | 0, /* 42 reserved */ | ||
10823 | 0, /* 43 reserved */ | ||
10824 | 0, /* 44 reserved */ | ||
10825 | 0, /* 45 reserved */ | ||
10826 | 0, /* 46 reserved */ | ||
10827 | 0, /* 47 reserved */ | ||
10828 | 0, /* 48 reserved */ | ||
10829 | 0, /* 49 reserved */ | ||
10830 | 0, /* 50 reserved */ | ||
10831 | 0, /* 51 reserved */ | ||
10832 | 0, /* 52 reserved */ | ||
10833 | 0, /* 53 reserved */ | ||
10834 | 0, /* 54 reserved */ | ||
10835 | 0, /* 55 reserved */ | ||
10836 | 0, /* 56 cisptr_lsw */ | ||
10837 | 0, /* 57 cisprt_msw */ | ||
10838 | PCI_VENDOR_ID_ASP, /* 58 subsysvid */ | ||
10839 | PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ | ||
10840 | 0, /* 60 reserved */ | ||
10841 | 0, /* 61 reserved */ | ||
10842 | 0, /* 62 reserved */ | ||
10843 | 0 /* 63 reserved */ | ||
10844 | }; | ||
10845 | 6533 | ||
10846 | static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = { | 6534 | iop_base = asc_dvc->iop_base; |
10847 | 0, /* 00 cfg_lsw */ | 6535 | warn_code = 0; |
10848 | 0, /* 01 cfg_msw */ | 6536 | for (i = 0; i <= ASC_MAX_TID; i++) { |
10849 | 0, /* 02 disc_enable */ | 6537 | AscPutMCodeInitSDTRAtID(iop_base, i, |
10850 | 0, /* 03 wdtr_able */ | 6538 | asc_dvc->cfg->sdtr_period_offset[i]); |
10851 | 0, /* 04 sdtr_speed1 */ | 6539 | } |
10852 | 0, /* 05 start_motor */ | ||
10853 | 0, /* 06 tagqng_able */ | ||
10854 | 0, /* 07 bios_scan */ | ||
10855 | 0, /* 08 scam_tolerant */ | ||
10856 | 1, /* 09 adapter_scsi_id */ | ||
10857 | 1, /* bios_boot_delay */ | ||
10858 | 1, /* 10 scsi_reset_delay */ | ||
10859 | 1, /* bios_id_lun */ | ||
10860 | 1, /* 11 termination_se */ | ||
10861 | 1, /* termination_lvd */ | ||
10862 | 0, /* 12 bios_ctrl */ | ||
10863 | 0, /* 13 sdtr_speed2 */ | ||
10864 | 0, /* 14 sdtr_speed3 */ | ||
10865 | 1, /* 15 max_host_qng */ | ||
10866 | 1, /* max_dvc_qng */ | ||
10867 | 0, /* 16 dvc_cntl */ | ||
10868 | 0, /* 17 sdtr_speed4 */ | ||
10869 | 0, /* 18 serial_number_word1 */ | ||
10870 | 0, /* 19 serial_number_word2 */ | ||
10871 | 0, /* 20 serial_number_word3 */ | ||
10872 | 0, /* 21 check_sum */ | ||
10873 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
10874 | , /* 22-29 oem_name[16] */ | ||
10875 | 0, /* 30 dvc_err_code */ | ||
10876 | 0, /* 31 adv_err_code */ | ||
10877 | 0, /* 32 adv_err_addr */ | ||
10878 | 0, /* 33 saved_dvc_err_code */ | ||
10879 | 0, /* 34 saved_adv_err_code */ | ||
10880 | 0, /* 35 saved_adv_err_addr */ | ||
10881 | 0, /* 36 reserved */ | ||
10882 | 0, /* 37 reserved */ | ||
10883 | 0, /* 38 reserved */ | ||
10884 | 0, /* 39 reserved */ | ||
10885 | 0, /* 40 reserved */ | ||
10886 | 0, /* 41 reserved */ | ||
10887 | 0, /* 42 reserved */ | ||
10888 | 0, /* 43 reserved */ | ||
10889 | 0, /* 44 reserved */ | ||
10890 | 0, /* 45 reserved */ | ||
10891 | 0, /* 46 reserved */ | ||
10892 | 0, /* 47 reserved */ | ||
10893 | 0, /* 48 reserved */ | ||
10894 | 0, /* 49 reserved */ | ||
10895 | 0, /* 50 reserved */ | ||
10896 | 0, /* 51 reserved */ | ||
10897 | 0, /* 52 reserved */ | ||
10898 | 0, /* 53 reserved */ | ||
10899 | 0, /* 54 reserved */ | ||
10900 | 0, /* 55 reserved */ | ||
10901 | 0, /* 56 cisptr_lsw */ | ||
10902 | 0, /* 57 cisprt_msw */ | ||
10903 | 0, /* 58 subsysvid */ | ||
10904 | 0, /* 59 subsysid */ | ||
10905 | 0, /* 60 reserved */ | ||
10906 | 0, /* 61 reserved */ | ||
10907 | 0, /* 62 reserved */ | ||
10908 | 0 /* 63 reserved */ | ||
10909 | }; | ||
10910 | 6540 | ||
10911 | static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = { | 6541 | AscInitQLinkVar(asc_dvc); |
10912 | ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ | 6542 | AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, |
10913 | 0x0000, /* 01 cfg_msw */ | 6543 | asc_dvc->cfg->disc_enable); |
10914 | 0xFFFF, /* 02 disc_enable */ | 6544 | AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, |
10915 | 0xFFFF, /* 03 wdtr_able */ | 6545 | ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); |
10916 | 0x5555, /* 04 sdtr_speed1 */ | ||
10917 | 0xFFFF, /* 05 start_motor */ | ||
10918 | 0xFFFF, /* 06 tagqng_able */ | ||
10919 | 0xFFFF, /* 07 bios_scan */ | ||
10920 | 0, /* 08 scam_tolerant */ | ||
10921 | 7, /* 09 adapter_scsi_id */ | ||
10922 | 0, /* bios_boot_delay */ | ||
10923 | 3, /* 10 scsi_reset_delay */ | ||
10924 | 0, /* bios_id_lun */ | ||
10925 | 0, /* 11 termination_se */ | ||
10926 | 0, /* termination_lvd */ | ||
10927 | 0xFFE7, /* 12 bios_ctrl */ | ||
10928 | 0x5555, /* 13 sdtr_speed2 */ | ||
10929 | 0x5555, /* 14 sdtr_speed3 */ | ||
10930 | ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ | ||
10931 | ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ | ||
10932 | 0, /* 16 dvc_cntl */ | ||
10933 | 0x5555, /* 17 sdtr_speed4 */ | ||
10934 | 0, /* 18 serial_number_word1 */ | ||
10935 | 0, /* 19 serial_number_word2 */ | ||
10936 | 0, /* 20 serial_number_word3 */ | ||
10937 | 0, /* 21 check_sum */ | ||
10938 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
10939 | , /* 22-29 oem_name[16] */ | ||
10940 | 0, /* 30 dvc_err_code */ | ||
10941 | 0, /* 31 adv_err_code */ | ||
10942 | 0, /* 32 adv_err_addr */ | ||
10943 | 0, /* 33 saved_dvc_err_code */ | ||
10944 | 0, /* 34 saved_adv_err_code */ | ||
10945 | 0, /* 35 saved_adv_err_addr */ | ||
10946 | 0, /* 36 reserved */ | ||
10947 | 0, /* 37 reserved */ | ||
10948 | 0, /* 38 reserved */ | ||
10949 | 0, /* 39 reserved */ | ||
10950 | 0, /* 40 reserved */ | ||
10951 | 0, /* 41 reserved */ | ||
10952 | 0, /* 42 reserved */ | ||
10953 | 0, /* 43 reserved */ | ||
10954 | 0, /* 44 reserved */ | ||
10955 | 0, /* 45 reserved */ | ||
10956 | 0, /* 46 reserved */ | ||
10957 | 0, /* 47 reserved */ | ||
10958 | 0, /* 48 reserved */ | ||
10959 | 0, /* 49 reserved */ | ||
10960 | 0, /* 50 reserved */ | ||
10961 | 0, /* 51 reserved */ | ||
10962 | 0, /* 52 reserved */ | ||
10963 | 0, /* 53 reserved */ | ||
10964 | 0, /* 54 reserved */ | ||
10965 | 0, /* 55 reserved */ | ||
10966 | 0, /* 56 cisptr_lsw */ | ||
10967 | 0, /* 57 cisprt_msw */ | ||
10968 | PCI_VENDOR_ID_ASP, /* 58 subsysvid */ | ||
10969 | PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ | ||
10970 | 0, /* 60 reserved */ | ||
10971 | 0, /* 61 reserved */ | ||
10972 | 0, /* 62 reserved */ | ||
10973 | 0 /* 63 reserved */ | ||
10974 | }; | ||
10975 | 6546 | ||
10976 | static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = { | 6547 | /* Align overrun buffer on an 8 byte boundary. */ |
10977 | 0, /* 00 cfg_lsw */ | 6548 | phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); |
10978 | 0, /* 01 cfg_msw */ | 6549 | phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); |
10979 | 0, /* 02 disc_enable */ | 6550 | AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, |
10980 | 0, /* 03 wdtr_able */ | 6551 | (uchar *)&phy_addr, 1); |
10981 | 0, /* 04 sdtr_speed1 */ | 6552 | phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); |
10982 | 0, /* 05 start_motor */ | 6553 | AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, |
10983 | 0, /* 06 tagqng_able */ | 6554 | (uchar *)&phy_size, 1); |
10984 | 0, /* 07 bios_scan */ | 6555 | |
10985 | 0, /* 08 scam_tolerant */ | 6556 | asc_dvc->cfg->mcode_date = |
10986 | 1, /* 09 adapter_scsi_id */ | 6557 | AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W); |
10987 | 1, /* bios_boot_delay */ | 6558 | asc_dvc->cfg->mcode_version = |
10988 | 1, /* 10 scsi_reset_delay */ | 6559 | AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W); |
10989 | 1, /* bios_id_lun */ | 6560 | |
10990 | 1, /* 11 termination_se */ | 6561 | AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); |
10991 | 1, /* termination_lvd */ | 6562 | if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { |
10992 | 0, /* 12 bios_ctrl */ | 6563 | asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; |
10993 | 0, /* 13 sdtr_speed2 */ | 6564 | return warn_code; |
10994 | 0, /* 14 sdtr_speed3 */ | 6565 | } |
10995 | 1, /* 15 max_host_qng */ | 6566 | if (AscStartChip(iop_base) != 1) { |
10996 | 1, /* max_dvc_qng */ | 6567 | asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; |
10997 | 0, /* 16 dvc_cntl */ | 6568 | return warn_code; |
10998 | 0, /* 17 sdtr_speed4 */ | 6569 | } |
10999 | 0, /* 18 serial_number_word1 */ | 6570 | |
11000 | 0, /* 19 serial_number_word2 */ | 6571 | return warn_code; |
11001 | 0, /* 20 serial_number_word3 */ | 6572 | } |
11002 | 0, /* 21 check_sum */ | 6573 | |
11003 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | 6574 | static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) |
11004 | , /* 22-29 oem_name[16] */ | 6575 | { |
11005 | 0, /* 30 dvc_err_code */ | 6576 | ushort warn_code; |
11006 | 0, /* 31 adv_err_code */ | 6577 | PortAddr iop_base; |
11007 | 0, /* 32 adv_err_addr */ | 6578 | |
11008 | 0, /* 33 saved_dvc_err_code */ | 6579 | iop_base = asc_dvc->iop_base; |
11009 | 0, /* 34 saved_adv_err_code */ | 6580 | warn_code = 0; |
11010 | 0, /* 35 saved_adv_err_addr */ | 6581 | if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && |
11011 | 0, /* 36 reserved */ | 6582 | !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { |
11012 | 0, /* 37 reserved */ | 6583 | AscResetChipAndScsiBus(asc_dvc); |
11013 | 0, /* 38 reserved */ | 6584 | mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ |
11014 | 0, /* 39 reserved */ | 6585 | } |
11015 | 0, /* 40 reserved */ | 6586 | asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; |
11016 | 0, /* 41 reserved */ | 6587 | if (asc_dvc->err_code != 0) |
11017 | 0, /* 42 reserved */ | 6588 | return UW_ERR; |
11018 | 0, /* 43 reserved */ | 6589 | if (!AscFindSignature(asc_dvc->iop_base)) { |
11019 | 0, /* 44 reserved */ | 6590 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; |
11020 | 0, /* 45 reserved */ | 6591 | return warn_code; |
11021 | 0, /* 46 reserved */ | 6592 | } |
11022 | 0, /* 47 reserved */ | 6593 | AscDisableInterrupt(iop_base); |
11023 | 0, /* 48 reserved */ | 6594 | warn_code |= AscInitLram(asc_dvc); |
11024 | 0, /* 49 reserved */ | 6595 | if (asc_dvc->err_code != 0) |
11025 | 0, /* 50 reserved */ | 6596 | return UW_ERR; |
11026 | 0, /* 51 reserved */ | 6597 | ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", |
11027 | 0, /* 52 reserved */ | 6598 | (ulong)_asc_mcode_chksum); |
11028 | 0, /* 53 reserved */ | 6599 | if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, |
11029 | 0, /* 54 reserved */ | 6600 | _asc_mcode_size) != _asc_mcode_chksum) { |
11030 | 0, /* 55 reserved */ | 6601 | asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; |
11031 | 0, /* 56 cisptr_lsw */ | 6602 | return warn_code; |
11032 | 0, /* 57 cisprt_msw */ | 6603 | } |
11033 | 0, /* 58 subsysvid */ | 6604 | warn_code |= AscInitMicroCodeVar(asc_dvc); |
11034 | 0, /* 59 subsysid */ | 6605 | asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; |
11035 | 0, /* 60 reserved */ | 6606 | AscEnableInterrupt(iop_base); |
11036 | 0, /* 61 reserved */ | 6607 | return warn_code; |
11037 | 0, /* 62 reserved */ | 6608 | } |
11038 | 0 /* 63 reserved */ | ||
11039 | }; | ||
11040 | 6609 | ||
11041 | #ifdef CONFIG_PCI | ||
11042 | /* | 6610 | /* |
11043 | * Initialize the ADV_DVC_VAR structure. | 6611 | * Load the Microcode |
11044 | * | 6612 | * |
11045 | * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. | 6613 | * Write the microcode image to RISC memory starting at address 0. |
11046 | * | 6614 | * |
11047 | * For a non-fatal error return a warning code. If there are no warnings | 6615 | * The microcode is stored compressed in the following format: |
11048 | * then 0 is returned. | 6616 | * |
6617 | * 254 word (508 byte) table indexed by byte code followed | ||
6618 | * by the following byte codes: | ||
6619 | * | ||
6620 | * 1-Byte Code: | ||
6621 | * 00: Emit word 0 in table. | ||
6622 | * 01: Emit word 1 in table. | ||
6623 | * . | ||
6624 | * FD: Emit word 253 in table. | ||
6625 | * | ||
6626 | * Multi-Byte Code: | ||
6627 | * FE WW WW: (3 byte code) Word to emit is the next word WW WW. | ||
6628 | * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. | ||
6629 | * | ||
6630 | * Returns 0 or an error if the checksum doesn't match | ||
11049 | */ | 6631 | */ |
11050 | static int __devinit | 6632 | static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size, |
11051 | AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp) | 6633 | int memsize, int chksum) |
11052 | { | 6634 | { |
11053 | ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var; | 6635 | int i, j, end, len = 0; |
11054 | unsigned short warn_code = 0; | 6636 | ADV_DCNT sum; |
11055 | AdvPortAddr iop_base = asc_dvc->iop_base; | ||
11056 | u16 cmd; | ||
11057 | int status; | ||
11058 | 6637 | ||
11059 | asc_dvc->err_code = 0; | 6638 | AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); |
11060 | 6639 | ||
11061 | /* | 6640 | for (i = 253 * 2; i < size; i++) { |
11062 | * Save the state of the PCI Configuration Command Register | 6641 | if (buf[i] == 0xff) { |
11063 | * "Parity Error Response Control" Bit. If the bit is clear (0), | 6642 | unsigned short word = (buf[i + 3] << 8) | buf[i + 2]; |
11064 | * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore | 6643 | for (j = 0; j < buf[i + 1]; j++) { |
11065 | * DMA parity errors. | 6644 | AdvWriteWordAutoIncLram(iop_base, word); |
11066 | */ | 6645 | len += 2; |
11067 | asc_dvc->cfg->control_flag = 0; | 6646 | } |
11068 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); | 6647 | i += 3; |
11069 | if ((cmd & PCI_COMMAND_PARITY) == 0) | 6648 | } else if (buf[i] == 0xfe) { |
11070 | asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; | 6649 | unsigned short word = (buf[i + 2] << 8) | buf[i + 1]; |
6650 | AdvWriteWordAutoIncLram(iop_base, word); | ||
6651 | i += 2; | ||
6652 | len += 2; | ||
6653 | } else { | ||
6654 | unsigned char off = buf[i] * 2; | ||
6655 | unsigned short word = (buf[off + 1] << 8) | buf[off]; | ||
6656 | AdvWriteWordAutoIncLram(iop_base, word); | ||
6657 | len += 2; | ||
6658 | } | ||
6659 | } | ||
11071 | 6660 | ||
11072 | asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | | 6661 | end = len; |
11073 | ADV_LIB_VERSION_MINOR; | ||
11074 | asc_dvc->cfg->chip_version = | ||
11075 | AdvGetChipVersion(iop_base, asc_dvc->bus_type); | ||
11076 | 6662 | ||
11077 | ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", | 6663 | while (len < memsize) { |
11078 | (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), | 6664 | AdvWriteWordAutoIncLram(iop_base, 0); |
11079 | (ushort)ADV_CHIP_ID_BYTE); | 6665 | len += 2; |
6666 | } | ||
11080 | 6667 | ||
11081 | ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", | 6668 | /* Verify the microcode checksum. */ |
11082 | (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), | 6669 | sum = 0; |
11083 | (ushort)ADV_CHIP_ID_WORD); | 6670 | AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); |
11084 | 6671 | ||
11085 | /* | 6672 | for (len = 0; len < end; len += 2) { |
11086 | * Reset the chip to start and allow register writes. | 6673 | sum += AdvReadWordAutoIncLram(iop_base); |
11087 | */ | 6674 | } |
11088 | if (AdvFindSignature(iop_base) == 0) { | ||
11089 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; | ||
11090 | return ADV_ERROR; | ||
11091 | } else { | ||
11092 | /* | ||
11093 | * The caller must set 'chip_type' to a valid setting. | ||
11094 | */ | ||
11095 | if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && | ||
11096 | asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && | ||
11097 | asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { | ||
11098 | asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; | ||
11099 | return ADV_ERROR; | ||
11100 | } | ||
11101 | 6675 | ||
11102 | /* | 6676 | if (sum != chksum) |
11103 | * Reset Chip. | 6677 | return ASC_IERR_MCODE_CHKSUM; |
11104 | */ | ||
11105 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, | ||
11106 | ADV_CTRL_REG_CMD_RESET); | ||
11107 | mdelay(100); | ||
11108 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, | ||
11109 | ADV_CTRL_REG_CMD_WR_IO_REG); | ||
11110 | 6678 | ||
11111 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | 6679 | return 0; |
11112 | status = AdvInitFrom38C1600EEP(asc_dvc); | 6680 | } |
11113 | } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
11114 | status = AdvInitFrom38C0800EEP(asc_dvc); | ||
11115 | } else { | ||
11116 | status = AdvInitFrom3550EEP(asc_dvc); | ||
11117 | } | ||
11118 | warn_code |= status; | ||
11119 | } | ||
11120 | 6681 | ||
11121 | if (warn_code != 0) { | 6682 | /* |
11122 | ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n", | 6683 | * DvcGetPhyAddr() |
11123 | boardp->id, warn_code); | 6684 | * |
11124 | } | 6685 | * Return the physical address of 'vaddr' and set '*lenp' to the |
6686 | * number of physically contiguous bytes that follow 'vaddr'. | ||
6687 | * 'flag' indicates the type of structure whose physical address | ||
6688 | * is being translated. | ||
6689 | * | ||
6690 | * Note: Because Linux currently doesn't page the kernel and all | ||
6691 | * kernel buffers are physically contiguous, leave '*lenp' unchanged. | ||
6692 | */ | ||
6693 | ADV_PADDR | ||
6694 | DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, | ||
6695 | uchar *vaddr, ADV_SDCNT *lenp, int flag) | ||
6696 | { | ||
6697 | ADV_PADDR paddr = virt_to_bus(vaddr); | ||
11125 | 6698 | ||
11126 | if (asc_dvc->err_code) { | 6699 | ASC_DBG4(4, "DvcGetPhyAddr: vaddr 0x%p, lenp 0x%p *lenp %lu, paddr 0x%lx\n", |
11127 | ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n", | 6700 | vaddr, lenp, (ulong)*((ulong *)lenp), (ulong)paddr); |
11128 | boardp->id, asc_dvc->err_code); | ||
11129 | } | ||
11130 | 6701 | ||
11131 | return asc_dvc->err_code; | 6702 | return paddr; |
11132 | } | 6703 | } |
11133 | #endif | ||
11134 | 6704 | ||
11135 | static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc) | 6705 | static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc) |
11136 | { | 6706 | { |
@@ -11183,75 +6753,117 @@ static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc) | |||
11183 | } | 6753 | } |
11184 | 6754 | ||
11185 | /* | 6755 | /* |
11186 | * Load the Microcode | 6756 | * Send an idle command to the chip and wait for completion. |
11187 | * | ||
11188 | * Write the microcode image to RISC memory starting at address 0. | ||
11189 | * | ||
11190 | * The microcode is stored compressed in the following format: | ||
11191 | * | ||
11192 | * 254 word (508 byte) table indexed by byte code followed | ||
11193 | * by the following byte codes: | ||
11194 | * | 6757 | * |
11195 | * 1-Byte Code: | 6758 | * Command completion is polled for once per microsecond. |
11196 | * 00: Emit word 0 in table. | ||
11197 | * 01: Emit word 1 in table. | ||
11198 | * . | ||
11199 | * FD: Emit word 253 in table. | ||
11200 | * | 6759 | * |
11201 | * Multi-Byte Code: | 6760 | * The function can be called from anywhere including an interrupt handler. |
11202 | * FE WW WW: (3 byte code) Word to emit is the next word WW WW. | 6761 | * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical() |
11203 | * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. | 6762 | * functions to prevent reentrancy. |
11204 | * | 6763 | * |
11205 | * Returns 0 or an error if the checksum doesn't match | 6764 | * Return Values: |
6765 | * ADV_TRUE - command completed successfully | ||
6766 | * ADV_FALSE - command failed | ||
6767 | * ADV_ERROR - command timed out | ||
11206 | */ | 6768 | */ |
11207 | static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size, | 6769 | static int |
11208 | int memsize, int chksum) | 6770 | AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, |
6771 | ushort idle_cmd, ADV_DCNT idle_cmd_parameter) | ||
11209 | { | 6772 | { |
11210 | int i, j, end, len = 0; | 6773 | int result; |
11211 | ADV_DCNT sum; | 6774 | ADV_DCNT i, j; |
6775 | AdvPortAddr iop_base; | ||
11212 | 6776 | ||
11213 | AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); | 6777 | iop_base = asc_dvc->iop_base; |
11214 | 6778 | ||
11215 | for (i = 253 * 2; i < size; i++) { | 6779 | /* |
11216 | if (buf[i] == 0xff) { | 6780 | * Clear the idle command status which is set by the microcode |
11217 | unsigned short word = (buf[i + 3] << 8) | buf[i + 2]; | 6781 | * to a non-zero value to indicate when the command is completed. |
11218 | for (j = 0; j < buf[i + 1]; j++) { | 6782 | * The non-zero result is one of the IDLE_CMD_STATUS_* values |
11219 | AdvWriteWordAutoIncLram(iop_base, word); | 6783 | */ |
11220 | len += 2; | 6784 | AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); |
11221 | } | 6785 | |
11222 | i += 3; | 6786 | /* |
11223 | } else if (buf[i] == 0xfe) { | 6787 | * Write the idle command value after the idle command parameter |
11224 | unsigned short word = (buf[i + 2] << 8) | buf[i + 1]; | 6788 | * has been written to avoid a race condition. If the order is not |
11225 | AdvWriteWordAutoIncLram(iop_base, word); | 6789 | * followed, the microcode may process the idle command before the |
11226 | i += 2; | 6790 | * parameters have been written to LRAM. |
11227 | len += 2; | 6791 | */ |
11228 | } else { | 6792 | AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, |
11229 | unsigned char off = buf[i] * 2; | 6793 | cpu_to_le32(idle_cmd_parameter)); |
11230 | unsigned short word = (buf[off + 1] << 8) | buf[off]; | 6794 | AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); |
11231 | AdvWriteWordAutoIncLram(iop_base, word); | 6795 | |
11232 | len += 2; | 6796 | /* |
6797 | * Tickle the RISC to tell it to process the idle command. | ||
6798 | */ | ||
6799 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); | ||
6800 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { | ||
6801 | /* | ||
6802 | * Clear the tickle value. In the ASC-3550 the RISC flag | ||
6803 | * command 'clr_tickle_b' does not work unless the host | ||
6804 | * value is cleared. | ||
6805 | */ | ||
6806 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); | ||
6807 | } | ||
6808 | |||
6809 | /* Wait for up to 100 millisecond for the idle command to timeout. */ | ||
6810 | for (i = 0; i < SCSI_WAIT_100_MSEC; i++) { | ||
6811 | /* Poll once each microsecond for command completion. */ | ||
6812 | for (j = 0; j < SCSI_US_PER_MSEC; j++) { | ||
6813 | AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, | ||
6814 | result); | ||
6815 | if (result != 0) | ||
6816 | return result; | ||
6817 | udelay(1); | ||
11233 | } | 6818 | } |
11234 | } | 6819 | } |
11235 | 6820 | ||
11236 | end = len; | 6821 | BUG(); /* The idle command should never timeout. */ |
6822 | return ADV_ERROR; | ||
6823 | } | ||
11237 | 6824 | ||
11238 | while (len < memsize) { | 6825 | /* |
11239 | AdvWriteWordAutoIncLram(iop_base, 0); | 6826 | * Reset SCSI Bus and purge all outstanding requests. |
11240 | len += 2; | 6827 | * |
6828 | * Return Value: | ||
6829 | * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset. | ||
6830 | * ADV_FALSE(0) - Microcode command failed. | ||
6831 | * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC | ||
6832 | * may be hung which requires driver recovery. | ||
6833 | */ | ||
6834 | static int AdvResetSB(ADV_DVC_VAR *asc_dvc) | ||
6835 | { | ||
6836 | int status; | ||
6837 | |||
6838 | /* | ||
6839 | * Send the SCSI Bus Reset idle start idle command which asserts | ||
6840 | * the SCSI Bus Reset signal. | ||
6841 | */ | ||
6842 | status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L); | ||
6843 | if (status != ADV_TRUE) { | ||
6844 | return status; | ||
11241 | } | 6845 | } |
11242 | 6846 | ||
11243 | /* Verify the microcode checksum. */ | 6847 | /* |
11244 | sum = 0; | 6848 | * Delay for the specified SCSI Bus Reset hold time. |
11245 | AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); | 6849 | * |
6850 | * The hold time delay is done on the host because the RISC has no | ||
6851 | * microsecond accurate timer. | ||
6852 | */ | ||
6853 | udelay(ASC_SCSI_RESET_HOLD_TIME_US); | ||
11246 | 6854 | ||
11247 | for (len = 0; len < end; len += 2) { | 6855 | /* |
11248 | sum += AdvReadWordAutoIncLram(iop_base); | 6856 | * Send the SCSI Bus Reset end idle command which de-asserts |
6857 | * the SCSI Bus Reset signal and purges any pending requests. | ||
6858 | */ | ||
6859 | status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L); | ||
6860 | if (status != ADV_TRUE) { | ||
6861 | return status; | ||
11249 | } | 6862 | } |
11250 | 6863 | ||
11251 | if (sum != chksum) | 6864 | mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ |
11252 | return ASC_IERR_MCODE_CHKSUM; | ||
11253 | 6865 | ||
11254 | return 0; | 6866 | return status; |
11255 | } | 6867 | } |
11256 | 6868 | ||
11257 | /* | 6869 | /* |
@@ -12661,6 +8273,4917 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) | |||
12661 | } | 8273 | } |
12662 | 8274 | ||
12663 | /* | 8275 | /* |
8276 | * Reset chip and SCSI Bus. | ||
8277 | * | ||
8278 | * Return Value: | ||
8279 | * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. | ||
8280 | * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. | ||
8281 | */ | ||
8282 | static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) | ||
8283 | { | ||
8284 | int status; | ||
8285 | ushort wdtr_able, sdtr_able, tagqng_able; | ||
8286 | ushort ppr_able = 0; | ||
8287 | uchar tid, max_cmd[ADV_MAX_TID + 1]; | ||
8288 | AdvPortAddr iop_base; | ||
8289 | ushort bios_sig; | ||
8290 | |||
8291 | iop_base = asc_dvc->iop_base; | ||
8292 | |||
8293 | /* | ||
8294 | * Save current per TID negotiated values. | ||
8295 | */ | ||
8296 | AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); | ||
8297 | AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); | ||
8298 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | ||
8299 | AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); | ||
8300 | } | ||
8301 | AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); | ||
8302 | for (tid = 0; tid <= ADV_MAX_TID; tid++) { | ||
8303 | AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, | ||
8304 | max_cmd[tid]); | ||
8305 | } | ||
8306 | |||
8307 | /* | ||
8308 | * Force the AdvInitAsc3550/38C0800Driver() function to | ||
8309 | * perform a SCSI Bus Reset by clearing the BIOS signature word. | ||
8310 | * The initialization functions assumes a SCSI Bus Reset is not | ||
8311 | * needed if the BIOS signature word is present. | ||
8312 | */ | ||
8313 | AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); | ||
8314 | AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); | ||
8315 | |||
8316 | /* | ||
8317 | * Stop chip and reset it. | ||
8318 | */ | ||
8319 | AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); | ||
8320 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); | ||
8321 | mdelay(100); | ||
8322 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, | ||
8323 | ADV_CTRL_REG_CMD_WR_IO_REG); | ||
8324 | |||
8325 | /* | ||
8326 | * Reset Adv Library error code, if any, and try | ||
8327 | * re-initializing the chip. | ||
8328 | */ | ||
8329 | asc_dvc->err_code = 0; | ||
8330 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | ||
8331 | status = AdvInitAsc38C1600Driver(asc_dvc); | ||
8332 | } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
8333 | status = AdvInitAsc38C0800Driver(asc_dvc); | ||
8334 | } else { | ||
8335 | status = AdvInitAsc3550Driver(asc_dvc); | ||
8336 | } | ||
8337 | |||
8338 | /* Translate initialization return value to status value. */ | ||
8339 | if (status == 0) { | ||
8340 | status = ADV_TRUE; | ||
8341 | } else { | ||
8342 | status = ADV_FALSE; | ||
8343 | } | ||
8344 | |||
8345 | /* | ||
8346 | * Restore the BIOS signature word. | ||
8347 | */ | ||
8348 | AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); | ||
8349 | |||
8350 | /* | ||
8351 | * Restore per TID negotiated values. | ||
8352 | */ | ||
8353 | AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); | ||
8354 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); | ||
8355 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | ||
8356 | AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); | ||
8357 | } | ||
8358 | AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); | ||
8359 | for (tid = 0; tid <= ADV_MAX_TID; tid++) { | ||
8360 | AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, | ||
8361 | max_cmd[tid]); | ||
8362 | } | ||
8363 | |||
8364 | return status; | ||
8365 | } | ||
8366 | |||
8367 | /* | ||
8368 | * adv_async_callback() - Adv Library asynchronous event callback function. | ||
8369 | */ | ||
8370 | static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) | ||
8371 | { | ||
8372 | switch (code) { | ||
8373 | case ADV_ASYNC_SCSI_BUS_RESET_DET: | ||
8374 | /* | ||
8375 | * The firmware detected a SCSI Bus reset. | ||
8376 | */ | ||
8377 | ASC_DBG(0, | ||
8378 | "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); | ||
8379 | break; | ||
8380 | |||
8381 | case ADV_ASYNC_RDMA_FAILURE: | ||
8382 | /* | ||
8383 | * Handle RDMA failure by resetting the SCSI Bus and | ||
8384 | * possibly the chip if it is unresponsive. Log the error | ||
8385 | * with a unique code. | ||
8386 | */ | ||
8387 | ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); | ||
8388 | AdvResetChipAndSB(adv_dvc_varp); | ||
8389 | break; | ||
8390 | |||
8391 | case ADV_HOST_SCSI_BUS_RESET: | ||
8392 | /* | ||
8393 | * Host generated SCSI bus reset occurred. | ||
8394 | */ | ||
8395 | ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); | ||
8396 | break; | ||
8397 | |||
8398 | default: | ||
8399 | ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); | ||
8400 | break; | ||
8401 | } | ||
8402 | } | ||
8403 | |||
8404 | /* | ||
8405 | * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR(). | ||
8406 | * | ||
8407 | * Callback function for the Wide SCSI Adv Library. | ||
8408 | */ | ||
8409 | static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) | ||
8410 | { | ||
8411 | asc_board_t *boardp; | ||
8412 | adv_req_t *reqp; | ||
8413 | adv_sgblk_t *sgblkp; | ||
8414 | struct scsi_cmnd *scp; | ||
8415 | struct Scsi_Host *shost; | ||
8416 | ADV_DCNT resid_cnt; | ||
8417 | |||
8418 | ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", | ||
8419 | (ulong)adv_dvc_varp, (ulong)scsiqp); | ||
8420 | ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); | ||
8421 | |||
8422 | /* | ||
8423 | * Get the adv_req_t structure for the command that has been | ||
8424 | * completed. The adv_req_t structure actually contains the | ||
8425 | * completed ADV_SCSI_REQ_Q structure. | ||
8426 | */ | ||
8427 | reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr); | ||
8428 | ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp); | ||
8429 | if (reqp == NULL) { | ||
8430 | ASC_PRINT("adv_isr_callback: reqp is NULL\n"); | ||
8431 | return; | ||
8432 | } | ||
8433 | |||
8434 | /* | ||
8435 | * Get the struct scsi_cmnd structure and Scsi_Host structure for the | ||
8436 | * command that has been completed. | ||
8437 | * | ||
8438 | * Note: The adv_req_t request structure and adv_sgblk_t structure, | ||
8439 | * if any, are dropped, because a board structure pointer can not be | ||
8440 | * determined. | ||
8441 | */ | ||
8442 | scp = reqp->cmndp; | ||
8443 | ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp); | ||
8444 | if (scp == NULL) { | ||
8445 | ASC_PRINT | ||
8446 | ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); | ||
8447 | return; | ||
8448 | } | ||
8449 | ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); | ||
8450 | |||
8451 | shost = scp->device->host; | ||
8452 | ASC_STATS(shost, callback); | ||
8453 | ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); | ||
8454 | |||
8455 | boardp = ASC_BOARDP(shost); | ||
8456 | BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var); | ||
8457 | |||
8458 | /* | ||
8459 | * 'done_status' contains the command's ending status. | ||
8460 | */ | ||
8461 | switch (scsiqp->done_status) { | ||
8462 | case QD_NO_ERROR: | ||
8463 | ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); | ||
8464 | scp->result = 0; | ||
8465 | |||
8466 | /* | ||
8467 | * Check for an underrun condition. | ||
8468 | * | ||
8469 | * If there was no error and an underrun condition, then | ||
8470 | * then return the number of underrun bytes. | ||
8471 | */ | ||
8472 | resid_cnt = le32_to_cpu(scsiqp->data_cnt); | ||
8473 | if (scp->request_bufflen != 0 && resid_cnt != 0 && | ||
8474 | resid_cnt <= scp->request_bufflen) { | ||
8475 | ASC_DBG1(1, | ||
8476 | "adv_isr_callback: underrun condition %lu bytes\n", | ||
8477 | (ulong)resid_cnt); | ||
8478 | scp->resid = resid_cnt; | ||
8479 | } | ||
8480 | break; | ||
8481 | |||
8482 | case QD_WITH_ERROR: | ||
8483 | ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); | ||
8484 | switch (scsiqp->host_status) { | ||
8485 | case QHSTA_NO_ERROR: | ||
8486 | if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { | ||
8487 | ASC_DBG(2, | ||
8488 | "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); | ||
8489 | ASC_DBG_PRT_SENSE(2, scp->sense_buffer, | ||
8490 | sizeof(scp->sense_buffer)); | ||
8491 | /* | ||
8492 | * Note: The 'status_byte()' macro used by | ||
8493 | * target drivers defined in scsi.h shifts the | ||
8494 | * status byte returned by host drivers right | ||
8495 | * by 1 bit. This is why target drivers also | ||
8496 | * use right shifted status byte definitions. | ||
8497 | * For instance target drivers use | ||
8498 | * CHECK_CONDITION, defined to 0x1, instead of | ||
8499 | * the SCSI defined check condition value of | ||
8500 | * 0x2. Host drivers are supposed to return | ||
8501 | * the status byte as it is defined by SCSI. | ||
8502 | */ | ||
8503 | scp->result = DRIVER_BYTE(DRIVER_SENSE) | | ||
8504 | STATUS_BYTE(scsiqp->scsi_status); | ||
8505 | } else { | ||
8506 | scp->result = STATUS_BYTE(scsiqp->scsi_status); | ||
8507 | } | ||
8508 | break; | ||
8509 | |||
8510 | default: | ||
8511 | /* Some other QHSTA error occurred. */ | ||
8512 | ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", | ||
8513 | scsiqp->host_status); | ||
8514 | scp->result = HOST_BYTE(DID_BAD_TARGET); | ||
8515 | break; | ||
8516 | } | ||
8517 | break; | ||
8518 | |||
8519 | case QD_ABORTED_BY_HOST: | ||
8520 | ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); | ||
8521 | scp->result = | ||
8522 | HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); | ||
8523 | break; | ||
8524 | |||
8525 | default: | ||
8526 | ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", | ||
8527 | scsiqp->done_status); | ||
8528 | scp->result = | ||
8529 | HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); | ||
8530 | break; | ||
8531 | } | ||
8532 | |||
8533 | /* | ||
8534 | * If the 'init_tidmask' bit isn't already set for the target and the | ||
8535 | * current request finished normally, then set the bit for the target | ||
8536 | * to indicate that a device is present. | ||
8537 | */ | ||
8538 | if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && | ||
8539 | scsiqp->done_status == QD_NO_ERROR && | ||
8540 | scsiqp->host_status == QHSTA_NO_ERROR) { | ||
8541 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); | ||
8542 | } | ||
8543 | |||
8544 | asc_scsi_done(scp); | ||
8545 | |||
8546 | /* | ||
8547 | * Free all 'adv_sgblk_t' structures allocated for the request. | ||
8548 | */ | ||
8549 | while ((sgblkp = reqp->sgblkp) != NULL) { | ||
8550 | /* Remove 'sgblkp' from the request list. */ | ||
8551 | reqp->sgblkp = sgblkp->next_sgblkp; | ||
8552 | |||
8553 | /* Add 'sgblkp' to the board free list. */ | ||
8554 | sgblkp->next_sgblkp = boardp->adv_sgblkp; | ||
8555 | boardp->adv_sgblkp = sgblkp; | ||
8556 | } | ||
8557 | |||
8558 | /* | ||
8559 | * Free the adv_req_t structure used with the command by adding | ||
8560 | * it back to the board free list. | ||
8561 | */ | ||
8562 | reqp->next_reqp = boardp->adv_reqp; | ||
8563 | boardp->adv_reqp = reqp; | ||
8564 | |||
8565 | ASC_DBG(1, "adv_isr_callback: done\n"); | ||
8566 | |||
8567 | return; | ||
8568 | } | ||
8569 | |||
8570 | /* | ||
8571 | * Adv Library Interrupt Service Routine | ||
8572 | * | ||
8573 | * This function is called by a driver's interrupt service routine. | ||
8574 | * The function disables and re-enables interrupts. | ||
8575 | * | ||
8576 | * When a microcode idle command is completed, the ADV_DVC_VAR | ||
8577 | * 'idle_cmd_done' field is set to ADV_TRUE. | ||
8578 | * | ||
8579 | * Note: AdvISR() can be called when interrupts are disabled or even | ||
8580 | * when there is no hardware interrupt condition present. It will | ||
8581 | * always check for completed idle commands and microcode requests. | ||
8582 | * This is an important feature that shouldn't be changed because it | ||
8583 | * allows commands to be completed from polling mode loops. | ||
8584 | * | ||
8585 | * Return: | ||
8586 | * ADV_TRUE(1) - interrupt was pending | ||
8587 | * ADV_FALSE(0) - no interrupt was pending | ||
8588 | */ | ||
8589 | static int AdvISR(ADV_DVC_VAR *asc_dvc) | ||
8590 | { | ||
8591 | AdvPortAddr iop_base; | ||
8592 | uchar int_stat; | ||
8593 | ushort target_bit; | ||
8594 | ADV_CARR_T *free_carrp; | ||
8595 | ADV_VADDR irq_next_vpa; | ||
8596 | ADV_SCSI_REQ_Q *scsiq; | ||
8597 | |||
8598 | iop_base = asc_dvc->iop_base; | ||
8599 | |||
8600 | /* Reading the register clears the interrupt. */ | ||
8601 | int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); | ||
8602 | |||
8603 | if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | | ||
8604 | ADV_INTR_STATUS_INTRC)) == 0) { | ||
8605 | return ADV_FALSE; | ||
8606 | } | ||
8607 | |||
8608 | /* | ||
8609 | * Notify the driver of an asynchronous microcode condition by | ||
8610 | * calling the adv_async_callback function. The function | ||
8611 | * is passed the microcode ASC_MC_INTRB_CODE byte value. | ||
8612 | */ | ||
8613 | if (int_stat & ADV_INTR_STATUS_INTRB) { | ||
8614 | uchar intrb_code; | ||
8615 | |||
8616 | AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); | ||
8617 | |||
8618 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || | ||
8619 | asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
8620 | if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && | ||
8621 | asc_dvc->carr_pending_cnt != 0) { | ||
8622 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, | ||
8623 | ADV_TICKLE_A); | ||
8624 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { | ||
8625 | AdvWriteByteRegister(iop_base, | ||
8626 | IOPB_TICKLE, | ||
8627 | ADV_TICKLE_NOP); | ||
8628 | } | ||
8629 | } | ||
8630 | } | ||
8631 | |||
8632 | adv_async_callback(asc_dvc, intrb_code); | ||
8633 | } | ||
8634 | |||
8635 | /* | ||
8636 | * Check if the IRQ stopper carrier contains a completed request. | ||
8637 | */ | ||
8638 | while (((irq_next_vpa = | ||
8639 | le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) { | ||
8640 | /* | ||
8641 | * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. | ||
8642 | * The RISC will have set 'areq_vpa' to a virtual address. | ||
8643 | * | ||
8644 | * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr | ||
8645 | * field to the carrier ADV_CARR_T.areq_vpa field. The conversion | ||
8646 | * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' | ||
8647 | * in AdvExeScsiQueue(). | ||
8648 | */ | ||
8649 | scsiq = (ADV_SCSI_REQ_Q *) | ||
8650 | ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); | ||
8651 | |||
8652 | /* | ||
8653 | * Request finished with good status and the queue was not | ||
8654 | * DMAed to host memory by the firmware. Set all status fields | ||
8655 | * to indicate good status. | ||
8656 | */ | ||
8657 | if ((irq_next_vpa & ASC_RQ_GOOD) != 0) { | ||
8658 | scsiq->done_status = QD_NO_ERROR; | ||
8659 | scsiq->host_status = scsiq->scsi_status = 0; | ||
8660 | scsiq->data_cnt = 0L; | ||
8661 | } | ||
8662 | |||
8663 | /* | ||
8664 | * Advance the stopper pointer to the next carrier | ||
8665 | * ignoring the lower four bits. Free the previous | ||
8666 | * stopper carrier. | ||
8667 | */ | ||
8668 | free_carrp = asc_dvc->irq_sp; | ||
8669 | asc_dvc->irq_sp = (ADV_CARR_T *) | ||
8670 | ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); | ||
8671 | |||
8672 | free_carrp->next_vpa = | ||
8673 | cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); | ||
8674 | asc_dvc->carr_freelist = free_carrp; | ||
8675 | asc_dvc->carr_pending_cnt--; | ||
8676 | |||
8677 | target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); | ||
8678 | |||
8679 | /* | ||
8680 | * Clear request microcode control flag. | ||
8681 | */ | ||
8682 | scsiq->cntl = 0; | ||
8683 | |||
8684 | /* | ||
8685 | * Notify the driver of the completed request by passing | ||
8686 | * the ADV_SCSI_REQ_Q pointer to its callback function. | ||
8687 | */ | ||
8688 | scsiq->a_flag |= ADV_SCSIQ_DONE; | ||
8689 | adv_isr_callback(asc_dvc, scsiq); | ||
8690 | /* | ||
8691 | * Note: After the driver callback function is called, 'scsiq' | ||
8692 | * can no longer be referenced. | ||
8693 | * | ||
8694 | * Fall through and continue processing other completed | ||
8695 | * requests... | ||
8696 | */ | ||
8697 | } | ||
8698 | return ADV_TRUE; | ||
8699 | } | ||
8700 | |||
8701 | static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code) | ||
8702 | { | ||
8703 | if (asc_dvc->err_code == 0) { | ||
8704 | asc_dvc->err_code = err_code; | ||
8705 | AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, | ||
8706 | err_code); | ||
8707 | } | ||
8708 | return err_code; | ||
8709 | } | ||
8710 | |||
8711 | static void AscAckInterrupt(PortAddr iop_base) | ||
8712 | { | ||
8713 | uchar host_flag; | ||
8714 | uchar risc_flag; | ||
8715 | ushort loop; | ||
8716 | |||
8717 | loop = 0; | ||
8718 | do { | ||
8719 | risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); | ||
8720 | if (loop++ > 0x7FFF) { | ||
8721 | break; | ||
8722 | } | ||
8723 | } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); | ||
8724 | host_flag = | ||
8725 | AscReadLramByte(iop_base, | ||
8726 | ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); | ||
8727 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, | ||
8728 | (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT)); | ||
8729 | AscSetChipStatus(iop_base, CIW_INT_ACK); | ||
8730 | loop = 0; | ||
8731 | while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { | ||
8732 | AscSetChipStatus(iop_base, CIW_INT_ACK); | ||
8733 | if (loop++ > 3) { | ||
8734 | break; | ||
8735 | } | ||
8736 | } | ||
8737 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); | ||
8738 | return; | ||
8739 | } | ||
8740 | |||
8741 | static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) | ||
8742 | { | ||
8743 | uchar *period_table; | ||
8744 | int max_index; | ||
8745 | int min_index; | ||
8746 | int i; | ||
8747 | |||
8748 | period_table = asc_dvc->sdtr_period_tbl; | ||
8749 | max_index = (int)asc_dvc->max_sdtr_index; | ||
8750 | min_index = (int)asc_dvc->host_init_sdtr_index; | ||
8751 | if ((syn_time <= period_table[max_index])) { | ||
8752 | for (i = min_index; i < (max_index - 1); i++) { | ||
8753 | if (syn_time <= period_table[i]) { | ||
8754 | return (uchar)i; | ||
8755 | } | ||
8756 | } | ||
8757 | return (uchar)max_index; | ||
8758 | } else { | ||
8759 | return (uchar)(max_index + 1); | ||
8760 | } | ||
8761 | } | ||
8762 | |||
8763 | static uchar | ||
8764 | AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) | ||
8765 | { | ||
8766 | EXT_MSG sdtr_buf; | ||
8767 | uchar sdtr_period_index; | ||
8768 | PortAddr iop_base; | ||
8769 | |||
8770 | iop_base = asc_dvc->iop_base; | ||
8771 | sdtr_buf.msg_type = EXTENDED_MESSAGE; | ||
8772 | sdtr_buf.msg_len = MS_SDTR_LEN; | ||
8773 | sdtr_buf.msg_req = EXTENDED_SDTR; | ||
8774 | sdtr_buf.xfer_period = sdtr_period; | ||
8775 | sdtr_offset &= ASC_SYN_MAX_OFFSET; | ||
8776 | sdtr_buf.req_ack_offset = sdtr_offset; | ||
8777 | sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period); | ||
8778 | if (sdtr_period_index <= asc_dvc->max_sdtr_index) { | ||
8779 | AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG, | ||
8780 | (uchar *)&sdtr_buf, | ||
8781 | sizeof(EXT_MSG) >> 1); | ||
8782 | return ((sdtr_period_index << 4) | sdtr_offset); | ||
8783 | } else { | ||
8784 | sdtr_buf.req_ack_offset = 0; | ||
8785 | AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG, | ||
8786 | (uchar *)&sdtr_buf, | ||
8787 | sizeof(EXT_MSG) >> 1); | ||
8788 | return 0; | ||
8789 | } | ||
8790 | } | ||
8791 | |||
8792 | static uchar | ||
8793 | AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) | ||
8794 | { | ||
8795 | uchar byte; | ||
8796 | uchar sdtr_period_ix; | ||
8797 | |||
8798 | sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); | ||
8799 | if (sdtr_period_ix > asc_dvc->max_sdtr_index) { | ||
8800 | return 0xFF; | ||
8801 | } | ||
8802 | byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); | ||
8803 | return byte; | ||
8804 | } | ||
8805 | |||
8806 | static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) | ||
8807 | { | ||
8808 | ASC_SCSI_BIT_ID_TYPE org_id; | ||
8809 | int i; | ||
8810 | int sta = TRUE; | ||
8811 | |||
8812 | AscSetBank(iop_base, 1); | ||
8813 | org_id = AscReadChipDvcID(iop_base); | ||
8814 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
8815 | if (org_id == (0x01 << i)) | ||
8816 | break; | ||
8817 | } | ||
8818 | org_id = (ASC_SCSI_BIT_ID_TYPE) i; | ||
8819 | AscWriteChipDvcID(iop_base, id); | ||
8820 | if (AscReadChipDvcID(iop_base) == (0x01 << id)) { | ||
8821 | AscSetBank(iop_base, 0); | ||
8822 | AscSetChipSyn(iop_base, sdtr_data); | ||
8823 | if (AscGetChipSyn(iop_base) != sdtr_data) { | ||
8824 | sta = FALSE; | ||
8825 | } | ||
8826 | } else { | ||
8827 | sta = FALSE; | ||
8828 | } | ||
8829 | AscSetBank(iop_base, 1); | ||
8830 | AscWriteChipDvcID(iop_base, org_id); | ||
8831 | AscSetBank(iop_base, 0); | ||
8832 | return (sta); | ||
8833 | } | ||
8834 | |||
8835 | static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no) | ||
8836 | { | ||
8837 | AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); | ||
8838 | AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); | ||
8839 | } | ||
8840 | |||
8841 | static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) | ||
8842 | { | ||
8843 | EXT_MSG ext_msg; | ||
8844 | EXT_MSG out_msg; | ||
8845 | ushort halt_q_addr; | ||
8846 | int sdtr_accept; | ||
8847 | ushort int_halt_code; | ||
8848 | ASC_SCSI_BIT_ID_TYPE scsi_busy; | ||
8849 | ASC_SCSI_BIT_ID_TYPE target_id; | ||
8850 | PortAddr iop_base; | ||
8851 | uchar tag_code; | ||
8852 | uchar q_status; | ||
8853 | uchar halt_qp; | ||
8854 | uchar sdtr_data; | ||
8855 | uchar target_ix; | ||
8856 | uchar q_cntl, tid_no; | ||
8857 | uchar cur_dvc_qng; | ||
8858 | uchar asyn_sdtr; | ||
8859 | uchar scsi_status; | ||
8860 | asc_board_t *boardp; | ||
8861 | |||
8862 | BUG_ON(!asc_dvc->drv_ptr); | ||
8863 | boardp = asc_dvc->drv_ptr; | ||
8864 | |||
8865 | iop_base = asc_dvc->iop_base; | ||
8866 | int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); | ||
8867 | |||
8868 | halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); | ||
8869 | halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); | ||
8870 | target_ix = AscReadLramByte(iop_base, | ||
8871 | (ushort)(halt_q_addr + | ||
8872 | (ushort)ASC_SCSIQ_B_TARGET_IX)); | ||
8873 | q_cntl = AscReadLramByte(iop_base, | ||
8874 | (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL)); | ||
8875 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
8876 | target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no); | ||
8877 | if (asc_dvc->pci_fix_asyn_xfer & target_id) { | ||
8878 | asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; | ||
8879 | } else { | ||
8880 | asyn_sdtr = 0; | ||
8881 | } | ||
8882 | if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { | ||
8883 | if (asc_dvc->pci_fix_asyn_xfer & target_id) { | ||
8884 | AscSetChipSDTR(iop_base, 0, tid_no); | ||
8885 | boardp->sdtr_data[tid_no] = 0; | ||
8886 | } | ||
8887 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
8888 | return (0); | ||
8889 | } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { | ||
8890 | if (asc_dvc->pci_fix_asyn_xfer & target_id) { | ||
8891 | AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); | ||
8892 | boardp->sdtr_data[tid_no] = asyn_sdtr; | ||
8893 | } | ||
8894 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
8895 | return (0); | ||
8896 | } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { | ||
8897 | AscMemWordCopyPtrFromLram(iop_base, | ||
8898 | ASCV_MSGIN_BEG, | ||
8899 | (uchar *)&ext_msg, | ||
8900 | sizeof(EXT_MSG) >> 1); | ||
8901 | |||
8902 | if (ext_msg.msg_type == EXTENDED_MESSAGE && | ||
8903 | ext_msg.msg_req == EXTENDED_SDTR && | ||
8904 | ext_msg.msg_len == MS_SDTR_LEN) { | ||
8905 | sdtr_accept = TRUE; | ||
8906 | if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { | ||
8907 | |||
8908 | sdtr_accept = FALSE; | ||
8909 | ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; | ||
8910 | } | ||
8911 | if ((ext_msg.xfer_period < | ||
8912 | asc_dvc->sdtr_period_tbl[asc_dvc-> | ||
8913 | host_init_sdtr_index]) | ||
8914 | || (ext_msg.xfer_period > | ||
8915 | asc_dvc->sdtr_period_tbl[asc_dvc-> | ||
8916 | max_sdtr_index])) { | ||
8917 | sdtr_accept = FALSE; | ||
8918 | ext_msg.xfer_period = | ||
8919 | asc_dvc->sdtr_period_tbl[asc_dvc-> | ||
8920 | host_init_sdtr_index]; | ||
8921 | } | ||
8922 | if (sdtr_accept) { | ||
8923 | sdtr_data = | ||
8924 | AscCalSDTRData(asc_dvc, ext_msg.xfer_period, | ||
8925 | ext_msg.req_ack_offset); | ||
8926 | if ((sdtr_data == 0xFF)) { | ||
8927 | |||
8928 | q_cntl |= QC_MSG_OUT; | ||
8929 | asc_dvc->init_sdtr &= ~target_id; | ||
8930 | asc_dvc->sdtr_done &= ~target_id; | ||
8931 | AscSetChipSDTR(iop_base, asyn_sdtr, | ||
8932 | tid_no); | ||
8933 | boardp->sdtr_data[tid_no] = asyn_sdtr; | ||
8934 | } | ||
8935 | } | ||
8936 | if (ext_msg.req_ack_offset == 0) { | ||
8937 | |||
8938 | q_cntl &= ~QC_MSG_OUT; | ||
8939 | asc_dvc->init_sdtr &= ~target_id; | ||
8940 | asc_dvc->sdtr_done &= ~target_id; | ||
8941 | AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); | ||
8942 | } else { | ||
8943 | if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { | ||
8944 | |||
8945 | q_cntl &= ~QC_MSG_OUT; | ||
8946 | asc_dvc->sdtr_done |= target_id; | ||
8947 | asc_dvc->init_sdtr |= target_id; | ||
8948 | asc_dvc->pci_fix_asyn_xfer &= | ||
8949 | ~target_id; | ||
8950 | sdtr_data = | ||
8951 | AscCalSDTRData(asc_dvc, | ||
8952 | ext_msg.xfer_period, | ||
8953 | ext_msg. | ||
8954 | req_ack_offset); | ||
8955 | AscSetChipSDTR(iop_base, sdtr_data, | ||
8956 | tid_no); | ||
8957 | boardp->sdtr_data[tid_no] = sdtr_data; | ||
8958 | } else { | ||
8959 | |||
8960 | q_cntl |= QC_MSG_OUT; | ||
8961 | AscMsgOutSDTR(asc_dvc, | ||
8962 | ext_msg.xfer_period, | ||
8963 | ext_msg.req_ack_offset); | ||
8964 | asc_dvc->pci_fix_asyn_xfer &= | ||
8965 | ~target_id; | ||
8966 | sdtr_data = | ||
8967 | AscCalSDTRData(asc_dvc, | ||
8968 | ext_msg.xfer_period, | ||
8969 | ext_msg. | ||
8970 | req_ack_offset); | ||
8971 | AscSetChipSDTR(iop_base, sdtr_data, | ||
8972 | tid_no); | ||
8973 | boardp->sdtr_data[tid_no] = sdtr_data; | ||
8974 | asc_dvc->sdtr_done |= target_id; | ||
8975 | asc_dvc->init_sdtr |= target_id; | ||
8976 | } | ||
8977 | } | ||
8978 | |||
8979 | AscWriteLramByte(iop_base, | ||
8980 | (ushort)(halt_q_addr + | ||
8981 | (ushort)ASC_SCSIQ_B_CNTL), | ||
8982 | q_cntl); | ||
8983 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
8984 | return (0); | ||
8985 | } else if (ext_msg.msg_type == EXTENDED_MESSAGE && | ||
8986 | ext_msg.msg_req == EXTENDED_WDTR && | ||
8987 | ext_msg.msg_len == MS_WDTR_LEN) { | ||
8988 | |||
8989 | ext_msg.wdtr_width = 0; | ||
8990 | AscMemWordCopyPtrToLram(iop_base, | ||
8991 | ASCV_MSGOUT_BEG, | ||
8992 | (uchar *)&ext_msg, | ||
8993 | sizeof(EXT_MSG) >> 1); | ||
8994 | q_cntl |= QC_MSG_OUT; | ||
8995 | AscWriteLramByte(iop_base, | ||
8996 | (ushort)(halt_q_addr + | ||
8997 | (ushort)ASC_SCSIQ_B_CNTL), | ||
8998 | q_cntl); | ||
8999 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
9000 | return (0); | ||
9001 | } else { | ||
9002 | |||
9003 | ext_msg.msg_type = MESSAGE_REJECT; | ||
9004 | AscMemWordCopyPtrToLram(iop_base, | ||
9005 | ASCV_MSGOUT_BEG, | ||
9006 | (uchar *)&ext_msg, | ||
9007 | sizeof(EXT_MSG) >> 1); | ||
9008 | q_cntl |= QC_MSG_OUT; | ||
9009 | AscWriteLramByte(iop_base, | ||
9010 | (ushort)(halt_q_addr + | ||
9011 | (ushort)ASC_SCSIQ_B_CNTL), | ||
9012 | q_cntl); | ||
9013 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
9014 | return (0); | ||
9015 | } | ||
9016 | } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { | ||
9017 | |||
9018 | q_cntl |= QC_REQ_SENSE; | ||
9019 | |||
9020 | if ((asc_dvc->init_sdtr & target_id) != 0) { | ||
9021 | |||
9022 | asc_dvc->sdtr_done &= ~target_id; | ||
9023 | |||
9024 | sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); | ||
9025 | q_cntl |= QC_MSG_OUT; | ||
9026 | AscMsgOutSDTR(asc_dvc, | ||
9027 | asc_dvc-> | ||
9028 | sdtr_period_tbl[(sdtr_data >> 4) & | ||
9029 | (uchar)(asc_dvc-> | ||
9030 | max_sdtr_index - | ||
9031 | 1)], | ||
9032 | (uchar)(sdtr_data & (uchar) | ||
9033 | ASC_SYN_MAX_OFFSET)); | ||
9034 | } | ||
9035 | |||
9036 | AscWriteLramByte(iop_base, | ||
9037 | (ushort)(halt_q_addr + | ||
9038 | (ushort)ASC_SCSIQ_B_CNTL), q_cntl); | ||
9039 | |||
9040 | tag_code = AscReadLramByte(iop_base, | ||
9041 | (ushort)(halt_q_addr + (ushort) | ||
9042 | ASC_SCSIQ_B_TAG_CODE)); | ||
9043 | tag_code &= 0xDC; | ||
9044 | if ((asc_dvc->pci_fix_asyn_xfer & target_id) | ||
9045 | && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) | ||
9046 | ) { | ||
9047 | |||
9048 | tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT | ||
9049 | | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); | ||
9050 | |||
9051 | } | ||
9052 | AscWriteLramByte(iop_base, | ||
9053 | (ushort)(halt_q_addr + | ||
9054 | (ushort)ASC_SCSIQ_B_TAG_CODE), | ||
9055 | tag_code); | ||
9056 | |||
9057 | q_status = AscReadLramByte(iop_base, | ||
9058 | (ushort)(halt_q_addr + (ushort) | ||
9059 | ASC_SCSIQ_B_STATUS)); | ||
9060 | q_status |= (QS_READY | QS_BUSY); | ||
9061 | AscWriteLramByte(iop_base, | ||
9062 | (ushort)(halt_q_addr + | ||
9063 | (ushort)ASC_SCSIQ_B_STATUS), | ||
9064 | q_status); | ||
9065 | |||
9066 | scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B); | ||
9067 | scsi_busy &= ~target_id; | ||
9068 | AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy); | ||
9069 | |||
9070 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
9071 | return (0); | ||
9072 | } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { | ||
9073 | |||
9074 | AscMemWordCopyPtrFromLram(iop_base, | ||
9075 | ASCV_MSGOUT_BEG, | ||
9076 | (uchar *)&out_msg, | ||
9077 | sizeof(EXT_MSG) >> 1); | ||
9078 | |||
9079 | if ((out_msg.msg_type == EXTENDED_MESSAGE) && | ||
9080 | (out_msg.msg_len == MS_SDTR_LEN) && | ||
9081 | (out_msg.msg_req == EXTENDED_SDTR)) { | ||
9082 | |||
9083 | asc_dvc->init_sdtr &= ~target_id; | ||
9084 | asc_dvc->sdtr_done &= ~target_id; | ||
9085 | AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); | ||
9086 | boardp->sdtr_data[tid_no] = asyn_sdtr; | ||
9087 | } | ||
9088 | q_cntl &= ~QC_MSG_OUT; | ||
9089 | AscWriteLramByte(iop_base, | ||
9090 | (ushort)(halt_q_addr + | ||
9091 | (ushort)ASC_SCSIQ_B_CNTL), q_cntl); | ||
9092 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
9093 | return (0); | ||
9094 | } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { | ||
9095 | |||
9096 | scsi_status = AscReadLramByte(iop_base, | ||
9097 | (ushort)((ushort)halt_q_addr + | ||
9098 | (ushort) | ||
9099 | ASC_SCSIQ_SCSI_STATUS)); | ||
9100 | cur_dvc_qng = | ||
9101 | AscReadLramByte(iop_base, | ||
9102 | (ushort)((ushort)ASC_QADR_BEG + | ||
9103 | (ushort)target_ix)); | ||
9104 | if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) { | ||
9105 | |||
9106 | scsi_busy = AscReadLramByte(iop_base, | ||
9107 | (ushort)ASCV_SCSIBUSY_B); | ||
9108 | scsi_busy |= target_id; | ||
9109 | AscWriteLramByte(iop_base, | ||
9110 | (ushort)ASCV_SCSIBUSY_B, scsi_busy); | ||
9111 | asc_dvc->queue_full_or_busy |= target_id; | ||
9112 | |||
9113 | if (scsi_status == SAM_STAT_TASK_SET_FULL) { | ||
9114 | if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { | ||
9115 | cur_dvc_qng -= 1; | ||
9116 | asc_dvc->max_dvc_qng[tid_no] = | ||
9117 | cur_dvc_qng; | ||
9118 | |||
9119 | AscWriteLramByte(iop_base, | ||
9120 | (ushort)((ushort) | ||
9121 | ASCV_MAX_DVC_QNG_BEG | ||
9122 | + (ushort) | ||
9123 | tid_no), | ||
9124 | cur_dvc_qng); | ||
9125 | |||
9126 | /* | ||
9127 | * Set the device queue depth to the | ||
9128 | * number of active requests when the | ||
9129 | * QUEUE FULL condition was encountered. | ||
9130 | */ | ||
9131 | boardp->queue_full |= target_id; | ||
9132 | boardp->queue_full_cnt[tid_no] = | ||
9133 | cur_dvc_qng; | ||
9134 | } | ||
9135 | } | ||
9136 | } | ||
9137 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
9138 | return (0); | ||
9139 | } | ||
9140 | #if CC_VERY_LONG_SG_LIST | ||
9141 | else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) { | ||
9142 | uchar q_no; | ||
9143 | ushort q_addr; | ||
9144 | uchar sg_wk_q_no; | ||
9145 | uchar first_sg_wk_q_no; | ||
9146 | ASC_SCSI_Q *scsiq; /* Ptr to driver request. */ | ||
9147 | ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */ | ||
9148 | ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */ | ||
9149 | ushort sg_list_dwords; | ||
9150 | ushort sg_entry_cnt; | ||
9151 | uchar next_qp; | ||
9152 | int i; | ||
9153 | |||
9154 | q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP); | ||
9155 | if (q_no == ASC_QLINK_END) | ||
9156 | return 0; | ||
9157 | |||
9158 | q_addr = ASC_QNO_TO_QADDR(q_no); | ||
9159 | |||
9160 | /* | ||
9161 | * Convert the request's SRB pointer to a host ASC_SCSI_REQ | ||
9162 | * structure pointer using a macro provided by the driver. | ||
9163 | * The ASC_SCSI_REQ pointer provides a pointer to the | ||
9164 | * host ASC_SG_HEAD structure. | ||
9165 | */ | ||
9166 | /* Read request's SRB pointer. */ | ||
9167 | scsiq = (ASC_SCSI_Q *) | ||
9168 | ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base, | ||
9169 | (ushort) | ||
9170 | (q_addr + | ||
9171 | ASC_SCSIQ_D_SRBPTR)))); | ||
9172 | |||
9173 | /* | ||
9174 | * Get request's first and working SG queue. | ||
9175 | */ | ||
9176 | sg_wk_q_no = AscReadLramByte(iop_base, | ||
9177 | (ushort)(q_addr + | ||
9178 | ASC_SCSIQ_B_SG_WK_QP)); | ||
9179 | |||
9180 | first_sg_wk_q_no = AscReadLramByte(iop_base, | ||
9181 | (ushort)(q_addr + | ||
9182 | ASC_SCSIQ_B_FIRST_SG_WK_QP)); | ||
9183 | |||
9184 | /* | ||
9185 | * Reset request's working SG queue back to the | ||
9186 | * first SG queue. | ||
9187 | */ | ||
9188 | AscWriteLramByte(iop_base, | ||
9189 | (ushort)(q_addr + | ||
9190 | (ushort)ASC_SCSIQ_B_SG_WK_QP), | ||
9191 | first_sg_wk_q_no); | ||
9192 | |||
9193 | sg_head = scsiq->sg_head; | ||
9194 | |||
9195 | /* | ||
9196 | * Set sg_entry_cnt to the number of SG elements | ||
9197 | * that will be completed on this interrupt. | ||
9198 | * | ||
9199 | * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1 | ||
9200 | * SG elements. The data_cnt and data_addr fields which | ||
9201 | * add 1 to the SG element capacity are not used when | ||
9202 | * restarting SG handling after a halt. | ||
9203 | */ | ||
9204 | if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) { | ||
9205 | sg_entry_cnt = ASC_MAX_SG_LIST - 1; | ||
9206 | |||
9207 | /* | ||
9208 | * Keep track of remaining number of SG elements that | ||
9209 | * will need to be handled on the next interrupt. | ||
9210 | */ | ||
9211 | scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); | ||
9212 | } else { | ||
9213 | sg_entry_cnt = scsiq->remain_sg_entry_cnt; | ||
9214 | scsiq->remain_sg_entry_cnt = 0; | ||
9215 | } | ||
9216 | |||
9217 | /* | ||
9218 | * Copy SG elements into the list of allocated SG queues. | ||
9219 | * | ||
9220 | * Last index completed is saved in scsiq->next_sg_index. | ||
9221 | */ | ||
9222 | next_qp = first_sg_wk_q_no; | ||
9223 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
9224 | scsi_sg_q.sg_head_qp = q_no; | ||
9225 | scsi_sg_q.cntl = QCSG_SG_XFER_LIST; | ||
9226 | for (i = 0; i < sg_head->queue_cnt; i++) { | ||
9227 | scsi_sg_q.seq_no = i + 1; | ||
9228 | if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { | ||
9229 | sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); | ||
9230 | sg_entry_cnt -= ASC_SG_LIST_PER_Q; | ||
9231 | /* | ||
9232 | * After very first SG queue RISC FW uses next | ||
9233 | * SG queue first element then checks sg_list_cnt | ||
9234 | * against zero and then decrements, so set | ||
9235 | * sg_list_cnt 1 less than number of SG elements | ||
9236 | * in each SG queue. | ||
9237 | */ | ||
9238 | scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; | ||
9239 | scsi_sg_q.sg_cur_list_cnt = | ||
9240 | ASC_SG_LIST_PER_Q - 1; | ||
9241 | } else { | ||
9242 | /* | ||
9243 | * This is the last SG queue in the list of | ||
9244 | * allocated SG queues. If there are more | ||
9245 | * SG elements than will fit in the allocated | ||
9246 | * queues, then set the QCSG_SG_XFER_MORE flag. | ||
9247 | */ | ||
9248 | if (scsiq->remain_sg_entry_cnt != 0) { | ||
9249 | scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; | ||
9250 | } else { | ||
9251 | scsi_sg_q.cntl |= QCSG_SG_XFER_END; | ||
9252 | } | ||
9253 | /* equals sg_entry_cnt * 2 */ | ||
9254 | sg_list_dwords = sg_entry_cnt << 1; | ||
9255 | scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; | ||
9256 | scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; | ||
9257 | sg_entry_cnt = 0; | ||
9258 | } | ||
9259 | |||
9260 | scsi_sg_q.q_no = next_qp; | ||
9261 | AscMemWordCopyPtrToLram(iop_base, | ||
9262 | q_addr + ASC_SCSIQ_SGHD_CPY_BEG, | ||
9263 | (uchar *)&scsi_sg_q, | ||
9264 | sizeof(ASC_SG_LIST_Q) >> 1); | ||
9265 | |||
9266 | AscMemDWordCopyPtrToLram(iop_base, | ||
9267 | q_addr + ASC_SGQ_LIST_BEG, | ||
9268 | (uchar *)&sg_head-> | ||
9269 | sg_list[scsiq->next_sg_index], | ||
9270 | sg_list_dwords); | ||
9271 | |||
9272 | scsiq->next_sg_index += ASC_SG_LIST_PER_Q; | ||
9273 | |||
9274 | /* | ||
9275 | * If the just completed SG queue contained the | ||
9276 | * last SG element, then no more SG queues need | ||
9277 | * to be written. | ||
9278 | */ | ||
9279 | if (scsi_sg_q.cntl & QCSG_SG_XFER_END) { | ||
9280 | break; | ||
9281 | } | ||
9282 | |||
9283 | next_qp = AscReadLramByte(iop_base, | ||
9284 | (ushort)(q_addr + | ||
9285 | ASC_SCSIQ_B_FWD)); | ||
9286 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
9287 | } | ||
9288 | |||
9289 | /* | ||
9290 | * Clear the halt condition so the RISC will be restarted | ||
9291 | * after the return. | ||
9292 | */ | ||
9293 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); | ||
9294 | return (0); | ||
9295 | } | ||
9296 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
9297 | return (0); | ||
9298 | } | ||
9299 | |||
9300 | /* | ||
9301 | * void | ||
9302 | * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) | ||
9303 | * | ||
9304 | * Calling/Exit State: | ||
9305 | * none | ||
9306 | * | ||
9307 | * Description: | ||
9308 | * Input an ASC_QDONE_INFO structure from the chip | ||
9309 | */ | ||
9310 | static void | ||
9311 | DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) | ||
9312 | { | ||
9313 | int i; | ||
9314 | ushort word; | ||
9315 | |||
9316 | AscSetChipLramAddr(iop_base, s_addr); | ||
9317 | for (i = 0; i < 2 * words; i += 2) { | ||
9318 | if (i == 10) { | ||
9319 | continue; | ||
9320 | } | ||
9321 | word = inpw(iop_base + IOP_RAM_DATA); | ||
9322 | inbuf[i] = word & 0xff; | ||
9323 | inbuf[i + 1] = (word >> 8) & 0xff; | ||
9324 | } | ||
9325 | ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); | ||
9326 | } | ||
9327 | |||
9328 | static uchar | ||
9329 | _AscCopyLramScsiDoneQ(PortAddr iop_base, | ||
9330 | ushort q_addr, | ||
9331 | ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count) | ||
9332 | { | ||
9333 | ushort _val; | ||
9334 | uchar sg_queue_cnt; | ||
9335 | |||
9336 | DvcGetQinfo(iop_base, | ||
9337 | q_addr + ASC_SCSIQ_DONE_INFO_BEG, | ||
9338 | (uchar *)scsiq, | ||
9339 | (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2); | ||
9340 | |||
9341 | _val = AscReadLramWord(iop_base, | ||
9342 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS)); | ||
9343 | scsiq->q_status = (uchar)_val; | ||
9344 | scsiq->q_no = (uchar)(_val >> 8); | ||
9345 | _val = AscReadLramWord(iop_base, | ||
9346 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL)); | ||
9347 | scsiq->cntl = (uchar)_val; | ||
9348 | sg_queue_cnt = (uchar)(_val >> 8); | ||
9349 | _val = AscReadLramWord(iop_base, | ||
9350 | (ushort)(q_addr + | ||
9351 | (ushort)ASC_SCSIQ_B_SENSE_LEN)); | ||
9352 | scsiq->sense_len = (uchar)_val; | ||
9353 | scsiq->extra_bytes = (uchar)(_val >> 8); | ||
9354 | |||
9355 | /* | ||
9356 | * Read high word of remain bytes from alternate location. | ||
9357 | */ | ||
9358 | scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base, | ||
9359 | (ushort)(q_addr + | ||
9360 | (ushort) | ||
9361 | ASC_SCSIQ_W_ALT_DC1))) | ||
9362 | << 16); | ||
9363 | /* | ||
9364 | * Read low word of remain bytes from original location. | ||
9365 | */ | ||
9366 | scsiq->remain_bytes += AscReadLramWord(iop_base, | ||
9367 | (ushort)(q_addr + (ushort) | ||
9368 | ASC_SCSIQ_DW_REMAIN_XFER_CNT)); | ||
9369 | |||
9370 | scsiq->remain_bytes &= max_dma_count; | ||
9371 | return sg_queue_cnt; | ||
9372 | } | ||
9373 | |||
9374 | /* | ||
9375 | * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). | ||
9376 | * | ||
9377 | * Interrupt callback function for the Narrow SCSI Asc Library. | ||
9378 | */ | ||
9379 | static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) | ||
9380 | { | ||
9381 | asc_board_t *boardp; | ||
9382 | struct scsi_cmnd *scp; | ||
9383 | struct Scsi_Host *shost; | ||
9384 | |||
9385 | ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", | ||
9386 | (ulong)asc_dvc_varp, (ulong)qdonep); | ||
9387 | ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); | ||
9388 | |||
9389 | /* | ||
9390 | * Get the struct scsi_cmnd structure and Scsi_Host structure for the | ||
9391 | * command that has been completed. | ||
9392 | */ | ||
9393 | scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); | ||
9394 | ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp); | ||
9395 | |||
9396 | if (scp == NULL) { | ||
9397 | ASC_PRINT("asc_isr_callback: scp is NULL\n"); | ||
9398 | return; | ||
9399 | } | ||
9400 | ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); | ||
9401 | |||
9402 | shost = scp->device->host; | ||
9403 | ASC_STATS(shost, callback); | ||
9404 | ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); | ||
9405 | |||
9406 | boardp = ASC_BOARDP(shost); | ||
9407 | BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var); | ||
9408 | |||
9409 | /* | ||
9410 | * 'qdonep' contains the command's ending status. | ||
9411 | */ | ||
9412 | switch (qdonep->d3.done_stat) { | ||
9413 | case QD_NO_ERROR: | ||
9414 | ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); | ||
9415 | scp->result = 0; | ||
9416 | |||
9417 | /* | ||
9418 | * Check for an underrun condition. | ||
9419 | * | ||
9420 | * If there was no error and an underrun condition, then | ||
9421 | * return the number of underrun bytes. | ||
9422 | */ | ||
9423 | if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && | ||
9424 | qdonep->remain_bytes <= scp->request_bufflen) { | ||
9425 | ASC_DBG1(1, | ||
9426 | "asc_isr_callback: underrun condition %u bytes\n", | ||
9427 | (unsigned)qdonep->remain_bytes); | ||
9428 | scp->resid = qdonep->remain_bytes; | ||
9429 | } | ||
9430 | break; | ||
9431 | |||
9432 | case QD_WITH_ERROR: | ||
9433 | ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); | ||
9434 | switch (qdonep->d3.host_stat) { | ||
9435 | case QHSTA_NO_ERROR: | ||
9436 | if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { | ||
9437 | ASC_DBG(2, | ||
9438 | "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); | ||
9439 | ASC_DBG_PRT_SENSE(2, scp->sense_buffer, | ||
9440 | sizeof(scp->sense_buffer)); | ||
9441 | /* | ||
9442 | * Note: The 'status_byte()' macro used by | ||
9443 | * target drivers defined in scsi.h shifts the | ||
9444 | * status byte returned by host drivers right | ||
9445 | * by 1 bit. This is why target drivers also | ||
9446 | * use right shifted status byte definitions. | ||
9447 | * For instance target drivers use | ||
9448 | * CHECK_CONDITION, defined to 0x1, instead of | ||
9449 | * the SCSI defined check condition value of | ||
9450 | * 0x2. Host drivers are supposed to return | ||
9451 | * the status byte as it is defined by SCSI. | ||
9452 | */ | ||
9453 | scp->result = DRIVER_BYTE(DRIVER_SENSE) | | ||
9454 | STATUS_BYTE(qdonep->d3.scsi_stat); | ||
9455 | } else { | ||
9456 | scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); | ||
9457 | } | ||
9458 | break; | ||
9459 | |||
9460 | default: | ||
9461 | /* QHSTA error occurred */ | ||
9462 | ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", | ||
9463 | qdonep->d3.host_stat); | ||
9464 | scp->result = HOST_BYTE(DID_BAD_TARGET); | ||
9465 | break; | ||
9466 | } | ||
9467 | break; | ||
9468 | |||
9469 | case QD_ABORTED_BY_HOST: | ||
9470 | ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); | ||
9471 | scp->result = | ||
9472 | HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3. | ||
9473 | scsi_msg) | | ||
9474 | STATUS_BYTE(qdonep->d3.scsi_stat); | ||
9475 | break; | ||
9476 | |||
9477 | default: | ||
9478 | ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", | ||
9479 | qdonep->d3.done_stat); | ||
9480 | scp->result = | ||
9481 | HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3. | ||
9482 | scsi_msg) | | ||
9483 | STATUS_BYTE(qdonep->d3.scsi_stat); | ||
9484 | break; | ||
9485 | } | ||
9486 | |||
9487 | /* | ||
9488 | * If the 'init_tidmask' bit isn't already set for the target and the | ||
9489 | * current request finished normally, then set the bit for the target | ||
9490 | * to indicate that a device is present. | ||
9491 | */ | ||
9492 | if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && | ||
9493 | qdonep->d3.done_stat == QD_NO_ERROR && | ||
9494 | qdonep->d3.host_stat == QHSTA_NO_ERROR) { | ||
9495 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); | ||
9496 | } | ||
9497 | |||
9498 | asc_scsi_done(scp); | ||
9499 | |||
9500 | return; | ||
9501 | } | ||
9502 | |||
9503 | static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) | ||
9504 | { | ||
9505 | uchar next_qp; | ||
9506 | uchar n_q_used; | ||
9507 | uchar sg_list_qp; | ||
9508 | uchar sg_queue_cnt; | ||
9509 | uchar q_cnt; | ||
9510 | uchar done_q_tail; | ||
9511 | uchar tid_no; | ||
9512 | ASC_SCSI_BIT_ID_TYPE scsi_busy; | ||
9513 | ASC_SCSI_BIT_ID_TYPE target_id; | ||
9514 | PortAddr iop_base; | ||
9515 | ushort q_addr; | ||
9516 | ushort sg_q_addr; | ||
9517 | uchar cur_target_qng; | ||
9518 | ASC_QDONE_INFO scsiq_buf; | ||
9519 | ASC_QDONE_INFO *scsiq; | ||
9520 | int false_overrun; | ||
9521 | |||
9522 | iop_base = asc_dvc->iop_base; | ||
9523 | n_q_used = 1; | ||
9524 | scsiq = (ASC_QDONE_INFO *)&scsiq_buf; | ||
9525 | done_q_tail = (uchar)AscGetVarDoneQTail(iop_base); | ||
9526 | q_addr = ASC_QNO_TO_QADDR(done_q_tail); | ||
9527 | next_qp = AscReadLramByte(iop_base, | ||
9528 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD)); | ||
9529 | if (next_qp != ASC_QLINK_END) { | ||
9530 | AscPutVarDoneQTail(iop_base, next_qp); | ||
9531 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
9532 | sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, | ||
9533 | asc_dvc->max_dma_count); | ||
9534 | AscWriteLramByte(iop_base, | ||
9535 | (ushort)(q_addr + | ||
9536 | (ushort)ASC_SCSIQ_B_STATUS), | ||
9537 | (uchar)(scsiq-> | ||
9538 | q_status & (uchar)~(QS_READY | | ||
9539 | QS_ABORTED))); | ||
9540 | tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); | ||
9541 | target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); | ||
9542 | if ((scsiq->cntl & QC_SG_HEAD) != 0) { | ||
9543 | sg_q_addr = q_addr; | ||
9544 | sg_list_qp = next_qp; | ||
9545 | for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { | ||
9546 | sg_list_qp = AscReadLramByte(iop_base, | ||
9547 | (ushort)(sg_q_addr | ||
9548 | + (ushort) | ||
9549 | ASC_SCSIQ_B_FWD)); | ||
9550 | sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); | ||
9551 | if (sg_list_qp == ASC_QLINK_END) { | ||
9552 | AscSetLibErrorCode(asc_dvc, | ||
9553 | ASCQ_ERR_SG_Q_LINKS); | ||
9554 | scsiq->d3.done_stat = QD_WITH_ERROR; | ||
9555 | scsiq->d3.host_stat = | ||
9556 | QHSTA_D_QDONE_SG_LIST_CORRUPTED; | ||
9557 | goto FATAL_ERR_QDONE; | ||
9558 | } | ||
9559 | AscWriteLramByte(iop_base, | ||
9560 | (ushort)(sg_q_addr + (ushort) | ||
9561 | ASC_SCSIQ_B_STATUS), | ||
9562 | QS_FREE); | ||
9563 | } | ||
9564 | n_q_used = sg_queue_cnt + 1; | ||
9565 | AscPutVarDoneQTail(iop_base, sg_list_qp); | ||
9566 | } | ||
9567 | if (asc_dvc->queue_full_or_busy & target_id) { | ||
9568 | cur_target_qng = AscReadLramByte(iop_base, | ||
9569 | (ushort)((ushort) | ||
9570 | ASC_QADR_BEG | ||
9571 | + (ushort) | ||
9572 | scsiq->d2. | ||
9573 | target_ix)); | ||
9574 | if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { | ||
9575 | scsi_busy = AscReadLramByte(iop_base, (ushort) | ||
9576 | ASCV_SCSIBUSY_B); | ||
9577 | scsi_busy &= ~target_id; | ||
9578 | AscWriteLramByte(iop_base, | ||
9579 | (ushort)ASCV_SCSIBUSY_B, | ||
9580 | scsi_busy); | ||
9581 | asc_dvc->queue_full_or_busy &= ~target_id; | ||
9582 | } | ||
9583 | } | ||
9584 | if (asc_dvc->cur_total_qng >= n_q_used) { | ||
9585 | asc_dvc->cur_total_qng -= n_q_used; | ||
9586 | if (asc_dvc->cur_dvc_qng[tid_no] != 0) { | ||
9587 | asc_dvc->cur_dvc_qng[tid_no]--; | ||
9588 | } | ||
9589 | } else { | ||
9590 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); | ||
9591 | scsiq->d3.done_stat = QD_WITH_ERROR; | ||
9592 | goto FATAL_ERR_QDONE; | ||
9593 | } | ||
9594 | if ((scsiq->d2.srb_ptr == 0UL) || | ||
9595 | ((scsiq->q_status & QS_ABORTED) != 0)) { | ||
9596 | return (0x11); | ||
9597 | } else if (scsiq->q_status == QS_DONE) { | ||
9598 | false_overrun = FALSE; | ||
9599 | if (scsiq->extra_bytes != 0) { | ||
9600 | scsiq->remain_bytes += | ||
9601 | (ADV_DCNT)scsiq->extra_bytes; | ||
9602 | } | ||
9603 | if (scsiq->d3.done_stat == QD_WITH_ERROR) { | ||
9604 | if (scsiq->d3.host_stat == | ||
9605 | QHSTA_M_DATA_OVER_RUN) { | ||
9606 | if ((scsiq-> | ||
9607 | cntl & (QC_DATA_IN | QC_DATA_OUT)) | ||
9608 | == 0) { | ||
9609 | scsiq->d3.done_stat = | ||
9610 | QD_NO_ERROR; | ||
9611 | scsiq->d3.host_stat = | ||
9612 | QHSTA_NO_ERROR; | ||
9613 | } else if (false_overrun) { | ||
9614 | scsiq->d3.done_stat = | ||
9615 | QD_NO_ERROR; | ||
9616 | scsiq->d3.host_stat = | ||
9617 | QHSTA_NO_ERROR; | ||
9618 | } | ||
9619 | } else if (scsiq->d3.host_stat == | ||
9620 | QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { | ||
9621 | AscStopChip(iop_base); | ||
9622 | AscSetChipControl(iop_base, | ||
9623 | (uchar)(CC_SCSI_RESET | ||
9624 | | CC_HALT)); | ||
9625 | udelay(60); | ||
9626 | AscSetChipControl(iop_base, CC_HALT); | ||
9627 | AscSetChipStatus(iop_base, | ||
9628 | CIW_CLR_SCSI_RESET_INT); | ||
9629 | AscSetChipStatus(iop_base, 0); | ||
9630 | AscSetChipControl(iop_base, 0); | ||
9631 | } | ||
9632 | } | ||
9633 | if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { | ||
9634 | asc_isr_callback(asc_dvc, scsiq); | ||
9635 | } else { | ||
9636 | if ((AscReadLramByte(iop_base, | ||
9637 | (ushort)(q_addr + (ushort) | ||
9638 | ASC_SCSIQ_CDB_BEG)) | ||
9639 | == START_STOP)) { | ||
9640 | asc_dvc->unit_not_ready &= ~target_id; | ||
9641 | if (scsiq->d3.done_stat != QD_NO_ERROR) { | ||
9642 | asc_dvc->start_motor &= | ||
9643 | ~target_id; | ||
9644 | } | ||
9645 | } | ||
9646 | } | ||
9647 | return (1); | ||
9648 | } else { | ||
9649 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); | ||
9650 | FATAL_ERR_QDONE: | ||
9651 | if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { | ||
9652 | asc_isr_callback(asc_dvc, scsiq); | ||
9653 | } | ||
9654 | return (0x80); | ||
9655 | } | ||
9656 | } | ||
9657 | return (0); | ||
9658 | } | ||
9659 | |||
9660 | static int AscISR(ASC_DVC_VAR *asc_dvc) | ||
9661 | { | ||
9662 | ASC_CS_TYPE chipstat; | ||
9663 | PortAddr iop_base; | ||
9664 | ushort saved_ram_addr; | ||
9665 | uchar ctrl_reg; | ||
9666 | uchar saved_ctrl_reg; | ||
9667 | int int_pending; | ||
9668 | int status; | ||
9669 | uchar host_flag; | ||
9670 | |||
9671 | iop_base = asc_dvc->iop_base; | ||
9672 | int_pending = FALSE; | ||
9673 | |||
9674 | if (AscIsIntPending(iop_base) == 0) | ||
9675 | return int_pending; | ||
9676 | |||
9677 | if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) { | ||
9678 | return ERR; | ||
9679 | } | ||
9680 | if (asc_dvc->in_critical_cnt != 0) { | ||
9681 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); | ||
9682 | return ERR; | ||
9683 | } | ||
9684 | if (asc_dvc->is_in_int) { | ||
9685 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); | ||
9686 | return ERR; | ||
9687 | } | ||
9688 | asc_dvc->is_in_int = TRUE; | ||
9689 | ctrl_reg = AscGetChipControl(iop_base); | ||
9690 | saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | | ||
9691 | CC_SINGLE_STEP | CC_DIAG | CC_TEST)); | ||
9692 | chipstat = AscGetChipStatus(iop_base); | ||
9693 | if (chipstat & CSW_SCSI_RESET_LATCH) { | ||
9694 | if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { | ||
9695 | int i = 10; | ||
9696 | int_pending = TRUE; | ||
9697 | asc_dvc->sdtr_done = 0; | ||
9698 | saved_ctrl_reg &= (uchar)(~CC_HALT); | ||
9699 | while ((AscGetChipStatus(iop_base) & | ||
9700 | CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) { | ||
9701 | mdelay(100); | ||
9702 | } | ||
9703 | AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); | ||
9704 | AscSetChipControl(iop_base, CC_HALT); | ||
9705 | AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); | ||
9706 | AscSetChipStatus(iop_base, 0); | ||
9707 | chipstat = AscGetChipStatus(iop_base); | ||
9708 | } | ||
9709 | } | ||
9710 | saved_ram_addr = AscGetChipLramAddr(iop_base); | ||
9711 | host_flag = AscReadLramByte(iop_base, | ||
9712 | ASCV_HOST_FLAG_B) & | ||
9713 | (uchar)(~ASC_HOST_FLAG_IN_ISR); | ||
9714 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, | ||
9715 | (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR)); | ||
9716 | if ((chipstat & CSW_INT_PENDING) || (int_pending)) { | ||
9717 | AscAckInterrupt(iop_base); | ||
9718 | int_pending = TRUE; | ||
9719 | if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) { | ||
9720 | if (AscIsrChipHalted(asc_dvc) == ERR) { | ||
9721 | goto ISR_REPORT_QDONE_FATAL_ERROR; | ||
9722 | } else { | ||
9723 | saved_ctrl_reg &= (uchar)(~CC_HALT); | ||
9724 | } | ||
9725 | } else { | ||
9726 | ISR_REPORT_QDONE_FATAL_ERROR: | ||
9727 | if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { | ||
9728 | while (((status = | ||
9729 | AscIsrQDone(asc_dvc)) & 0x01) != 0) { | ||
9730 | } | ||
9731 | } else { | ||
9732 | do { | ||
9733 | if ((status = | ||
9734 | AscIsrQDone(asc_dvc)) == 1) { | ||
9735 | break; | ||
9736 | } | ||
9737 | } while (status == 0x11); | ||
9738 | } | ||
9739 | if ((status & 0x80) != 0) | ||
9740 | int_pending = ERR; | ||
9741 | } | ||
9742 | } | ||
9743 | AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); | ||
9744 | AscSetChipLramAddr(iop_base, saved_ram_addr); | ||
9745 | AscSetChipControl(iop_base, saved_ctrl_reg); | ||
9746 | asc_dvc->is_in_int = FALSE; | ||
9747 | return int_pending; | ||
9748 | } | ||
9749 | |||
9750 | /* | ||
9751 | * advansys_reset() | ||
9752 | * | ||
9753 | * Reset the bus associated with the command 'scp'. | ||
9754 | * | ||
9755 | * This function runs its own thread. Interrupts must be blocked but | ||
9756 | * sleeping is allowed and no locking other than for host structures is | ||
9757 | * required. Returns SUCCESS or FAILED. | ||
9758 | */ | ||
9759 | static int advansys_reset(struct scsi_cmnd *scp) | ||
9760 | { | ||
9761 | struct Scsi_Host *shost; | ||
9762 | asc_board_t *boardp; | ||
9763 | ASC_DVC_VAR *asc_dvc_varp; | ||
9764 | ADV_DVC_VAR *adv_dvc_varp; | ||
9765 | ulong flags; | ||
9766 | int status; | ||
9767 | int ret = SUCCESS; | ||
9768 | |||
9769 | ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp); | ||
9770 | |||
9771 | #ifdef ADVANSYS_STATS | ||
9772 | if (scp->device->host != NULL) { | ||
9773 | ASC_STATS(scp->device->host, reset); | ||
9774 | } | ||
9775 | #endif /* ADVANSYS_STATS */ | ||
9776 | |||
9777 | if ((shost = scp->device->host) == NULL) { | ||
9778 | scp->result = HOST_BYTE(DID_ERROR); | ||
9779 | return FAILED; | ||
9780 | } | ||
9781 | |||
9782 | boardp = ASC_BOARDP(shost); | ||
9783 | |||
9784 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", | ||
9785 | boardp->id); | ||
9786 | /* | ||
9787 | * Check for re-entrancy. | ||
9788 | */ | ||
9789 | spin_lock_irqsave(&boardp->lock, flags); | ||
9790 | if (boardp->flags & ASC_HOST_IN_RESET) { | ||
9791 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
9792 | return FAILED; | ||
9793 | } | ||
9794 | boardp->flags |= ASC_HOST_IN_RESET; | ||
9795 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
9796 | |||
9797 | if (ASC_NARROW_BOARD(boardp)) { | ||
9798 | /* | ||
9799 | * Narrow Board | ||
9800 | */ | ||
9801 | asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; | ||
9802 | |||
9803 | /* | ||
9804 | * Reset the chip and SCSI bus. | ||
9805 | */ | ||
9806 | ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); | ||
9807 | status = AscInitAsc1000Driver(asc_dvc_varp); | ||
9808 | |||
9809 | /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ | ||
9810 | if (asc_dvc_varp->err_code) { | ||
9811 | ASC_PRINT2("advansys_reset: board %d: SCSI bus reset " | ||
9812 | "error: 0x%x\n", boardp->id, | ||
9813 | asc_dvc_varp->err_code); | ||
9814 | ret = FAILED; | ||
9815 | } else if (status) { | ||
9816 | ASC_PRINT2("advansys_reset: board %d: SCSI bus reset " | ||
9817 | "warning: 0x%x\n", boardp->id, status); | ||
9818 | } else { | ||
9819 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset " | ||
9820 | "successful.\n", boardp->id); | ||
9821 | } | ||
9822 | |||
9823 | ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); | ||
9824 | spin_lock_irqsave(&boardp->lock, flags); | ||
9825 | |||
9826 | } else { | ||
9827 | /* | ||
9828 | * Wide Board | ||
9829 | * | ||
9830 | * If the suggest reset bus flags are set, then reset the bus. | ||
9831 | * Otherwise only reset the device. | ||
9832 | */ | ||
9833 | adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; | ||
9834 | |||
9835 | /* | ||
9836 | * Reset the target's SCSI bus. | ||
9837 | */ | ||
9838 | ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); | ||
9839 | switch (AdvResetChipAndSB(adv_dvc_varp)) { | ||
9840 | case ASC_TRUE: | ||
9841 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset " | ||
9842 | "successful.\n", boardp->id); | ||
9843 | break; | ||
9844 | case ASC_FALSE: | ||
9845 | default: | ||
9846 | ASC_PRINT1("advansys_reset: board %d: SCSI bus reset " | ||
9847 | "error.\n", boardp->id); | ||
9848 | ret = FAILED; | ||
9849 | break; | ||
9850 | } | ||
9851 | spin_lock_irqsave(&boardp->lock, flags); | ||
9852 | AdvISR(adv_dvc_varp); | ||
9853 | } | ||
9854 | /* Board lock is held. */ | ||
9855 | |||
9856 | /* Save the time of the most recently completed reset. */ | ||
9857 | boardp->last_reset = jiffies; | ||
9858 | |||
9859 | /* Clear reset flag. */ | ||
9860 | boardp->flags &= ~ASC_HOST_IN_RESET; | ||
9861 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
9862 | |||
9863 | ASC_DBG1(1, "advansys_reset: ret %d\n", ret); | ||
9864 | |||
9865 | return ret; | ||
9866 | } | ||
9867 | |||
9868 | /* | ||
9869 | * advansys_biosparam() | ||
9870 | * | ||
9871 | * Translate disk drive geometry if the "BIOS greater than 1 GB" | ||
9872 | * support is enabled for a drive. | ||
9873 | * | ||
9874 | * ip (information pointer) is an int array with the following definition: | ||
9875 | * ip[0]: heads | ||
9876 | * ip[1]: sectors | ||
9877 | * ip[2]: cylinders | ||
9878 | */ | ||
9879 | static int | ||
9880 | advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, | ||
9881 | sector_t capacity, int ip[]) | ||
9882 | { | ||
9883 | asc_board_t *boardp; | ||
9884 | |||
9885 | ASC_DBG(1, "advansys_biosparam: begin\n"); | ||
9886 | ASC_STATS(sdev->host, biosparam); | ||
9887 | boardp = ASC_BOARDP(sdev->host); | ||
9888 | if (ASC_NARROW_BOARD(boardp)) { | ||
9889 | if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & | ||
9890 | ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { | ||
9891 | ip[0] = 255; | ||
9892 | ip[1] = 63; | ||
9893 | } else { | ||
9894 | ip[0] = 64; | ||
9895 | ip[1] = 32; | ||
9896 | } | ||
9897 | } else { | ||
9898 | if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & | ||
9899 | BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { | ||
9900 | ip[0] = 255; | ||
9901 | ip[1] = 63; | ||
9902 | } else { | ||
9903 | ip[0] = 64; | ||
9904 | ip[1] = 32; | ||
9905 | } | ||
9906 | } | ||
9907 | ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); | ||
9908 | ASC_DBG(1, "advansys_biosparam: end\n"); | ||
9909 | return 0; | ||
9910 | } | ||
9911 | |||
9912 | /* | ||
9913 | * First-level interrupt handler. | ||
9914 | * | ||
9915 | * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host. | ||
9916 | */ | ||
9917 | static irqreturn_t advansys_interrupt(int irq, void *dev_id) | ||
9918 | { | ||
9919 | unsigned long flags; | ||
9920 | struct Scsi_Host *shost = dev_id; | ||
9921 | asc_board_t *boardp = ASC_BOARDP(shost); | ||
9922 | irqreturn_t result = IRQ_NONE; | ||
9923 | |||
9924 | ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp); | ||
9925 | spin_lock_irqsave(&boardp->lock, flags); | ||
9926 | if (ASC_NARROW_BOARD(boardp)) { | ||
9927 | if (AscIsIntPending(shost->io_port)) { | ||
9928 | result = IRQ_HANDLED; | ||
9929 | ASC_STATS(shost, interrupt); | ||
9930 | ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); | ||
9931 | AscISR(&boardp->dvc_var.asc_dvc_var); | ||
9932 | } | ||
9933 | } else { | ||
9934 | ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); | ||
9935 | if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { | ||
9936 | result = IRQ_HANDLED; | ||
9937 | ASC_STATS(shost, interrupt); | ||
9938 | } | ||
9939 | } | ||
9940 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
9941 | |||
9942 | ASC_DBG(1, "advansys_interrupt: end\n"); | ||
9943 | return result; | ||
9944 | } | ||
9945 | |||
9946 | static int AscHostReqRiscHalt(PortAddr iop_base) | ||
9947 | { | ||
9948 | int count = 0; | ||
9949 | int sta = 0; | ||
9950 | uchar saved_stop_code; | ||
9951 | |||
9952 | if (AscIsChipHalted(iop_base)) | ||
9953 | return (1); | ||
9954 | saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); | ||
9955 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, | ||
9956 | ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP); | ||
9957 | do { | ||
9958 | if (AscIsChipHalted(iop_base)) { | ||
9959 | sta = 1; | ||
9960 | break; | ||
9961 | } | ||
9962 | mdelay(100); | ||
9963 | } while (count++ < 20); | ||
9964 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); | ||
9965 | return (sta); | ||
9966 | } | ||
9967 | |||
9968 | static int | ||
9969 | AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) | ||
9970 | { | ||
9971 | int sta = FALSE; | ||
9972 | |||
9973 | if (AscHostReqRiscHalt(iop_base)) { | ||
9974 | sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); | ||
9975 | AscStartChip(iop_base); | ||
9976 | } | ||
9977 | return sta; | ||
9978 | } | ||
9979 | |||
9980 | static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev) | ||
9981 | { | ||
9982 | char type = sdev->type; | ||
9983 | ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id; | ||
9984 | |||
9985 | if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN)) | ||
9986 | return; | ||
9987 | if (asc_dvc->init_sdtr & tid_bits) | ||
9988 | return; | ||
9989 | |||
9990 | if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0)) | ||
9991 | asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; | ||
9992 | |||
9993 | asc_dvc->pci_fix_asyn_xfer |= tid_bits; | ||
9994 | if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) || | ||
9995 | (type == TYPE_ROM) || (type == TYPE_TAPE)) | ||
9996 | asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; | ||
9997 | |||
9998 | if (asc_dvc->pci_fix_asyn_xfer & tid_bits) | ||
9999 | AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id, | ||
10000 | ASYN_SDTR_DATA_FIX_PCI_REV_AB); | ||
10001 | } | ||
10002 | |||
10003 | static void | ||
10004 | advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc) | ||
10005 | { | ||
10006 | ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id; | ||
10007 | ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng; | ||
10008 | |||
10009 | if (sdev->lun == 0) { | ||
10010 | ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr; | ||
10011 | if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) { | ||
10012 | asc_dvc->init_sdtr |= tid_bit; | ||
10013 | } else { | ||
10014 | asc_dvc->init_sdtr &= ~tid_bit; | ||
10015 | } | ||
10016 | |||
10017 | if (orig_init_sdtr != asc_dvc->init_sdtr) | ||
10018 | AscAsyncFix(asc_dvc, sdev); | ||
10019 | } | ||
10020 | |||
10021 | if (sdev->tagged_supported) { | ||
10022 | if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) { | ||
10023 | if (sdev->lun == 0) { | ||
10024 | asc_dvc->cfg->can_tagged_qng |= tid_bit; | ||
10025 | asc_dvc->use_tagged_qng |= tid_bit; | ||
10026 | } | ||
10027 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, | ||
10028 | asc_dvc->max_dvc_qng[sdev->id]); | ||
10029 | } | ||
10030 | } else { | ||
10031 | if (sdev->lun == 0) { | ||
10032 | asc_dvc->cfg->can_tagged_qng &= ~tid_bit; | ||
10033 | asc_dvc->use_tagged_qng &= ~tid_bit; | ||
10034 | } | ||
10035 | scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); | ||
10036 | } | ||
10037 | |||
10038 | if ((sdev->lun == 0) && | ||
10039 | (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) { | ||
10040 | AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, | ||
10041 | asc_dvc->cfg->disc_enable); | ||
10042 | AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, | ||
10043 | asc_dvc->use_tagged_qng); | ||
10044 | AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, | ||
10045 | asc_dvc->cfg->can_tagged_qng); | ||
10046 | |||
10047 | asc_dvc->max_dvc_qng[sdev->id] = | ||
10048 | asc_dvc->cfg->max_tag_qng[sdev->id]; | ||
10049 | AscWriteLramByte(asc_dvc->iop_base, | ||
10050 | (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id), | ||
10051 | asc_dvc->max_dvc_qng[sdev->id]); | ||
10052 | } | ||
10053 | } | ||
10054 | |||
10055 | /* | ||
10056 | * Wide Transfers | ||
10057 | * | ||
10058 | * If the EEPROM enabled WDTR for the device and the device supports wide | ||
10059 | * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and | ||
10060 | * write the new value to the microcode. | ||
10061 | */ | ||
10062 | static void | ||
10063 | advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask) | ||
10064 | { | ||
10065 | unsigned short cfg_word; | ||
10066 | AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); | ||
10067 | if ((cfg_word & tidmask) != 0) | ||
10068 | return; | ||
10069 | |||
10070 | cfg_word |= tidmask; | ||
10071 | AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); | ||
10072 | |||
10073 | /* | ||
10074 | * Clear the microcode SDTR and WDTR negotiation done indicators for | ||
10075 | * the target to cause it to negotiate with the new setting set above. | ||
10076 | * WDTR when accepted causes the target to enter asynchronous mode, so | ||
10077 | * SDTR must be negotiated. | ||
10078 | */ | ||
10079 | AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
10080 | cfg_word &= ~tidmask; | ||
10081 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
10082 | AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); | ||
10083 | cfg_word &= ~tidmask; | ||
10084 | AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); | ||
10085 | } | ||
10086 | |||
10087 | /* | ||
10088 | * Synchronous Transfers | ||
10089 | * | ||
10090 | * If the EEPROM enabled SDTR for the device and the device | ||
10091 | * supports synchronous transfers, then turn on the device's | ||
10092 | * 'sdtr_able' bit. Write the new value to the microcode. | ||
10093 | */ | ||
10094 | static void | ||
10095 | advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask) | ||
10096 | { | ||
10097 | unsigned short cfg_word; | ||
10098 | AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); | ||
10099 | if ((cfg_word & tidmask) != 0) | ||
10100 | return; | ||
10101 | |||
10102 | cfg_word |= tidmask; | ||
10103 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); | ||
10104 | |||
10105 | /* | ||
10106 | * Clear the microcode "SDTR negotiation" done indicator for the | ||
10107 | * target to cause it to negotiate with the new setting set above. | ||
10108 | */ | ||
10109 | AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
10110 | cfg_word &= ~tidmask; | ||
10111 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); | ||
10112 | } | ||
10113 | |||
10114 | /* | ||
10115 | * PPR (Parallel Protocol Request) Capable | ||
10116 | * | ||
10117 | * If the device supports DT mode, then it must be PPR capable. | ||
10118 | * The PPR message will be used in place of the SDTR and WDTR | ||
10119 | * messages to negotiate synchronous speed and offset, transfer | ||
10120 | * width, and protocol options. | ||
10121 | */ | ||
10122 | static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc, | ||
10123 | AdvPortAddr iop_base, unsigned short tidmask) | ||
10124 | { | ||
10125 | AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able); | ||
10126 | adv_dvc->ppr_able |= tidmask; | ||
10127 | AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able); | ||
10128 | } | ||
10129 | |||
10130 | static void | ||
10131 | advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc) | ||
10132 | { | ||
10133 | AdvPortAddr iop_base = adv_dvc->iop_base; | ||
10134 | unsigned short tidmask = 1 << sdev->id; | ||
10135 | |||
10136 | if (sdev->lun == 0) { | ||
10137 | /* | ||
10138 | * Handle WDTR, SDTR, and Tag Queuing. If the feature | ||
10139 | * is enabled in the EEPROM and the device supports the | ||
10140 | * feature, then enable it in the microcode. | ||
10141 | */ | ||
10142 | |||
10143 | if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr) | ||
10144 | advansys_wide_enable_wdtr(iop_base, tidmask); | ||
10145 | if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr) | ||
10146 | advansys_wide_enable_sdtr(iop_base, tidmask); | ||
10147 | if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr) | ||
10148 | advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask); | ||
10149 | |||
10150 | /* | ||
10151 | * Tag Queuing is disabled for the BIOS which runs in polled | ||
10152 | * mode and would see no benefit from Tag Queuing. Also by | ||
10153 | * disabling Tag Queuing in the BIOS devices with Tag Queuing | ||
10154 | * bugs will at least work with the BIOS. | ||
10155 | */ | ||
10156 | if ((adv_dvc->tagqng_able & tidmask) && | ||
10157 | sdev->tagged_supported) { | ||
10158 | unsigned short cfg_word; | ||
10159 | AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); | ||
10160 | cfg_word |= tidmask; | ||
10161 | AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, | ||
10162 | cfg_word); | ||
10163 | AdvWriteByteLram(iop_base, | ||
10164 | ASC_MC_NUMBER_OF_MAX_CMD + sdev->id, | ||
10165 | adv_dvc->max_dvc_qng); | ||
10166 | } | ||
10167 | } | ||
10168 | |||
10169 | if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) { | ||
10170 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, | ||
10171 | adv_dvc->max_dvc_qng); | ||
10172 | } else { | ||
10173 | scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); | ||
10174 | } | ||
10175 | } | ||
10176 | |||
10177 | /* | ||
10178 | * Set the number of commands to queue per device for the | ||
10179 | * specified host adapter. | ||
10180 | */ | ||
10181 | static int advansys_slave_configure(struct scsi_device *sdev) | ||
10182 | { | ||
10183 | asc_board_t *boardp = ASC_BOARDP(sdev->host); | ||
10184 | boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; | ||
10185 | |||
10186 | /* | ||
10187 | * Save a pointer to the sdev and set its initial/maximum | ||
10188 | * queue depth. Only save the pointer for a lun0 dev though. | ||
10189 | */ | ||
10190 | if (sdev->lun == 0) | ||
10191 | boardp->device[sdev->id] = sdev; | ||
10192 | |||
10193 | if (ASC_NARROW_BOARD(boardp)) | ||
10194 | advansys_narrow_slave_configure(sdev, | ||
10195 | &boardp->dvc_var.asc_dvc_var); | ||
10196 | else | ||
10197 | advansys_wide_slave_configure(sdev, | ||
10198 | &boardp->dvc_var.adv_dvc_var); | ||
10199 | |||
10200 | return 0; | ||
10201 | } | ||
10202 | |||
10203 | /* | ||
10204 | * Build a request structure for the Asc Library (Narrow Board). | ||
10205 | * | ||
10206 | * The global structures 'asc_scsi_q' and 'asc_sg_head' are | ||
10207 | * used to build the request. | ||
10208 | * | ||
10209 | * If an error occurs, then return ASC_ERROR. | ||
10210 | */ | ||
10211 | static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | ||
10212 | { | ||
10213 | /* | ||
10214 | * Mutually exclusive access is required to 'asc_scsi_q' and | ||
10215 | * 'asc_sg_head' until after the request is started. | ||
10216 | */ | ||
10217 | memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); | ||
10218 | |||
10219 | /* | ||
10220 | * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. | ||
10221 | */ | ||
10222 | asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); | ||
10223 | |||
10224 | /* | ||
10225 | * Build the ASC_SCSI_Q request. | ||
10226 | */ | ||
10227 | asc_scsi_q.cdbptr = &scp->cmnd[0]; | ||
10228 | asc_scsi_q.q2.cdb_len = scp->cmd_len; | ||
10229 | asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); | ||
10230 | asc_scsi_q.q1.target_lun = scp->device->lun; | ||
10231 | asc_scsi_q.q2.target_ix = | ||
10232 | ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); | ||
10233 | asc_scsi_q.q1.sense_addr = | ||
10234 | cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); | ||
10235 | asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); | ||
10236 | |||
10237 | /* | ||
10238 | * If there are any outstanding requests for the current target, | ||
10239 | * then every 255th request send an ORDERED request. This heuristic | ||
10240 | * tries to retain the benefit of request sorting while preventing | ||
10241 | * request starvation. 255 is the max number of tags or pending commands | ||
10242 | * a device may have outstanding. | ||
10243 | * | ||
10244 | * The request count is incremented below for every successfully | ||
10245 | * started request. | ||
10246 | * | ||
10247 | */ | ||
10248 | if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && | ||
10249 | (boardp->reqcnt[scp->device->id] % 255) == 0) { | ||
10250 | asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; | ||
10251 | } else { | ||
10252 | asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; | ||
10253 | } | ||
10254 | |||
10255 | /* | ||
10256 | * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather | ||
10257 | * buffer command. | ||
10258 | */ | ||
10259 | if (scp->use_sg == 0) { | ||
10260 | /* | ||
10261 | * CDB request of single contiguous buffer. | ||
10262 | */ | ||
10263 | ASC_STATS(scp->device->host, cont_cnt); | ||
10264 | scp->SCp.dma_handle = scp->request_bufflen ? | ||
10265 | dma_map_single(boardp->dev, scp->request_buffer, | ||
10266 | scp->request_bufflen, | ||
10267 | scp->sc_data_direction) : 0; | ||
10268 | asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); | ||
10269 | asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); | ||
10270 | ASC_STATS_ADD(scp->device->host, cont_xfer, | ||
10271 | ASC_CEILING(scp->request_bufflen, 512)); | ||
10272 | asc_scsi_q.q1.sg_queue_cnt = 0; | ||
10273 | asc_scsi_q.sg_head = NULL; | ||
10274 | } else { | ||
10275 | /* | ||
10276 | * CDB scatter-gather request list. | ||
10277 | */ | ||
10278 | int sgcnt; | ||
10279 | int use_sg; | ||
10280 | struct scatterlist *slp; | ||
10281 | |||
10282 | slp = (struct scatterlist *)scp->request_buffer; | ||
10283 | use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg, | ||
10284 | scp->sc_data_direction); | ||
10285 | |||
10286 | if (use_sg > scp->device->host->sg_tablesize) { | ||
10287 | ASC_PRINT3("asc_build_req: board %d: use_sg %d > " | ||
10288 | "sg_tablesize %d\n", boardp->id, use_sg, | ||
10289 | scp->device->host->sg_tablesize); | ||
10290 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, | ||
10291 | scp->sc_data_direction); | ||
10292 | scp->result = HOST_BYTE(DID_ERROR); | ||
10293 | return ASC_ERROR; | ||
10294 | } | ||
10295 | |||
10296 | ASC_STATS(scp->device->host, sg_cnt); | ||
10297 | |||
10298 | /* | ||
10299 | * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q | ||
10300 | * structure to point to it. | ||
10301 | */ | ||
10302 | memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); | ||
10303 | |||
10304 | asc_scsi_q.q1.cntl |= QC_SG_HEAD; | ||
10305 | asc_scsi_q.sg_head = &asc_sg_head; | ||
10306 | asc_scsi_q.q1.data_cnt = 0; | ||
10307 | asc_scsi_q.q1.data_addr = 0; | ||
10308 | /* This is a byte value, otherwise it would need to be swapped. */ | ||
10309 | asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; | ||
10310 | ASC_STATS_ADD(scp->device->host, sg_elem, | ||
10311 | asc_sg_head.entry_cnt); | ||
10312 | |||
10313 | /* | ||
10314 | * Convert scatter-gather list into ASC_SG_HEAD list. | ||
10315 | */ | ||
10316 | for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { | ||
10317 | asc_sg_head.sg_list[sgcnt].addr = | ||
10318 | cpu_to_le32(sg_dma_address(slp)); | ||
10319 | asc_sg_head.sg_list[sgcnt].bytes = | ||
10320 | cpu_to_le32(sg_dma_len(slp)); | ||
10321 | ASC_STATS_ADD(scp->device->host, sg_xfer, | ||
10322 | ASC_CEILING(sg_dma_len(slp), 512)); | ||
10323 | } | ||
10324 | } | ||
10325 | |||
10326 | ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); | ||
10327 | ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); | ||
10328 | |||
10329 | return ASC_NOERROR; | ||
10330 | } | ||
10331 | |||
10332 | /* | ||
10333 | * Build scatter-gather list for Adv Library (Wide Board). | ||
10334 | * | ||
10335 | * Additional ADV_SG_BLOCK structures will need to be allocated | ||
10336 | * if the total number of scatter-gather elements exceeds | ||
10337 | * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are | ||
10338 | * assumed to be physically contiguous. | ||
10339 | * | ||
10340 | * Return: | ||
10341 | * ADV_SUCCESS(1) - SG List successfully created | ||
10342 | * ADV_ERROR(-1) - SG List creation failed | ||
10343 | */ | ||
10344 | static int | ||
10345 | adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, | ||
10346 | int use_sg) | ||
10347 | { | ||
10348 | adv_sgblk_t *sgblkp; | ||
10349 | ADV_SCSI_REQ_Q *scsiqp; | ||
10350 | struct scatterlist *slp; | ||
10351 | int sg_elem_cnt; | ||
10352 | ADV_SG_BLOCK *sg_block, *prev_sg_block; | ||
10353 | ADV_PADDR sg_block_paddr; | ||
10354 | int i; | ||
10355 | |||
10356 | scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); | ||
10357 | slp = (struct scatterlist *)scp->request_buffer; | ||
10358 | sg_elem_cnt = use_sg; | ||
10359 | prev_sg_block = NULL; | ||
10360 | reqp->sgblkp = NULL; | ||
10361 | |||
10362 | for (;;) { | ||
10363 | /* | ||
10364 | * Allocate a 'adv_sgblk_t' structure from the board free | ||
10365 | * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK | ||
10366 | * (15) scatter-gather elements. | ||
10367 | */ | ||
10368 | if ((sgblkp = boardp->adv_sgblkp) == NULL) { | ||
10369 | ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); | ||
10370 | ASC_STATS(scp->device->host, adv_build_nosg); | ||
10371 | |||
10372 | /* | ||
10373 | * Allocation failed. Free 'adv_sgblk_t' structures | ||
10374 | * already allocated for the request. | ||
10375 | */ | ||
10376 | while ((sgblkp = reqp->sgblkp) != NULL) { | ||
10377 | /* Remove 'sgblkp' from the request list. */ | ||
10378 | reqp->sgblkp = sgblkp->next_sgblkp; | ||
10379 | |||
10380 | /* Add 'sgblkp' to the board free list. */ | ||
10381 | sgblkp->next_sgblkp = boardp->adv_sgblkp; | ||
10382 | boardp->adv_sgblkp = sgblkp; | ||
10383 | } | ||
10384 | return ASC_BUSY; | ||
10385 | } | ||
10386 | |||
10387 | /* Complete 'adv_sgblk_t' board allocation. */ | ||
10388 | boardp->adv_sgblkp = sgblkp->next_sgblkp; | ||
10389 | sgblkp->next_sgblkp = NULL; | ||
10390 | |||
10391 | /* | ||
10392 | * Get 8 byte aligned virtual and physical addresses | ||
10393 | * for the allocated ADV_SG_BLOCK structure. | ||
10394 | */ | ||
10395 | sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block); | ||
10396 | sg_block_paddr = virt_to_bus(sg_block); | ||
10397 | |||
10398 | /* | ||
10399 | * Check if this is the first 'adv_sgblk_t' for the | ||
10400 | * request. | ||
10401 | */ | ||
10402 | if (reqp->sgblkp == NULL) { | ||
10403 | /* Request's first scatter-gather block. */ | ||
10404 | reqp->sgblkp = sgblkp; | ||
10405 | |||
10406 | /* | ||
10407 | * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical | ||
10408 | * address pointers. | ||
10409 | */ | ||
10410 | scsiqp->sg_list_ptr = sg_block; | ||
10411 | scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr); | ||
10412 | } else { | ||
10413 | /* Request's second or later scatter-gather block. */ | ||
10414 | sgblkp->next_sgblkp = reqp->sgblkp; | ||
10415 | reqp->sgblkp = sgblkp; | ||
10416 | |||
10417 | /* | ||
10418 | * Point the previous ADV_SG_BLOCK structure to | ||
10419 | * the newly allocated ADV_SG_BLOCK structure. | ||
10420 | */ | ||
10421 | prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr); | ||
10422 | } | ||
10423 | |||
10424 | for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { | ||
10425 | sg_block->sg_list[i].sg_addr = | ||
10426 | cpu_to_le32(sg_dma_address(slp)); | ||
10427 | sg_block->sg_list[i].sg_count = | ||
10428 | cpu_to_le32(sg_dma_len(slp)); | ||
10429 | ASC_STATS_ADD(scp->device->host, sg_xfer, | ||
10430 | ASC_CEILING(sg_dma_len(slp), 512)); | ||
10431 | |||
10432 | if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ | ||
10433 | sg_block->sg_cnt = i + 1; | ||
10434 | sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ | ||
10435 | return ADV_SUCCESS; | ||
10436 | } | ||
10437 | slp++; | ||
10438 | } | ||
10439 | sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; | ||
10440 | prev_sg_block = sg_block; | ||
10441 | } | ||
10442 | } | ||
10443 | |||
10444 | /* | ||
10445 | * Build a request structure for the Adv Library (Wide Board). | ||
10446 | * | ||
10447 | * If an adv_req_t can not be allocated to issue the request, | ||
10448 | * then return ASC_BUSY. If an error occurs, then return ASC_ERROR. | ||
10449 | * | ||
10450 | * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the | ||
10451 | * microcode for DMA addresses or math operations are byte swapped | ||
10452 | * to little-endian order. | ||
10453 | */ | ||
10454 | static int | ||
10455 | adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, | ||
10456 | ADV_SCSI_REQ_Q **adv_scsiqpp) | ||
10457 | { | ||
10458 | adv_req_t *reqp; | ||
10459 | ADV_SCSI_REQ_Q *scsiqp; | ||
10460 | int i; | ||
10461 | int ret; | ||
10462 | |||
10463 | /* | ||
10464 | * Allocate an adv_req_t structure from the board to execute | ||
10465 | * the command. | ||
10466 | */ | ||
10467 | if (boardp->adv_reqp == NULL) { | ||
10468 | ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); | ||
10469 | ASC_STATS(scp->device->host, adv_build_noreq); | ||
10470 | return ASC_BUSY; | ||
10471 | } else { | ||
10472 | reqp = boardp->adv_reqp; | ||
10473 | boardp->adv_reqp = reqp->next_reqp; | ||
10474 | reqp->next_reqp = NULL; | ||
10475 | } | ||
10476 | |||
10477 | /* | ||
10478 | * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. | ||
10479 | */ | ||
10480 | scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); | ||
10481 | |||
10482 | /* | ||
10483 | * Initialize the structure. | ||
10484 | */ | ||
10485 | scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; | ||
10486 | |||
10487 | /* | ||
10488 | * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. | ||
10489 | */ | ||
10490 | scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); | ||
10491 | |||
10492 | /* | ||
10493 | * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. | ||
10494 | */ | ||
10495 | reqp->cmndp = scp; | ||
10496 | |||
10497 | /* | ||
10498 | * Build the ADV_SCSI_REQ_Q request. | ||
10499 | */ | ||
10500 | |||
10501 | /* Set CDB length and copy it to the request structure. */ | ||
10502 | scsiqp->cdb_len = scp->cmd_len; | ||
10503 | /* Copy first 12 CDB bytes to cdb[]. */ | ||
10504 | for (i = 0; i < scp->cmd_len && i < 12; i++) { | ||
10505 | scsiqp->cdb[i] = scp->cmnd[i]; | ||
10506 | } | ||
10507 | /* Copy last 4 CDB bytes, if present, to cdb16[]. */ | ||
10508 | for (; i < scp->cmd_len; i++) { | ||
10509 | scsiqp->cdb16[i - 12] = scp->cmnd[i]; | ||
10510 | } | ||
10511 | |||
10512 | scsiqp->target_id = scp->device->id; | ||
10513 | scsiqp->target_lun = scp->device->lun; | ||
10514 | |||
10515 | scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); | ||
10516 | scsiqp->sense_len = sizeof(scp->sense_buffer); | ||
10517 | |||
10518 | /* | ||
10519 | * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather | ||
10520 | * buffer command. | ||
10521 | */ | ||
10522 | |||
10523 | scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); | ||
10524 | scsiqp->vdata_addr = scp->request_buffer; | ||
10525 | scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); | ||
10526 | |||
10527 | if (scp->use_sg == 0) { | ||
10528 | /* | ||
10529 | * CDB request of single contiguous buffer. | ||
10530 | */ | ||
10531 | reqp->sgblkp = NULL; | ||
10532 | scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); | ||
10533 | if (scp->request_bufflen) { | ||
10534 | scsiqp->vdata_addr = scp->request_buffer; | ||
10535 | scp->SCp.dma_handle = | ||
10536 | dma_map_single(boardp->dev, scp->request_buffer, | ||
10537 | scp->request_bufflen, | ||
10538 | scp->sc_data_direction); | ||
10539 | } else { | ||
10540 | scsiqp->vdata_addr = NULL; | ||
10541 | scp->SCp.dma_handle = 0; | ||
10542 | } | ||
10543 | scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); | ||
10544 | scsiqp->sg_list_ptr = NULL; | ||
10545 | scsiqp->sg_real_addr = 0; | ||
10546 | ASC_STATS(scp->device->host, cont_cnt); | ||
10547 | ASC_STATS_ADD(scp->device->host, cont_xfer, | ||
10548 | ASC_CEILING(scp->request_bufflen, 512)); | ||
10549 | } else { | ||
10550 | /* | ||
10551 | * CDB scatter-gather request list. | ||
10552 | */ | ||
10553 | struct scatterlist *slp; | ||
10554 | int use_sg; | ||
10555 | |||
10556 | slp = (struct scatterlist *)scp->request_buffer; | ||
10557 | use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg, | ||
10558 | scp->sc_data_direction); | ||
10559 | |||
10560 | if (use_sg > ADV_MAX_SG_LIST) { | ||
10561 | ASC_PRINT3("adv_build_req: board %d: use_sg %d > " | ||
10562 | "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg, | ||
10563 | scp->device->host->sg_tablesize); | ||
10564 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, | ||
10565 | scp->sc_data_direction); | ||
10566 | scp->result = HOST_BYTE(DID_ERROR); | ||
10567 | |||
10568 | /* | ||
10569 | * Free the 'adv_req_t' structure by adding it back | ||
10570 | * to the board free list. | ||
10571 | */ | ||
10572 | reqp->next_reqp = boardp->adv_reqp; | ||
10573 | boardp->adv_reqp = reqp; | ||
10574 | |||
10575 | return ASC_ERROR; | ||
10576 | } | ||
10577 | |||
10578 | ret = adv_get_sglist(boardp, reqp, scp, use_sg); | ||
10579 | if (ret != ADV_SUCCESS) { | ||
10580 | /* | ||
10581 | * Free the adv_req_t structure by adding it back to | ||
10582 | * the board free list. | ||
10583 | */ | ||
10584 | reqp->next_reqp = boardp->adv_reqp; | ||
10585 | boardp->adv_reqp = reqp; | ||
10586 | |||
10587 | return ret; | ||
10588 | } | ||
10589 | |||
10590 | ASC_STATS(scp->device->host, sg_cnt); | ||
10591 | ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); | ||
10592 | } | ||
10593 | |||
10594 | ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); | ||
10595 | ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); | ||
10596 | |||
10597 | *adv_scsiqpp = scsiqp; | ||
10598 | |||
10599 | return ASC_NOERROR; | ||
10600 | } | ||
10601 | |||
10602 | static int AscSgListToQueue(int sg_list) | ||
10603 | { | ||
10604 | int n_sg_list_qs; | ||
10605 | |||
10606 | n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); | ||
10607 | if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) | ||
10608 | n_sg_list_qs++; | ||
10609 | return n_sg_list_qs + 1; | ||
10610 | } | ||
10611 | |||
10612 | static uint | ||
10613 | AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) | ||
10614 | { | ||
10615 | uint cur_used_qs; | ||
10616 | uint cur_free_qs; | ||
10617 | ASC_SCSI_BIT_ID_TYPE target_id; | ||
10618 | uchar tid_no; | ||
10619 | |||
10620 | target_id = ASC_TIX_TO_TARGET_ID(target_ix); | ||
10621 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
10622 | if ((asc_dvc->unit_not_ready & target_id) || | ||
10623 | (asc_dvc->queue_full_or_busy & target_id)) { | ||
10624 | return 0; | ||
10625 | } | ||
10626 | if (n_qs == 1) { | ||
10627 | cur_used_qs = (uint) asc_dvc->cur_total_qng + | ||
10628 | (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q; | ||
10629 | } else { | ||
10630 | cur_used_qs = (uint) asc_dvc->cur_total_qng + | ||
10631 | (uint) ASC_MIN_FREE_Q; | ||
10632 | } | ||
10633 | if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { | ||
10634 | cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; | ||
10635 | if (asc_dvc->cur_dvc_qng[tid_no] >= | ||
10636 | asc_dvc->max_dvc_qng[tid_no]) { | ||
10637 | return 0; | ||
10638 | } | ||
10639 | return cur_free_qs; | ||
10640 | } | ||
10641 | if (n_qs > 1) { | ||
10642 | if ((n_qs > asc_dvc->last_q_shortage) | ||
10643 | && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { | ||
10644 | asc_dvc->last_q_shortage = n_qs; | ||
10645 | } | ||
10646 | } | ||
10647 | return 0; | ||
10648 | } | ||
10649 | |||
10650 | static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) | ||
10651 | { | ||
10652 | ushort q_addr; | ||
10653 | uchar next_qp; | ||
10654 | uchar q_status; | ||
10655 | |||
10656 | q_addr = ASC_QNO_TO_QADDR(free_q_head); | ||
10657 | q_status = (uchar)AscReadLramByte(iop_base, | ||
10658 | (ushort)(q_addr + | ||
10659 | ASC_SCSIQ_B_STATUS)); | ||
10660 | next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD)); | ||
10661 | if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) | ||
10662 | return next_qp; | ||
10663 | return ASC_QLINK_END; | ||
10664 | } | ||
10665 | |||
10666 | static uchar | ||
10667 | AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) | ||
10668 | { | ||
10669 | uchar i; | ||
10670 | |||
10671 | for (i = 0; i < n_free_q; i++) { | ||
10672 | free_q_head = AscAllocFreeQueue(iop_base, free_q_head); | ||
10673 | if (free_q_head == ASC_QLINK_END) | ||
10674 | break; | ||
10675 | } | ||
10676 | return free_q_head; | ||
10677 | } | ||
10678 | |||
10679 | /* | ||
10680 | * void | ||
10681 | * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) | ||
10682 | * | ||
10683 | * Calling/Exit State: | ||
10684 | * none | ||
10685 | * | ||
10686 | * Description: | ||
10687 | * Output an ASC_SCSI_Q structure to the chip | ||
10688 | */ | ||
10689 | static void | ||
10690 | DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) | ||
10691 | { | ||
10692 | int i; | ||
10693 | |||
10694 | ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); | ||
10695 | AscSetChipLramAddr(iop_base, s_addr); | ||
10696 | for (i = 0; i < 2 * words; i += 2) { | ||
10697 | if (i == 4 || i == 20) { | ||
10698 | continue; | ||
10699 | } | ||
10700 | outpw(iop_base + IOP_RAM_DATA, | ||
10701 | ((ushort)outbuf[i + 1] << 8) | outbuf[i]); | ||
10702 | } | ||
10703 | } | ||
10704 | |||
10705 | static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) | ||
10706 | { | ||
10707 | ushort q_addr; | ||
10708 | uchar tid_no; | ||
10709 | uchar sdtr_data; | ||
10710 | uchar syn_period_ix; | ||
10711 | uchar syn_offset; | ||
10712 | PortAddr iop_base; | ||
10713 | |||
10714 | iop_base = asc_dvc->iop_base; | ||
10715 | if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && | ||
10716 | ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { | ||
10717 | tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); | ||
10718 | sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); | ||
10719 | syn_period_ix = | ||
10720 | (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); | ||
10721 | syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; | ||
10722 | AscMsgOutSDTR(asc_dvc, | ||
10723 | asc_dvc->sdtr_period_tbl[syn_period_ix], | ||
10724 | syn_offset); | ||
10725 | scsiq->q1.cntl |= QC_MSG_OUT; | ||
10726 | } | ||
10727 | q_addr = ASC_QNO_TO_QADDR(q_no); | ||
10728 | if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { | ||
10729 | scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; | ||
10730 | } | ||
10731 | scsiq->q1.status = QS_FREE; | ||
10732 | AscMemWordCopyPtrToLram(iop_base, | ||
10733 | q_addr + ASC_SCSIQ_CDB_BEG, | ||
10734 | (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1); | ||
10735 | |||
10736 | DvcPutScsiQ(iop_base, | ||
10737 | q_addr + ASC_SCSIQ_CPY_BEG, | ||
10738 | (uchar *)&scsiq->q1.cntl, | ||
10739 | ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); | ||
10740 | AscWriteLramWord(iop_base, | ||
10741 | (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), | ||
10742 | (ushort)(((ushort)scsiq->q1. | ||
10743 | q_no << 8) | (ushort)QS_READY)); | ||
10744 | return 1; | ||
10745 | } | ||
10746 | |||
10747 | static int | ||
10748 | AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) | ||
10749 | { | ||
10750 | int sta; | ||
10751 | int i; | ||
10752 | ASC_SG_HEAD *sg_head; | ||
10753 | ASC_SG_LIST_Q scsi_sg_q; | ||
10754 | ASC_DCNT saved_data_addr; | ||
10755 | ASC_DCNT saved_data_cnt; | ||
10756 | PortAddr iop_base; | ||
10757 | ushort sg_list_dwords; | ||
10758 | ushort sg_index; | ||
10759 | ushort sg_entry_cnt; | ||
10760 | ushort q_addr; | ||
10761 | uchar next_qp; | ||
10762 | |||
10763 | iop_base = asc_dvc->iop_base; | ||
10764 | sg_head = scsiq->sg_head; | ||
10765 | saved_data_addr = scsiq->q1.data_addr; | ||
10766 | saved_data_cnt = scsiq->q1.data_cnt; | ||
10767 | scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; | ||
10768 | scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; | ||
10769 | #if CC_VERY_LONG_SG_LIST | ||
10770 | /* | ||
10771 | * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST | ||
10772 | * then not all SG elements will fit in the allocated queues. | ||
10773 | * The rest of the SG elements will be copied when the RISC | ||
10774 | * completes the SG elements that fit and halts. | ||
10775 | */ | ||
10776 | if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { | ||
10777 | /* | ||
10778 | * Set sg_entry_cnt to be the number of SG elements that | ||
10779 | * will fit in the allocated SG queues. It is minus 1, because | ||
10780 | * the first SG element is handled above. ASC_MAX_SG_LIST is | ||
10781 | * already inflated by 1 to account for this. For example it | ||
10782 | * may be 50 which is 1 + 7 queues * 7 SG elements. | ||
10783 | */ | ||
10784 | sg_entry_cnt = ASC_MAX_SG_LIST - 1; | ||
10785 | |||
10786 | /* | ||
10787 | * Keep track of remaining number of SG elements that will | ||
10788 | * need to be handled from a_isr.c. | ||
10789 | */ | ||
10790 | scsiq->remain_sg_entry_cnt = | ||
10791 | sg_head->entry_cnt - ASC_MAX_SG_LIST; | ||
10792 | } else { | ||
10793 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
10794 | /* | ||
10795 | * Set sg_entry_cnt to be the number of SG elements that | ||
10796 | * will fit in the allocated SG queues. It is minus 1, because | ||
10797 | * the first SG element is handled above. | ||
10798 | */ | ||
10799 | sg_entry_cnt = sg_head->entry_cnt - 1; | ||
10800 | #if CC_VERY_LONG_SG_LIST | ||
10801 | } | ||
10802 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
10803 | if (sg_entry_cnt != 0) { | ||
10804 | scsiq->q1.cntl |= QC_SG_HEAD; | ||
10805 | q_addr = ASC_QNO_TO_QADDR(q_no); | ||
10806 | sg_index = 1; | ||
10807 | scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; | ||
10808 | scsi_sg_q.sg_head_qp = q_no; | ||
10809 | scsi_sg_q.cntl = QCSG_SG_XFER_LIST; | ||
10810 | for (i = 0; i < sg_head->queue_cnt; i++) { | ||
10811 | scsi_sg_q.seq_no = i + 1; | ||
10812 | if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { | ||
10813 | sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); | ||
10814 | sg_entry_cnt -= ASC_SG_LIST_PER_Q; | ||
10815 | if (i == 0) { | ||
10816 | scsi_sg_q.sg_list_cnt = | ||
10817 | ASC_SG_LIST_PER_Q; | ||
10818 | scsi_sg_q.sg_cur_list_cnt = | ||
10819 | ASC_SG_LIST_PER_Q; | ||
10820 | } else { | ||
10821 | scsi_sg_q.sg_list_cnt = | ||
10822 | ASC_SG_LIST_PER_Q - 1; | ||
10823 | scsi_sg_q.sg_cur_list_cnt = | ||
10824 | ASC_SG_LIST_PER_Q - 1; | ||
10825 | } | ||
10826 | } else { | ||
10827 | #if CC_VERY_LONG_SG_LIST | ||
10828 | /* | ||
10829 | * This is the last SG queue in the list of | ||
10830 | * allocated SG queues. If there are more | ||
10831 | * SG elements than will fit in the allocated | ||
10832 | * queues, then set the QCSG_SG_XFER_MORE flag. | ||
10833 | */ | ||
10834 | if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { | ||
10835 | scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; | ||
10836 | } else { | ||
10837 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
10838 | scsi_sg_q.cntl |= QCSG_SG_XFER_END; | ||
10839 | #if CC_VERY_LONG_SG_LIST | ||
10840 | } | ||
10841 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
10842 | sg_list_dwords = sg_entry_cnt << 1; | ||
10843 | if (i == 0) { | ||
10844 | scsi_sg_q.sg_list_cnt = sg_entry_cnt; | ||
10845 | scsi_sg_q.sg_cur_list_cnt = | ||
10846 | sg_entry_cnt; | ||
10847 | } else { | ||
10848 | scsi_sg_q.sg_list_cnt = | ||
10849 | sg_entry_cnt - 1; | ||
10850 | scsi_sg_q.sg_cur_list_cnt = | ||
10851 | sg_entry_cnt - 1; | ||
10852 | } | ||
10853 | sg_entry_cnt = 0; | ||
10854 | } | ||
10855 | next_qp = AscReadLramByte(iop_base, | ||
10856 | (ushort)(q_addr + | ||
10857 | ASC_SCSIQ_B_FWD)); | ||
10858 | scsi_sg_q.q_no = next_qp; | ||
10859 | q_addr = ASC_QNO_TO_QADDR(next_qp); | ||
10860 | AscMemWordCopyPtrToLram(iop_base, | ||
10861 | q_addr + ASC_SCSIQ_SGHD_CPY_BEG, | ||
10862 | (uchar *)&scsi_sg_q, | ||
10863 | sizeof(ASC_SG_LIST_Q) >> 1); | ||
10864 | AscMemDWordCopyPtrToLram(iop_base, | ||
10865 | q_addr + ASC_SGQ_LIST_BEG, | ||
10866 | (uchar *)&sg_head-> | ||
10867 | sg_list[sg_index], | ||
10868 | sg_list_dwords); | ||
10869 | sg_index += ASC_SG_LIST_PER_Q; | ||
10870 | scsiq->next_sg_index = sg_index; | ||
10871 | } | ||
10872 | } else { | ||
10873 | scsiq->q1.cntl &= ~QC_SG_HEAD; | ||
10874 | } | ||
10875 | sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); | ||
10876 | scsiq->q1.data_addr = saved_data_addr; | ||
10877 | scsiq->q1.data_cnt = saved_data_cnt; | ||
10878 | return (sta); | ||
10879 | } | ||
10880 | |||
10881 | static int | ||
10882 | AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) | ||
10883 | { | ||
10884 | PortAddr iop_base; | ||
10885 | uchar free_q_head; | ||
10886 | uchar next_qp; | ||
10887 | uchar tid_no; | ||
10888 | uchar target_ix; | ||
10889 | int sta; | ||
10890 | |||
10891 | iop_base = asc_dvc->iop_base; | ||
10892 | target_ix = scsiq->q2.target_ix; | ||
10893 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
10894 | sta = 0; | ||
10895 | free_q_head = (uchar)AscGetVarFreeQHead(iop_base); | ||
10896 | if (n_q_required > 1) { | ||
10897 | next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head, | ||
10898 | (uchar)n_q_required); | ||
10899 | if (next_qp != ASC_QLINK_END) { | ||
10900 | asc_dvc->last_q_shortage = 0; | ||
10901 | scsiq->sg_head->queue_cnt = n_q_required - 1; | ||
10902 | scsiq->q1.q_no = free_q_head; | ||
10903 | sta = AscPutReadySgListQueue(asc_dvc, scsiq, | ||
10904 | free_q_head); | ||
10905 | } | ||
10906 | } else if (n_q_required == 1) { | ||
10907 | next_qp = AscAllocFreeQueue(iop_base, free_q_head); | ||
10908 | if (next_qp != ASC_QLINK_END) { | ||
10909 | scsiq->q1.q_no = free_q_head; | ||
10910 | sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head); | ||
10911 | } | ||
10912 | } | ||
10913 | if (sta == 1) { | ||
10914 | AscPutVarFreeQHead(iop_base, next_qp); | ||
10915 | asc_dvc->cur_total_qng += n_q_required; | ||
10916 | asc_dvc->cur_dvc_qng[tid_no]++; | ||
10917 | } | ||
10918 | return sta; | ||
10919 | } | ||
10920 | |||
10921 | #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 | ||
10922 | static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { | ||
10923 | INQUIRY, | ||
10924 | REQUEST_SENSE, | ||
10925 | READ_CAPACITY, | ||
10926 | READ_TOC, | ||
10927 | MODE_SELECT, | ||
10928 | MODE_SENSE, | ||
10929 | MODE_SELECT_10, | ||
10930 | MODE_SENSE_10, | ||
10931 | 0xFF, | ||
10932 | 0xFF, | ||
10933 | 0xFF, | ||
10934 | 0xFF, | ||
10935 | 0xFF, | ||
10936 | 0xFF, | ||
10937 | 0xFF, | ||
10938 | 0xFF | ||
10939 | }; | ||
10940 | |||
10941 | static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) | ||
10942 | { | ||
10943 | PortAddr iop_base; | ||
10944 | int sta; | ||
10945 | int n_q_required; | ||
10946 | int disable_syn_offset_one_fix; | ||
10947 | int i; | ||
10948 | ASC_PADDR addr; | ||
10949 | ushort sg_entry_cnt = 0; | ||
10950 | ushort sg_entry_cnt_minus_one = 0; | ||
10951 | uchar target_ix; | ||
10952 | uchar tid_no; | ||
10953 | uchar sdtr_data; | ||
10954 | uchar extra_bytes; | ||
10955 | uchar scsi_cmd; | ||
10956 | uchar disable_cmd; | ||
10957 | ASC_SG_HEAD *sg_head; | ||
10958 | ASC_DCNT data_cnt; | ||
10959 | |||
10960 | iop_base = asc_dvc->iop_base; | ||
10961 | sg_head = scsiq->sg_head; | ||
10962 | if (asc_dvc->err_code != 0) | ||
10963 | return (ERR); | ||
10964 | scsiq->q1.q_no = 0; | ||
10965 | if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { | ||
10966 | scsiq->q1.extra_bytes = 0; | ||
10967 | } | ||
10968 | sta = 0; | ||
10969 | target_ix = scsiq->q2.target_ix; | ||
10970 | tid_no = ASC_TIX_TO_TID(target_ix); | ||
10971 | n_q_required = 1; | ||
10972 | if (scsiq->cdbptr[0] == REQUEST_SENSE) { | ||
10973 | if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { | ||
10974 | asc_dvc->sdtr_done &= ~scsiq->q1.target_id; | ||
10975 | sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); | ||
10976 | AscMsgOutSDTR(asc_dvc, | ||
10977 | asc_dvc-> | ||
10978 | sdtr_period_tbl[(sdtr_data >> 4) & | ||
10979 | (uchar)(asc_dvc-> | ||
10980 | max_sdtr_index - | ||
10981 | 1)], | ||
10982 | (uchar)(sdtr_data & (uchar) | ||
10983 | ASC_SYN_MAX_OFFSET)); | ||
10984 | scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); | ||
10985 | } | ||
10986 | } | ||
10987 | if (asc_dvc->in_critical_cnt != 0) { | ||
10988 | AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); | ||
10989 | return (ERR); | ||
10990 | } | ||
10991 | asc_dvc->in_critical_cnt++; | ||
10992 | if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { | ||
10993 | if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { | ||
10994 | asc_dvc->in_critical_cnt--; | ||
10995 | return (ERR); | ||
10996 | } | ||
10997 | #if !CC_VERY_LONG_SG_LIST | ||
10998 | if (sg_entry_cnt > ASC_MAX_SG_LIST) { | ||
10999 | asc_dvc->in_critical_cnt--; | ||
11000 | return (ERR); | ||
11001 | } | ||
11002 | #endif /* !CC_VERY_LONG_SG_LIST */ | ||
11003 | if (sg_entry_cnt == 1) { | ||
11004 | scsiq->q1.data_addr = | ||
11005 | (ADV_PADDR)sg_head->sg_list[0].addr; | ||
11006 | scsiq->q1.data_cnt = | ||
11007 | (ADV_DCNT)sg_head->sg_list[0].bytes; | ||
11008 | scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); | ||
11009 | } | ||
11010 | sg_entry_cnt_minus_one = sg_entry_cnt - 1; | ||
11011 | } | ||
11012 | scsi_cmd = scsiq->cdbptr[0]; | ||
11013 | disable_syn_offset_one_fix = FALSE; | ||
11014 | if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && | ||
11015 | !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { | ||
11016 | if (scsiq->q1.cntl & QC_SG_HEAD) { | ||
11017 | data_cnt = 0; | ||
11018 | for (i = 0; i < sg_entry_cnt; i++) { | ||
11019 | data_cnt += | ||
11020 | (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i]. | ||
11021 | bytes); | ||
11022 | } | ||
11023 | } else { | ||
11024 | data_cnt = le32_to_cpu(scsiq->q1.data_cnt); | ||
11025 | } | ||
11026 | if (data_cnt != 0UL) { | ||
11027 | if (data_cnt < 512UL) { | ||
11028 | disable_syn_offset_one_fix = TRUE; | ||
11029 | } else { | ||
11030 | for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; | ||
11031 | i++) { | ||
11032 | disable_cmd = | ||
11033 | _syn_offset_one_disable_cmd[i]; | ||
11034 | if (disable_cmd == 0xFF) { | ||
11035 | break; | ||
11036 | } | ||
11037 | if (scsi_cmd == disable_cmd) { | ||
11038 | disable_syn_offset_one_fix = | ||
11039 | TRUE; | ||
11040 | break; | ||
11041 | } | ||
11042 | } | ||
11043 | } | ||
11044 | } | ||
11045 | } | ||
11046 | if (disable_syn_offset_one_fix) { | ||
11047 | scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; | ||
11048 | scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | | ||
11049 | ASC_TAG_FLAG_DISABLE_DISCONNECT); | ||
11050 | } else { | ||
11051 | scsiq->q2.tag_code &= 0x27; | ||
11052 | } | ||
11053 | if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { | ||
11054 | if (asc_dvc->bug_fix_cntl) { | ||
11055 | if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { | ||
11056 | if ((scsi_cmd == READ_6) || | ||
11057 | (scsi_cmd == READ_10)) { | ||
11058 | addr = | ||
11059 | (ADV_PADDR)le32_to_cpu(sg_head-> | ||
11060 | sg_list | ||
11061 | [sg_entry_cnt_minus_one]. | ||
11062 | addr) + | ||
11063 | (ADV_DCNT)le32_to_cpu(sg_head-> | ||
11064 | sg_list | ||
11065 | [sg_entry_cnt_minus_one]. | ||
11066 | bytes); | ||
11067 | extra_bytes = | ||
11068 | (uchar)((ushort)addr & 0x0003); | ||
11069 | if ((extra_bytes != 0) | ||
11070 | && | ||
11071 | ((scsiq->q2. | ||
11072 | tag_code & | ||
11073 | ASC_TAG_FLAG_EXTRA_BYTES) | ||
11074 | == 0)) { | ||
11075 | scsiq->q2.tag_code |= | ||
11076 | ASC_TAG_FLAG_EXTRA_BYTES; | ||
11077 | scsiq->q1.extra_bytes = | ||
11078 | extra_bytes; | ||
11079 | data_cnt = | ||
11080 | le32_to_cpu(sg_head-> | ||
11081 | sg_list | ||
11082 | [sg_entry_cnt_minus_one]. | ||
11083 | bytes); | ||
11084 | data_cnt -= | ||
11085 | (ASC_DCNT) extra_bytes; | ||
11086 | sg_head-> | ||
11087 | sg_list | ||
11088 | [sg_entry_cnt_minus_one]. | ||
11089 | bytes = | ||
11090 | cpu_to_le32(data_cnt); | ||
11091 | } | ||
11092 | } | ||
11093 | } | ||
11094 | } | ||
11095 | sg_head->entry_to_copy = sg_head->entry_cnt; | ||
11096 | #if CC_VERY_LONG_SG_LIST | ||
11097 | /* | ||
11098 | * Set the sg_entry_cnt to the maximum possible. The rest of | ||
11099 | * the SG elements will be copied when the RISC completes the | ||
11100 | * SG elements that fit and halts. | ||
11101 | */ | ||
11102 | if (sg_entry_cnt > ASC_MAX_SG_LIST) { | ||
11103 | sg_entry_cnt = ASC_MAX_SG_LIST; | ||
11104 | } | ||
11105 | #endif /* CC_VERY_LONG_SG_LIST */ | ||
11106 | n_q_required = AscSgListToQueue(sg_entry_cnt); | ||
11107 | if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= | ||
11108 | (uint) n_q_required) | ||
11109 | || ((scsiq->q1.cntl & QC_URGENT) != 0)) { | ||
11110 | if ((sta = | ||
11111 | AscSendScsiQueue(asc_dvc, scsiq, | ||
11112 | n_q_required)) == 1) { | ||
11113 | asc_dvc->in_critical_cnt--; | ||
11114 | return (sta); | ||
11115 | } | ||
11116 | } | ||
11117 | } else { | ||
11118 | if (asc_dvc->bug_fix_cntl) { | ||
11119 | if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { | ||
11120 | if ((scsi_cmd == READ_6) || | ||
11121 | (scsi_cmd == READ_10)) { | ||
11122 | addr = | ||
11123 | le32_to_cpu(scsiq->q1.data_addr) + | ||
11124 | le32_to_cpu(scsiq->q1.data_cnt); | ||
11125 | extra_bytes = | ||
11126 | (uchar)((ushort)addr & 0x0003); | ||
11127 | if ((extra_bytes != 0) | ||
11128 | && | ||
11129 | ((scsiq->q2. | ||
11130 | tag_code & | ||
11131 | ASC_TAG_FLAG_EXTRA_BYTES) | ||
11132 | == 0)) { | ||
11133 | data_cnt = | ||
11134 | le32_to_cpu(scsiq->q1. | ||
11135 | data_cnt); | ||
11136 | if (((ushort)data_cnt & 0x01FF) | ||
11137 | == 0) { | ||
11138 | scsiq->q2.tag_code |= | ||
11139 | ASC_TAG_FLAG_EXTRA_BYTES; | ||
11140 | data_cnt -= (ASC_DCNT) | ||
11141 | extra_bytes; | ||
11142 | scsiq->q1.data_cnt = | ||
11143 | cpu_to_le32 | ||
11144 | (data_cnt); | ||
11145 | scsiq->q1.extra_bytes = | ||
11146 | extra_bytes; | ||
11147 | } | ||
11148 | } | ||
11149 | } | ||
11150 | } | ||
11151 | } | ||
11152 | n_q_required = 1; | ||
11153 | if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || | ||
11154 | ((scsiq->q1.cntl & QC_URGENT) != 0)) { | ||
11155 | if ((sta = AscSendScsiQueue(asc_dvc, scsiq, | ||
11156 | n_q_required)) == 1) { | ||
11157 | asc_dvc->in_critical_cnt--; | ||
11158 | return (sta); | ||
11159 | } | ||
11160 | } | ||
11161 | } | ||
11162 | asc_dvc->in_critical_cnt--; | ||
11163 | return (sta); | ||
11164 | } | ||
11165 | |||
11166 | /* | ||
11167 | * AdvExeScsiQueue() - Send a request to the RISC microcode program. | ||
11168 | * | ||
11169 | * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q, | ||
11170 | * add the carrier to the ICQ (Initiator Command Queue), and tickle the | ||
11171 | * RISC to notify it a new command is ready to be executed. | ||
11172 | * | ||
11173 | * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be | ||
11174 | * set to SCSI_MAX_RETRY. | ||
11175 | * | ||
11176 | * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode | ||
11177 | * for DMA addresses or math operations are byte swapped to little-endian | ||
11178 | * order. | ||
11179 | * | ||
11180 | * Return: | ||
11181 | * ADV_SUCCESS(1) - The request was successfully queued. | ||
11182 | * ADV_BUSY(0) - Resource unavailable; Retry again after pending | ||
11183 | * request completes. | ||
11184 | * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure | ||
11185 | * host IC error. | ||
11186 | */ | ||
11187 | static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) | ||
11188 | { | ||
11189 | AdvPortAddr iop_base; | ||
11190 | ADV_DCNT req_size; | ||
11191 | ADV_PADDR req_paddr; | ||
11192 | ADV_CARR_T *new_carrp; | ||
11193 | |||
11194 | /* | ||
11195 | * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. | ||
11196 | */ | ||
11197 | if (scsiq->target_id > ADV_MAX_TID) { | ||
11198 | scsiq->host_status = QHSTA_M_INVALID_DEVICE; | ||
11199 | scsiq->done_status = QD_WITH_ERROR; | ||
11200 | return ADV_ERROR; | ||
11201 | } | ||
11202 | |||
11203 | iop_base = asc_dvc->iop_base; | ||
11204 | |||
11205 | /* | ||
11206 | * Allocate a carrier ensuring at least one carrier always | ||
11207 | * remains on the freelist and initialize fields. | ||
11208 | */ | ||
11209 | if ((new_carrp = asc_dvc->carr_freelist) == NULL) { | ||
11210 | return ADV_BUSY; | ||
11211 | } | ||
11212 | asc_dvc->carr_freelist = (ADV_CARR_T *) | ||
11213 | ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); | ||
11214 | asc_dvc->carr_pending_cnt++; | ||
11215 | |||
11216 | /* | ||
11217 | * Set the carrier to be a stopper by setting 'next_vpa' | ||
11218 | * to the stopper value. The current stopper will be changed | ||
11219 | * below to point to the new stopper. | ||
11220 | */ | ||
11221 | new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); | ||
11222 | |||
11223 | /* | ||
11224 | * Clear the ADV_SCSI_REQ_Q done flag. | ||
11225 | */ | ||
11226 | scsiq->a_flag &= ~ADV_SCSIQ_DONE; | ||
11227 | |||
11228 | req_size = sizeof(ADV_SCSI_REQ_Q); | ||
11229 | req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq, | ||
11230 | (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG); | ||
11231 | |||
11232 | BUG_ON(req_paddr & 31); | ||
11233 | BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q)); | ||
11234 | |||
11235 | /* Wait for assertion before making little-endian */ | ||
11236 | req_paddr = cpu_to_le32(req_paddr); | ||
11237 | |||
11238 | /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ | ||
11239 | scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); | ||
11240 | scsiq->scsiq_rptr = req_paddr; | ||
11241 | |||
11242 | scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); | ||
11243 | /* | ||
11244 | * Every ADV_CARR_T.carr_pa is byte swapped to little-endian | ||
11245 | * order during initialization. | ||
11246 | */ | ||
11247 | scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; | ||
11248 | |||
11249 | /* | ||
11250 | * Use the current stopper to send the ADV_SCSI_REQ_Q command to | ||
11251 | * the microcode. The newly allocated stopper will become the new | ||
11252 | * stopper. | ||
11253 | */ | ||
11254 | asc_dvc->icq_sp->areq_vpa = req_paddr; | ||
11255 | |||
11256 | /* | ||
11257 | * Set the 'next_vpa' pointer for the old stopper to be the | ||
11258 | * physical address of the new stopper. The RISC can only | ||
11259 | * follow physical addresses. | ||
11260 | */ | ||
11261 | asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; | ||
11262 | |||
11263 | /* | ||
11264 | * Set the host adapter stopper pointer to point to the new carrier. | ||
11265 | */ | ||
11266 | asc_dvc->icq_sp = new_carrp; | ||
11267 | |||
11268 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || | ||
11269 | asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
11270 | /* | ||
11271 | * Tickle the RISC to tell it to read its Command Queue Head pointer. | ||
11272 | */ | ||
11273 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); | ||
11274 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { | ||
11275 | /* | ||
11276 | * Clear the tickle value. In the ASC-3550 the RISC flag | ||
11277 | * command 'clr_tickle_a' does not work unless the host | ||
11278 | * value is cleared. | ||
11279 | */ | ||
11280 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, | ||
11281 | ADV_TICKLE_NOP); | ||
11282 | } | ||
11283 | } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | ||
11284 | /* | ||
11285 | * Notify the RISC a carrier is ready by writing the physical | ||
11286 | * address of the new carrier stopper to the COMMA register. | ||
11287 | */ | ||
11288 | AdvWriteDWordRegister(iop_base, IOPDW_COMMA, | ||
11289 | le32_to_cpu(new_carrp->carr_pa)); | ||
11290 | } | ||
11291 | |||
11292 | return ADV_SUCCESS; | ||
11293 | } | ||
11294 | |||
11295 | /* | ||
11296 | * Execute a single 'Scsi_Cmnd'. | ||
11297 | * | ||
11298 | * The function 'done' is called when the request has been completed. | ||
11299 | * | ||
11300 | * Scsi_Cmnd: | ||
11301 | * | ||
11302 | * host - board controlling device | ||
11303 | * device - device to send command | ||
11304 | * target - target of device | ||
11305 | * lun - lun of device | ||
11306 | * cmd_len - length of SCSI CDB | ||
11307 | * cmnd - buffer for SCSI 8, 10, or 12 byte CDB | ||
11308 | * use_sg - if non-zero indicates scatter-gather request with use_sg elements | ||
11309 | * | ||
11310 | * if (use_sg == 0) { | ||
11311 | * request_buffer - buffer address for request | ||
11312 | * request_bufflen - length of request buffer | ||
11313 | * } else { | ||
11314 | * request_buffer - pointer to scatterlist structure | ||
11315 | * } | ||
11316 | * | ||
11317 | * sense_buffer - sense command buffer | ||
11318 | * | ||
11319 | * result (4 bytes of an int): | ||
11320 | * Byte Meaning | ||
11321 | * 0 SCSI Status Byte Code | ||
11322 | * 1 SCSI One Byte Message Code | ||
11323 | * 2 Host Error Code | ||
11324 | * 3 Mid-Level Error Code | ||
11325 | * | ||
11326 | * host driver fields: | ||
11327 | * SCp - Scsi_Pointer used for command processing status | ||
11328 | * scsi_done - used to save caller's done function | ||
11329 | * host_scribble - used for pointer to another struct scsi_cmnd | ||
11330 | * | ||
11331 | * If this function returns ASC_NOERROR the request will be completed | ||
11332 | * from the interrupt handler. | ||
11333 | * | ||
11334 | * If this function returns ASC_ERROR the host error code has been set, | ||
11335 | * and the called must call asc_scsi_done. | ||
11336 | * | ||
11337 | * If ASC_BUSY is returned the request will be returned to the midlayer | ||
11338 | * and re-tried later. | ||
11339 | */ | ||
11340 | static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | ||
11341 | { | ||
11342 | asc_board_t *boardp; | ||
11343 | ASC_DVC_VAR *asc_dvc_varp; | ||
11344 | ADV_DVC_VAR *adv_dvc_varp; | ||
11345 | ADV_SCSI_REQ_Q *adv_scsiqp; | ||
11346 | struct scsi_device *device; | ||
11347 | int ret; | ||
11348 | |||
11349 | ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", | ||
11350 | (ulong)scp, (ulong)scp->scsi_done); | ||
11351 | |||
11352 | boardp = ASC_BOARDP(scp->device->host); | ||
11353 | device = boardp->device[scp->device->id]; | ||
11354 | |||
11355 | if (ASC_NARROW_BOARD(boardp)) { | ||
11356 | /* | ||
11357 | * Build and execute Narrow Board request. | ||
11358 | */ | ||
11359 | |||
11360 | asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; | ||
11361 | |||
11362 | /* | ||
11363 | * Build Asc Library request structure using the | ||
11364 | * global structures 'asc_scsi_req' and 'asc_sg_head'. | ||
11365 | * | ||
11366 | * If an error is returned, then the request has been | ||
11367 | * queued on the board done queue. It will be completed | ||
11368 | * by the caller. | ||
11369 | * | ||
11370 | * asc_build_req() can not return ASC_BUSY. | ||
11371 | */ | ||
11372 | if (asc_build_req(boardp, scp) == ASC_ERROR) { | ||
11373 | ASC_STATS(scp->device->host, build_error); | ||
11374 | return ASC_ERROR; | ||
11375 | } | ||
11376 | |||
11377 | switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { | ||
11378 | case ASC_NOERROR: | ||
11379 | ASC_STATS(scp->device->host, exe_noerror); | ||
11380 | /* | ||
11381 | * Increment monotonically increasing per device | ||
11382 | * successful request counter. Wrapping doesn't matter. | ||
11383 | */ | ||
11384 | boardp->reqcnt[scp->device->id]++; | ||
11385 | ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), " | ||
11386 | "ASC_NOERROR\n"); | ||
11387 | break; | ||
11388 | case ASC_BUSY: | ||
11389 | ASC_STATS(scp->device->host, exe_busy); | ||
11390 | break; | ||
11391 | case ASC_ERROR: | ||
11392 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
11393 | "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", | ||
11394 | boardp->id, asc_dvc_varp->err_code); | ||
11395 | ASC_STATS(scp->device->host, exe_error); | ||
11396 | scp->result = HOST_BYTE(DID_ERROR); | ||
11397 | break; | ||
11398 | default: | ||
11399 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
11400 | "AscExeScsiQueue() unknown, err_code 0x%x\n", | ||
11401 | boardp->id, asc_dvc_varp->err_code); | ||
11402 | ASC_STATS(scp->device->host, exe_unknown); | ||
11403 | scp->result = HOST_BYTE(DID_ERROR); | ||
11404 | break; | ||
11405 | } | ||
11406 | } else { | ||
11407 | /* | ||
11408 | * Build and execute Wide Board request. | ||
11409 | */ | ||
11410 | adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; | ||
11411 | |||
11412 | /* | ||
11413 | * Build and get a pointer to an Adv Library request structure. | ||
11414 | * | ||
11415 | * If the request is successfully built then send it below, | ||
11416 | * otherwise return with an error. | ||
11417 | */ | ||
11418 | switch (adv_build_req(boardp, scp, &adv_scsiqp)) { | ||
11419 | case ASC_NOERROR: | ||
11420 | ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req " | ||
11421 | "ASC_NOERROR\n"); | ||
11422 | break; | ||
11423 | case ASC_BUSY: | ||
11424 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " | ||
11425 | "ASC_BUSY\n"); | ||
11426 | /* | ||
11427 | * The asc_stats fields 'adv_build_noreq' and | ||
11428 | * 'adv_build_nosg' count wide board busy conditions. | ||
11429 | * They are updated in adv_build_req and | ||
11430 | * adv_get_sglist, respectively. | ||
11431 | */ | ||
11432 | return ASC_BUSY; | ||
11433 | case ASC_ERROR: | ||
11434 | default: | ||
11435 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " | ||
11436 | "ASC_ERROR\n"); | ||
11437 | ASC_STATS(scp->device->host, build_error); | ||
11438 | return ASC_ERROR; | ||
11439 | } | ||
11440 | |||
11441 | switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { | ||
11442 | case ASC_NOERROR: | ||
11443 | ASC_STATS(scp->device->host, exe_noerror); | ||
11444 | /* | ||
11445 | * Increment monotonically increasing per device | ||
11446 | * successful request counter. Wrapping doesn't matter. | ||
11447 | */ | ||
11448 | boardp->reqcnt[scp->device->id]++; | ||
11449 | ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), " | ||
11450 | "ASC_NOERROR\n"); | ||
11451 | break; | ||
11452 | case ASC_BUSY: | ||
11453 | ASC_STATS(scp->device->host, exe_busy); | ||
11454 | break; | ||
11455 | case ASC_ERROR: | ||
11456 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
11457 | "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", | ||
11458 | boardp->id, adv_dvc_varp->err_code); | ||
11459 | ASC_STATS(scp->device->host, exe_error); | ||
11460 | scp->result = HOST_BYTE(DID_ERROR); | ||
11461 | break; | ||
11462 | default: | ||
11463 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | ||
11464 | "AdvExeScsiQueue() unknown, err_code 0x%x\n", | ||
11465 | boardp->id, adv_dvc_varp->err_code); | ||
11466 | ASC_STATS(scp->device->host, exe_unknown); | ||
11467 | scp->result = HOST_BYTE(DID_ERROR); | ||
11468 | break; | ||
11469 | } | ||
11470 | } | ||
11471 | |||
11472 | ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); | ||
11473 | return ret; | ||
11474 | } | ||
11475 | |||
11476 | /* | ||
11477 | * advansys_queuecommand() - interrupt-driven I/O entrypoint. | ||
11478 | * | ||
11479 | * This function always returns 0. Command return status is saved | ||
11480 | * in the 'scp' result field. | ||
11481 | */ | ||
11482 | static int | ||
11483 | advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) | ||
11484 | { | ||
11485 | struct Scsi_Host *shost = scp->device->host; | ||
11486 | asc_board_t *boardp = ASC_BOARDP(shost); | ||
11487 | unsigned long flags; | ||
11488 | int asc_res, result = 0; | ||
11489 | |||
11490 | ASC_STATS(shost, queuecommand); | ||
11491 | scp->scsi_done = done; | ||
11492 | |||
11493 | /* | ||
11494 | * host_lock taken by mid-level prior to call, but need | ||
11495 | * to protect against own ISR | ||
11496 | */ | ||
11497 | spin_lock_irqsave(&boardp->lock, flags); | ||
11498 | asc_res = asc_execute_scsi_cmnd(scp); | ||
11499 | spin_unlock_irqrestore(&boardp->lock, flags); | ||
11500 | |||
11501 | switch (asc_res) { | ||
11502 | case ASC_NOERROR: | ||
11503 | break; | ||
11504 | case ASC_BUSY: | ||
11505 | result = SCSI_MLQUEUE_HOST_BUSY; | ||
11506 | break; | ||
11507 | case ASC_ERROR: | ||
11508 | default: | ||
11509 | asc_scsi_done(scp); | ||
11510 | break; | ||
11511 | } | ||
11512 | |||
11513 | return result; | ||
11514 | } | ||
11515 | |||
11516 | static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base) | ||
11517 | { | ||
11518 | PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | | ||
11519 | (PortAddr) (ASC_EISA_CFG_IOP_MASK); | ||
11520 | return inpw(eisa_cfg_iop); | ||
11521 | } | ||
11522 | |||
11523 | /* | ||
11524 | * Return the BIOS address of the adapter at the specified | ||
11525 | * I/O port and with the specified bus type. | ||
11526 | */ | ||
11527 | static unsigned short __devinit | ||
11528 | AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type) | ||
11529 | { | ||
11530 | unsigned short cfg_lsw; | ||
11531 | unsigned short bios_addr; | ||
11532 | |||
11533 | /* | ||
11534 | * The PCI BIOS is re-located by the motherboard BIOS. Because | ||
11535 | * of this the driver can not determine where a PCI BIOS is | ||
11536 | * loaded and executes. | ||
11537 | */ | ||
11538 | if (bus_type & ASC_IS_PCI) | ||
11539 | return 0; | ||
11540 | |||
11541 | if ((bus_type & ASC_IS_EISA) != 0) { | ||
11542 | cfg_lsw = AscGetEisaChipCfg(iop_base); | ||
11543 | cfg_lsw &= 0x000F; | ||
11544 | bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE; | ||
11545 | return bios_addr; | ||
11546 | } | ||
11547 | |||
11548 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
11549 | |||
11550 | /* | ||
11551 | * ISA PnP uses the top bit as the 32K BIOS flag | ||
11552 | */ | ||
11553 | if (bus_type == ASC_IS_ISAPNP) | ||
11554 | cfg_lsw &= 0x7FFF; | ||
11555 | bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE; | ||
11556 | return bios_addr; | ||
11557 | } | ||
11558 | |||
11559 | static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) | ||
11560 | { | ||
11561 | ushort cfg_lsw; | ||
11562 | |||
11563 | if (AscGetChipScsiID(iop_base) == new_host_id) { | ||
11564 | return (new_host_id); | ||
11565 | } | ||
11566 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
11567 | cfg_lsw &= 0xF8FF; | ||
11568 | cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8); | ||
11569 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
11570 | return (AscGetChipScsiID(iop_base)); | ||
11571 | } | ||
11572 | |||
11573 | static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base) | ||
11574 | { | ||
11575 | unsigned char sc; | ||
11576 | |||
11577 | AscSetBank(iop_base, 1); | ||
11578 | sc = inp(iop_base + IOP_REG_SC); | ||
11579 | AscSetBank(iop_base, 0); | ||
11580 | return sc; | ||
11581 | } | ||
11582 | |||
11583 | static unsigned char __devinit | ||
11584 | AscGetChipVersion(PortAddr iop_base, unsigned short bus_type) | ||
11585 | { | ||
11586 | if (bus_type & ASC_IS_EISA) { | ||
11587 | PortAddr eisa_iop; | ||
11588 | unsigned char revision; | ||
11589 | eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | | ||
11590 | (PortAddr) ASC_EISA_REV_IOP_MASK; | ||
11591 | revision = inp(eisa_iop); | ||
11592 | return ASC_CHIP_MIN_VER_EISA - 1 + revision; | ||
11593 | } | ||
11594 | return AscGetChipVerNo(iop_base); | ||
11595 | } | ||
11596 | |||
11597 | static void __devinit AscToggleIRQAct(PortAddr iop_base) | ||
11598 | { | ||
11599 | AscSetChipStatus(iop_base, CIW_IRQ_ACT); | ||
11600 | AscSetChipStatus(iop_base, 0); | ||
11601 | return; | ||
11602 | } | ||
11603 | |||
11604 | static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type) | ||
11605 | { | ||
11606 | ushort cfg_lsw; | ||
11607 | uchar chip_irq; | ||
11608 | |||
11609 | if ((bus_type & ASC_IS_EISA) != 0) { | ||
11610 | cfg_lsw = AscGetEisaChipCfg(iop_base); | ||
11611 | chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10); | ||
11612 | if ((chip_irq == 13) || (chip_irq > 15)) { | ||
11613 | return (0); | ||
11614 | } | ||
11615 | return (chip_irq); | ||
11616 | } | ||
11617 | if ((bus_type & ASC_IS_VL) != 0) { | ||
11618 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
11619 | chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07)); | ||
11620 | if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) { | ||
11621 | return (0); | ||
11622 | } | ||
11623 | return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1))); | ||
11624 | } | ||
11625 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
11626 | chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03)); | ||
11627 | if (chip_irq == 3) | ||
11628 | chip_irq += (uchar)2; | ||
11629 | return ((uchar)(chip_irq + ASC_MIN_IRQ_NO)); | ||
11630 | } | ||
11631 | |||
11632 | static uchar __devinit | ||
11633 | AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type) | ||
11634 | { | ||
11635 | ushort cfg_lsw; | ||
11636 | |||
11637 | if ((bus_type & ASC_IS_VL) != 0) { | ||
11638 | if (irq_no != 0) { | ||
11639 | if ((irq_no < ASC_MIN_IRQ_NO) | ||
11640 | || (irq_no > ASC_MAX_IRQ_NO)) { | ||
11641 | irq_no = 0; | ||
11642 | } else { | ||
11643 | irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1)); | ||
11644 | } | ||
11645 | } | ||
11646 | cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3); | ||
11647 | cfg_lsw |= (ushort)0x0010; | ||
11648 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
11649 | AscToggleIRQAct(iop_base); | ||
11650 | cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0); | ||
11651 | cfg_lsw |= (ushort)((irq_no & 0x07) << 2); | ||
11652 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
11653 | AscToggleIRQAct(iop_base); | ||
11654 | return (AscGetChipIRQ(iop_base, bus_type)); | ||
11655 | } | ||
11656 | if ((bus_type & (ASC_IS_ISA)) != 0) { | ||
11657 | if (irq_no == 15) | ||
11658 | irq_no -= (uchar)2; | ||
11659 | irq_no -= (uchar)ASC_MIN_IRQ_NO; | ||
11660 | cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3); | ||
11661 | cfg_lsw |= (ushort)((irq_no & 0x03) << 2); | ||
11662 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
11663 | return (AscGetChipIRQ(iop_base, bus_type)); | ||
11664 | } | ||
11665 | return (0); | ||
11666 | } | ||
11667 | |||
11668 | #ifdef CONFIG_ISA | ||
11669 | static void __devinit AscEnableIsaDma(uchar dma_channel) | ||
11670 | { | ||
11671 | if (dma_channel < 4) { | ||
11672 | outp(0x000B, (ushort)(0xC0 | dma_channel)); | ||
11673 | outp(0x000A, dma_channel); | ||
11674 | } else if (dma_channel < 8) { | ||
11675 | outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4))); | ||
11676 | outp(0x00D4, (ushort)(dma_channel - 4)); | ||
11677 | } | ||
11678 | return; | ||
11679 | } | ||
11680 | #endif /* CONFIG_ISA */ | ||
11681 | |||
11682 | static int AscStopQueueExe(PortAddr iop_base) | ||
11683 | { | ||
11684 | int count = 0; | ||
11685 | |||
11686 | if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { | ||
11687 | AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, | ||
11688 | ASC_STOP_REQ_RISC_STOP); | ||
11689 | do { | ||
11690 | if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & | ||
11691 | ASC_STOP_ACK_RISC_STOP) { | ||
11692 | return (1); | ||
11693 | } | ||
11694 | mdelay(100); | ||
11695 | } while (count++ < 20); | ||
11696 | } | ||
11697 | return (0); | ||
11698 | } | ||
11699 | |||
11700 | static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type) | ||
11701 | { | ||
11702 | if (bus_type & ASC_IS_ISA) | ||
11703 | return ASC_MAX_ISA_DMA_COUNT; | ||
11704 | else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) | ||
11705 | return ASC_MAX_VL_DMA_COUNT; | ||
11706 | return ASC_MAX_PCI_DMA_COUNT; | ||
11707 | } | ||
11708 | |||
11709 | #ifdef CONFIG_ISA | ||
11710 | static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base) | ||
11711 | { | ||
11712 | ushort channel; | ||
11713 | |||
11714 | channel = AscGetChipCfgLsw(iop_base) & 0x0003; | ||
11715 | if (channel == 0x03) | ||
11716 | return (0); | ||
11717 | else if (channel == 0x00) | ||
11718 | return (7); | ||
11719 | return (channel + 4); | ||
11720 | } | ||
11721 | |||
11722 | static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) | ||
11723 | { | ||
11724 | ushort cfg_lsw; | ||
11725 | uchar value; | ||
11726 | |||
11727 | if ((dma_channel >= 5) && (dma_channel <= 7)) { | ||
11728 | if (dma_channel == 7) | ||
11729 | value = 0x00; | ||
11730 | else | ||
11731 | value = dma_channel - 4; | ||
11732 | cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; | ||
11733 | cfg_lsw |= value; | ||
11734 | AscSetChipCfgLsw(iop_base, cfg_lsw); | ||
11735 | return (AscGetIsaDmaChannel(iop_base)); | ||
11736 | } | ||
11737 | return 0; | ||
11738 | } | ||
11739 | |||
11740 | static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base) | ||
11741 | { | ||
11742 | uchar speed_value; | ||
11743 | |||
11744 | AscSetBank(iop_base, 1); | ||
11745 | speed_value = AscReadChipDmaSpeed(iop_base); | ||
11746 | speed_value &= 0x07; | ||
11747 | AscSetBank(iop_base, 0); | ||
11748 | return speed_value; | ||
11749 | } | ||
11750 | |||
11751 | static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value) | ||
11752 | { | ||
11753 | speed_value &= 0x07; | ||
11754 | AscSetBank(iop_base, 1); | ||
11755 | AscWriteChipDmaSpeed(iop_base, speed_value); | ||
11756 | AscSetBank(iop_base, 0); | ||
11757 | return AscGetIsaDmaSpeed(iop_base); | ||
11758 | } | ||
11759 | #endif /* CONFIG_ISA */ | ||
11760 | |||
11761 | static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) | ||
11762 | { | ||
11763 | int i; | ||
11764 | PortAddr iop_base; | ||
11765 | ushort warn_code; | ||
11766 | uchar chip_version; | ||
11767 | |||
11768 | iop_base = asc_dvc->iop_base; | ||
11769 | warn_code = 0; | ||
11770 | asc_dvc->err_code = 0; | ||
11771 | if ((asc_dvc->bus_type & | ||
11772 | (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { | ||
11773 | asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; | ||
11774 | } | ||
11775 | AscSetChipControl(iop_base, CC_HALT); | ||
11776 | AscSetChipStatus(iop_base, 0); | ||
11777 | asc_dvc->bug_fix_cntl = 0; | ||
11778 | asc_dvc->pci_fix_asyn_xfer = 0; | ||
11779 | asc_dvc->pci_fix_asyn_xfer_always = 0; | ||
11780 | /* asc_dvc->init_state initalized in AscInitGetConfig(). */ | ||
11781 | asc_dvc->sdtr_done = 0; | ||
11782 | asc_dvc->cur_total_qng = 0; | ||
11783 | asc_dvc->is_in_int = 0; | ||
11784 | asc_dvc->in_critical_cnt = 0; | ||
11785 | asc_dvc->last_q_shortage = 0; | ||
11786 | asc_dvc->use_tagged_qng = 0; | ||
11787 | asc_dvc->no_scam = 0; | ||
11788 | asc_dvc->unit_not_ready = 0; | ||
11789 | asc_dvc->queue_full_or_busy = 0; | ||
11790 | asc_dvc->redo_scam = 0; | ||
11791 | asc_dvc->res2 = 0; | ||
11792 | asc_dvc->host_init_sdtr_index = 0; | ||
11793 | asc_dvc->cfg->can_tagged_qng = 0; | ||
11794 | asc_dvc->cfg->cmd_qng_enabled = 0; | ||
11795 | asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; | ||
11796 | asc_dvc->init_sdtr = 0; | ||
11797 | asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; | ||
11798 | asc_dvc->scsi_reset_wait = 3; | ||
11799 | asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; | ||
11800 | asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); | ||
11801 | asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; | ||
11802 | asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; | ||
11803 | asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; | ||
11804 | asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; | ||
11805 | asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | | ||
11806 | ASC_LIB_VERSION_MINOR; | ||
11807 | chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); | ||
11808 | asc_dvc->cfg->chip_version = chip_version; | ||
11809 | asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; | ||
11810 | asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; | ||
11811 | asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; | ||
11812 | asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; | ||
11813 | asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; | ||
11814 | asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; | ||
11815 | asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; | ||
11816 | asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; | ||
11817 | asc_dvc->max_sdtr_index = 7; | ||
11818 | if ((asc_dvc->bus_type & ASC_IS_PCI) && | ||
11819 | (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { | ||
11820 | asc_dvc->bus_type = ASC_IS_PCI_ULTRA; | ||
11821 | asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; | ||
11822 | asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; | ||
11823 | asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; | ||
11824 | asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; | ||
11825 | asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; | ||
11826 | asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; | ||
11827 | asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; | ||
11828 | asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; | ||
11829 | asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; | ||
11830 | asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; | ||
11831 | asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; | ||
11832 | asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; | ||
11833 | asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; | ||
11834 | asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; | ||
11835 | asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; | ||
11836 | asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; | ||
11837 | asc_dvc->max_sdtr_index = 15; | ||
11838 | if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) { | ||
11839 | AscSetExtraControl(iop_base, | ||
11840 | (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); | ||
11841 | } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { | ||
11842 | AscSetExtraControl(iop_base, | ||
11843 | (SEC_ACTIVE_NEGATE | | ||
11844 | SEC_ENABLE_FILTER)); | ||
11845 | } | ||
11846 | } | ||
11847 | if (asc_dvc->bus_type == ASC_IS_PCI) { | ||
11848 | AscSetExtraControl(iop_base, | ||
11849 | (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); | ||
11850 | } | ||
11851 | |||
11852 | asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; | ||
11853 | #ifdef CONFIG_ISA | ||
11854 | if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { | ||
11855 | if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) { | ||
11856 | AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); | ||
11857 | asc_dvc->bus_type = ASC_IS_ISAPNP; | ||
11858 | } | ||
11859 | asc_dvc->cfg->isa_dma_channel = | ||
11860 | (uchar)AscGetIsaDmaChannel(iop_base); | ||
11861 | } | ||
11862 | #endif /* CONFIG_ISA */ | ||
11863 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
11864 | asc_dvc->cur_dvc_qng[i] = 0; | ||
11865 | asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; | ||
11866 | asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L; | ||
11867 | asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L; | ||
11868 | asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; | ||
11869 | } | ||
11870 | return warn_code; | ||
11871 | } | ||
11872 | |||
11873 | static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) | ||
11874 | { | ||
11875 | int retry; | ||
11876 | |||
11877 | for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) { | ||
11878 | unsigned char read_back; | ||
11879 | AscSetChipEEPCmd(iop_base, cmd_reg); | ||
11880 | mdelay(1); | ||
11881 | read_back = AscGetChipEEPCmd(iop_base); | ||
11882 | if (read_back == cmd_reg) | ||
11883 | return 1; | ||
11884 | } | ||
11885 | return 0; | ||
11886 | } | ||
11887 | |||
11888 | static void __devinit AscWaitEEPRead(void) | ||
11889 | { | ||
11890 | mdelay(1); | ||
11891 | } | ||
11892 | |||
11893 | static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr) | ||
11894 | { | ||
11895 | ushort read_wval; | ||
11896 | uchar cmd_reg; | ||
11897 | |||
11898 | AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); | ||
11899 | AscWaitEEPRead(); | ||
11900 | cmd_reg = addr | ASC_EEP_CMD_READ; | ||
11901 | AscWriteEEPCmdReg(iop_base, cmd_reg); | ||
11902 | AscWaitEEPRead(); | ||
11903 | read_wval = AscGetChipEEPData(iop_base); | ||
11904 | AscWaitEEPRead(); | ||
11905 | return read_wval; | ||
11906 | } | ||
11907 | |||
11908 | static ushort __devinit | ||
11909 | AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) | ||
11910 | { | ||
11911 | ushort wval; | ||
11912 | ushort sum; | ||
11913 | ushort *wbuf; | ||
11914 | int cfg_beg; | ||
11915 | int cfg_end; | ||
11916 | int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; | ||
11917 | int s_addr; | ||
11918 | |||
11919 | wbuf = (ushort *)cfg_buf; | ||
11920 | sum = 0; | ||
11921 | /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ | ||
11922 | for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { | ||
11923 | *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
11924 | sum += *wbuf; | ||
11925 | } | ||
11926 | if (bus_type & ASC_IS_VL) { | ||
11927 | cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; | ||
11928 | cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; | ||
11929 | } else { | ||
11930 | cfg_beg = ASC_EEP_DVC_CFG_BEG; | ||
11931 | cfg_end = ASC_EEP_MAX_DVC_ADDR; | ||
11932 | } | ||
11933 | for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { | ||
11934 | wval = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
11935 | if (s_addr <= uchar_end_in_config) { | ||
11936 | /* | ||
11937 | * Swap all char fields - must unswap bytes already swapped | ||
11938 | * by AscReadEEPWord(). | ||
11939 | */ | ||
11940 | *wbuf = le16_to_cpu(wval); | ||
11941 | } else { | ||
11942 | /* Don't swap word field at the end - cntl field. */ | ||
11943 | *wbuf = wval; | ||
11944 | } | ||
11945 | sum += wval; /* Checksum treats all EEPROM data as words. */ | ||
11946 | } | ||
11947 | /* | ||
11948 | * Read the checksum word which will be compared against 'sum' | ||
11949 | * by the caller. Word field already swapped. | ||
11950 | */ | ||
11951 | *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
11952 | return sum; | ||
11953 | } | ||
11954 | |||
11955 | static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc) | ||
11956 | { | ||
11957 | PortAddr iop_base; | ||
11958 | ushort q_addr; | ||
11959 | ushort saved_word; | ||
11960 | int sta; | ||
11961 | |||
11962 | iop_base = asc_dvc->iop_base; | ||
11963 | sta = 0; | ||
11964 | q_addr = ASC_QNO_TO_QADDR(241); | ||
11965 | saved_word = AscReadLramWord(iop_base, q_addr); | ||
11966 | AscSetChipLramAddr(iop_base, q_addr); | ||
11967 | AscSetChipLramData(iop_base, 0x55AA); | ||
11968 | mdelay(10); | ||
11969 | AscSetChipLramAddr(iop_base, q_addr); | ||
11970 | if (AscGetChipLramData(iop_base) == 0x55AA) { | ||
11971 | sta = 1; | ||
11972 | AscWriteLramWord(iop_base, q_addr, saved_word); | ||
11973 | } | ||
11974 | return (sta); | ||
11975 | } | ||
11976 | |||
11977 | static void __devinit AscWaitEEPWrite(void) | ||
11978 | { | ||
11979 | mdelay(20); | ||
11980 | return; | ||
11981 | } | ||
11982 | |||
11983 | static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) | ||
11984 | { | ||
11985 | ushort read_back; | ||
11986 | int retry; | ||
11987 | |||
11988 | retry = 0; | ||
11989 | while (TRUE) { | ||
11990 | AscSetChipEEPData(iop_base, data_reg); | ||
11991 | mdelay(1); | ||
11992 | read_back = AscGetChipEEPData(iop_base); | ||
11993 | if (read_back == data_reg) { | ||
11994 | return (1); | ||
11995 | } | ||
11996 | if (retry++ > ASC_EEP_MAX_RETRY) { | ||
11997 | return (0); | ||
11998 | } | ||
11999 | } | ||
12000 | } | ||
12001 | |||
12002 | static ushort __devinit | ||
12003 | AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) | ||
12004 | { | ||
12005 | ushort read_wval; | ||
12006 | |||
12007 | read_wval = AscReadEEPWord(iop_base, addr); | ||
12008 | if (read_wval != word_val) { | ||
12009 | AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); | ||
12010 | AscWaitEEPRead(); | ||
12011 | AscWriteEEPDataReg(iop_base, word_val); | ||
12012 | AscWaitEEPRead(); | ||
12013 | AscWriteEEPCmdReg(iop_base, | ||
12014 | (uchar)((uchar)ASC_EEP_CMD_WRITE | addr)); | ||
12015 | AscWaitEEPWrite(); | ||
12016 | AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); | ||
12017 | AscWaitEEPRead(); | ||
12018 | return (AscReadEEPWord(iop_base, addr)); | ||
12019 | } | ||
12020 | return (read_wval); | ||
12021 | } | ||
12022 | |||
12023 | static int __devinit | ||
12024 | AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) | ||
12025 | { | ||
12026 | int n_error; | ||
12027 | ushort *wbuf; | ||
12028 | ushort word; | ||
12029 | ushort sum; | ||
12030 | int s_addr; | ||
12031 | int cfg_beg; | ||
12032 | int cfg_end; | ||
12033 | int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; | ||
12034 | |||
12035 | wbuf = (ushort *)cfg_buf; | ||
12036 | n_error = 0; | ||
12037 | sum = 0; | ||
12038 | /* Write two config words; AscWriteEEPWord() will swap bytes. */ | ||
12039 | for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { | ||
12040 | sum += *wbuf; | ||
12041 | if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { | ||
12042 | n_error++; | ||
12043 | } | ||
12044 | } | ||
12045 | if (bus_type & ASC_IS_VL) { | ||
12046 | cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; | ||
12047 | cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; | ||
12048 | } else { | ||
12049 | cfg_beg = ASC_EEP_DVC_CFG_BEG; | ||
12050 | cfg_end = ASC_EEP_MAX_DVC_ADDR; | ||
12051 | } | ||
12052 | for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { | ||
12053 | if (s_addr <= uchar_end_in_config) { | ||
12054 | /* | ||
12055 | * This is a char field. Swap char fields before they are | ||
12056 | * swapped again by AscWriteEEPWord(). | ||
12057 | */ | ||
12058 | word = cpu_to_le16(*wbuf); | ||
12059 | if (word != | ||
12060 | AscWriteEEPWord(iop_base, (uchar)s_addr, word)) { | ||
12061 | n_error++; | ||
12062 | } | ||
12063 | } else { | ||
12064 | /* Don't swap word field at the end - cntl field. */ | ||
12065 | if (*wbuf != | ||
12066 | AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { | ||
12067 | n_error++; | ||
12068 | } | ||
12069 | } | ||
12070 | sum += *wbuf; /* Checksum calculated from word values. */ | ||
12071 | } | ||
12072 | /* Write checksum word. It will be swapped by AscWriteEEPWord(). */ | ||
12073 | *wbuf = sum; | ||
12074 | if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) { | ||
12075 | n_error++; | ||
12076 | } | ||
12077 | |||
12078 | /* Read EEPROM back again. */ | ||
12079 | wbuf = (ushort *)cfg_buf; | ||
12080 | /* | ||
12081 | * Read two config words; Byte-swapping done by AscReadEEPWord(). | ||
12082 | */ | ||
12083 | for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { | ||
12084 | if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) { | ||
12085 | n_error++; | ||
12086 | } | ||
12087 | } | ||
12088 | if (bus_type & ASC_IS_VL) { | ||
12089 | cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; | ||
12090 | cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; | ||
12091 | } else { | ||
12092 | cfg_beg = ASC_EEP_DVC_CFG_BEG; | ||
12093 | cfg_end = ASC_EEP_MAX_DVC_ADDR; | ||
12094 | } | ||
12095 | for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { | ||
12096 | if (s_addr <= uchar_end_in_config) { | ||
12097 | /* | ||
12098 | * Swap all char fields. Must unswap bytes already swapped | ||
12099 | * by AscReadEEPWord(). | ||
12100 | */ | ||
12101 | word = | ||
12102 | le16_to_cpu(AscReadEEPWord | ||
12103 | (iop_base, (uchar)s_addr)); | ||
12104 | } else { | ||
12105 | /* Don't swap word field at the end - cntl field. */ | ||
12106 | word = AscReadEEPWord(iop_base, (uchar)s_addr); | ||
12107 | } | ||
12108 | if (*wbuf != word) { | ||
12109 | n_error++; | ||
12110 | } | ||
12111 | } | ||
12112 | /* Read checksum; Byte swapping not needed. */ | ||
12113 | if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) { | ||
12114 | n_error++; | ||
12115 | } | ||
12116 | return n_error; | ||
12117 | } | ||
12118 | |||
12119 | static int __devinit | ||
12120 | AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) | ||
12121 | { | ||
12122 | int retry; | ||
12123 | int n_error; | ||
12124 | |||
12125 | retry = 0; | ||
12126 | while (TRUE) { | ||
12127 | if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, | ||
12128 | bus_type)) == 0) { | ||
12129 | break; | ||
12130 | } | ||
12131 | if (++retry > ASC_EEP_MAX_RETRY) { | ||
12132 | break; | ||
12133 | } | ||
12134 | } | ||
12135 | return n_error; | ||
12136 | } | ||
12137 | |||
12138 | static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc) | ||
12139 | { | ||
12140 | ASCEEP_CONFIG eep_config_buf; | ||
12141 | ASCEEP_CONFIG *eep_config; | ||
12142 | PortAddr iop_base; | ||
12143 | ushort chksum; | ||
12144 | ushort warn_code; | ||
12145 | ushort cfg_msw, cfg_lsw; | ||
12146 | int i; | ||
12147 | int write_eep = 0; | ||
12148 | |||
12149 | iop_base = asc_dvc->iop_base; | ||
12150 | warn_code = 0; | ||
12151 | AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); | ||
12152 | AscStopQueueExe(iop_base); | ||
12153 | if ((AscStopChip(iop_base) == FALSE) || | ||
12154 | (AscGetChipScsiCtrl(iop_base) != 0)) { | ||
12155 | asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; | ||
12156 | AscResetChipAndScsiBus(asc_dvc); | ||
12157 | mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ | ||
12158 | } | ||
12159 | if (AscIsChipHalted(iop_base) == FALSE) { | ||
12160 | asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; | ||
12161 | return (warn_code); | ||
12162 | } | ||
12163 | AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); | ||
12164 | if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { | ||
12165 | asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; | ||
12166 | return (warn_code); | ||
12167 | } | ||
12168 | eep_config = (ASCEEP_CONFIG *)&eep_config_buf; | ||
12169 | cfg_msw = AscGetChipCfgMsw(iop_base); | ||
12170 | cfg_lsw = AscGetChipCfgLsw(iop_base); | ||
12171 | if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { | ||
12172 | cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; | ||
12173 | warn_code |= ASC_WARN_CFG_MSW_RECOVER; | ||
12174 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
12175 | } | ||
12176 | chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); | ||
12177 | ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); | ||
12178 | if (chksum == 0) { | ||
12179 | chksum = 0xaa55; | ||
12180 | } | ||
12181 | if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { | ||
12182 | warn_code |= ASC_WARN_AUTO_CONFIG; | ||
12183 | if (asc_dvc->cfg->chip_version == 3) { | ||
12184 | if (eep_config->cfg_lsw != cfg_lsw) { | ||
12185 | warn_code |= ASC_WARN_EEPROM_RECOVER; | ||
12186 | eep_config->cfg_lsw = | ||
12187 | AscGetChipCfgLsw(iop_base); | ||
12188 | } | ||
12189 | if (eep_config->cfg_msw != cfg_msw) { | ||
12190 | warn_code |= ASC_WARN_EEPROM_RECOVER; | ||
12191 | eep_config->cfg_msw = | ||
12192 | AscGetChipCfgMsw(iop_base); | ||
12193 | } | ||
12194 | } | ||
12195 | } | ||
12196 | eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; | ||
12197 | eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; | ||
12198 | ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", | ||
12199 | eep_config->chksum); | ||
12200 | if (chksum != eep_config->chksum) { | ||
12201 | if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == | ||
12202 | ASC_CHIP_VER_PCI_ULTRA_3050) { | ||
12203 | ASC_DBG(1, | ||
12204 | "AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); | ||
12205 | eep_config->init_sdtr = 0xFF; | ||
12206 | eep_config->disc_enable = 0xFF; | ||
12207 | eep_config->start_motor = 0xFF; | ||
12208 | eep_config->use_cmd_qng = 0; | ||
12209 | eep_config->max_total_qng = 0xF0; | ||
12210 | eep_config->max_tag_qng = 0x20; | ||
12211 | eep_config->cntl = 0xBFFF; | ||
12212 | ASC_EEP_SET_CHIP_ID(eep_config, 7); | ||
12213 | eep_config->no_scam = 0; | ||
12214 | eep_config->adapter_info[0] = 0; | ||
12215 | eep_config->adapter_info[1] = 0; | ||
12216 | eep_config->adapter_info[2] = 0; | ||
12217 | eep_config->adapter_info[3] = 0; | ||
12218 | eep_config->adapter_info[4] = 0; | ||
12219 | /* Indicate EEPROM-less board. */ | ||
12220 | eep_config->adapter_info[5] = 0xBB; | ||
12221 | } else { | ||
12222 | ASC_PRINT | ||
12223 | ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); | ||
12224 | write_eep = 1; | ||
12225 | warn_code |= ASC_WARN_EEPROM_CHKSUM; | ||
12226 | } | ||
12227 | } | ||
12228 | asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; | ||
12229 | asc_dvc->cfg->disc_enable = eep_config->disc_enable; | ||
12230 | asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; | ||
12231 | asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); | ||
12232 | asc_dvc->start_motor = eep_config->start_motor; | ||
12233 | asc_dvc->dvc_cntl = eep_config->cntl; | ||
12234 | asc_dvc->no_scam = eep_config->no_scam; | ||
12235 | asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; | ||
12236 | asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; | ||
12237 | asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; | ||
12238 | asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; | ||
12239 | asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; | ||
12240 | asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; | ||
12241 | if (!AscTestExternalLram(asc_dvc)) { | ||
12242 | if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == | ||
12243 | ASC_IS_PCI_ULTRA)) { | ||
12244 | eep_config->max_total_qng = | ||
12245 | ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; | ||
12246 | eep_config->max_tag_qng = | ||
12247 | ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; | ||
12248 | } else { | ||
12249 | eep_config->cfg_msw |= 0x0800; | ||
12250 | cfg_msw |= 0x0800; | ||
12251 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
12252 | eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; | ||
12253 | eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; | ||
12254 | } | ||
12255 | } else { | ||
12256 | } | ||
12257 | if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { | ||
12258 | eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; | ||
12259 | } | ||
12260 | if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { | ||
12261 | eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; | ||
12262 | } | ||
12263 | if (eep_config->max_tag_qng > eep_config->max_total_qng) { | ||
12264 | eep_config->max_tag_qng = eep_config->max_total_qng; | ||
12265 | } | ||
12266 | if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { | ||
12267 | eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; | ||
12268 | } | ||
12269 | asc_dvc->max_total_qng = eep_config->max_total_qng; | ||
12270 | if ((eep_config->use_cmd_qng & eep_config->disc_enable) != | ||
12271 | eep_config->use_cmd_qng) { | ||
12272 | eep_config->disc_enable = eep_config->use_cmd_qng; | ||
12273 | warn_code |= ASC_WARN_CMD_QNG_CONFLICT; | ||
12274 | } | ||
12275 | if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { | ||
12276 | asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); | ||
12277 | } | ||
12278 | ASC_EEP_SET_CHIP_ID(eep_config, | ||
12279 | ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); | ||
12280 | asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); | ||
12281 | if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && | ||
12282 | !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { | ||
12283 | asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; | ||
12284 | } | ||
12285 | |||
12286 | for (i = 0; i <= ASC_MAX_TID; i++) { | ||
12287 | asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; | ||
12288 | asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; | ||
12289 | asc_dvc->cfg->sdtr_period_offset[i] = | ||
12290 | (uchar)(ASC_DEF_SDTR_OFFSET | | ||
12291 | (asc_dvc->host_init_sdtr_index << 4)); | ||
12292 | } | ||
12293 | eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); | ||
12294 | if (write_eep) { | ||
12295 | if ((i = AscSetEEPConfig(iop_base, eep_config, | ||
12296 | asc_dvc->bus_type)) != 0) { | ||
12297 | ASC_PRINT1 | ||
12298 | ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", | ||
12299 | i); | ||
12300 | } else { | ||
12301 | ASC_PRINT | ||
12302 | ("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); | ||
12303 | } | ||
12304 | } | ||
12305 | return (warn_code); | ||
12306 | } | ||
12307 | |||
12308 | static int __devinit AscInitGetConfig(asc_board_t *boardp) | ||
12309 | { | ||
12310 | ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; | ||
12311 | unsigned short warn_code = 0; | ||
12312 | |||
12313 | asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; | ||
12314 | if (asc_dvc->err_code != 0) | ||
12315 | return asc_dvc->err_code; | ||
12316 | |||
12317 | if (AscFindSignature(asc_dvc->iop_base)) { | ||
12318 | warn_code |= AscInitAscDvcVar(asc_dvc); | ||
12319 | warn_code |= AscInitFromEEP(asc_dvc); | ||
12320 | asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; | ||
12321 | if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) | ||
12322 | asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; | ||
12323 | } else { | ||
12324 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; | ||
12325 | } | ||
12326 | |||
12327 | switch (warn_code) { | ||
12328 | case 0: /* No error */ | ||
12329 | break; | ||
12330 | case ASC_WARN_IO_PORT_ROTATE: | ||
12331 | ASC_PRINT1("AscInitGetConfig: board %d: I/O port address " | ||
12332 | "modified\n", boardp->id); | ||
12333 | break; | ||
12334 | case ASC_WARN_AUTO_CONFIG: | ||
12335 | ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment " | ||
12336 | "switch enabled\n", boardp->id); | ||
12337 | break; | ||
12338 | case ASC_WARN_EEPROM_CHKSUM: | ||
12339 | ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum " | ||
12340 | "error\n", boardp->id); | ||
12341 | break; | ||
12342 | case ASC_WARN_IRQ_MODIFIED: | ||
12343 | ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n", | ||
12344 | boardp->id); | ||
12345 | break; | ||
12346 | case ASC_WARN_CMD_QNG_CONFLICT: | ||
12347 | ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled " | ||
12348 | "w/o disconnects\n", boardp->id); | ||
12349 | break; | ||
12350 | default: | ||
12351 | ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: " | ||
12352 | "0x%x\n", boardp->id, warn_code); | ||
12353 | break; | ||
12354 | } | ||
12355 | |||
12356 | if (asc_dvc->err_code != 0) { | ||
12357 | ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, " | ||
12358 | "err_code 0x%x\n", boardp->id, asc_dvc->init_state, | ||
12359 | asc_dvc->err_code); | ||
12360 | } | ||
12361 | |||
12362 | return asc_dvc->err_code; | ||
12363 | } | ||
12364 | |||
12365 | static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp) | ||
12366 | { | ||
12367 | ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; | ||
12368 | PortAddr iop_base = asc_dvc->iop_base; | ||
12369 | unsigned short cfg_msw; | ||
12370 | unsigned short warn_code = 0; | ||
12371 | |||
12372 | asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; | ||
12373 | if (asc_dvc->err_code != 0) | ||
12374 | return asc_dvc->err_code; | ||
12375 | if (!AscFindSignature(asc_dvc->iop_base)) { | ||
12376 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; | ||
12377 | return asc_dvc->err_code; | ||
12378 | } | ||
12379 | |||
12380 | cfg_msw = AscGetChipCfgMsw(iop_base); | ||
12381 | if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { | ||
12382 | cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; | ||
12383 | warn_code |= ASC_WARN_CFG_MSW_RECOVER; | ||
12384 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
12385 | } | ||
12386 | if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != | ||
12387 | asc_dvc->cfg->cmd_qng_enabled) { | ||
12388 | asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; | ||
12389 | warn_code |= ASC_WARN_CMD_QNG_CONFLICT; | ||
12390 | } | ||
12391 | if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { | ||
12392 | warn_code |= ASC_WARN_AUTO_CONFIG; | ||
12393 | } | ||
12394 | if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { | ||
12395 | if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) | ||
12396 | != asc_dvc->irq_no) { | ||
12397 | asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; | ||
12398 | } | ||
12399 | } | ||
12400 | #ifdef CONFIG_PCI | ||
12401 | if (asc_dvc->bus_type & ASC_IS_PCI) { | ||
12402 | cfg_msw &= 0xFFC0; | ||
12403 | AscSetChipCfgMsw(iop_base, cfg_msw); | ||
12404 | if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { | ||
12405 | } else { | ||
12406 | if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) || | ||
12407 | (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) { | ||
12408 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; | ||
12409 | asc_dvc->bug_fix_cntl |= | ||
12410 | ASC_BUG_FIX_ASYN_USE_SYN; | ||
12411 | } | ||
12412 | } | ||
12413 | } else | ||
12414 | #endif /* CONFIG_PCI */ | ||
12415 | if (asc_dvc->bus_type == ASC_IS_ISAPNP) { | ||
12416 | if (AscGetChipVersion(iop_base, asc_dvc->bus_type) | ||
12417 | == ASC_CHIP_VER_ASYN_BUG) { | ||
12418 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; | ||
12419 | } | ||
12420 | } | ||
12421 | if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != | ||
12422 | asc_dvc->cfg->chip_scsi_id) { | ||
12423 | asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; | ||
12424 | } | ||
12425 | #ifdef CONFIG_ISA | ||
12426 | if (asc_dvc->bus_type & ASC_IS_ISA) { | ||
12427 | AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); | ||
12428 | AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); | ||
12429 | } | ||
12430 | #endif /* CONFIG_ISA */ | ||
12431 | |||
12432 | asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; | ||
12433 | |||
12434 | switch (warn_code) { | ||
12435 | case 0: /* No error. */ | ||
12436 | break; | ||
12437 | case ASC_WARN_IO_PORT_ROTATE: | ||
12438 | ASC_PRINT1("AscInitSetConfig: board %d: I/O port address " | ||
12439 | "modified\n", boardp->id); | ||
12440 | break; | ||
12441 | case ASC_WARN_AUTO_CONFIG: | ||
12442 | ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment " | ||
12443 | "switch enabled\n", boardp->id); | ||
12444 | break; | ||
12445 | case ASC_WARN_EEPROM_CHKSUM: | ||
12446 | ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum " | ||
12447 | "error\n", boardp->id); | ||
12448 | break; | ||
12449 | case ASC_WARN_IRQ_MODIFIED: | ||
12450 | ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n", | ||
12451 | boardp->id); | ||
12452 | break; | ||
12453 | case ASC_WARN_CMD_QNG_CONFLICT: | ||
12454 | ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o " | ||
12455 | "disconnects\n", | ||
12456 | boardp->id); | ||
12457 | break; | ||
12458 | default: | ||
12459 | ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: " | ||
12460 | "0x%x\n", boardp->id, warn_code); | ||
12461 | break; | ||
12462 | } | ||
12463 | |||
12464 | if (asc_dvc->err_code != 0) { | ||
12465 | ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, " | ||
12466 | "err_code 0x%x\n", boardp->id, asc_dvc->init_state, | ||
12467 | asc_dvc->err_code); | ||
12468 | } | ||
12469 | |||
12470 | return asc_dvc->err_code; | ||
12471 | } | ||
12472 | |||
12473 | /* | ||
12474 | * EEPROM Configuration. | ||
12475 | * | ||
12476 | * All drivers should use this structure to set the default EEPROM | ||
12477 | * configuration. The BIOS now uses this structure when it is built. | ||
12478 | * Additional structure information can be found in a_condor.h where | ||
12479 | * the structure is defined. | ||
12480 | * | ||
12481 | * The *_Field_IsChar structs are needed to correct for endianness. | ||
12482 | * These values are read from the board 16 bits at a time directly | ||
12483 | * into the structs. Because some fields are char, the values will be | ||
12484 | * in the wrong order. The *_Field_IsChar tells when to flip the | ||
12485 | * bytes. Data read and written to PCI memory is automatically swapped | ||
12486 | * on big-endian platforms so char fields read as words are actually being | ||
12487 | * unswapped on big-endian platforms. | ||
12488 | */ | ||
12489 | static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = { | ||
12490 | ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ | ||
12491 | 0x0000, /* cfg_msw */ | ||
12492 | 0xFFFF, /* disc_enable */ | ||
12493 | 0xFFFF, /* wdtr_able */ | ||
12494 | 0xFFFF, /* sdtr_able */ | ||
12495 | 0xFFFF, /* start_motor */ | ||
12496 | 0xFFFF, /* tagqng_able */ | ||
12497 | 0xFFFF, /* bios_scan */ | ||
12498 | 0, /* scam_tolerant */ | ||
12499 | 7, /* adapter_scsi_id */ | ||
12500 | 0, /* bios_boot_delay */ | ||
12501 | 3, /* scsi_reset_delay */ | ||
12502 | 0, /* bios_id_lun */ | ||
12503 | 0, /* termination */ | ||
12504 | 0, /* reserved1 */ | ||
12505 | 0xFFE7, /* bios_ctrl */ | ||
12506 | 0xFFFF, /* ultra_able */ | ||
12507 | 0, /* reserved2 */ | ||
12508 | ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ | ||
12509 | ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ | ||
12510 | 0, /* dvc_cntl */ | ||
12511 | 0, /* bug_fix */ | ||
12512 | 0, /* serial_number_word1 */ | ||
12513 | 0, /* serial_number_word2 */ | ||
12514 | 0, /* serial_number_word3 */ | ||
12515 | 0, /* check_sum */ | ||
12516 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
12517 | , /* oem_name[16] */ | ||
12518 | 0, /* dvc_err_code */ | ||
12519 | 0, /* adv_err_code */ | ||
12520 | 0, /* adv_err_addr */ | ||
12521 | 0, /* saved_dvc_err_code */ | ||
12522 | 0, /* saved_adv_err_code */ | ||
12523 | 0, /* saved_adv_err_addr */ | ||
12524 | 0 /* num_of_err */ | ||
12525 | }; | ||
12526 | |||
12527 | static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = { | ||
12528 | 0, /* cfg_lsw */ | ||
12529 | 0, /* cfg_msw */ | ||
12530 | 0, /* -disc_enable */ | ||
12531 | 0, /* wdtr_able */ | ||
12532 | 0, /* sdtr_able */ | ||
12533 | 0, /* start_motor */ | ||
12534 | 0, /* tagqng_able */ | ||
12535 | 0, /* bios_scan */ | ||
12536 | 0, /* scam_tolerant */ | ||
12537 | 1, /* adapter_scsi_id */ | ||
12538 | 1, /* bios_boot_delay */ | ||
12539 | 1, /* scsi_reset_delay */ | ||
12540 | 1, /* bios_id_lun */ | ||
12541 | 1, /* termination */ | ||
12542 | 1, /* reserved1 */ | ||
12543 | 0, /* bios_ctrl */ | ||
12544 | 0, /* ultra_able */ | ||
12545 | 0, /* reserved2 */ | ||
12546 | 1, /* max_host_qng */ | ||
12547 | 1, /* max_dvc_qng */ | ||
12548 | 0, /* dvc_cntl */ | ||
12549 | 0, /* bug_fix */ | ||
12550 | 0, /* serial_number_word1 */ | ||
12551 | 0, /* serial_number_word2 */ | ||
12552 | 0, /* serial_number_word3 */ | ||
12553 | 0, /* check_sum */ | ||
12554 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
12555 | , /* oem_name[16] */ | ||
12556 | 0, /* dvc_err_code */ | ||
12557 | 0, /* adv_err_code */ | ||
12558 | 0, /* adv_err_addr */ | ||
12559 | 0, /* saved_dvc_err_code */ | ||
12560 | 0, /* saved_adv_err_code */ | ||
12561 | 0, /* saved_adv_err_addr */ | ||
12562 | 0 /* num_of_err */ | ||
12563 | }; | ||
12564 | |||
12565 | static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = { | ||
12566 | ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ | ||
12567 | 0x0000, /* 01 cfg_msw */ | ||
12568 | 0xFFFF, /* 02 disc_enable */ | ||
12569 | 0xFFFF, /* 03 wdtr_able */ | ||
12570 | 0x4444, /* 04 sdtr_speed1 */ | ||
12571 | 0xFFFF, /* 05 start_motor */ | ||
12572 | 0xFFFF, /* 06 tagqng_able */ | ||
12573 | 0xFFFF, /* 07 bios_scan */ | ||
12574 | 0, /* 08 scam_tolerant */ | ||
12575 | 7, /* 09 adapter_scsi_id */ | ||
12576 | 0, /* bios_boot_delay */ | ||
12577 | 3, /* 10 scsi_reset_delay */ | ||
12578 | 0, /* bios_id_lun */ | ||
12579 | 0, /* 11 termination_se */ | ||
12580 | 0, /* termination_lvd */ | ||
12581 | 0xFFE7, /* 12 bios_ctrl */ | ||
12582 | 0x4444, /* 13 sdtr_speed2 */ | ||
12583 | 0x4444, /* 14 sdtr_speed3 */ | ||
12584 | ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ | ||
12585 | ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ | ||
12586 | 0, /* 16 dvc_cntl */ | ||
12587 | 0x4444, /* 17 sdtr_speed4 */ | ||
12588 | 0, /* 18 serial_number_word1 */ | ||
12589 | 0, /* 19 serial_number_word2 */ | ||
12590 | 0, /* 20 serial_number_word3 */ | ||
12591 | 0, /* 21 check_sum */ | ||
12592 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
12593 | , /* 22-29 oem_name[16] */ | ||
12594 | 0, /* 30 dvc_err_code */ | ||
12595 | 0, /* 31 adv_err_code */ | ||
12596 | 0, /* 32 adv_err_addr */ | ||
12597 | 0, /* 33 saved_dvc_err_code */ | ||
12598 | 0, /* 34 saved_adv_err_code */ | ||
12599 | 0, /* 35 saved_adv_err_addr */ | ||
12600 | 0, /* 36 reserved */ | ||
12601 | 0, /* 37 reserved */ | ||
12602 | 0, /* 38 reserved */ | ||
12603 | 0, /* 39 reserved */ | ||
12604 | 0, /* 40 reserved */ | ||
12605 | 0, /* 41 reserved */ | ||
12606 | 0, /* 42 reserved */ | ||
12607 | 0, /* 43 reserved */ | ||
12608 | 0, /* 44 reserved */ | ||
12609 | 0, /* 45 reserved */ | ||
12610 | 0, /* 46 reserved */ | ||
12611 | 0, /* 47 reserved */ | ||
12612 | 0, /* 48 reserved */ | ||
12613 | 0, /* 49 reserved */ | ||
12614 | 0, /* 50 reserved */ | ||
12615 | 0, /* 51 reserved */ | ||
12616 | 0, /* 52 reserved */ | ||
12617 | 0, /* 53 reserved */ | ||
12618 | 0, /* 54 reserved */ | ||
12619 | 0, /* 55 reserved */ | ||
12620 | 0, /* 56 cisptr_lsw */ | ||
12621 | 0, /* 57 cisprt_msw */ | ||
12622 | PCI_VENDOR_ID_ASP, /* 58 subsysvid */ | ||
12623 | PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ | ||
12624 | 0, /* 60 reserved */ | ||
12625 | 0, /* 61 reserved */ | ||
12626 | 0, /* 62 reserved */ | ||
12627 | 0 /* 63 reserved */ | ||
12628 | }; | ||
12629 | |||
12630 | static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = { | ||
12631 | 0, /* 00 cfg_lsw */ | ||
12632 | 0, /* 01 cfg_msw */ | ||
12633 | 0, /* 02 disc_enable */ | ||
12634 | 0, /* 03 wdtr_able */ | ||
12635 | 0, /* 04 sdtr_speed1 */ | ||
12636 | 0, /* 05 start_motor */ | ||
12637 | 0, /* 06 tagqng_able */ | ||
12638 | 0, /* 07 bios_scan */ | ||
12639 | 0, /* 08 scam_tolerant */ | ||
12640 | 1, /* 09 adapter_scsi_id */ | ||
12641 | 1, /* bios_boot_delay */ | ||
12642 | 1, /* 10 scsi_reset_delay */ | ||
12643 | 1, /* bios_id_lun */ | ||
12644 | 1, /* 11 termination_se */ | ||
12645 | 1, /* termination_lvd */ | ||
12646 | 0, /* 12 bios_ctrl */ | ||
12647 | 0, /* 13 sdtr_speed2 */ | ||
12648 | 0, /* 14 sdtr_speed3 */ | ||
12649 | 1, /* 15 max_host_qng */ | ||
12650 | 1, /* max_dvc_qng */ | ||
12651 | 0, /* 16 dvc_cntl */ | ||
12652 | 0, /* 17 sdtr_speed4 */ | ||
12653 | 0, /* 18 serial_number_word1 */ | ||
12654 | 0, /* 19 serial_number_word2 */ | ||
12655 | 0, /* 20 serial_number_word3 */ | ||
12656 | 0, /* 21 check_sum */ | ||
12657 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
12658 | , /* 22-29 oem_name[16] */ | ||
12659 | 0, /* 30 dvc_err_code */ | ||
12660 | 0, /* 31 adv_err_code */ | ||
12661 | 0, /* 32 adv_err_addr */ | ||
12662 | 0, /* 33 saved_dvc_err_code */ | ||
12663 | 0, /* 34 saved_adv_err_code */ | ||
12664 | 0, /* 35 saved_adv_err_addr */ | ||
12665 | 0, /* 36 reserved */ | ||
12666 | 0, /* 37 reserved */ | ||
12667 | 0, /* 38 reserved */ | ||
12668 | 0, /* 39 reserved */ | ||
12669 | 0, /* 40 reserved */ | ||
12670 | 0, /* 41 reserved */ | ||
12671 | 0, /* 42 reserved */ | ||
12672 | 0, /* 43 reserved */ | ||
12673 | 0, /* 44 reserved */ | ||
12674 | 0, /* 45 reserved */ | ||
12675 | 0, /* 46 reserved */ | ||
12676 | 0, /* 47 reserved */ | ||
12677 | 0, /* 48 reserved */ | ||
12678 | 0, /* 49 reserved */ | ||
12679 | 0, /* 50 reserved */ | ||
12680 | 0, /* 51 reserved */ | ||
12681 | 0, /* 52 reserved */ | ||
12682 | 0, /* 53 reserved */ | ||
12683 | 0, /* 54 reserved */ | ||
12684 | 0, /* 55 reserved */ | ||
12685 | 0, /* 56 cisptr_lsw */ | ||
12686 | 0, /* 57 cisprt_msw */ | ||
12687 | 0, /* 58 subsysvid */ | ||
12688 | 0, /* 59 subsysid */ | ||
12689 | 0, /* 60 reserved */ | ||
12690 | 0, /* 61 reserved */ | ||
12691 | 0, /* 62 reserved */ | ||
12692 | 0 /* 63 reserved */ | ||
12693 | }; | ||
12694 | |||
12695 | static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = { | ||
12696 | ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ | ||
12697 | 0x0000, /* 01 cfg_msw */ | ||
12698 | 0xFFFF, /* 02 disc_enable */ | ||
12699 | 0xFFFF, /* 03 wdtr_able */ | ||
12700 | 0x5555, /* 04 sdtr_speed1 */ | ||
12701 | 0xFFFF, /* 05 start_motor */ | ||
12702 | 0xFFFF, /* 06 tagqng_able */ | ||
12703 | 0xFFFF, /* 07 bios_scan */ | ||
12704 | 0, /* 08 scam_tolerant */ | ||
12705 | 7, /* 09 adapter_scsi_id */ | ||
12706 | 0, /* bios_boot_delay */ | ||
12707 | 3, /* 10 scsi_reset_delay */ | ||
12708 | 0, /* bios_id_lun */ | ||
12709 | 0, /* 11 termination_se */ | ||
12710 | 0, /* termination_lvd */ | ||
12711 | 0xFFE7, /* 12 bios_ctrl */ | ||
12712 | 0x5555, /* 13 sdtr_speed2 */ | ||
12713 | 0x5555, /* 14 sdtr_speed3 */ | ||
12714 | ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ | ||
12715 | ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ | ||
12716 | 0, /* 16 dvc_cntl */ | ||
12717 | 0x5555, /* 17 sdtr_speed4 */ | ||
12718 | 0, /* 18 serial_number_word1 */ | ||
12719 | 0, /* 19 serial_number_word2 */ | ||
12720 | 0, /* 20 serial_number_word3 */ | ||
12721 | 0, /* 21 check_sum */ | ||
12722 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
12723 | , /* 22-29 oem_name[16] */ | ||
12724 | 0, /* 30 dvc_err_code */ | ||
12725 | 0, /* 31 adv_err_code */ | ||
12726 | 0, /* 32 adv_err_addr */ | ||
12727 | 0, /* 33 saved_dvc_err_code */ | ||
12728 | 0, /* 34 saved_adv_err_code */ | ||
12729 | 0, /* 35 saved_adv_err_addr */ | ||
12730 | 0, /* 36 reserved */ | ||
12731 | 0, /* 37 reserved */ | ||
12732 | 0, /* 38 reserved */ | ||
12733 | 0, /* 39 reserved */ | ||
12734 | 0, /* 40 reserved */ | ||
12735 | 0, /* 41 reserved */ | ||
12736 | 0, /* 42 reserved */ | ||
12737 | 0, /* 43 reserved */ | ||
12738 | 0, /* 44 reserved */ | ||
12739 | 0, /* 45 reserved */ | ||
12740 | 0, /* 46 reserved */ | ||
12741 | 0, /* 47 reserved */ | ||
12742 | 0, /* 48 reserved */ | ||
12743 | 0, /* 49 reserved */ | ||
12744 | 0, /* 50 reserved */ | ||
12745 | 0, /* 51 reserved */ | ||
12746 | 0, /* 52 reserved */ | ||
12747 | 0, /* 53 reserved */ | ||
12748 | 0, /* 54 reserved */ | ||
12749 | 0, /* 55 reserved */ | ||
12750 | 0, /* 56 cisptr_lsw */ | ||
12751 | 0, /* 57 cisprt_msw */ | ||
12752 | PCI_VENDOR_ID_ASP, /* 58 subsysvid */ | ||
12753 | PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ | ||
12754 | 0, /* 60 reserved */ | ||
12755 | 0, /* 61 reserved */ | ||
12756 | 0, /* 62 reserved */ | ||
12757 | 0 /* 63 reserved */ | ||
12758 | }; | ||
12759 | |||
12760 | static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = { | ||
12761 | 0, /* 00 cfg_lsw */ | ||
12762 | 0, /* 01 cfg_msw */ | ||
12763 | 0, /* 02 disc_enable */ | ||
12764 | 0, /* 03 wdtr_able */ | ||
12765 | 0, /* 04 sdtr_speed1 */ | ||
12766 | 0, /* 05 start_motor */ | ||
12767 | 0, /* 06 tagqng_able */ | ||
12768 | 0, /* 07 bios_scan */ | ||
12769 | 0, /* 08 scam_tolerant */ | ||
12770 | 1, /* 09 adapter_scsi_id */ | ||
12771 | 1, /* bios_boot_delay */ | ||
12772 | 1, /* 10 scsi_reset_delay */ | ||
12773 | 1, /* bios_id_lun */ | ||
12774 | 1, /* 11 termination_se */ | ||
12775 | 1, /* termination_lvd */ | ||
12776 | 0, /* 12 bios_ctrl */ | ||
12777 | 0, /* 13 sdtr_speed2 */ | ||
12778 | 0, /* 14 sdtr_speed3 */ | ||
12779 | 1, /* 15 max_host_qng */ | ||
12780 | 1, /* max_dvc_qng */ | ||
12781 | 0, /* 16 dvc_cntl */ | ||
12782 | 0, /* 17 sdtr_speed4 */ | ||
12783 | 0, /* 18 serial_number_word1 */ | ||
12784 | 0, /* 19 serial_number_word2 */ | ||
12785 | 0, /* 20 serial_number_word3 */ | ||
12786 | 0, /* 21 check_sum */ | ||
12787 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
12788 | , /* 22-29 oem_name[16] */ | ||
12789 | 0, /* 30 dvc_err_code */ | ||
12790 | 0, /* 31 adv_err_code */ | ||
12791 | 0, /* 32 adv_err_addr */ | ||
12792 | 0, /* 33 saved_dvc_err_code */ | ||
12793 | 0, /* 34 saved_adv_err_code */ | ||
12794 | 0, /* 35 saved_adv_err_addr */ | ||
12795 | 0, /* 36 reserved */ | ||
12796 | 0, /* 37 reserved */ | ||
12797 | 0, /* 38 reserved */ | ||
12798 | 0, /* 39 reserved */ | ||
12799 | 0, /* 40 reserved */ | ||
12800 | 0, /* 41 reserved */ | ||
12801 | 0, /* 42 reserved */ | ||
12802 | 0, /* 43 reserved */ | ||
12803 | 0, /* 44 reserved */ | ||
12804 | 0, /* 45 reserved */ | ||
12805 | 0, /* 46 reserved */ | ||
12806 | 0, /* 47 reserved */ | ||
12807 | 0, /* 48 reserved */ | ||
12808 | 0, /* 49 reserved */ | ||
12809 | 0, /* 50 reserved */ | ||
12810 | 0, /* 51 reserved */ | ||
12811 | 0, /* 52 reserved */ | ||
12812 | 0, /* 53 reserved */ | ||
12813 | 0, /* 54 reserved */ | ||
12814 | 0, /* 55 reserved */ | ||
12815 | 0, /* 56 cisptr_lsw */ | ||
12816 | 0, /* 57 cisprt_msw */ | ||
12817 | 0, /* 58 subsysvid */ | ||
12818 | 0, /* 59 subsysid */ | ||
12819 | 0, /* 60 reserved */ | ||
12820 | 0, /* 61 reserved */ | ||
12821 | 0, /* 62 reserved */ | ||
12822 | 0 /* 63 reserved */ | ||
12823 | }; | ||
12824 | |||
12825 | #ifdef CONFIG_PCI | ||
12826 | /* | ||
12827 | * Wait for EEPROM command to complete | ||
12828 | */ | ||
12829 | static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base) | ||
12830 | { | ||
12831 | int eep_delay_ms; | ||
12832 | |||
12833 | for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) { | ||
12834 | if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & | ||
12835 | ASC_EEP_CMD_DONE) { | ||
12836 | break; | ||
12837 | } | ||
12838 | mdelay(1); | ||
12839 | } | ||
12840 | if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == | ||
12841 | 0) | ||
12842 | BUG(); | ||
12843 | } | ||
12844 | |||
12845 | /* | ||
12846 | * Read the EEPROM from specified location | ||
12847 | */ | ||
12848 | static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) | ||
12849 | { | ||
12850 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
12851 | ASC_EEP_CMD_READ | eep_word_addr); | ||
12852 | AdvWaitEEPCmd(iop_base); | ||
12853 | return AdvReadWordRegister(iop_base, IOPW_EE_DATA); | ||
12854 | } | ||
12855 | |||
12856 | /* | ||
12857 | * Write the EEPROM from 'cfg_buf'. | ||
12858 | */ | ||
12859 | void __devinit | ||
12860 | AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) | ||
12861 | { | ||
12862 | ushort *wbuf; | ||
12863 | ushort addr, chksum; | ||
12864 | ushort *charfields; | ||
12865 | |||
12866 | wbuf = (ushort *)cfg_buf; | ||
12867 | charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; | ||
12868 | chksum = 0; | ||
12869 | |||
12870 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); | ||
12871 | AdvWaitEEPCmd(iop_base); | ||
12872 | |||
12873 | /* | ||
12874 | * Write EEPROM from word 0 to word 20. | ||
12875 | */ | ||
12876 | for (addr = ADV_EEP_DVC_CFG_BEGIN; | ||
12877 | addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { | ||
12878 | ushort word; | ||
12879 | |||
12880 | if (*charfields++) { | ||
12881 | word = cpu_to_le16(*wbuf); | ||
12882 | } else { | ||
12883 | word = *wbuf; | ||
12884 | } | ||
12885 | chksum += *wbuf; /* Checksum is calculated from word values. */ | ||
12886 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
12887 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
12888 | ASC_EEP_CMD_WRITE | addr); | ||
12889 | AdvWaitEEPCmd(iop_base); | ||
12890 | mdelay(ADV_EEP_DELAY_MS); | ||
12891 | } | ||
12892 | |||
12893 | /* | ||
12894 | * Write EEPROM checksum at word 21. | ||
12895 | */ | ||
12896 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); | ||
12897 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); | ||
12898 | AdvWaitEEPCmd(iop_base); | ||
12899 | wbuf++; | ||
12900 | charfields++; | ||
12901 | |||
12902 | /* | ||
12903 | * Write EEPROM OEM name at words 22 to 29. | ||
12904 | */ | ||
12905 | for (addr = ADV_EEP_DVC_CTL_BEGIN; | ||
12906 | addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { | ||
12907 | ushort word; | ||
12908 | |||
12909 | if (*charfields++) { | ||
12910 | word = cpu_to_le16(*wbuf); | ||
12911 | } else { | ||
12912 | word = *wbuf; | ||
12913 | } | ||
12914 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
12915 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
12916 | ASC_EEP_CMD_WRITE | addr); | ||
12917 | AdvWaitEEPCmd(iop_base); | ||
12918 | } | ||
12919 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); | ||
12920 | AdvWaitEEPCmd(iop_base); | ||
12921 | } | ||
12922 | |||
12923 | /* | ||
12924 | * Write the EEPROM from 'cfg_buf'. | ||
12925 | */ | ||
12926 | void __devinit | ||
12927 | AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) | ||
12928 | { | ||
12929 | ushort *wbuf; | ||
12930 | ushort *charfields; | ||
12931 | ushort addr, chksum; | ||
12932 | |||
12933 | wbuf = (ushort *)cfg_buf; | ||
12934 | charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; | ||
12935 | chksum = 0; | ||
12936 | |||
12937 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); | ||
12938 | AdvWaitEEPCmd(iop_base); | ||
12939 | |||
12940 | /* | ||
12941 | * Write EEPROM from word 0 to word 20. | ||
12942 | */ | ||
12943 | for (addr = ADV_EEP_DVC_CFG_BEGIN; | ||
12944 | addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { | ||
12945 | ushort word; | ||
12946 | |||
12947 | if (*charfields++) { | ||
12948 | word = cpu_to_le16(*wbuf); | ||
12949 | } else { | ||
12950 | word = *wbuf; | ||
12951 | } | ||
12952 | chksum += *wbuf; /* Checksum is calculated from word values. */ | ||
12953 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
12954 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
12955 | ASC_EEP_CMD_WRITE | addr); | ||
12956 | AdvWaitEEPCmd(iop_base); | ||
12957 | mdelay(ADV_EEP_DELAY_MS); | ||
12958 | } | ||
12959 | |||
12960 | /* | ||
12961 | * Write EEPROM checksum at word 21. | ||
12962 | */ | ||
12963 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); | ||
12964 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); | ||
12965 | AdvWaitEEPCmd(iop_base); | ||
12966 | wbuf++; | ||
12967 | charfields++; | ||
12968 | |||
12969 | /* | ||
12970 | * Write EEPROM OEM name at words 22 to 29. | ||
12971 | */ | ||
12972 | for (addr = ADV_EEP_DVC_CTL_BEGIN; | ||
12973 | addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { | ||
12974 | ushort word; | ||
12975 | |||
12976 | if (*charfields++) { | ||
12977 | word = cpu_to_le16(*wbuf); | ||
12978 | } else { | ||
12979 | word = *wbuf; | ||
12980 | } | ||
12981 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
12982 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
12983 | ASC_EEP_CMD_WRITE | addr); | ||
12984 | AdvWaitEEPCmd(iop_base); | ||
12985 | } | ||
12986 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); | ||
12987 | AdvWaitEEPCmd(iop_base); | ||
12988 | } | ||
12989 | |||
12990 | /* | ||
12991 | * Write the EEPROM from 'cfg_buf'. | ||
12992 | */ | ||
12993 | void __devinit | ||
12994 | AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) | ||
12995 | { | ||
12996 | ushort *wbuf; | ||
12997 | ushort *charfields; | ||
12998 | ushort addr, chksum; | ||
12999 | |||
13000 | wbuf = (ushort *)cfg_buf; | ||
13001 | charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; | ||
13002 | chksum = 0; | ||
13003 | |||
13004 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); | ||
13005 | AdvWaitEEPCmd(iop_base); | ||
13006 | |||
13007 | /* | ||
13008 | * Write EEPROM from word 0 to word 20. | ||
13009 | */ | ||
13010 | for (addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13011 | addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { | ||
13012 | ushort word; | ||
13013 | |||
13014 | if (*charfields++) { | ||
13015 | word = cpu_to_le16(*wbuf); | ||
13016 | } else { | ||
13017 | word = *wbuf; | ||
13018 | } | ||
13019 | chksum += *wbuf; /* Checksum is calculated from word values. */ | ||
13020 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13021 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13022 | ASC_EEP_CMD_WRITE | addr); | ||
13023 | AdvWaitEEPCmd(iop_base); | ||
13024 | mdelay(ADV_EEP_DELAY_MS); | ||
13025 | } | ||
13026 | |||
13027 | /* | ||
13028 | * Write EEPROM checksum at word 21. | ||
13029 | */ | ||
13030 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); | ||
13031 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); | ||
13032 | AdvWaitEEPCmd(iop_base); | ||
13033 | wbuf++; | ||
13034 | charfields++; | ||
13035 | |||
13036 | /* | ||
13037 | * Write EEPROM OEM name at words 22 to 29. | ||
13038 | */ | ||
13039 | for (addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13040 | addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { | ||
13041 | ushort word; | ||
13042 | |||
13043 | if (*charfields++) { | ||
13044 | word = cpu_to_le16(*wbuf); | ||
13045 | } else { | ||
13046 | word = *wbuf; | ||
13047 | } | ||
13048 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13049 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13050 | ASC_EEP_CMD_WRITE | addr); | ||
13051 | AdvWaitEEPCmd(iop_base); | ||
13052 | } | ||
13053 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); | ||
13054 | AdvWaitEEPCmd(iop_base); | ||
13055 | } | ||
13056 | |||
13057 | /* | ||
13058 | * Read EEPROM configuration into the specified buffer. | ||
13059 | * | ||
13060 | * Return a checksum based on the EEPROM configuration read. | ||
13061 | */ | ||
13062 | static ushort __devinit | ||
13063 | AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) | ||
13064 | { | ||
13065 | ushort wval, chksum; | ||
13066 | ushort *wbuf; | ||
13067 | int eep_addr; | ||
13068 | ushort *charfields; | ||
13069 | |||
13070 | charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; | ||
13071 | wbuf = (ushort *)cfg_buf; | ||
13072 | chksum = 0; | ||
13073 | |||
13074 | for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13075 | eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { | ||
13076 | wval = AdvReadEEPWord(iop_base, eep_addr); | ||
13077 | chksum += wval; /* Checksum is calculated from word values. */ | ||
13078 | if (*charfields++) { | ||
13079 | *wbuf = le16_to_cpu(wval); | ||
13080 | } else { | ||
13081 | *wbuf = wval; | ||
13082 | } | ||
13083 | } | ||
13084 | /* Read checksum word. */ | ||
13085 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13086 | wbuf++; | ||
13087 | charfields++; | ||
13088 | |||
13089 | /* Read rest of EEPROM not covered by the checksum. */ | ||
13090 | for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13091 | eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { | ||
13092 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13093 | if (*charfields++) { | ||
13094 | *wbuf = le16_to_cpu(*wbuf); | ||
13095 | } | ||
13096 | } | ||
13097 | return chksum; | ||
13098 | } | ||
13099 | |||
13100 | /* | ||
13101 | * Read EEPROM configuration into the specified buffer. | ||
13102 | * | ||
13103 | * Return a checksum based on the EEPROM configuration read. | ||
13104 | */ | ||
13105 | static ushort __devinit | ||
13106 | AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) | ||
13107 | { | ||
13108 | ushort wval, chksum; | ||
13109 | ushort *wbuf; | ||
13110 | int eep_addr; | ||
13111 | ushort *charfields; | ||
13112 | |||
13113 | charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; | ||
13114 | wbuf = (ushort *)cfg_buf; | ||
13115 | chksum = 0; | ||
13116 | |||
13117 | for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13118 | eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { | ||
13119 | wval = AdvReadEEPWord(iop_base, eep_addr); | ||
13120 | chksum += wval; /* Checksum is calculated from word values. */ | ||
13121 | if (*charfields++) { | ||
13122 | *wbuf = le16_to_cpu(wval); | ||
13123 | } else { | ||
13124 | *wbuf = wval; | ||
13125 | } | ||
13126 | } | ||
13127 | /* Read checksum word. */ | ||
13128 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13129 | wbuf++; | ||
13130 | charfields++; | ||
13131 | |||
13132 | /* Read rest of EEPROM not covered by the checksum. */ | ||
13133 | for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13134 | eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { | ||
13135 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13136 | if (*charfields++) { | ||
13137 | *wbuf = le16_to_cpu(*wbuf); | ||
13138 | } | ||
13139 | } | ||
13140 | return chksum; | ||
13141 | } | ||
13142 | |||
13143 | /* | ||
13144 | * Read EEPROM configuration into the specified buffer. | ||
13145 | * | ||
13146 | * Return a checksum based on the EEPROM configuration read. | ||
13147 | */ | ||
13148 | static ushort __devinit | ||
13149 | AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) | ||
13150 | { | ||
13151 | ushort wval, chksum; | ||
13152 | ushort *wbuf; | ||
13153 | int eep_addr; | ||
13154 | ushort *charfields; | ||
13155 | |||
13156 | charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; | ||
13157 | wbuf = (ushort *)cfg_buf; | ||
13158 | chksum = 0; | ||
13159 | |||
13160 | for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13161 | eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { | ||
13162 | wval = AdvReadEEPWord(iop_base, eep_addr); | ||
13163 | chksum += wval; /* Checksum is calculated from word values. */ | ||
13164 | if (*charfields++) { | ||
13165 | *wbuf = le16_to_cpu(wval); | ||
13166 | } else { | ||
13167 | *wbuf = wval; | ||
13168 | } | ||
13169 | } | ||
13170 | /* Read checksum word. */ | ||
13171 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13172 | wbuf++; | ||
13173 | charfields++; | ||
13174 | |||
13175 | /* Read rest of EEPROM not covered by the checksum. */ | ||
13176 | for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13177 | eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { | ||
13178 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13179 | if (*charfields++) { | ||
13180 | *wbuf = le16_to_cpu(*wbuf); | ||
13181 | } | ||
13182 | } | ||
13183 | return chksum; | ||
13184 | } | ||
13185 | |||
13186 | /* | ||
12664 | * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and | 13187 | * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and |
12665 | * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while | 13188 | * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while |
12666 | * all of this is done. | 13189 | * all of this is done. |
@@ -13234,834 +13757,124 @@ static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) | |||
13234 | } | 13757 | } |
13235 | 13758 | ||
13236 | /* | 13759 | /* |
13237 | * Read EEPROM configuration into the specified buffer. | 13760 | * Initialize the ADV_DVC_VAR structure. |
13238 | * | ||
13239 | * Return a checksum based on the EEPROM configuration read. | ||
13240 | */ | ||
13241 | static ushort __devinit | ||
13242 | AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) | ||
13243 | { | ||
13244 | ushort wval, chksum; | ||
13245 | ushort *wbuf; | ||
13246 | int eep_addr; | ||
13247 | ushort *charfields; | ||
13248 | |||
13249 | charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; | ||
13250 | wbuf = (ushort *)cfg_buf; | ||
13251 | chksum = 0; | ||
13252 | |||
13253 | for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13254 | eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { | ||
13255 | wval = AdvReadEEPWord(iop_base, eep_addr); | ||
13256 | chksum += wval; /* Checksum is calculated from word values. */ | ||
13257 | if (*charfields++) { | ||
13258 | *wbuf = le16_to_cpu(wval); | ||
13259 | } else { | ||
13260 | *wbuf = wval; | ||
13261 | } | ||
13262 | } | ||
13263 | /* Read checksum word. */ | ||
13264 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13265 | wbuf++; | ||
13266 | charfields++; | ||
13267 | |||
13268 | /* Read rest of EEPROM not covered by the checksum. */ | ||
13269 | for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13270 | eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { | ||
13271 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13272 | if (*charfields++) { | ||
13273 | *wbuf = le16_to_cpu(*wbuf); | ||
13274 | } | ||
13275 | } | ||
13276 | return chksum; | ||
13277 | } | ||
13278 | |||
13279 | /* | ||
13280 | * Read EEPROM configuration into the specified buffer. | ||
13281 | * | 13761 | * |
13282 | * Return a checksum based on the EEPROM configuration read. | 13762 | * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. |
13283 | */ | ||
13284 | static ushort __devinit | ||
13285 | AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) | ||
13286 | { | ||
13287 | ushort wval, chksum; | ||
13288 | ushort *wbuf; | ||
13289 | int eep_addr; | ||
13290 | ushort *charfields; | ||
13291 | |||
13292 | charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; | ||
13293 | wbuf = (ushort *)cfg_buf; | ||
13294 | chksum = 0; | ||
13295 | |||
13296 | for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13297 | eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { | ||
13298 | wval = AdvReadEEPWord(iop_base, eep_addr); | ||
13299 | chksum += wval; /* Checksum is calculated from word values. */ | ||
13300 | if (*charfields++) { | ||
13301 | *wbuf = le16_to_cpu(wval); | ||
13302 | } else { | ||
13303 | *wbuf = wval; | ||
13304 | } | ||
13305 | } | ||
13306 | /* Read checksum word. */ | ||
13307 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13308 | wbuf++; | ||
13309 | charfields++; | ||
13310 | |||
13311 | /* Read rest of EEPROM not covered by the checksum. */ | ||
13312 | for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13313 | eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { | ||
13314 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13315 | if (*charfields++) { | ||
13316 | *wbuf = le16_to_cpu(*wbuf); | ||
13317 | } | ||
13318 | } | ||
13319 | return chksum; | ||
13320 | } | ||
13321 | |||
13322 | /* | ||
13323 | * Read EEPROM configuration into the specified buffer. | ||
13324 | * | 13763 | * |
13325 | * Return a checksum based on the EEPROM configuration read. | 13764 | * For a non-fatal error return a warning code. If there are no warnings |
13326 | */ | 13765 | * then 0 is returned. |
13327 | static ushort __devinit | ||
13328 | AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) | ||
13329 | { | ||
13330 | ushort wval, chksum; | ||
13331 | ushort *wbuf; | ||
13332 | int eep_addr; | ||
13333 | ushort *charfields; | ||
13334 | |||
13335 | charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; | ||
13336 | wbuf = (ushort *)cfg_buf; | ||
13337 | chksum = 0; | ||
13338 | |||
13339 | for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13340 | eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { | ||
13341 | wval = AdvReadEEPWord(iop_base, eep_addr); | ||
13342 | chksum += wval; /* Checksum is calculated from word values. */ | ||
13343 | if (*charfields++) { | ||
13344 | *wbuf = le16_to_cpu(wval); | ||
13345 | } else { | ||
13346 | *wbuf = wval; | ||
13347 | } | ||
13348 | } | ||
13349 | /* Read checksum word. */ | ||
13350 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13351 | wbuf++; | ||
13352 | charfields++; | ||
13353 | |||
13354 | /* Read rest of EEPROM not covered by the checksum. */ | ||
13355 | for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13356 | eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { | ||
13357 | *wbuf = AdvReadEEPWord(iop_base, eep_addr); | ||
13358 | if (*charfields++) { | ||
13359 | *wbuf = le16_to_cpu(*wbuf); | ||
13360 | } | ||
13361 | } | ||
13362 | return chksum; | ||
13363 | } | ||
13364 | |||
13365 | /* | ||
13366 | * Read the EEPROM from specified location | ||
13367 | */ | ||
13368 | static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) | ||
13369 | { | ||
13370 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13371 | ASC_EEP_CMD_READ | eep_word_addr); | ||
13372 | AdvWaitEEPCmd(iop_base); | ||
13373 | return AdvReadWordRegister(iop_base, IOPW_EE_DATA); | ||
13374 | } | ||
13375 | |||
13376 | /* | ||
13377 | * Wait for EEPROM command to complete | ||
13378 | */ | ||
13379 | static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base) | ||
13380 | { | ||
13381 | int eep_delay_ms; | ||
13382 | |||
13383 | for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) { | ||
13384 | if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & | ||
13385 | ASC_EEP_CMD_DONE) { | ||
13386 | break; | ||
13387 | } | ||
13388 | mdelay(1); | ||
13389 | } | ||
13390 | if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == | ||
13391 | 0) | ||
13392 | BUG(); | ||
13393 | return; | ||
13394 | } | ||
13395 | |||
13396 | /* | ||
13397 | * Write the EEPROM from 'cfg_buf'. | ||
13398 | */ | ||
13399 | void __devinit | ||
13400 | AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) | ||
13401 | { | ||
13402 | ushort *wbuf; | ||
13403 | ushort addr, chksum; | ||
13404 | ushort *charfields; | ||
13405 | |||
13406 | wbuf = (ushort *)cfg_buf; | ||
13407 | charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; | ||
13408 | chksum = 0; | ||
13409 | |||
13410 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); | ||
13411 | AdvWaitEEPCmd(iop_base); | ||
13412 | |||
13413 | /* | ||
13414 | * Write EEPROM from word 0 to word 20. | ||
13415 | */ | ||
13416 | for (addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13417 | addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { | ||
13418 | ushort word; | ||
13419 | |||
13420 | if (*charfields++) { | ||
13421 | word = cpu_to_le16(*wbuf); | ||
13422 | } else { | ||
13423 | word = *wbuf; | ||
13424 | } | ||
13425 | chksum += *wbuf; /* Checksum is calculated from word values. */ | ||
13426 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13427 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13428 | ASC_EEP_CMD_WRITE | addr); | ||
13429 | AdvWaitEEPCmd(iop_base); | ||
13430 | mdelay(ADV_EEP_DELAY_MS); | ||
13431 | } | ||
13432 | |||
13433 | /* | ||
13434 | * Write EEPROM checksum at word 21. | ||
13435 | */ | ||
13436 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); | ||
13437 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); | ||
13438 | AdvWaitEEPCmd(iop_base); | ||
13439 | wbuf++; | ||
13440 | charfields++; | ||
13441 | |||
13442 | /* | ||
13443 | * Write EEPROM OEM name at words 22 to 29. | ||
13444 | */ | ||
13445 | for (addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13446 | addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { | ||
13447 | ushort word; | ||
13448 | |||
13449 | if (*charfields++) { | ||
13450 | word = cpu_to_le16(*wbuf); | ||
13451 | } else { | ||
13452 | word = *wbuf; | ||
13453 | } | ||
13454 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13455 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13456 | ASC_EEP_CMD_WRITE | addr); | ||
13457 | AdvWaitEEPCmd(iop_base); | ||
13458 | } | ||
13459 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); | ||
13460 | AdvWaitEEPCmd(iop_base); | ||
13461 | return; | ||
13462 | } | ||
13463 | |||
13464 | /* | ||
13465 | * Write the EEPROM from 'cfg_buf'. | ||
13466 | */ | ||
13467 | void __devinit | ||
13468 | AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) | ||
13469 | { | ||
13470 | ushort *wbuf; | ||
13471 | ushort *charfields; | ||
13472 | ushort addr, chksum; | ||
13473 | |||
13474 | wbuf = (ushort *)cfg_buf; | ||
13475 | charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; | ||
13476 | chksum = 0; | ||
13477 | |||
13478 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); | ||
13479 | AdvWaitEEPCmd(iop_base); | ||
13480 | |||
13481 | /* | ||
13482 | * Write EEPROM from word 0 to word 20. | ||
13483 | */ | ||
13484 | for (addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13485 | addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { | ||
13486 | ushort word; | ||
13487 | |||
13488 | if (*charfields++) { | ||
13489 | word = cpu_to_le16(*wbuf); | ||
13490 | } else { | ||
13491 | word = *wbuf; | ||
13492 | } | ||
13493 | chksum += *wbuf; /* Checksum is calculated from word values. */ | ||
13494 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13495 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13496 | ASC_EEP_CMD_WRITE | addr); | ||
13497 | AdvWaitEEPCmd(iop_base); | ||
13498 | mdelay(ADV_EEP_DELAY_MS); | ||
13499 | } | ||
13500 | |||
13501 | /* | ||
13502 | * Write EEPROM checksum at word 21. | ||
13503 | */ | ||
13504 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); | ||
13505 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); | ||
13506 | AdvWaitEEPCmd(iop_base); | ||
13507 | wbuf++; | ||
13508 | charfields++; | ||
13509 | |||
13510 | /* | ||
13511 | * Write EEPROM OEM name at words 22 to 29. | ||
13512 | */ | ||
13513 | for (addr = ADV_EEP_DVC_CTL_BEGIN; | ||
13514 | addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { | ||
13515 | ushort word; | ||
13516 | |||
13517 | if (*charfields++) { | ||
13518 | word = cpu_to_le16(*wbuf); | ||
13519 | } else { | ||
13520 | word = *wbuf; | ||
13521 | } | ||
13522 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13523 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13524 | ASC_EEP_CMD_WRITE | addr); | ||
13525 | AdvWaitEEPCmd(iop_base); | ||
13526 | } | ||
13527 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); | ||
13528 | AdvWaitEEPCmd(iop_base); | ||
13529 | return; | ||
13530 | } | ||
13531 | |||
13532 | /* | ||
13533 | * Write the EEPROM from 'cfg_buf'. | ||
13534 | */ | 13766 | */ |
13535 | void __devinit | 13767 | static int __devinit |
13536 | AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) | 13768 | AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp) |
13537 | { | 13769 | { |
13538 | ushort *wbuf; | 13770 | ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var; |
13539 | ushort *charfields; | 13771 | unsigned short warn_code = 0; |
13540 | ushort addr, chksum; | 13772 | AdvPortAddr iop_base = asc_dvc->iop_base; |
13541 | 13773 | u16 cmd; | |
13542 | wbuf = (ushort *)cfg_buf; | 13774 | int status; |
13543 | charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; | ||
13544 | chksum = 0; | ||
13545 | |||
13546 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); | ||
13547 | AdvWaitEEPCmd(iop_base); | ||
13548 | |||
13549 | /* | ||
13550 | * Write EEPROM from word 0 to word 20. | ||
13551 | */ | ||
13552 | for (addr = ADV_EEP_DVC_CFG_BEGIN; | ||
13553 | addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { | ||
13554 | ushort word; | ||
13555 | 13775 | ||
13556 | if (*charfields++) { | 13776 | asc_dvc->err_code = 0; |
13557 | word = cpu_to_le16(*wbuf); | ||
13558 | } else { | ||
13559 | word = *wbuf; | ||
13560 | } | ||
13561 | chksum += *wbuf; /* Checksum is calculated from word values. */ | ||
13562 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13563 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13564 | ASC_EEP_CMD_WRITE | addr); | ||
13565 | AdvWaitEEPCmd(iop_base); | ||
13566 | mdelay(ADV_EEP_DELAY_MS); | ||
13567 | } | ||
13568 | 13777 | ||
13569 | /* | 13778 | /* |
13570 | * Write EEPROM checksum at word 21. | 13779 | * Save the state of the PCI Configuration Command Register |
13780 | * "Parity Error Response Control" Bit. If the bit is clear (0), | ||
13781 | * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore | ||
13782 | * DMA parity errors. | ||
13571 | */ | 13783 | */ |
13572 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); | 13784 | asc_dvc->cfg->control_flag = 0; |
13573 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); | 13785 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); |
13574 | AdvWaitEEPCmd(iop_base); | 13786 | if ((cmd & PCI_COMMAND_PARITY) == 0) |
13575 | wbuf++; | 13787 | asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; |
13576 | charfields++; | ||
13577 | 13788 | ||
13578 | /* | 13789 | asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | |
13579 | * Write EEPROM OEM name at words 22 to 29. | 13790 | ADV_LIB_VERSION_MINOR; |
13580 | */ | 13791 | asc_dvc->cfg->chip_version = |
13581 | for (addr = ADV_EEP_DVC_CTL_BEGIN; | 13792 | AdvGetChipVersion(iop_base, asc_dvc->bus_type); |
13582 | addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { | ||
13583 | ushort word; | ||
13584 | 13793 | ||
13585 | if (*charfields++) { | 13794 | ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", |
13586 | word = cpu_to_le16(*wbuf); | 13795 | (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), |
13587 | } else { | 13796 | (ushort)ADV_CHIP_ID_BYTE); |
13588 | word = *wbuf; | ||
13589 | } | ||
13590 | AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); | ||
13591 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, | ||
13592 | ASC_EEP_CMD_WRITE | addr); | ||
13593 | AdvWaitEEPCmd(iop_base); | ||
13594 | } | ||
13595 | AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); | ||
13596 | AdvWaitEEPCmd(iop_base); | ||
13597 | return; | ||
13598 | } | ||
13599 | 13797 | ||
13600 | /* | 13798 | ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", |
13601 | * AdvExeScsiQueue() - Send a request to the RISC microcode program. | 13799 | (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), |
13602 | * | 13800 | (ushort)ADV_CHIP_ID_WORD); |
13603 | * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q, | ||
13604 | * add the carrier to the ICQ (Initiator Command Queue), and tickle the | ||
13605 | * RISC to notify it a new command is ready to be executed. | ||
13606 | * | ||
13607 | * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be | ||
13608 | * set to SCSI_MAX_RETRY. | ||
13609 | * | ||
13610 | * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode | ||
13611 | * for DMA addresses or math operations are byte swapped to little-endian | ||
13612 | * order. | ||
13613 | * | ||
13614 | * Return: | ||
13615 | * ADV_SUCCESS(1) - The request was successfully queued. | ||
13616 | * ADV_BUSY(0) - Resource unavailable; Retry again after pending | ||
13617 | * request completes. | ||
13618 | * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure | ||
13619 | * host IC error. | ||
13620 | */ | ||
13621 | static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) | ||
13622 | { | ||
13623 | AdvPortAddr iop_base; | ||
13624 | ADV_DCNT req_size; | ||
13625 | ADV_PADDR req_paddr; | ||
13626 | ADV_CARR_T *new_carrp; | ||
13627 | 13801 | ||
13628 | /* | 13802 | /* |
13629 | * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. | 13803 | * Reset the chip to start and allow register writes. |
13630 | */ | 13804 | */ |
13631 | if (scsiq->target_id > ADV_MAX_TID) { | 13805 | if (AdvFindSignature(iop_base) == 0) { |
13632 | scsiq->host_status = QHSTA_M_INVALID_DEVICE; | 13806 | asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; |
13633 | scsiq->done_status = QD_WITH_ERROR; | ||
13634 | return ADV_ERROR; | 13807 | return ADV_ERROR; |
13635 | } | 13808 | } else { |
13636 | |||
13637 | iop_base = asc_dvc->iop_base; | ||
13638 | |||
13639 | /* | ||
13640 | * Allocate a carrier ensuring at least one carrier always | ||
13641 | * remains on the freelist and initialize fields. | ||
13642 | */ | ||
13643 | if ((new_carrp = asc_dvc->carr_freelist) == NULL) { | ||
13644 | return ADV_BUSY; | ||
13645 | } | ||
13646 | asc_dvc->carr_freelist = (ADV_CARR_T *) | ||
13647 | ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); | ||
13648 | asc_dvc->carr_pending_cnt++; | ||
13649 | |||
13650 | /* | ||
13651 | * Set the carrier to be a stopper by setting 'next_vpa' | ||
13652 | * to the stopper value. The current stopper will be changed | ||
13653 | * below to point to the new stopper. | ||
13654 | */ | ||
13655 | new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); | ||
13656 | |||
13657 | /* | ||
13658 | * Clear the ADV_SCSI_REQ_Q done flag. | ||
13659 | */ | ||
13660 | scsiq->a_flag &= ~ADV_SCSIQ_DONE; | ||
13661 | |||
13662 | req_size = sizeof(ADV_SCSI_REQ_Q); | ||
13663 | req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq, | ||
13664 | (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG); | ||
13665 | |||
13666 | BUG_ON(req_paddr & 31); | ||
13667 | BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q)); | ||
13668 | |||
13669 | /* Wait for assertion before making little-endian */ | ||
13670 | req_paddr = cpu_to_le32(req_paddr); | ||
13671 | |||
13672 | /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ | ||
13673 | scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); | ||
13674 | scsiq->scsiq_rptr = req_paddr; | ||
13675 | |||
13676 | scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); | ||
13677 | /* | ||
13678 | * Every ADV_CARR_T.carr_pa is byte swapped to little-endian | ||
13679 | * order during initialization. | ||
13680 | */ | ||
13681 | scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; | ||
13682 | |||
13683 | /* | ||
13684 | * Use the current stopper to send the ADV_SCSI_REQ_Q command to | ||
13685 | * the microcode. The newly allocated stopper will become the new | ||
13686 | * stopper. | ||
13687 | */ | ||
13688 | asc_dvc->icq_sp->areq_vpa = req_paddr; | ||
13689 | |||
13690 | /* | ||
13691 | * Set the 'next_vpa' pointer for the old stopper to be the | ||
13692 | * physical address of the new stopper. The RISC can only | ||
13693 | * follow physical addresses. | ||
13694 | */ | ||
13695 | asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; | ||
13696 | |||
13697 | /* | ||
13698 | * Set the host adapter stopper pointer to point to the new carrier. | ||
13699 | */ | ||
13700 | asc_dvc->icq_sp = new_carrp; | ||
13701 | |||
13702 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || | ||
13703 | asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
13704 | /* | 13809 | /* |
13705 | * Tickle the RISC to tell it to read its Command Queue Head pointer. | 13810 | * The caller must set 'chip_type' to a valid setting. |
13706 | */ | 13811 | */ |
13707 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); | 13812 | if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && |
13708 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { | 13813 | asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && |
13709 | /* | 13814 | asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { |
13710 | * Clear the tickle value. In the ASC-3550 the RISC flag | 13815 | asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; |
13711 | * command 'clr_tickle_a' does not work unless the host | 13816 | return ADV_ERROR; |
13712 | * value is cleared. | ||
13713 | */ | ||
13714 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, | ||
13715 | ADV_TICKLE_NOP); | ||
13716 | } | 13817 | } |
13717 | } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | 13818 | |
13718 | /* | 13819 | /* |
13719 | * Notify the RISC a carrier is ready by writing the physical | 13820 | * Reset Chip. |
13720 | * address of the new carrier stopper to the COMMA register. | ||
13721 | */ | 13821 | */ |
13722 | AdvWriteDWordRegister(iop_base, IOPDW_COMMA, | 13822 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, |
13723 | le32_to_cpu(new_carrp->carr_pa)); | 13823 | ADV_CTRL_REG_CMD_RESET); |
13724 | } | 13824 | mdelay(100); |
13725 | 13825 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, | |
13726 | return ADV_SUCCESS; | 13826 | ADV_CTRL_REG_CMD_WR_IO_REG); |
13727 | } | ||
13728 | |||
13729 | /* | ||
13730 | * Reset SCSI Bus and purge all outstanding requests. | ||
13731 | * | ||
13732 | * Return Value: | ||
13733 | * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset. | ||
13734 | * ADV_FALSE(0) - Microcode command failed. | ||
13735 | * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC | ||
13736 | * may be hung which requires driver recovery. | ||
13737 | */ | ||
13738 | static int AdvResetSB(ADV_DVC_VAR *asc_dvc) | ||
13739 | { | ||
13740 | int status; | ||
13741 | |||
13742 | /* | ||
13743 | * Send the SCSI Bus Reset idle start idle command which asserts | ||
13744 | * the SCSI Bus Reset signal. | ||
13745 | */ | ||
13746 | status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L); | ||
13747 | if (status != ADV_TRUE) { | ||
13748 | return status; | ||
13749 | } | ||
13750 | |||
13751 | /* | ||
13752 | * Delay for the specified SCSI Bus Reset hold time. | ||
13753 | * | ||
13754 | * The hold time delay is done on the host because the RISC has no | ||
13755 | * microsecond accurate timer. | ||
13756 | */ | ||
13757 | udelay(ASC_SCSI_RESET_HOLD_TIME_US); | ||
13758 | |||
13759 | /* | ||
13760 | * Send the SCSI Bus Reset end idle command which de-asserts | ||
13761 | * the SCSI Bus Reset signal and purges any pending requests. | ||
13762 | */ | ||
13763 | status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L); | ||
13764 | if (status != ADV_TRUE) { | ||
13765 | return status; | ||
13766 | } | ||
13767 | |||
13768 | mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ | ||
13769 | |||
13770 | return status; | ||
13771 | } | ||
13772 | |||
13773 | /* | ||
13774 | * Reset chip and SCSI Bus. | ||
13775 | * | ||
13776 | * Return Value: | ||
13777 | * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. | ||
13778 | * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. | ||
13779 | */ | ||
13780 | static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) | ||
13781 | { | ||
13782 | int status; | ||
13783 | ushort wdtr_able, sdtr_able, tagqng_able; | ||
13784 | ushort ppr_able = 0; | ||
13785 | uchar tid, max_cmd[ADV_MAX_TID + 1]; | ||
13786 | AdvPortAddr iop_base; | ||
13787 | ushort bios_sig; | ||
13788 | |||
13789 | iop_base = asc_dvc->iop_base; | ||
13790 | |||
13791 | /* | ||
13792 | * Save current per TID negotiated values. | ||
13793 | */ | ||
13794 | AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); | ||
13795 | AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); | ||
13796 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | ||
13797 | AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); | ||
13798 | } | ||
13799 | AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); | ||
13800 | for (tid = 0; tid <= ADV_MAX_TID; tid++) { | ||
13801 | AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, | ||
13802 | max_cmd[tid]); | ||
13803 | } | ||
13804 | |||
13805 | /* | ||
13806 | * Force the AdvInitAsc3550/38C0800Driver() function to | ||
13807 | * perform a SCSI Bus Reset by clearing the BIOS signature word. | ||
13808 | * The initialization functions assumes a SCSI Bus Reset is not | ||
13809 | * needed if the BIOS signature word is present. | ||
13810 | */ | ||
13811 | AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); | ||
13812 | AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); | ||
13813 | |||
13814 | /* | ||
13815 | * Stop chip and reset it. | ||
13816 | */ | ||
13817 | AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); | ||
13818 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); | ||
13819 | mdelay(100); | ||
13820 | AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, | ||
13821 | ADV_CTRL_REG_CMD_WR_IO_REG); | ||
13822 | |||
13823 | /* | ||
13824 | * Reset Adv Library error code, if any, and try | ||
13825 | * re-initializing the chip. | ||
13826 | */ | ||
13827 | asc_dvc->err_code = 0; | ||
13828 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | ||
13829 | status = AdvInitAsc38C1600Driver(asc_dvc); | ||
13830 | } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
13831 | status = AdvInitAsc38C0800Driver(asc_dvc); | ||
13832 | } else { | ||
13833 | status = AdvInitAsc3550Driver(asc_dvc); | ||
13834 | } | ||
13835 | |||
13836 | /* Translate initialization return value to status value. */ | ||
13837 | if (status == 0) { | ||
13838 | status = ADV_TRUE; | ||
13839 | } else { | ||
13840 | status = ADV_FALSE; | ||
13841 | } | ||
13842 | |||
13843 | /* | ||
13844 | * Restore the BIOS signature word. | ||
13845 | */ | ||
13846 | AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); | ||
13847 | 13827 | ||
13848 | /* | 13828 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { |
13849 | * Restore per TID negotiated values. | 13829 | status = AdvInitFrom38C1600EEP(asc_dvc); |
13850 | */ | 13830 | } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { |
13851 | AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); | 13831 | status = AdvInitFrom38C0800EEP(asc_dvc); |
13852 | AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); | 13832 | } else { |
13853 | if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { | 13833 | status = AdvInitFrom3550EEP(asc_dvc); |
13854 | AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); | 13834 | } |
13855 | } | 13835 | warn_code |= status; |
13856 | AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); | ||
13857 | for (tid = 0; tid <= ADV_MAX_TID; tid++) { | ||
13858 | AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, | ||
13859 | max_cmd[tid]); | ||
13860 | } | 13836 | } |
13861 | 13837 | ||
13862 | return status; | 13838 | if (warn_code != 0) { |
13863 | } | 13839 | ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n", |
13864 | 13840 | boardp->id, warn_code); | |
13865 | /* | ||
13866 | * Adv Library Interrupt Service Routine | ||
13867 | * | ||
13868 | * This function is called by a driver's interrupt service routine. | ||
13869 | * The function disables and re-enables interrupts. | ||
13870 | * | ||
13871 | * When a microcode idle command is completed, the ADV_DVC_VAR | ||
13872 | * 'idle_cmd_done' field is set to ADV_TRUE. | ||
13873 | * | ||
13874 | * Note: AdvISR() can be called when interrupts are disabled or even | ||
13875 | * when there is no hardware interrupt condition present. It will | ||
13876 | * always check for completed idle commands and microcode requests. | ||
13877 | * This is an important feature that shouldn't be changed because it | ||
13878 | * allows commands to be completed from polling mode loops. | ||
13879 | * | ||
13880 | * Return: | ||
13881 | * ADV_TRUE(1) - interrupt was pending | ||
13882 | * ADV_FALSE(0) - no interrupt was pending | ||
13883 | */ | ||
13884 | static int AdvISR(ADV_DVC_VAR *asc_dvc) | ||
13885 | { | ||
13886 | AdvPortAddr iop_base; | ||
13887 | uchar int_stat; | ||
13888 | ushort target_bit; | ||
13889 | ADV_CARR_T *free_carrp; | ||
13890 | ADV_VADDR irq_next_vpa; | ||
13891 | ADV_SCSI_REQ_Q *scsiq; | ||
13892 | |||
13893 | iop_base = asc_dvc->iop_base; | ||
13894 | |||
13895 | /* Reading the register clears the interrupt. */ | ||
13896 | int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); | ||
13897 | |||
13898 | if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | | ||
13899 | ADV_INTR_STATUS_INTRC)) == 0) { | ||
13900 | return ADV_FALSE; | ||
13901 | } | 13841 | } |
13902 | 13842 | ||
13903 | /* | 13843 | if (asc_dvc->err_code) { |
13904 | * Notify the driver of an asynchronous microcode condition by | 13844 | ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n", |
13905 | * calling the adv_async_callback function. The function | 13845 | boardp->id, asc_dvc->err_code); |
13906 | * is passed the microcode ASC_MC_INTRB_CODE byte value. | ||
13907 | */ | ||
13908 | if (int_stat & ADV_INTR_STATUS_INTRB) { | ||
13909 | uchar intrb_code; | ||
13910 | |||
13911 | AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); | ||
13912 | |||
13913 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || | ||
13914 | asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { | ||
13915 | if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && | ||
13916 | asc_dvc->carr_pending_cnt != 0) { | ||
13917 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, | ||
13918 | ADV_TICKLE_A); | ||
13919 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { | ||
13920 | AdvWriteByteRegister(iop_base, | ||
13921 | IOPB_TICKLE, | ||
13922 | ADV_TICKLE_NOP); | ||
13923 | } | ||
13924 | } | ||
13925 | } | ||
13926 | |||
13927 | adv_async_callback(asc_dvc, intrb_code); | ||
13928 | } | 13846 | } |
13929 | 13847 | ||
13930 | /* | 13848 | return asc_dvc->err_code; |
13931 | * Check if the IRQ stopper carrier contains a completed request. | ||
13932 | */ | ||
13933 | while (((irq_next_vpa = | ||
13934 | le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) { | ||
13935 | /* | ||
13936 | * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. | ||
13937 | * The RISC will have set 'areq_vpa' to a virtual address. | ||
13938 | * | ||
13939 | * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr | ||
13940 | * field to the carrier ADV_CARR_T.areq_vpa field. The conversion | ||
13941 | * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' | ||
13942 | * in AdvExeScsiQueue(). | ||
13943 | */ | ||
13944 | scsiq = (ADV_SCSI_REQ_Q *) | ||
13945 | ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); | ||
13946 | |||
13947 | /* | ||
13948 | * Request finished with good status and the queue was not | ||
13949 | * DMAed to host memory by the firmware. Set all status fields | ||
13950 | * to indicate good status. | ||
13951 | */ | ||
13952 | if ((irq_next_vpa & ASC_RQ_GOOD) != 0) { | ||
13953 | scsiq->done_status = QD_NO_ERROR; | ||
13954 | scsiq->host_status = scsiq->scsi_status = 0; | ||
13955 | scsiq->data_cnt = 0L; | ||
13956 | } | ||
13957 | |||
13958 | /* | ||
13959 | * Advance the stopper pointer to the next carrier | ||
13960 | * ignoring the lower four bits. Free the previous | ||
13961 | * stopper carrier. | ||
13962 | */ | ||
13963 | free_carrp = asc_dvc->irq_sp; | ||
13964 | asc_dvc->irq_sp = (ADV_CARR_T *) | ||
13965 | ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); | ||
13966 | |||
13967 | free_carrp->next_vpa = | ||
13968 | cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); | ||
13969 | asc_dvc->carr_freelist = free_carrp; | ||
13970 | asc_dvc->carr_pending_cnt--; | ||
13971 | |||
13972 | target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); | ||
13973 | |||
13974 | /* | ||
13975 | * Clear request microcode control flag. | ||
13976 | */ | ||
13977 | scsiq->cntl = 0; | ||
13978 | |||
13979 | /* | ||
13980 | * Notify the driver of the completed request by passing | ||
13981 | * the ADV_SCSI_REQ_Q pointer to its callback function. | ||
13982 | */ | ||
13983 | scsiq->a_flag |= ADV_SCSIQ_DONE; | ||
13984 | adv_isr_callback(asc_dvc, scsiq); | ||
13985 | /* | ||
13986 | * Note: After the driver callback function is called, 'scsiq' | ||
13987 | * can no longer be referenced. | ||
13988 | * | ||
13989 | * Fall through and continue processing other completed | ||
13990 | * requests... | ||
13991 | */ | ||
13992 | } | ||
13993 | return ADV_TRUE; | ||
13994 | } | 13849 | } |
13850 | #endif | ||
13995 | 13851 | ||
13996 | /* | 13852 | static struct scsi_host_template advansys_template = { |
13997 | * Send an idle command to the chip and wait for completion. | 13853 | .proc_name = DRV_NAME, |
13998 | * | 13854 | #ifdef CONFIG_PROC_FS |
13999 | * Command completion is polled for once per microsecond. | 13855 | .proc_info = advansys_proc_info, |
14000 | * | 13856 | #endif |
14001 | * The function can be called from anywhere including an interrupt handler. | 13857 | .name = DRV_NAME, |
14002 | * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical() | 13858 | .info = advansys_info, |
14003 | * functions to prevent reentrancy. | 13859 | .queuecommand = advansys_queuecommand, |
14004 | * | 13860 | .eh_bus_reset_handler = advansys_reset, |
14005 | * Return Values: | 13861 | .bios_param = advansys_biosparam, |
14006 | * ADV_TRUE - command completed successfully | 13862 | .slave_configure = advansys_slave_configure, |
14007 | * ADV_FALSE - command failed | ||
14008 | * ADV_ERROR - command timed out | ||
14009 | */ | ||
14010 | static int | ||
14011 | AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, | ||
14012 | ushort idle_cmd, ADV_DCNT idle_cmd_parameter) | ||
14013 | { | ||
14014 | int result; | ||
14015 | ADV_DCNT i, j; | ||
14016 | AdvPortAddr iop_base; | ||
14017 | |||
14018 | iop_base = asc_dvc->iop_base; | ||
14019 | |||
14020 | /* | ||
14021 | * Clear the idle command status which is set by the microcode | ||
14022 | * to a non-zero value to indicate when the command is completed. | ||
14023 | * The non-zero result is one of the IDLE_CMD_STATUS_* values | ||
14024 | */ | ||
14025 | AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); | ||
14026 | |||
14027 | /* | 13863 | /* |
14028 | * Write the idle command value after the idle command parameter | 13864 | * Because the driver may control an ISA adapter 'unchecked_isa_dma' |
14029 | * has been written to avoid a race condition. If the order is not | 13865 | * must be set. The flag will be cleared in advansys_board_found |
14030 | * followed, the microcode may process the idle command before the | 13866 | * for non-ISA adapters. |
14031 | * parameters have been written to LRAM. | ||
14032 | */ | 13867 | */ |
14033 | AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, | 13868 | .unchecked_isa_dma = 1, |
14034 | cpu_to_le32(idle_cmd_parameter)); | ||
14035 | AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); | ||
14036 | |||
14037 | /* | 13869 | /* |
14038 | * Tickle the RISC to tell it to process the idle command. | 13870 | * All adapters controlled by this driver are capable of large |
13871 | * scatter-gather lists. According to the mid-level SCSI documentation | ||
13872 | * this obviates any performance gain provided by setting | ||
13873 | * 'use_clustering'. But empirically while CPU utilization is increased | ||
13874 | * by enabling clustering, I/O throughput increases as well. | ||
14039 | */ | 13875 | */ |
14040 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); | 13876 | .use_clustering = ENABLE_CLUSTERING, |
14041 | if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { | 13877 | }; |
14042 | /* | ||
14043 | * Clear the tickle value. In the ASC-3550 the RISC flag | ||
14044 | * command 'clr_tickle_b' does not work unless the host | ||
14045 | * value is cleared. | ||
14046 | */ | ||
14047 | AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); | ||
14048 | } | ||
14049 | |||
14050 | /* Wait for up to 100 millisecond for the idle command to timeout. */ | ||
14051 | for (i = 0; i < SCSI_WAIT_100_MSEC; i++) { | ||
14052 | /* Poll once each microsecond for command completion. */ | ||
14053 | for (j = 0; j < SCSI_US_PER_MSEC; j++) { | ||
14054 | AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, | ||
14055 | result); | ||
14056 | if (result != 0) | ||
14057 | return result; | ||
14058 | udelay(1); | ||
14059 | } | ||
14060 | } | ||
14061 | |||
14062 | BUG(); /* The idle command should never timeout. */ | ||
14063 | return ADV_ERROR; | ||
14064 | } | ||
14065 | 13878 | ||
14066 | static int __devinit | 13879 | static int __devinit |
14067 | advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp) | 13880 | advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp) |