⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ray_cs.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
    dev->get_wireless_stats = ray_get_wireless_stats;#endif    dev->set_multicast_list = &set_multicast_list;    DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n");    SET_MODULE_OWNER(dev);    dev->init = &ray_dev_init;    dev->open = &ray_open;    dev->stop = &ray_dev_close;    netif_stop_queue(dev);    /* Register with Card Services */    link->next = dev_list;    dev_list = link;    client_reg.dev_info = &dev_info;    client_reg.EventMask =        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;    client_reg.event_handler = &ray_event;    client_reg.Version = 0x0210;    client_reg.event_callback_args.client_data = link;    DEBUG(2,"ray_cs ray_attach calling pcmcia_register_client(...)\n");    init_timer(&local->timer);    ret = pcmcia_register_client(&link->handle, &client_reg);    if (ret != 0) {        printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");        cs_error(link->handle, RegisterClient, ret);        ray_detach(link);        return NULL;    }    DEBUG(2,"ray_cs ray_attach ending\n");    return link;fail_alloc_dev:    kfree(link);    return NULL;} /* ray_attach *//*=============================================================================    This deletes a driver "instance".  The device is de-registered    with Card Services.  If it has been released, all local data    structures are freed.  Otherwise, the structures will be freed    when the device is released.=============================================================================*/static void ray_detach(dev_link_t *link){    dev_link_t **linkp;    DEBUG(1, "ray_detach(0x%p)\n", link);        /* Locate device structure */    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)        if (*linkp == link) break;    if (*linkp == NULL)        return;    /* If the device is currently configured and active, we won't      actually delete it yet.  Instead, it is marked so that when      the release() function is called, that will trigger a proper      detach().    */    if (link->state & DEV_CONFIG)        ray_release(link);    /* Break the link with Card Services */    if (link->handle)        pcmcia_deregister_client(link->handle);        /* Unlink device structure, free pieces */    *linkp = link->next;    if (link->priv) {        struct net_device *dev = link->priv;	if (link->dev) unregister_netdev(dev);        free_netdev(dev);    }    kfree(link);    DEBUG(2,"ray_cs ray_detach ending\n");} /* ray_detach *//*=============================================================================    ray_config() is run after a CARD_INSERTION event    is received, to configure the PCMCIA socket, and to make the    ethernet device available to the system.=============================================================================*/#define CS_CHECK(fn, ret) \do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)#define MAX_TUPLE_SIZE 128static void ray_config(dev_link_t *link){    client_handle_t handle = link->handle;    tuple_t tuple;    cisparse_t parse;    int last_fn = 0, last_ret = 0;    int i;    u_char buf[MAX_TUPLE_SIZE];    win_req_t req;    memreq_t mem;    struct net_device *dev = (struct net_device *)link->priv;    ray_dev_t *local = (ray_dev_t *)dev->priv;    DEBUG(1, "ray_config(0x%p)\n", link);    /* This reads the card's CONFIG tuple to find its configuration regs */    tuple.DesiredTuple = CISTPL_CONFIG;    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));    tuple.TupleData = buf;    tuple.TupleDataMax = MAX_TUPLE_SIZE;    tuple.TupleOffset = 0;    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));    link->conf.ConfigBase = parse.config.base;    link->conf.Present = parse.config.rmask[0];    /* Determine card type and firmware version */    buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;    tuple.DesiredTuple = CISTPL_VERS_1;    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));    tuple.TupleData = buf;    tuple.TupleDataMax = MAX_TUPLE_SIZE;    tuple.TupleOffset = 2;    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));    for (i=0; i<tuple.TupleDataLen - 4; i++)         if (buf[i] == 0) buf[i] = ' ';    printk(KERN_INFO "ray_cs Detected: %s\n",buf);    /* Configure card */    link->state |= DEV_CONFIG;    /* Now allocate an interrupt line.  Note that this does not       actually assign a handler to the interrupt.    */    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));    dev->irq = link->irq.AssignedIRQ;        /* This actually configures the PCMCIA socket -- setting up       the I/O windows and the interrupt mapping.    */    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));/*** Set up 32k window for shared memory (transmit and control) ************/    req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;    req.Base = 0;    req.Size = 0x8000;    req.AccessSpeed = ray_mem_speed;    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));    mem.CardOffset = 0x0000; mem.Page = 0;    CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));    local->sram = ioremap(req.Base,req.Size);/*** Set up 16k window for shared memory (receive buffer) ***************/    req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;    req.Base = 0;    req.Size = 0x4000;    req.AccessSpeed = ray_mem_speed;    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));    mem.CardOffset = 0x8000; mem.Page = 0;    CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));    local->rmem = ioremap(req.Base,req.Size);/*** Set up window for attribute memory ***********************************/    req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;    req.Base = 0;    req.Size = 0x1000;    req.AccessSpeed = ray_mem_speed;    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));    mem.CardOffset = 0x0000; mem.Page = 0;    CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));    local->amem = ioremap(req.Base,req.Size);    DEBUG(3,"ray_config sram=%p\n",local->sram);    DEBUG(3,"ray_config rmem=%p\n",local->rmem);    DEBUG(3,"ray_config amem=%p\n",local->amem);    if (ray_init(dev) < 0) {        ray_release(link);        return;    }    SET_NETDEV_DEV(dev, &handle_to_dev(handle));    i = register_netdev(dev);    if (i != 0) {        printk("ray_config register_netdev() failed\n");        ray_release(link);        return;    }    strcpy(local->node.dev_name, dev->name);    link->dev = &local->node;    link->state &= ~DEV_CONFIG_PENDING;    printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",       dev->name, dev->irq);    for (i = 0; i < 6; i++)    printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));    return;cs_failed:    cs_error(link->handle, last_fn, last_ret);    ray_release(link);} /* ray_config */static inline struct ccs __iomem *ccs_base(ray_dev_t *dev){	return dev->sram + CCS_BASE;}static inline struct rcs __iomem *rcs_base(ray_dev_t *dev){	/*	 * This looks nonsensical, since there is a separate	 * RCS_BASE. But the difference between a "struct rcs"	 * and a "struct ccs" ends up being in the _index_ off	 * the base, so the base pointer is the same for both	 * ccs/rcs.	 */	return dev->sram + CCS_BASE;}/*===========================================================================*/static int ray_init(struct net_device *dev){    int i;    UCHAR *p;    struct ccs __iomem *pccs;    ray_dev_t *local = (ray_dev_t *)dev->priv;    dev_link_t *link = local->finder;    DEBUG(1, "ray_init(0x%p)\n", dev);    if (!(link->state & DEV_PRESENT)) {        DEBUG(0,"ray_init - device not present\n");        return -1;    }    local->net_type = net_type;    local->sta_type = TYPE_STA;    /* Copy the startup results to local memory */    memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE,\           sizeof(struct startup_res_6));    /* Check Power up test status and get mac address from card */    if (local->startup_res.startup_word != 0x80) {    printk(KERN_INFO "ray_init ERROR card status = %2x\n",           local->startup_res.startup_word);        local->card_status = CARD_INIT_ERROR;        return -1;    }    local->fw_ver = local->startup_res.firmware_version[0];    local->fw_bld = local->startup_res.firmware_version[1];    local->fw_var = local->startup_res.firmware_version[2];    DEBUG(1,"ray_init firmware version %d.%d \n",local->fw_ver, local->fw_bld);    local->tib_length = 0x20;    if ((local->fw_ver == 5) && (local->fw_bld >= 30))        local->tib_length = local->startup_res.tib_length;    DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length);    /* Initialize CCS's to buffer free state */    pccs = ccs_base(local);    for (i=0;  i<NUMBER_OF_CCS;  i++) {        writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);    }    init_startup_params(local);    /* copy mac address to startup parameters */    if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr))    {        p = local->sparm.b4.a_mac_addr;    }    else    {        memcpy(&local->sparm.b4.a_mac_addr,               &local->startup_res.station_addr, ADDRLEN);        p = local->sparm.b4.a_mac_addr;    }    clear_interrupt(local); /* Clear any interrupt from the card */    local->card_status = CARD_AWAITING_PARAM;    DEBUG(2,"ray_init ending\n");    return 0;} /* ray_init *//*===========================================================================*//* Download startup parameters to the card and command it to read them       */static int dl_startup_params(struct net_device *dev){    int ccsindex;    ray_dev_t *local = (ray_dev_t *)dev->priv;    struct ccs __iomem *pccs;    dev_link_t *link = local->finder;    DEBUG(1,"dl_startup_params entered\n");    if (!(link->state & DEV_PRESENT)) {        DEBUG(2,"ray_cs dl_startup_params - device not present\n");        return -1;    }        /* Copy parameters to host to ECF area */    if (local->fw_ver == 0x55)         memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4,               sizeof(struct b4_startup_params));    else        memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5,               sizeof(struct b5_startup_params));        /* Fill in the CCS fields for the ECF */    if ((ccsindex = get_free_ccs(local)) < 0) return -1;    local->dl_param_ccs = ccsindex;    pccs = ccs_base(local) + ccsindex;    writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd);    DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs);    /* Interrupt the firmware to process the command */    if (interrupt_ecf(local, ccsindex)) {        printk(KERN_INFO "ray dl_startup_params failed - "           "ECF not ready for intr\n");        local->card_status = CARD_DL_PARAM_ERROR;        writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);        return -2;    }    local->card_status = CARD_DL_PARAM;    /* Start kernel timer to wait for dl startup to complete. */    local->timer.expires = jiffies + HZ/2;    local->timer.data = (long)local;    local->timer.function = &verify_dl_startup;    add_timer(&local->timer);    DEBUG(2,"ray_cs dl_startup_params started timer for verify_dl_startup\n");    return 0;} /* dl_startup_params *//*===========================================================================*/static void init_startup_params(ray_dev_t *local){    int i;     if (country > JAPAN_TEST) country = USA;    else        if (country < USA) country = USA;    /* structure for hop time and beacon period is defined here using      * New 802.11D6.1 format.  Card firmware is still using old format     * until version 6.     *    Before                    After     *    a_hop_time ms byte        a_hop_time ms byte     *    a_hop_time 2s byte        a_hop_time ls byte     *    a_hop_time ls byte        a_beacon_period ms byte     *    a_beacon_period           a_beacon_period ls byte     *     *    a_hop_time = uS           a_hop_time = KuS     *    a_beacon_period = hops    a_beacon_period = KuS     */                             /* 64ms = 010000 */    if (local->fw_ver == 0x55)  {        memcpy((UCHAR *)&local->sparm.b4, b4_default_startup_parms,                sizeof(struct b4_startup_params));        /* Translate sane kus input values to old build 4/5 format */        /* i = hop time in uS truncated to 3 bytes */        i = (hop_dwell * 1024) & 0xffffff;        local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff;        local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff;        local->sparm.b4.a_beacon_period[0] = 0;        local->sparm.b4.a_beacon_period[1] =            ((beacon_period/hop_dwell) - 1) & 0xff;        local->sparm.b4.a_curr_country_code = country;        local->sparm.b4.a_hop_pattern_length =             hop_pattern_length[(int)country] - 1;        if (bc)        {            local->sparm.b4.a_ack_timeout = 0x50;            local->sparm.b4.a_sifs = 0x3f;        }    }    else {    /* Version 5 uses real kus values */        memcpy((UCHAR *)&local->sparm.b5, b5_default_startup_parms,                sizeof(struct b5_startup_params));        local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff;        local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff;        local->sparm.b5.a_beacon_period[0] = (beacon_period >> 8) & 0xff;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -