📄 ray_cs.c
字号:
* 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; local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff; if (psm) local->sparm.b5.a_power_mgt_state = 1; local->sparm.b5.a_curr_country_code = country; local->sparm.b5.a_hop_pattern_length = hop_pattern_length[(int)country]; } local->sparm.b4.a_network_type = net_type & 0x01; local->sparm.b4.a_acting_as_ap_status = TYPE_STA; if (essid != NULL) strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);} /* init_startup_params */ /*===========================================================================*/static void verify_dl_startup(u_long data){ ray_dev_t *local = (ray_dev_t *)data; struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs; UCHAR status; dev_link_t *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); return; } spin_lock(&local->ray_lock);#ifdef PCMCIA_DEBUG if (pc_debug > 2) { int i; printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n", local->dl_param_ccs); for (i=0; i<sizeof(struct b5_startup_params); i++) { printk(" %2x", (unsigned int) readb(local->sram + HOST_TO_ECF_BASE + i)); } printk("\n"); }#endif status = readb(&pccs->buffer_status); if (status!= CCS_BUFFER_FREE) { printk(KERN_INFO "Download startup params failed. Status = %d\n", status); local->card_status = CARD_DL_PARAM_ERROR; spin_unlock(&local->ray_lock); return; } if (local->sparm.b4.a_network_type == ADHOC) start_net((u_long)local); else join_net((u_long)local); spin_unlock(&local->ray_lock); return;} /* end verify_dl_startup *//*===========================================================================*//* Command card to start a network */static void start_net(u_long data){ ray_dev_t *local = (ray_dev_t *)data; struct ccs *pccs; int ccsindex; dev_link_t *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs start_net - device not present\n"); return; } /* Fill in the CCS fields for the ECF */ if ((ccsindex = get_free_ccs(local)) < 0) return; pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; writeb(CCS_START_NETWORK, &pccs->cmd); writeb(0, &pccs->var.start_network.update_param); /* Interrupt the firmware to process the command */ if (interrupt_ecf(local, ccsindex)) { DEBUG(1,"ray start net failed - card not ready for intr\n"); writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); return; } local->card_status = CARD_DOING_ACQ; return;} /* end start_net *//*===========================================================================*//* Command card to join a network */static void join_net(u_long data){ ray_dev_t *local = (ray_dev_t *)data; struct ccs *pccs; int ccsindex; dev_link_t *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs join_net - device not present\n"); return; } /* Fill in the CCS fields for the ECF */ if ((ccsindex = get_free_ccs(local)) < 0) return; pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; writeb(CCS_JOIN_NETWORK, &pccs->cmd); writeb(0, &pccs->var.join_network.update_param); writeb(0, &pccs->var.join_network.net_initiated); /* Interrupt the firmware to process the command */ if (interrupt_ecf(local, ccsindex)) { DEBUG(1,"ray join net failed - card not ready for intr\n"); writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); return; } local->card_status = CARD_DOING_ACQ; return;}/*============================================================================ After a card is removed, ray_release() will unregister the net device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed.=============================================================================*/static void ray_release(u_long arg){ dev_link_t *link = (dev_link_t *)arg; struct net_device *dev = link->priv; ray_dev_t *local = dev->priv; int i; DEBUG(1, "ray_release(0x%p)\n", link); /* If the device is currently in use, we won't release until it is actually closed. */ if (link->open) { DEBUG(1, "ray_cs: release postponed, '%s' still open\n", link->dev->dev_name); link->state |= DEV_STALE_CONFIG; return; } del_timer(&local->timer); link->state &= ~DEV_CONFIG; iounmap(local->sram); iounmap(local->rmem); iounmap(local->amem); /* Do bother checking to see if these succeed or not */ i = CardServices(ReleaseWindow, link->win); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i); i = CardServices(ReleaseWindow, local->amem_handle); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); i = CardServices(ReleaseWindow, local->rmem_handle); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); i = CardServices(ReleaseConfiguration, link->handle); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i); i = CardServices(ReleaseIRQ, link->handle, &link->irq); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); DEBUG(2,"ray_release ending\n");} /* ray_release *//*============================================================================= The card status event handler. Mostly, this schedules other stuff to run after an event is received. A CARD_REMOVAL event also sets some flags to discourage the net drivers from trying to talk to the card any more. When a CARD_REMOVAL event is received, we immediately set a flag to block future accesses to this device. All the functions that actually access the device should check this flag to make sure the card is still present.=============================================================================*/static int ray_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t *link = args->client_data; struct net_device *dev = link->priv; ray_dev_t *local = (ray_dev_t *)dev->priv; DEBUG(1, "ray_event(0x%06x)\n", event); switch (event) { case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { netif_device_detach(dev); mod_timer(&link->release, jiffies + HZ/20); del_timer(&local->timer); } break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ray_config(link); break; case CS_EVENT_PM_SUSPEND: link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) netif_device_detach(dev); CardServices(ReleaseConfiguration, link->handle); } break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { ray_reset(dev); netif_device_attach(dev); } } break; } DEBUG(2,"ray_event ending\n"); return 0;} /* ray_event *//*===========================================================================*/int init_module(void){ int rc; servinfo_t serv; printk(KERN_INFO "%s\n", rcsid); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "ray: Card Services release does not match!\n"); return -EINVAL; } rc = register_pcmcia_driver(&dev_info, &ray_attach, &ray_detach); DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc); register_symtab(&ray_cs_syms);#ifdef HAS_PROC_BUS create_proc_read_entry("ray_cs", 0, &proc_root, ray_cs_proc_read, NULL);#endif if (translate != 0) translate = 1;#ifdef PCMCIA_DEBUG if (ray_debug != 0) pc_debug = ray_debug;#endif return 0;} /* init_module *//*===========================================================================*/void cleanup_module(void){ DEBUG(0, "ray_cs: cleanup_module\n"); unregister_pcmcia_driver(&dev_info); while (dev_list != NULL) ray_detach(dev_list);#ifdef HAS_PROC_BUS remove_proc_entry("ray_cs", &proc_root);#endif} /* cleanup_module *//*===========================================================================*/static int ray_dev_init(struct net_device *dev){#ifdef RAY_IMMEDIATE_INIT int i;#endif /* RAY_IMMEDIATE_INIT */ ray_dev_t *local = dev->priv; dev_link_t *link = local->finder; DEBUG(1,"ray_dev_init(dev=%p)\n",dev); if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_dev_init - device not present\n"); return -1; } spin_lock(&local->ray_lock);#ifdef RAY_IMMEDIATE_INIT /* Download startup parameters */ if ( (i = dl_startup_params(dev)) < 0) { printk(KERN_INFO "ray_dev_init dl_startup_params failed - " "returns 0x%x\n",i); spin_unlock(&local->ray_lock); return -1; }#else /* RAY_IMMEDIATE_INIT */ /* Postpone the card init so that we can still configure the card, * for example using the Wireless Extensions. The init will happen * in ray_open() - Jean II */ DEBUG(1,"ray_dev_init: postponing card init to ray_open() ; Status = %d\n", local->card_status);#endif /* RAY_IMMEDIATE_INIT */ /* copy mac and broadcast addresses to linux device */ memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); memset(dev->broadcast, 0xff, ETH_ALEN); DEBUG(2,"ray_dev_init ending\n"); spin_unlock(&local->ray_lock); return 0;}/*===========================================================================*/static int ray_dev_config(struct net_device *dev, struct ifmap *map){ ray_dev_t *local = dev->priv; dev_link_t *link = local->finder; /* Dummy routine to satisfy device structure */ DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); if (!DEV_OK(link)) { DEBUG(2,"ray_dev_config - device not present\n"); return -1; } return 0;}/*===========================================================================*/static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev){ ray_dev_t *local = dev->priv; dev_link_t *link = local->finder; short length; if (!DEV_OK(link)) { DEBUG(2,"ray_dev_start_xmit - device not present\n"); return -1; } DEBUG(3,"ray_dev_start_xmit(skb=%p, dev=%p)\n",skb,dev);#ifndef HAVE_NETIF_QUEUE if (netif_queue_stopped(dev)) { printk(KERN_NOTICE "ray_dev_start_xmit busy\n"); return 1; }#endif skb_tx_check(dev, skb);#ifdef __SMP__ disable_irq(dev->irq);#endif spin_lock(&local->ray_lock); if (local->authentication_state == NEED_TO_AUTH) { DEBUG(0,"ray_cs Sending authentication request.\n"); if (!build_auth_frame (local, local->auth_id, OPEN_AUTH_REQUEST)) { local->authentication_state = AUTHENTICATED; netif_stop_queue(dev); spin_unlock(&local->ray_lock);#ifdef __SMP__ enable_irq(dev->irq);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -