📄 ray_cs.c
字号:
link->irq.Handler = &ray_interrupt; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; /* Allocate space for private device-specific data */ dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); if (dev == NULL) { kfree(link); return NULL; } memset(dev, 0, sizeof(struct net_device)); link->priv = dev; link->irq.Instance = dev; local = kmalloc(sizeof(ray_dev_t), GFP_KERNEL); if (local == NULL) { kfree(dev); kfree(link); return NULL; } memset(local, 0, sizeof(ray_dev_t)); dev->priv = local; local->finder = link; local->card_status = CARD_INSERTED; local->authentication_state = UNAUTHENTICATED; local->num_multi = 0; spin_lock_init(&local->ray_lock); DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n", link,dev,local,&ray_interrupt); /* Raylink entries in the device structure */ dev->hard_start_xmit = &ray_dev_start_xmit; dev->set_config = &ray_dev_config; dev->get_stats = &ray_get_stats; dev->do_ioctl = &ray_dev_ioctl;#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */ 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"); ether_setup(dev); /* dev->mtu = 1468; */ init_dev_name(dev, local->node); dev->init = &ray_dev_init; dev->open = &ray_open; dev->stop = &ray_dev_close; /* Register with Card Services */ link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; 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 CardServices(RegisterClient...)\n"); init_timer(&local->timer); ret = CardServices(RegisterClient, &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;} /* 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(). */ del_timer(&link->release); if (link->state & DEV_CONFIG) { ray_release((u_long)link); if(link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; } } /* Break the link with Card Services */ if (link->handle) CardServices(DeregisterClient, 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); if (dev->priv) kfree(dev->priv); kfree(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, args...) \while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed#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, last_ret; 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, handle, &tuple); tuple.TupleData = buf; tuple.TupleDataMax = MAX_TUPLE_SIZE; tuple.TupleOffset = 0; CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(ParseTuple, 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, handle, &tuple); tuple.TupleData = buf; tuple.TupleDataMax = MAX_TUPLE_SIZE; tuple.TupleOffset = 2; CS_CHECK(GetTupleData, 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, 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, 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; link->win = (window_handle_t)link->handle; CS_CHECK(RequestWindow, &link->win, &req); mem.CardOffset = 0x0000; mem.Page = 0; CS_CHECK(MapMemPage, link->win, &mem); local->sram = (UCHAR *)(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; local->rmem_handle = (window_handle_t)link->handle; CS_CHECK(RequestWindow, &local->rmem_handle, &req); mem.CardOffset = 0x8000; mem.Page = 0; CS_CHECK(MapMemPage, local->rmem_handle, &mem); local->rmem = (UCHAR *)(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; local->amem_handle = (window_handle_t)link->handle; CS_CHECK(RequestWindow, &local->amem_handle, &req); mem.CardOffset = 0x0000; mem.Page = 0; CS_CHECK(MapMemPage, local->amem_handle, &mem); local->amem = (UCHAR *)(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) goto config_failed; i = register_netdev(dev); if (i != 0) { printk(KERN_INFO "ray_config register_netdev() failed\n"); goto config_failed; } copy_dev_name(local->node, dev); link->dev = &local->node; local->card_status = CARD_AWAITING_PARAM; clear_interrupt(local); /* Clear any interrupt from the card */ 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")); link->state &= ~DEV_CONFIG_PENDING; return;cs_failed: cs_error(link->handle, last_fn, last_ret);config_failed: ray_release((u_long)link); link->state &= ~DEV_CONFIG_PENDING;} /* ray_config *//*===========================================================================*/static int ray_init(struct net_device *dev){ int i; UCHAR *p; struct ccs *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)) { printk(KERN_INFO "ray_init - device not present\n"); return -1; } local->net_type = net_type; local->sta_type = TYPE_STA; spin_lock(&local->ray_lock); /* 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; spin_unlock(&local->ray_lock); 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 = (struct ccs *)(local->sram + CCS_BASE); 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; } local->card_status = CARD_AWAITING_PARAM; spin_unlock(&local->ray_lock); 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 *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 = ((struct ccs *)(local->sram + CCS_BASE)) + 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. */ del_timer(&local->timer); /* If already exist, remove */ local->timer.expires = jiffies + HZ/2; local->timer.data = (long)local; local->timer.function = &verify_dl_startup; add_timer(&local->timer); /* Parameters changed, so we need to re-authenticate */ local->authentication_state = UNAUTHENTICATED; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -