Changeset 6e5369b in mainline
- Timestamp:
- 2012-04-08T05:17:27Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5b7ba8d
- Parents:
- 6c76e75
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/res.c
r6c76e75 r6e5369b 46 46 47 47 #include "res.h" 48 49 #define PAGE_SIZE_MASK 0xfffff00050 48 51 49 #define HCC_PARAMS_OFFSET 0x8 … … 130 128 } 131 129 /*----------------------------------------------------------------------------*/ 132 /** Implements BIOS handoff routine as decribed in EHCI spec 133 * 134 * @param[in] device Device asking for interrupts 130 /** Implements BIOS hands-off routine as described in EHCI spec 131 * 132 * @param device EHCI device 133 * @param eecp Value of EHCI Extended Capabilities pointer. 135 134 * @return Error code. 136 135 */ 137 int disable_legacy(const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)136 static int disable_extended_caps(const ddf_dev_t *device, unsigned eecp) 138 137 { 139 assert(device); 138 /* nothing to do */ 139 if (eecp == 0) 140 return EOK; 141 140 142 async_sess_t *parent_sess = devman_parent_device_connect( 141 143 EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING); … … 143 145 return ENOMEM; 144 146 145 #define CHECK_RET_ RETURN(ret, message...) \147 #define CHECK_RET_HANGUP_RETURN(ret, message...) \ 146 148 if (ret != EOK) { \ 147 149 usb_log_error(message); \ … … 150 152 } else (void)0 151 153 154 /* Read the first EEC. i.e. Legacy Support register */ 155 uint32_t usblegsup; 156 int ret = pci_config_space_read_32(parent_sess, 157 eecp + USBLEGSUP_OFFSET, &usblegsup); 158 CHECK_RET_HANGUP_RETURN(ret, 159 "Failed to read USBLEGSUP: %s.\n", str_error(ret)); 160 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 161 162 /* Request control from firmware/BIOS by writing 1 to highest 163 * byte. (OS Control semaphore)*/ 164 usb_log_debug("Requesting OS control.\n"); 165 ret = pci_config_space_write_8(parent_sess, 166 eecp + USBLEGSUP_OFFSET + 3, 1); 167 CHECK_RET_HANGUP_RETURN(ret, "Failed to request OS EHCI control: %s.\n", 168 str_error(ret)); 169 170 size_t wait = 0; 171 /* Wait for BIOS to release control. */ 172 ret = pci_config_space_read_32( 173 parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup); 174 while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 175 async_usleep(WAIT_STEP); 176 ret = pci_config_space_read_32(parent_sess, 177 eecp + USBLEGSUP_OFFSET, &usblegsup); 178 wait += WAIT_STEP; 179 } 180 181 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) { 182 usb_log_info("BIOS released control after %zu usec.\n", wait); 183 async_hangup(parent_sess); 184 return EOK; 185 } 186 187 /* BIOS failed to hand over control, this should not happen. */ 188 usb_log_warning( "BIOS failed to release control after " 189 "%zu usecs, force it.\n", wait); 190 ret = pci_config_space_write_32(parent_sess, 191 eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL); 192 CHECK_RET_HANGUP_RETURN(ret, "Failed to force OS control: " 193 "%s.\n", str_error(ret)); 194 /* 195 * Check capability type here, value of 01h identifies the capability 196 * as Legacy Support. This extended capability requires one additional 197 * 32-bit register for control/status information and this register is 198 * located at offset EECP+04h 199 */ 200 if ((usblegsup & 0xff) == 1) { 201 /* Read the second EEC Legacy Support and Control register */ 202 uint32_t usblegctlsts; 203 ret = pci_config_space_read_32(parent_sess, 204 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 205 CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS: %s.\n", 206 str_error(ret)); 207 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts); 208 /* 209 * Zero SMI enables in legacy control register. 210 * It should prevent pre-OS code from 211 * interfering. NOTE: Three upper bits are WC 212 */ 213 ret = pci_config_space_write_32(parent_sess, 214 eecp + USBLEGCTLSTS_OFFSET, 0xe0000000); 215 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret); 216 udelay(10); 217 ret = pci_config_space_read_32(parent_sess, 218 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 219 CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS 2: %s.\n", 220 str_error(ret)); 221 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n", 222 usblegctlsts); 223 } 224 225 /* Read again Legacy Support register */ 226 ret = pci_config_space_read_32(parent_sess, 227 eecp + USBLEGSUP_OFFSET, &usblegsup); 228 CHECK_RET_HANGUP_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", 229 str_error(ret)); 230 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 231 async_hangup(parent_sess); 232 return EOK; 233 #undef CHECK_RET_HANGUP_RETURN 234 } 235 236 int disable_legacy(const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size) 237 { 238 assert(device); 239 240 #define CHECK_RET_RETURN(ret, message...) \ 241 if (ret != EOK) { \ 242 usb_log_error(message); \ 243 return ret; \ 244 } else (void)0 245 152 246 /* Map EHCI registers */ 153 247 void *regs = NULL; … … 166 260 usb_log_debug("Value of EECP: %x.\n", eecp); 167 261 168 /* Read the first EEC. i.e. Legacy Support register */ 169 uint32_t usblegsup; 170 ret = pci_config_space_read_32(parent_sess, 171 eecp + USBLEGSUP_OFFSET, &usblegsup); 172 CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret)); 173 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 174 175 /* Request control from firmware/BIOS, by writing 1 to highest byte. 176 * (OS Control semaphore)*/ 177 usb_log_debug("Requesting OS control.\n"); 178 ret = pci_config_space_write_8(parent_sess, 179 eecp + USBLEGSUP_OFFSET + 3, 1); 180 CHECK_RET_RETURN(ret, "Failed to request OS EHCI control: %s.\n", 262 ret = disable_extended_caps(device, eecp); 263 CHECK_RET_RETURN(ret, "Failed to disable extended capabilities: %s.\n", 181 264 str_error(ret)); 182 265 183 size_t wait = 0;184 /* Wait for BIOS to release control. */185 ret = pci_config_space_read_32(parent_sess,186 eecp + USBLEGSUP_OFFSET, &usblegsup);187 while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {188 async_usleep(WAIT_STEP);189 ret = pci_config_space_read_32(parent_sess,190 eecp + USBLEGSUP_OFFSET, &usblegsup);191 wait += WAIT_STEP;192 }193 194 195 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {196 usb_log_info("BIOS released control after %zu usec.\n", wait);197 } else {198 /* BIOS failed to hand over control, this should not happen. */199 usb_log_warning( "BIOS failed to release control after "200 "%zu usecs, force it.\n", wait);201 ret = pci_config_space_write_32(parent_sess,202 eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);203 CHECK_RET_RETURN(ret, "Failed to force OS control: %s.\n",204 str_error(ret));205 /* Check capability type here, A value of 01h206 * identifies the capability as Legacy Support.207 * This extended capability requires one208 * additional 32-bit register for control/status information,209 * and this register is located at offset EECP+04h210 * */211 if ((usblegsup & 0xff) == 1) {212 /* Read the second EEC213 * Legacy Support and Control register */214 uint32_t usblegctlsts;215 ret = pci_config_space_read_32(parent_sess,216 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);217 CHECK_RET_RETURN(ret,218 "Failed to get USBLEGCTLSTS: %s.\n", str_error(ret));219 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n",220 usblegctlsts);221 /* Zero SMI enables in legacy control register.222 * It should prevent pre-OS code from interfering.223 * Three upper bits are WC */224 ret = pci_config_space_write_32(parent_sess,225 eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);226 CHECK_RET_RETURN(ret,227 "Failed(%d) zero USBLEGCTLSTS.\n", ret);228 udelay(10);229 ret = pci_config_space_read_32(parent_sess,230 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);231 CHECK_RET_RETURN(ret,232 "Failed to get USBLEGCTLSTS 2: %s.\n",233 str_error(ret));234 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",235 usblegctlsts);236 }237 }238 239 240 /* Read again Legacy Support register */241 ret = pci_config_space_read_32(parent_sess,242 eecp + USBLEGSUP_OFFSET, &usblegsup);243 CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));244 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);245 246 async_hangup(parent_sess);247 266 #undef CHECK_RET_RETURN 248 267
Note:
See TracChangeset
for help on using the changeset viewer.