Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 78ab6d4 in mainline


Ignore:
Timestamp:
2011-07-10T22:45:08Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
4d62aa0
Parents:
1f6eb7d
Message:

OHCI: Device access fixes.

Only access Legacy support registers if their presence is indicated.
Fix setting host controller functional state, it's 2 bit value and standard
& and | operators are not enough.
Some comment fixes.

Tested on vbox.

Location:
uspace/drv/bus/usb/ohci
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/hc.c

    r1f6eb7d r78ab6d4  
    147147
    148148        fibril_mutex_initialize(&instance->guard);
     149
    149150        hc_gain_control(instance);
    150 
    151         rh_init(&instance->rh, instance->registers);
    152151
    153152        if (!interrupts) {
     
    157156        }
    158157
    159         return EOK;
    160 }
    161 /*----------------------------------------------------------------------------*/
     158        rh_init(&instance->rh, instance->registers);
     159
     160        return EOK;
     161}
     162/*----------------------------------------------------------------------------*/
     163/** Get number of commands used in IRQ code.
     164 * @return Number of commands.
     165 */
    162166size_t hc_irq_cmd_count(void)
    163167{
     
    165169}
    166170/*----------------------------------------------------------------------------*/
     171/** Generate IRQ code commands.
     172 * @param[out] cmds Place to store the commands.
     173 * @param[in] cmd_size Size of the place (bytes).
     174 * @param[in] regs Physical address of device's registers.
     175 * @param[in] reg_size Size of the register area (bytes).
     176 *
     177 * @return Error code.
     178 */
    167179int hc_get_irq_commands(
    168180    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
     
    172184                return EOVERFLOW;
    173185
    174         /* Create register mapping to use in IRQ handler
    175          * this mapping should be present in kernel only.
     186        /* Create register mapping to use in IRQ handler.
     187         * This mapping should be present in kernel only.
    176188         * Remove it from here when kernel knows how to create mappings
    177189         * and accepts physical addresses in IRQ code.
     
    181193
    182194        /* Some bogus access to force create mapping. DO NOT remove,
    183          * unless whole virtual addresses in irq is replaced */
     195         * unless whole virtual addresses in irq is replaced
     196         * NOTE: Compiler won't remove this as ohci_regs_t members
     197         * are declared volatile. */
    184198        registers->revision;
    185199
     
    195209}
    196210/*----------------------------------------------------------------------------*/
    197 /** Create and register endpoint structures
     211/** Create and register endpoint structures.
    198212 *
    199213 * @param[in] instance OHCI driver structure.
     
    444458/** Turn off any (BIOS)driver that might be in control of the device.
    445459 *
     460 * This function implements routines described in chapter 5.1.1.3 of the OHCI
     461 * specification (page 40, pdf page 54).
     462 *
    446463 * @param[in] instance OHCI hc driver structure.
    447464 */
     
    449466{
    450467        assert(instance);
     468
    451469        usb_log_debug("Requesting OHCI control.\n");
    452         /* Turn off legacy emulation */
    453         volatile uint32_t *ohci_emulation_reg =
    454             (uint32_t*)((char*)instance->registers + 0x100);
    455         usb_log_debug("OHCI legacy register %p: %x.\n",
    456             ohci_emulation_reg, *ohci_emulation_reg);
    457         /* Do not change A20 state */
    458         *ohci_emulation_reg &= 0x100;
    459         usb_log_debug("OHCI legacy register %p: %x.\n",
    460             ohci_emulation_reg, *ohci_emulation_reg);
     470        if (instance->registers->revision & R_LEGACY_FLAG) {
     471                /* Turn off legacy emulation, it should be enough to zero
     472                 * the lowest bit, but it caused problems. Thus clear all
     473                 * except GateA20 (causes restart on some hw).
     474                 * See page 145 of the specs for details.
     475                 */
     476                volatile uint32_t *ohci_emulation_reg =
     477                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
     478                usb_log_debug("OHCI legacy register %p: %x.\n",
     479                    ohci_emulation_reg, *ohci_emulation_reg);
     480                /* Zero everything but A20State */
     481                *ohci_emulation_reg &= 0x100;
     482                usb_log_debug(
     483                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
     484                    ohci_emulation_reg, *ohci_emulation_reg);
     485        }
    461486
    462487        /* Interrupt routing enabled => smm driver is active */
     
    464489                usb_log_debug("SMM driver: request ownership change.\n");
    465490                instance->registers->command_status |= CS_OCR;
     491                /* Hope that SMM actually knows its stuff or we can hang here */
    466492                while (instance->registers->control & C_IR) {
    467493                        async_usleep(1000);
    468494                }
    469495                usb_log_info("SMM driver: Ownership taken.\n");
    470                 instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
     496                C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
    471497                async_usleep(50000);
    472498                return;
    473499        }
    474500
    475         const unsigned hc_status =
    476             (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
     501        const unsigned hc_status = C_HCFS_GET(instance->registers->control);
    477502        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    478503        if (hc_status != C_HCFS_RESET) {
     
    482507                        return;
    483508                }
    484                 /* HC is suspended assert resume for 20ms */
    485                 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
     509                /* HC is suspended assert resume for 20ms, */
     510                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    486511                async_usleep(20000);
    487512                usb_log_info("BIOS driver: HC resumed.\n");
     
    561586            instance->registers->periodic_start, frame_length);
    562587
    563         instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
     588        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    564589        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    565590            instance->registers->control);
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r1f6eb7d r78ab6d4  
    3636#include <stdint.h>
    3737
     38#define LEGACY_REGS_OFFSET 0x100
     39
    3840/** OHCI memory mapped registers structure */
    3941typedef struct ohci_regs {
    4042        const volatile uint32_t revision;
     43#define R_REVISION_MASK (0x3f)
     44#define R_REVISION_SHIFT (0)
     45#define R_LEGACY_FLAG   (0x80)
     46
    4147        volatile uint32_t control;
    4248#define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
     
    5864#define C_HCFS_SUSPEND     (0x3)
    5965#define C_HCFS_SHIFT       (6)
     66
     67#define C_HCFS_GET(reg) \
     68        ((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)
     69#define C_HCFS_SET(reg, hcfs_state) \
     70do { \
     71        reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \
     72            | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \
     73} while (0)
     74
    6075
    6176#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
Note: See TracChangeset for help on using the changeset viewer.