| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Andrew Vasquez | fa90c54 | 2005-10-27 11:10:08 -0700 | [diff] [blame] | 2 | * QLogic Fibre Channel HBA Driver | 
|  | 3 | * Copyright (c)  2003-2005 QLogic Corporation | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4 | * | 
| Andrew Vasquez | fa90c54 | 2005-10-27 11:10:08 -0700 | [diff] [blame] | 5 | * See LICENSE.qla2xxx for copyright and licensing details. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6 | */ | 
|  | 7 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8 | static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *); | 
|  | 9 | /* | 
|  | 10 | * qla2x00_debounce_register | 
|  | 11 | *      Debounce register. | 
|  | 12 | * | 
|  | 13 | * Input: | 
|  | 14 | *      port = register address. | 
|  | 15 | * | 
|  | 16 | * Returns: | 
|  | 17 | *      register value. | 
|  | 18 | */ | 
|  | 19 | static __inline__ uint16_t | 
| Andrew Vasquez | fa2a1ce | 2005-07-06 10:32:07 -0700 | [diff] [blame] | 20 | qla2x00_debounce_register(volatile uint16_t __iomem *addr) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 | { | 
|  | 22 | volatile uint16_t first; | 
|  | 23 | volatile uint16_t second; | 
|  | 24 |  | 
|  | 25 | do { | 
|  | 26 | first = RD_REG_WORD(addr); | 
|  | 27 | barrier(); | 
|  | 28 | cpu_relax(); | 
|  | 29 | second = RD_REG_WORD(addr); | 
|  | 30 | } while (first != second); | 
|  | 31 |  | 
|  | 32 | return (first); | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | static __inline__ int qla2x00_normalize_dma_addr( | 
|  | 36 | dma_addr_t *e_addr,  uint32_t *e_len, | 
|  | 37 | dma_addr_t *ne_addr, uint32_t *ne_len); | 
|  | 38 |  | 
|  | 39 | /** | 
|  | 40 | * qla2x00_normalize_dma_addr() - Normalize an DMA address. | 
|  | 41 | * @e_addr: Raw DMA address | 
|  | 42 | * @e_len: Raw DMA length | 
|  | 43 | * @ne_addr: Normalized second DMA address | 
|  | 44 | * @ne_len: Normalized second DMA length | 
|  | 45 | * | 
|  | 46 | * If the address does not span a 4GB page boundary, the contents of @ne_addr | 
|  | 47 | * and @ne_len are undefined.  @e_len is updated to reflect a normalization. | 
|  | 48 | * | 
|  | 49 | * Example: | 
|  | 50 | * | 
|  | 51 | * 	ffffabc0ffffeeee	(e_addr) start of DMA address | 
|  | 52 | * 	0000000020000000	(e_len)  length of DMA transfer | 
|  | 53 | *	ffffabc11fffeeed	end of DMA transfer | 
|  | 54 | * | 
|  | 55 | * Is the 4GB boundary crossed? | 
|  | 56 | * | 
|  | 57 | * 	ffffabc0ffffeeee	(e_addr) | 
|  | 58 | *	ffffabc11fffeeed	(e_addr + e_len - 1) | 
|  | 59 | *	00000001e0000003	((e_addr ^ (e_addr + e_len - 1)) | 
|  | 60 | *	0000000100000000	((e_addr ^ (e_addr + e_len - 1)) & ~(0xffffffff) | 
|  | 61 | * | 
|  | 62 | * Compute start of second DMA segment: | 
|  | 63 | * | 
|  | 64 | * 	ffffabc0ffffeeee	(e_addr) | 
|  | 65 | *	ffffabc1ffffeeee	(0x100000000 + e_addr) | 
|  | 66 | *	ffffabc100000000	(0x100000000 + e_addr) & ~(0xffffffff) | 
|  | 67 | *	ffffabc100000000	(ne_addr) | 
| Andrew Vasquez | fa2a1ce | 2005-07-06 10:32:07 -0700 | [diff] [blame] | 68 | * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 | * Compute length of second DMA segment: | 
|  | 70 | * | 
|  | 71 | *	00000000ffffeeee	(e_addr & 0xffffffff) | 
|  | 72 | *	0000000000001112	(0x100000000 - (e_addr & 0xffffffff)) | 
|  | 73 | *	000000001fffeeee	(e_len - (0x100000000 - (e_addr & 0xffffffff)) | 
|  | 74 | *	000000001fffeeee	(ne_len) | 
|  | 75 | * | 
|  | 76 | * Adjust length of first DMA segment | 
|  | 77 | * | 
|  | 78 | * 	0000000020000000	(e_len) | 
|  | 79 | *	0000000000001112	(e_len - ne_len) | 
|  | 80 | *	0000000000001112	(e_len) | 
|  | 81 | * | 
|  | 82 | * Returns non-zero if the specified address was normalized, else zero. | 
|  | 83 | */ | 
|  | 84 | static __inline__ int | 
|  | 85 | qla2x00_normalize_dma_addr( | 
|  | 86 | dma_addr_t *e_addr,  uint32_t *e_len, | 
|  | 87 | dma_addr_t *ne_addr, uint32_t *ne_len) | 
|  | 88 | { | 
|  | 89 | int normalized; | 
|  | 90 |  | 
|  | 91 | normalized = 0; | 
|  | 92 | if ((*e_addr ^ (*e_addr + *e_len - 1)) & ~(0xFFFFFFFFULL)) { | 
|  | 93 | /* Compute normalized crossed address and len */ | 
|  | 94 | *ne_addr = (0x100000000ULL + *e_addr) & ~(0xFFFFFFFFULL); | 
|  | 95 | *ne_len = *e_len - (0x100000000ULL - (*e_addr & 0xFFFFFFFFULL)); | 
|  | 96 | *e_len -= *ne_len; | 
|  | 97 |  | 
|  | 98 | normalized++; | 
|  | 99 | } | 
|  | 100 | return (normalized); | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | static __inline__ void qla2x00_poll(scsi_qla_host_t *); | 
| Andrew Vasquez | fa2a1ce | 2005-07-06 10:32:07 -0700 | [diff] [blame] | 104 | static inline void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 | qla2x00_poll(scsi_qla_host_t *ha) | 
|  | 106 | { | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 107 | ha->isp_ops.intr_handler(0, ha); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 108 | } | 
|  | 109 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 110 | static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *); | 
|  | 111 | /* | 
|  | 112 | * This routine will wait for fabric devices for | 
|  | 113 | * the reset delay. | 
|  | 114 | */ | 
| Andrew Vasquez | fa2a1ce | 2005-07-06 10:32:07 -0700 | [diff] [blame] | 115 | static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *ha) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 116 | { | 
|  | 117 | uint16_t	fw_state; | 
|  | 118 |  | 
|  | 119 | qla2x00_get_firmware_state(ha, &fw_state); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | /** | 
|  | 123 | * qla2x00_issue_marker() - Issue a Marker IOCB if necessary. | 
|  | 124 | * @ha: HA context | 
|  | 125 | * @ha_locked: is function called with the hardware lock | 
|  | 126 | * | 
|  | 127 | * Returns non-zero if a failure occured, else zero. | 
|  | 128 | */ | 
|  | 129 | static inline int | 
|  | 130 | qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked) | 
|  | 131 | { | 
|  | 132 | /* Send marker if required */ | 
|  | 133 | if (ha->marker_needed != 0) { | 
|  | 134 | if (ha_locked) { | 
|  | 135 | if (__qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != | 
|  | 136 | QLA_SUCCESS) | 
|  | 137 | return (QLA_FUNCTION_FAILED); | 
|  | 138 | } else { | 
|  | 139 | if (qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != | 
|  | 140 | QLA_SUCCESS) | 
|  | 141 | return (QLA_FUNCTION_FAILED); | 
|  | 142 | } | 
|  | 143 | ha->marker_needed = 0; | 
|  | 144 | } | 
|  | 145 | return (QLA_SUCCESS); | 
|  | 146 | } | 
|  | 147 |  | 
| Andrew Vasquez | 2b6c0ce | 2005-07-06 10:31:17 -0700 | [diff] [blame] | 148 | static inline uint8_t *host_to_fcp_swap(uint8_t *, uint32_t); | 
|  | 149 | static inline uint8_t * | 
|  | 150 | host_to_fcp_swap(uint8_t *fcp, uint32_t bsize) | 
|  | 151 | { | 
|  | 152 | uint32_t *ifcp = (uint32_t *) fcp; | 
|  | 153 | uint32_t *ofcp = (uint32_t *) fcp; | 
|  | 154 | uint32_t iter = bsize >> 2; | 
|  | 155 |  | 
|  | 156 | for (; iter ; iter--) | 
|  | 157 | *ofcp++ = swab32(*ifcp++); | 
|  | 158 |  | 
|  | 159 | return fcp; | 
|  | 160 | } | 
| Andrew Vasquez | 3d71644 | 2005-07-06 10:30:26 -0700 | [diff] [blame] | 161 |  | 
|  | 162 | static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t); | 
|  | 163 | static inline int | 
|  | 164 | qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) | 
|  | 165 | { | 
| andrew.vasquez@qlogic.com | 044cc6c | 2006-03-09 14:27:13 -0800 | [diff] [blame] | 166 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 
| Andrew Vasquez | 3d71644 | 2005-07-06 10:30:26 -0700 | [diff] [blame] | 167 | return (loop_id > NPH_LAST_HANDLE); | 
|  | 168 |  | 
|  | 169 | return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || | 
|  | 170 | loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST); | 
|  | 171 | }; |