Changeset bfc5c9dd in mainline
- Timestamp:
- 2012-02-23T20:42:30Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 815b244a
- Parents:
- ffcc5776
- Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
rffcc5776 rbfc5c9dd 242 242 switch (ep->transfer_type) { 243 243 case USB_TRANSFER_CONTROL: 244 instance->registers->control &= ~C_CLE;244 OHCI_CLR(instance->registers->control, C_CLE); 245 245 endpoint_list_add_ep(list, ohci_ep); 246 instance->registers->control_current = 0;247 instance->registers->control |= C_CLE;246 OHCI_WR(instance->registers->control_current, 0); 247 OHCI_SET(instance->registers->control, C_CLE); 248 248 break; 249 249 case USB_TRANSFER_BULK: 250 instance->registers->control &= ~C_BLE;250 OHCI_CLR(instance->registers->control, C_BLE); 251 251 endpoint_list_add_ep(list, ohci_ep); 252 instance->registers->control |= C_BLE; 252 OHCI_WR(instance->registers->bulk_current, 0); 253 OHCI_SET(instance->registers->control, C_BLE); 253 254 break; 254 255 case USB_TRANSFER_ISOCHRONOUS: 255 256 case USB_TRANSFER_INTERRUPT: 256 instance->registers->control &= (~C_PLE & ~C_IE);257 OHCI_CLR(instance->registers->control, C_PLE | C_IE); 257 258 endpoint_list_add_ep(list, ohci_ep); 258 instance->registers->control |= C_PLE | C_IE;259 OHCI_SET(instance->registers->control, C_PLE | C_IE); 259 260 break; 260 261 } … … 274 275 switch (ep->transfer_type) { 275 276 case USB_TRANSFER_CONTROL: 276 instance->registers->control &= ~C_CLE;277 OHCI_CLR(instance->registers->control, C_CLE); 277 278 endpoint_list_remove_ep(list, ohci_ep); 278 instance->registers->control_current = 0;279 instance->registers->control |= C_CLE;279 OHCI_WR(instance->registers->control_current, 0); 280 OHCI_SET(instance->registers->control, C_CLE); 280 281 break; 281 282 case USB_TRANSFER_BULK: 282 instance->registers->control &= ~C_BLE;283 OHCI_CLR(instance->registers->control, C_BLE); 283 284 endpoint_list_remove_ep(list, ohci_ep); 284 instance->registers->control |= C_BLE; 285 OHCI_WR(instance->registers->bulk_current, 0); 286 OHCI_SET(instance->registers->control, C_BLE); 285 287 break; 286 288 case USB_TRANSFER_ISOCHRONOUS: 287 289 case USB_TRANSFER_INTERRUPT: 288 instance->registers->control &= (~C_PLE & ~C_IE);290 OHCI_CLR(instance->registers->control, C_PLE | C_IE); 289 291 endpoint_list_remove_ep(list, ohci_ep); 290 instance->registers->control |= C_PLE | C_IE;292 OHCI_SET(instance->registers->control, C_PLE | C_IE); 291 293 break; 292 294 default: … … 325 327 { 326 328 case USB_TRANSFER_CONTROL: 327 instance->registers->command_status |= CS_CLF;329 OHCI_SET(instance->registers->command_status, CS_CLF); 328 330 break; 329 331 case USB_TRANSFER_BULK: 330 instance->registers->command_status |= CS_BLF;332 OHCI_SET(instance->registers->command_status, CS_BLF); 331 333 break; 332 334 default: … … 344 346 void hc_interrupt(hc_t *instance, uint32_t status) 345 347 { 348 status = ohci_reg2host(status); 346 349 assert(instance); 347 350 if ((status & ~I_SF) == 0) /* ignore sof status */ … … 354 357 fibril_mutex_lock(&instance->guard); 355 358 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca, 356 instance->registers->hcca,359 OHCI_RD(instance->registers->hcca), 357 360 (void *) addr_to_phys(instance->hcca)); 358 361 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 359 instance->registers->periodic_current);362 OHCI_RD(instance->registers->periodic_current)); 360 363 361 364 link_t *current = list_first(&instance->pending_batches); … … 412 415 413 416 usb_log_debug("Requesting OHCI control.\n"); 414 if ( instance->registers->revision& R_LEGACY_FLAG) {417 if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) { 415 418 /* Turn off legacy emulation, it should be enough to zero 416 419 * the lowest bit, but it caused problems. Thus clear all … … 421 424 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 422 425 usb_log_debug("OHCI legacy register %p: %x.\n", 423 ohci_emulation_reg, *ohci_emulation_reg);426 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 424 427 /* Zero everything but A20State */ 425 *ohci_emulation_reg &= 0x100;428 OHCI_CLR(*ohci_emulation_reg, ~0x100); 426 429 usb_log_debug( 427 430 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 428 ohci_emulation_reg, *ohci_emulation_reg);431 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 429 432 } 430 433 431 434 /* Interrupt routing enabled => smm driver is active */ 432 if ( instance->registers->control& C_IR) {435 if (OHCI_RD(instance->registers->control) & C_IR) { 433 436 usb_log_debug("SMM driver: request ownership change.\n"); 434 instance->registers->command_status |= CS_OCR;437 OHCI_SET(instance->registers->command_status, CS_OCR); 435 438 /* Hope that SMM actually knows its stuff or we can hang here */ 436 while ( instance->registers->control & C_IR) {439 while (OHCI_RD(instance->registers->control & C_IR)) { 437 440 async_usleep(1000); 438 441 } … … 442 445 return; 443 446 } 444 445 447 const unsigned hc_status = C_HCFS_GET(instance->registers->control); 446 448 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ … … 451 453 return; 452 454 } 453 /* HC is suspended assert resume for 20ms ,*/455 /* HC is suspended assert resume for 20ms */ 454 456 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME); 455 457 async_usleep(20000); … … 475 477 476 478 /* Save contents of fm_interval register */ 477 const uint32_t fm_interval = instance->registers->fm_interval;479 const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval); 478 480 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 479 481 … … 481 483 usb_log_debug2("HC reset.\n"); 482 484 size_t time = 0; 483 instance->registers->command_status = CS_HCR;484 while ( instance->registers->command_status& CS_HCR) {485 OHCI_WR(instance->registers->command_status, CS_HCR); 486 while (OHCI_RD(instance->registers->command_status) & CS_HCR) { 485 487 async_usleep(10); 486 488 time += 10; … … 489 491 490 492 /* Restore fm_interval */ 491 instance->registers->fm_interval = fm_interval;492 assert(( instance->registers->command_status& CS_HCR) == 0);493 OHCI_WR(instance->registers->fm_interval, fm_interval); 494 assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0); 493 495 494 496 /* hc is now in suspend state */ 495 497 usb_log_debug2("HC should be in suspend state(%x).\n", 496 instance->registers->control);498 OHCI_RD(instance->registers->control)); 497 499 498 500 /* Use HCCA */ 499 instance->registers->hcca = addr_to_phys(instance->hcca);501 OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca)); 500 502 501 503 /* Use queues */ 502 instance->registers->bulk_head =503 instance->lists[USB_TRANSFER_BULK].list_head_pa ;504 OHCI_WR(instance->registers->bulk_head, 505 instance->lists[USB_TRANSFER_BULK].list_head_pa); 504 506 usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n", 505 507 instance->lists[USB_TRANSFER_BULK].list_head, 506 508 instance->lists[USB_TRANSFER_BULK].list_head_pa); 507 509 508 instance->registers->control_head =509 instance->lists[USB_TRANSFER_CONTROL].list_head_pa ;510 OHCI_WR(instance->registers->control_head, 511 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 510 512 usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n", 511 513 instance->lists[USB_TRANSFER_CONTROL].list_head, … … 513 515 514 516 /* Enable queues */ 515 // instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);516 // usb_log_debug 2("All queues enabled(%x).\n",517 // instance->registers->control);517 // OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE)); 518 // usb_log_debug("Queues enabled(%x).\n", 519 // OHCI_RD(instance->registers->control)); 518 520 519 521 /* Enable interrupts */ 520 instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;521 usb_log_debug 2("Enabled interrupts: %x.\n",522 instance->registers->interrupt_enable);523 instance->registers->interrupt_enable = I_MI;522 OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS); 523 usb_log_debug("Enabled interrupts: %x.\n", 524 OHCI_RD(instance->registers->interrupt_enable)); 525 OHCI_WR(instance->registers->interrupt_enable, I_MI); 524 526 525 527 /* Set periodic start to 90% */ 526 const uint32_t frame_length = FMI_FL_GET(fm_interval); 527 PS_SET(instance->registers->periodic_start, (frame_length / 10) * 9); 528 const uint32_t frame_length = 529 (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK; 530 OHCI_WR(instance->registers->periodic_start, 531 ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT); 528 532 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 529 PS_GET(instance->registers->periodic_start), 530 PS_GET(instance->registers->periodic_start), frame_length); 531 533 OHCI_RD(instance->registers->periodic_start), 534 OHCI_RD(instance->registers->periodic_start), frame_length); 532 535 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL); 533 536 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 534 instance->registers->control);537 OHCI_RD(instance->registers->control)); 535 538 } 536 539 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/main.c
rffcc5776 rbfc5c9dd 83 83 int main(int argc, char *argv[]) 84 84 { 85 sleep(5);86 85 usb_log_enable(USB_LOG_LEVEL_DEBUG2, NAME); 87 86 return ddf_driver_main(&ohci_driver); -
uspace/drv/bus/usb/ohci/ohci_regs.h
rffcc5776 rbfc5c9dd 42 42 #define ohci_reg2host(value) uint32_t_le2host(value) 43 43 44 #define OHCI_WR(reg, val) reg = host2uint32_t_le(val) 45 #define OHCI_RD(reg) uint32_t_le2host(reg) 46 #define OHCI_SET(reg, val) reg |= host2uint32_t_le(val) 47 #define OHCI_CLR(reg, val) reg &= host2uint32_t_le(val) 48 49 44 50 #define LEGACY_REGS_OFFSET 0x100 45 51 … … 47 53 typedef struct ohci_regs { 48 54 const ioport32_t revision; 49 #define R_REVISION_ (reg) (ohci_reg2host(reg) &0x3f)50 #define R_LEGACY_FLAG host2ohci_reg(0x80)55 #define R_REVISION_MASK (0x3f) 56 #define R_LEGACY_FLAG (0x80) 51 57 52 58 ioport32_t control; … … 56 62 #define C_CBSR_1_3 (0x2) 57 63 #define C_CBSR_1_4 (0x3) 58 #define C_CBSR_GET(reg) (ohci_reg2host(reg) & 0x3) 59 #define C_CBSR_SET(reg, value) \ 60 do { \ 61 reg = (reg & host2ohci_reg(~0x3) | host2ohci_reg(value & 0x3)) \ 62 } while (0) 63 64 #define C_PLE host2ohci_reg(1 << 2) /* Periodic list enable */ 65 #define C_IE host2ohci_reg(1 << 3) /* Isochronous enable */ 66 #define C_CLE host2ohci_reg(1 << 4) /* Control list enable */ 67 #define C_BLE host2ohci_reg(1 << 5) /* Bulk list enable */ 64 #define C_CBSR_MASK (0x3) 65 #define C_CBSR_SHIFT 0 66 67 #define C_PLE (1 << 2) /* Periodic list enable */ 68 #define C_IE (1 << 3) /* Isochronous enable */ 69 #define C_CLE (1 << 4) /* Control list enable */ 70 #define C_BLE (1 << 5) /* Bulk list enable */ 68 71 69 72 /* Host controller functional state */ … … 72 75 #define C_HCFS_OPERATIONAL (0x2) 73 76 #define C_HCFS_SUSPEND (0x3) 74 #define C_HCFS_GET(reg) (( ohci_reg2host(reg) >> 6) & 0x3)77 #define C_HCFS_GET(reg) ((OHCI_RD(reg) >> 6) & 0x3) 75 78 #define C_HCFS_SET(reg, value) \ 76 79 do { \ 77 reg = (reg & host2ohci_reg(~(0x3 << 6))) \ 78 | host2ohci_reg((value & 0x3) << 6); \ 80 uint32_t r = OHCI_RD(reg); \ 81 r &= ~(0x3 << 6); \ 82 r |= (value & 0x3) << 6; \ 83 OHCI_WR(reg, r); \ 79 84 } while (0) 80 85 81 #define C_IR host2ohci_reg(1 << 8) /* Interrupt routing, make sure it's 0 */82 #define C_RWC host2ohci_reg(1 << 9) /* Remote wakeup connected, host specific */83 #define C_RWE host2ohci_reg(1 << 10) /* Remote wakeup enable */86 #define C_IR (1 << 8) /* Interrupt routing, make sure it's 0 */ 87 #define C_RWC (1 << 9) /* Remote wakeup connected, host specific */ 88 #define C_RWE (1 << 10) /* Remote wakeup enable */ 84 89 85 90 ioport32_t command_status; 86 #define CS_HCR host2ohci_reg(1 << 0) /* Host controller reset */87 #define CS_CLF host2ohci_reg(1 << 1) /* Control list filled */88 #define CS_BLF host2ohci_reg(1 << 2) /* Bulk list filled */89 #define CS_OCR host2ohci_reg(1 << 3) /* Ownership change request */91 #define CS_HCR (1 << 0) /* Host controller reset */ 92 #define CS_CLF (1 << 1) /* Control list filled */ 93 #define CS_BLF (1 << 2) /* Bulk list filled */ 94 #define CS_OCR (1 << 3) /* Ownership change request */ 90 95 #if 0 91 96 #define CS_SOC_MASK (0x3) /* Scheduling overrun count */ … … 100 105 ioport32_t interrupt_enable; 101 106 ioport32_t interrupt_disable; 102 #define I_SO host2ohci_reg(1 << 0) /* Scheduling overrun */103 #define I_WDH host2ohci_reg(1 << 1) /* Done head write-back */104 #define I_SF host2ohci_reg(1 << 2) /* Start of frame */105 #define I_RD host2ohci_reg(1 << 3) /* Resume detect */106 #define I_UE host2ohci_reg(1 << 4) /* Unrecoverable error */107 #define I_FNO host2ohci_reg(1 << 5) /* Frame number overflow */108 #define I_RHSC host2ohci_reg(1 << 6) /* Root hub status change */109 #define I_OC host2ohci_reg(1 << 30) /* Ownership change */110 #define I_MI host2ohci_reg(1 << 31) /* Master interrupt (any/all) */107 #define I_SO (1 << 0) /* Scheduling overrun */ 108 #define I_WDH (1 << 1) /* Done head write-back */ 109 #define I_SF (1 << 2) /* Start of frame */ 110 #define I_RD (1 << 3) /* Resume detect */ 111 #define I_UE (1 << 4) /* Unrecoverable error */ 112 #define I_FNO (1 << 5) /* Frame number overflow */ 113 #define I_RHSC (1 << 6) /* Root hub status change */ 114 #define I_OC (1 << 30) /* Ownership change */ 115 #define I_MI (1 << 31) /* Master interrupt (any/all) */ 111 116 112 117 /** HCCA pointer (see hw_struct hcca.h) */ … … 134 139 /** Frame time and max packet size for all transfers */ 135 140 ioport32_t fm_interval; 136 #define FMI_FL_GET(reg) (ohci_reg2host(reg) & 0x3fff)137 #if 0138 141 #define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/ 139 142 #define FMI_FI_SHIFT (0) … … 141 144 #define FMI_FSMPS_SHIFT (16) 142 145 #define FMI_TOGGLE_FLAG (1 << 31) 143 #endif144 146 145 147 /** Bit times remaining in current frame */ 146 148 const ioport32_t fm_remaining; 147 #define FMR_R_GET(reg) (ohci_reg2host(reg) & 0x3fff)148 #if 0149 149 #define FMR_FR_MASK FMI_FI_MASK 150 150 #define FMR_FR_SHIFT FMI_FI_SHIFT 151 151 #define FMR_TOGGLE_FLAG FMI_TOGGLE_FLAG 152 #endif 152 153 153 /** Frame number */ 154 154 const ioport32_t fm_number; 155 #if 0156 155 #define FMN_NUMBER_MASK (0xffff) 157 #endif 156 158 157 /** Remaining bit time in frame to start periodic transfers */ 159 158 ioport32_t periodic_start; 160 #define PS_GET(reg) (ohci_reg2host(reg) & 0x3fff) 161 #define PS_SET(reg, value) \ 162 do { \ 163 reg = (reg & host2ohci_reg(~0x3fff)) | host2ohci_reg(value & 0x3fff); \ 164 } while (0) 159 #define PS_MASK 0x3fff 160 #define PS_SHIFT 0 165 161 166 162 /** Threshold for starting LS transaction */ 167 163 ioport32_t ls_threshold; 168 //#define LST_LST_MASK (0x7fff)164 #define LST_LST_MASK (0x7fff) 169 165 170 166 /** The first root hub control register */ 171 167 ioport32_t rh_desc_a; 172 168 /** Number of downstream ports, max 15 */ 173 #define RHDA_NDS (reg) (ohci_reg2host(reg) &0xff)169 #define RHDA_NDS_MASK (0xff) 174 170 /** Power switching mode: 0-global, 1-per port*/ 175 #define RHDA_PSM_FLAG host2ohci_reg(1 << 8)171 #define RHDA_PSM_FLAG (1 << 8) 176 172 /** No power switch: 1-power on, 0-use PSM*/ 177 #define RHDA_NPS_FLAG host2ohci_reg(1 << 9)173 #define RHDA_NPS_FLAG (1 << 9) 178 174 /** 1-Compound device, must be 0 */ 179 #define RHDA_DT_FLAG host2ohci_reg(1 << 10)175 #define RHDA_DT_FLAG (1 << 10) 180 176 /** Over-current mode: 0-global, 1-per port */ 181 #define RHDA_OCPM_FLAG host2ohci_reg(1 << 11)177 #define RHDA_OCPM_FLAG (1 << 11) 182 178 /** OC control: 0-use OCPM, 1-OC off */ 183 #define RHDA_NOCP_FLAG host2ohci_reg(1 << 12)179 #define RHDA_NOCP_FLAG (1 << 12) 184 180 /** Power on to power good time */ 185 #define RHDA_POTPGT (reg) (ohci_reg2host(reg) >> 24)181 #define RHDA_POTPGT_SHIFT 24 186 182 187 183 /** The other root hub control register */ 188 184 ioport32_t rh_desc_b; 189 185 /** Device removable mask */ 190 #define RHDB_DR_ READ(reg) (ohci_reg2host(reg) & 0xffff)191 #define RHDB_DR_ WRITE(val) host2ohci_reg(val & 0xffff)186 #define RHDB_DR_SHIFT 0 187 #define RHDB_DR_MASK 0xffff 192 188 /** Power control mask */ 193 #define RHDB_PCC_READ(reg) (ohci_reg2host(reg) >> 16) 194 #define RHDB_PCC_WRITE(val) host2ohci_reg(val << 16) 195 /* Port device removable status */ 196 #define RHDB_DR_FLAG(port) \ 197 host2ohci_reg(((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT) 198 /* Port power control status: 1-per port power control, 0-global power switch */ 199 #define RHDB_PPC_FLAG(port) \ 200 host2ohci_reg(((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT) 189 #define RHDB_PCC_MASK (0xffff) 190 #define RHDB_PCC_SHIFT 16 201 191 202 192 /** Root hub status register */ … … 207 197 * specified in PPCM(RHDB), or all ports, 208 198 * if power is set globally */ 209 #define RHS_LPS_FLAG host2ohci_reg(1 << 0)199 #define RHS_LPS_FLAG (1 << 0) 210 200 #define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */ 211 201 /** Over-current indicator, if per-port: 0 */ 212 #define RHS_OCI_FLAG host2ohci_reg(1 << 1)202 #define RHS_OCI_FLAG (1 << 1) 213 203 214 204 /* read: 0-connect status change does not wake HC 215 205 * 1-connect status change wakes HC 216 206 * write: 1-set DRWE, 0-no effect */ 217 #define RHS_DRWE_FLAG host2ohci_reg(1 << 15)207 #define RHS_DRWE_FLAG (1 << 15) 218 208 #define RHS_SET_DRWE RHS_DRWE_FLAG 219 209 /* read: 0, … … 222 212 * specified in PPCM(RHDB), or all ports, 223 213 * if power is set globally */ 224 #define RHS_LPSC_FLAG host2ohci_reg(1 << 16)214 #define RHS_LPSC_FLAG (1 << 16) 225 215 #define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */ 226 216 /** Over-current change indicator*/ 227 #define RHS_OCIC_FLAG host2ohci_reg(1 << 17)228 #define RHS_CLEAR_DRWE host2ohci_reg(1 << 31)217 #define RHS_OCIC_FLAG (1 << 17) 218 #define RHS_CLEAR_DRWE (1 << 31) 229 219 230 220 /** Root hub per port status */ 231 221 ioport32_t rh_port_status[]; 232 #define RHPS_CCS_FLAG host2ohci_reg(1 << 0) /* r: current connect status,222 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status, 233 223 * w: 1-clear port enable, 0-N/S*/ 234 224 #define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG 235 #define RHPS_PES_FLAG host2ohci_reg(1 << 1) /* r: port enable status225 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status 236 226 * w: 1-set port enable, 0-N/S */ 237 227 #define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG 238 #define RHPS_PSS_FLAG host2ohci_reg(1 << 2) /* r: port suspend status228 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status 239 229 * w: 1-set port suspend, 0-N/S */ 240 230 #define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG 241 #define RHPS_POCI_FLAG host2ohci_reg(1 << 3) /* r: port over-current231 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current 242 232 * (if reports are per-port 243 233 * w: 1-clear port suspend … … 245 235 * 0-nothing */ 246 236 #define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG 247 #define RHPS_PRS_FLAG host2ohci_reg(1 << 4) /* r: port reset status237 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status 248 238 * w: 1-set port reset, 0-N/S */ 249 239 #define RHPS_SET_PORT_RESET RHPS_PRS_FLAG 250 #define RHPS_PPS_FLAG host2ohci_reg(1 << 8) /* r: port power status240 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status 251 241 * w: 1-set port power, 0-N/S */ 252 242 #define RHPS_SET_PORT_POWER RHPS_PPS_FLAG 253 #define RHPS_LSDA_FLAG host2ohci_reg(1 << 9) /* r: low speed device attached243 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached 254 244 * w: 1-clear port power, 0-N/S*/ 255 245 #define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG 256 #define RHPS_CSC_FLAG host2ohci_reg(1 << 16) /* connect status change WC */ 257 #define RHPS_PESC_FLAG host2ohci_reg(1 << 17) /* port enable status change WC */ 258 #define RHPS_PSSC_FLAG host2ohci_reg(1 << 18) /* port suspend status change WC */ 259 #define RHPS_OCIC_FLAG host2ohci_reg(1 << 19) /* port over-current change WC */ 260 #define RHPS_PRSC_FLAG host2ohci_reg(1 << 20) /* port reset status change WC */ 261 #define RHPS_CHANGE_WC_MASK host2ohci_reg(0x1f0000) 262 /** OHCI designers were kind enough to make bits correspond to feature # */ 263 #define RHPS_FEATURE_BIT(feature) host2ohci_reg(1 << feature) 246 #define RHPS_CSC_FLAG (1 << 16) /* connect status change WC */ 247 #define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */ 248 #define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */ 249 #define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */ 250 #define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */ 251 #define RHPS_CHANGE_WC_MASK (0x1f0000) 264 252 } __attribute__((packed)) ohci_regs_t; 265 253 #endif -
uspace/drv/bus/usb/ohci/root_hub.c
rffcc5776 rbfc5c9dd 154 154 155 155 instance->registers = regs; 156 instance->port_count = RHDA_NDS(instance->registers->rh_desc_a);157 usb_log_debug ("rh_desc_a: %x.\n", instance->registers->rh_desc_a);156 instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK; 157 usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a)); 158 158 if (instance->port_count > 15) { 159 159 usb_log_warning("OHCI specification does not allow more than 15" … … 167 167 168 168 #if defined OHCI_POWER_SWITCH_no 169 usb_log_debug("OHCI rh: Set power mode to no power switching.\n"); 169 170 /* Set port power mode to no power-switching. (always on) */ 170 instance->registers->rh_desc_a |= RHDA_NPS_FLAG;171 OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG); 171 172 172 173 /* Set to no over-current reporting */ 173 instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;174 OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG); 174 175 175 176 #elif defined OHCI_POWER_SWITCH_ganged 176 /* Set port power mode to no ganged power-switching. */ 177 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 178 instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG; 179 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 177 usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n"); 178 /* Set port power mode to ganged power-switching. */ 179 OHCI_CLEAR(regs->rh_desc_a, RHDA_NPS_FLAG); 180 OHCI_CLEAR(regs->rh_desc_a, RHDA_PSM_FLAG); 181 182 /* Turn off power (hub driver will turn this back on)*/ 183 OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER); 180 184 181 185 /* Set to global over-current */ 182 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;183 instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;186 OHCI_CLEAR(regs->rh_desc_a, RHDA_NOCP_FLAG); 187 OHCI_CLEAR(regs->rh_desc_a, RHDA_OCPM_FLAG); 184 188 #else 185 /* Set port power mode to no per port power-switching. */ 186 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 187 instance->registers->rh_desc_a |= RHDA_PSM_FLAG; 189 usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n"); 190 /* Set port power mode to per port power-switching. */ 191 OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG); 192 OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG); 188 193 189 194 /* Control all ports by global switch and turn them off */ 190 instance->registers->rh_desc_b &= ~RHDB_PCC_WRITE(~0);191 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;195 OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT); 196 OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER); 192 197 193 198 /* Return control to per port state */ 194 instance->registers->rh_desc_b |= RHDB_PCC_WRITE(~0);199 OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT); 195 200 196 201 /* Set per port over-current */ 197 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;198 instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;202 OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG); 203 OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG); 199 204 #endif 200 205 … … 285 290 instance->hub_descriptor_size = size; 286 291 287 const uint32_t hub_desc = instance->registers->rh_desc_a;288 const uint32_t port_desc = instance->registers->rh_desc_b;292 const uint32_t hub_desc = OHCI_RD(instance->registers->rh_desc_a); 293 const uint32_t port_desc = OHCI_RD(instance->registers->rh_desc_b); 289 294 290 295 /* bDescLength */ … … 308 313 instance->descriptors.hub[4] = 0; 309 314 /* bPwrOn2PwrGood */ 310 instance->descriptors.hub[5] = RHDA_POTPGT(hub_desc);315 instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT; 311 316 /* bHubContrCurrent, root hubs don't need no power. */ 312 317 instance->descriptors.hub[6] = 0; 313 318 314 319 /* Device Removable and some legacy 1.0 stuff*/ 315 instance->descriptors.hub[7] = RHDB_DR_READ(port_desc) & 0xff;320 instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff; 316 321 instance->descriptors.hub[8] = 0xff; 317 322 if (instance->interrupt_mask_size == 2) { 318 instance->descriptors.hub[8] = RHDB_DR_READ(port_desc) >> 8; 323 instance->descriptors.hub[8] = 324 (port_desc >> RHDB_DR_SHIFT) >> 8; 319 325 instance->descriptors.hub[9] = 0xff; 320 326 instance->descriptors.hub[10] = 0xff; … … 364 370 365 371 /* Only local power source change and over-current change can happen */ 366 if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) { 372 if (OHCI_RD(instance->registers->rh_status) 373 & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) { 367 374 mask |= 1; 368 375 } 369 376 for (size_t port = 1; port <= instance->port_count; ++port) { 370 377 /* Write-clean bits are those that indicate change */ 371 if (RHPS_CHANGE_WC_MASK 372 & instance->registers->rh_port_status[port - 1]) { 373 378 if (OHCI_RD(instance->registers->rh_port_status[port - 1]) 379 & RHPS_CHANGE_WC_MASK) { 374 380 mask |= (1 << port); 375 381 } … … 396 402 usb_device_request_setup_packet_t *request_packet = 397 403 (usb_device_request_setup_packet_t*)request->setup_buffer; 404 405 const uint16_t index = uint16_usb2host(request_packet->index); 398 406 399 407 switch (request_packet->request_type) … … 406 414 TRANSFER_END(request, EOVERFLOW); 407 415 } else { 408 uint32_t data = instance->registers->rh_status & 409 (RHS_LPS_FLAG | RHS_LPSC_FLAG 410 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 416 const uint32_t data = 417 OHCI_RD(instance->registers->rh_status) & 418 (RHS_LPS_FLAG | RHS_LPSC_FLAG 419 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 411 420 TRANSFER_END_DATA(request, &data, sizeof(data)); 412 421 } … … 420 429 TRANSFER_END(request, EOVERFLOW); 421 430 } else { 422 unsigned port = request_packet->index;431 const unsigned port = index; 423 432 if (port < 1 || port > instance->port_count) 424 433 TRANSFER_END(request, EINVAL); 425 426 uint32_t data = 427 instance->registers->rh_port_status[port - 1]; 434 /* Register format matches the format of port status 435 * field */ 436 const uint32_t data = uint32_usb2host(OHCI_RD( 437 instance->registers->rh_port_status[port - 1])); 428 438 TRANSFER_END_DATA(request, &data, sizeof(data)); 429 439 } … … 441 451 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE): 442 452 /* Hubs are allowed to have only one interface */ 443 if ( request_packet->index != 0)453 if (index != 0) 444 454 TRANSFER_END(request, EINVAL); 445 455 /* Fall through, as the answer will be the same: 0x0000 */ 446 456 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT): 447 457 /* Endpoint 0 (default control) and 1 (interrupt) */ 448 if ( request_packet->index >= 2)458 if (index >= 2) 449 459 TRANSFER_END(request, EINVAL); 450 460 … … 455 465 } else { 456 466 /* Endpoints are OK. (We don't halt) */ 457 uint16_t data = 0;467 const uint16_t data = 0; 458 468 TRANSFER_END_DATA(request, &data, sizeof(data)); 459 469 } … … 556 566 switch (feature) 557 567 { 558 case USB_HUB_FEATURE_PORT_POWER: //8 559 /* No power switching */ 560 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 561 return EOK; 562 /* Ganged power switching */ 563 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 564 instance->registers->rh_status = RHS_SET_GLOBAL_POWER; 565 return EOK; 568 case USB_HUB_FEATURE_PORT_POWER: /*8*/ 569 { 570 const uint32_t rhda = 571 OHCI_RD(instance->registers->rh_desc_a); 572 /* No power switching */ 573 if (rhda & RHDA_NPS_FLAG) 574 return EOK; 575 /* Ganged power switching, one port powers all */ 576 if (!(rhda & RHDA_PSM_FLAG)) { 577 OHCI_WR(instance->registers->rh_status, 578 RHS_SET_GLOBAL_POWER); 579 return EOK; 580 } 566 581 } 567 case USB_HUB_FEATURE_PORT_ENABLE: //1568 case USB_HUB_FEATURE_PORT_ SUSPEND: //2569 case USB_HUB_FEATURE_PORT_ RESET: //4570 usb_log_debug2(571 "Setting port ENABLE, SUSPEND or RESET on port %zu.\n",572 port);573 instance->registers->rh_port_status[port - 1] =574 RHPS_FEATURE_BIT(feature);582 /* Fall through */ 583 case USB_HUB_FEATURE_PORT_ENABLE: /*1*/ 584 case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/ 585 case USB_HUB_FEATURE_PORT_RESET: /*4*/ 586 usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET " 587 "on port %zu.\n", port); 588 OHCI_WR(instance->registers->rh_port_status[port - 1], 589 1 << feature); 575 590 return EOK; 576 591 default: … … 598 613 switch (feature) 599 614 { 600 case USB_HUB_FEATURE_PORT_POWER: //8 601 /* No power switching */ 602 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 603 return ENOTSUP; 604 /* Ganged power switching */ 605 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 606 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 615 case USB_HUB_FEATURE_PORT_POWER: /*8*/ 616 { 617 const uint32_t rhda = 618 OHCI_RD(instance->registers->rh_desc_a); 619 /* No power switching */ 620 if (rhda & RHDA_NPS_FLAG) 621 return ENOTSUP; 622 /* Ganged power switching, one port powers all */ 623 if (!(rhda & RHDA_PSM_FLAG)) { 624 OHCI_WR(instance->registers->rh_status, 625 RHS_CLEAR_GLOBAL_POWER); 626 return EOK; 627 } 628 OHCI_WR(instance->registers->rh_port_status[port - 1], 629 RHPS_CLEAR_PORT_POWER); 607 630 return EOK; 608 631 } 609 instance->registers->rh_port_status[port - 1] = 610 RHPS_CLEAR_PORT_POWER; 632 633 case USB_HUB_FEATURE_PORT_ENABLE: /*1*/ 634 OHCI_WR(instance->registers->rh_port_status[port - 1], 635 RHPS_CLEAR_PORT_ENABLE); 611 636 return EOK; 612 637 613 case USB_HUB_FEATURE_PORT_ ENABLE: //1614 instance->registers->rh_port_status[port - 1] =615 RHPS_CLEAR_PORT_ENABLE;638 case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/ 639 OHCI_WR(instance->registers->rh_port_status[port - 1], 640 RHPS_CLEAR_PORT_SUSPEND); 616 641 return EOK; 617 642 618 case USB_HUB_FEATURE_PORT_SUSPEND: //2 619 instance->registers->rh_port_status[port - 1] = 620 RHPS_CLEAR_PORT_SUSPEND; 621 return EOK; 622 623 case USB_HUB_FEATURE_C_PORT_CONNECTION: //16 624 case USB_HUB_FEATURE_C_PORT_ENABLE: //17 625 case USB_HUB_FEATURE_C_PORT_SUSPEND: //18 626 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19 627 case USB_HUB_FEATURE_C_PORT_RESET: //20 643 case USB_HUB_FEATURE_C_PORT_CONNECTION: /*16*/ 644 case USB_HUB_FEATURE_C_PORT_ENABLE: /*17*/ 645 case USB_HUB_FEATURE_C_PORT_SUSPEND: /*18*/ 646 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/ 647 case USB_HUB_FEATURE_C_PORT_RESET: /*20*/ 628 648 usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, " 629 "C_SUSPEND or C_RESET on port %zu.\n",630 port);631 instance->registers->rh_port_status[port - 1] =632 RHPS_FEATURE_BIT(feature);649 "C_SUSPEND, C_OC or C_RESET on port %zu.\n", port); 650 /* Bit offsets correspond to the feature number */ 651 OHCI_WR(instance->registers->rh_port_status[port - 1], 652 1 << feature); 633 653 return EOK; 634 654 … … 658 678 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 659 679 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 660 int ret = set_feature_port(instance,680 const int ret = set_feature_port(instance, 661 681 setup_request->value, setup_request->index); 662 682 TRANSFER_END(request, ret); … … 697 717 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 698 718 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 699 int ret = clear_feature_port(instance,719 const int ret = clear_feature_port(instance, 700 720 setup_request->value, setup_request->index); 701 721 TRANSFER_END(request, ret); … … 710 730 * as root hubs do not support local power status feature. 711 731 * (OHCI pg. 127) */ 712 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 713 instance->registers->rh_status = RHS_OCIC_FLAG; 732 if (uint16_usb2host(setup_request->value) 733 == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 734 OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG); 714 735 TRANSFER_END(request, EOK); 715 736 } … … 775 796 if (request->buffer_size == 0) 776 797 TRANSFER_END(request, EOVERFLOW); 777 uint8_t config = 1;798 const uint8_t config = 1; 778 799 TRANSFER_END_DATA(request, &config, sizeof(config)); 779 800 … … 794 815 TRANSFER_END(request, EINVAL); 795 816 796 instance->address = setup_request->value;817 instance->address = uint16_usb2host(setup_request->value); 797 818 TRANSFER_END(request, EOK); 798 819
Note:
See TracChangeset
for help on using the changeset viewer.