📄 ray_cs.c
字号:
case ECARDGONE: netif_stop_queue(dev); return XMIT_NO_CCS; default: break; } addr = TX_BUF_BASE + (ccsindex << 11); if (msg_type == DATA_TYPE) { local->stats.tx_bytes += len; local->stats.tx_packets++; } ptx = (struct tx_msg *)(local->sram + addr); ray_build_header(local, ptx, msg_type, data); if (translate) { offset = translate_frame(local, ptx, data, len); } else { /* Encapsulate frame */ /* TBD TIB length will move address of ptx->var */ memcpy_toio(&ptx->var, data, len); offset = 0; } /* fill in the CCS */ pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; len += TX_HEADER_LENGTH + offset; writeb(CCS_TX_REQUEST, &pccs->cmd); writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]); writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]); writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]);/* TBD still need psm_cam? */ writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode); writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate); writeb(0, &pccs->var.tx_request.antenna); DEBUG(3,"ray_hw_xmit default_tx_rate = 0x%x\n",\ local->net_default_tx_rate); /* Interrupt the firmware to process the command */ if (interrupt_ecf(local, ccsindex)) { DEBUG(2,"ray_hw_xmit failed - ECF not ready for intr\n");/* TBD very inefficient to copy packet to buffer, and then not send it, but the alternative is to queue the messages and that won't be done for a while. Maybe set tbusy until a CCS is free?*/ writeb(CCS_BUFFER_FREE, &pccs->buffer_status); return XMIT_NO_INTR; } return XMIT_OK;} /* end ray_hw_xmit *//*===========================================================================*/static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, int len){ unsigned short int proto = ((struct ethhdr *)data)->h_proto; if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ DEBUG(3,"ray_cs translate_frame DIX II\n"); /* Copy LLC header to card buffer */ memcpy_toio((UCHAR *)&ptx->var, eth2_llc, sizeof(eth2_llc)); memcpy_toio( ((UCHAR *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2); if ((proto == 0xf380) || (proto == 0x3781)) { /* This is the selective translation table, only 2 entries */ writeb(0xf8, (UCHAR *) &((struct snaphdr_t *)ptx->var)->org[3]); } /* Copy body of ethernet packet without ethernet header */ memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \ data + ETH_HLEN, len - ETH_HLEN); return (int) sizeof(struct snaphdr_t) - ETH_HLEN; } else { /* already 802 type, and proto is length */ DEBUG(3,"ray_cs translate_frame 802\n"); if (proto == 0xffff) { /* evil netware IPX 802.3 without LLC */ DEBUG(3,"ray_cs translate_frame evil IPX\n"); memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN, len - ETH_HLEN); return 0 - ETH_HLEN; } memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN, len - ETH_HLEN); return 0 - ETH_HLEN; } /* TBD do other frame types */} /* end translate_frame *//*===========================================================================*/static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, unsigned char *data){ writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1);/*** IEEE 802.11 Address field assignments ************* TODS FROMDS addr_1 addr_2 addr_3 addr_4Adhoc 0 0 dest src (terminal) BSSID N/AAP to Terminal 0 1 dest AP(BSSID) source N/ATerminal to AP 1 0 AP(BSSID) src (terminal) dest N/AAP to AP 1 1 dest AP src AP dest source *******************************************************/ if (local->net_type == ADHOC) { writeb(0, &ptx->mac.frame_ctl_2); memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, 2 * ADDRLEN); memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); } else /* infrastructure */ { if (local->sparm.b4.a_acting_as_ap_status) { writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2); memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, ADDRLEN); memcpy_toio(ptx->mac.addr_2, local->bss_id, 6); memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_source, ADDRLEN); } else /* Terminal */ { writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2); memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN); memcpy_toio(ptx->mac.addr_2, ((struct ethhdr *)data)->h_source, ADDRLEN); memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_dest, ADDRLEN); } }} /* end encapsulate_frame *//*===========================================================================*/static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){ ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; int err = 0;#if WIRELESS_EXT > 7 struct iwreq *wrq = (struct iwreq *) ifr;#endif /* WIRELESS_EXT > 7 */ if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_dev_ioctl - device not present\n"); return -1; } DEBUG(2,"ray_cs IOCTL dev=%p, ifr=%p, cmd = 0x%x\n",dev,ifr,cmd); /* Validate the command */ switch (cmd) {#if WIRELESS_EXT > 7 /* --------------- WIRELESS EXTENSIONS --------------- */ /* Get name */ case SIOCGIWNAME: strcpy(wrq->u.name, "IEEE 802.11-FH"); break; /* Get frequency/channel */ case SIOCGIWFREQ: wrq->u.freq.m = local->sparm.b5.a_hop_pattern; wrq->u.freq.e = 0; break; /* Get current network name (ESSID) */ case SIOCGIWESSID: if (wrq->u.data.pointer) { char essid[IW_ESSID_MAX_SIZE + 1]; /* Get the essid that was set */ memcpy(essid, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); essid[IW_ESSID_MAX_SIZE] = '\0'; /* Push it out ! */ wrq->u.data.length = strlen(essid) + 1; wrq->u.data.flags = 1; /* active */ copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)); } break; /* Get current Access Point (BSSID in our case) */ case SIOCGIWAP: memcpy(wrq->u.ap_addr.sa_data, local->bss_id, ETH_ALEN); wrq->u.ap_addr.sa_family = ARPHRD_ETHER; break; /* Get the current bit-rate */ case SIOCGIWRATE: if(local->net_default_tx_rate == 3) wrq->u.bitrate.value = 2000000; /* Hum... */ else wrq->u.bitrate.value = local->net_default_tx_rate * 500000; wrq->u.bitrate.fixed = 0; /* We are in auto mode */ break; /* Set the desired bit-rate */ case SIOCSIWRATE: /* Check if rate is in range */ if((wrq->u.bitrate.value != 1000000) && (wrq->u.bitrate.value != 2000000)) { err = -EINVAL; break; } /* Hack for 1.5 Mb/s instead of 2 Mb/s */ if((local->fw_ver == 0x55) && /* Please check */ (wrq->u.bitrate.value == 2000000)) local->net_default_tx_rate = 3; else local->net_default_tx_rate = wrq->u.bitrate.value/500000; break; /* Get the current RTS threshold */ case SIOCGIWRTS: wrq->u.rts.value = (local->sparm.b5.a_rts_threshold[0] << 8) + local->sparm.b5.a_rts_threshold[1];#if WIRELESS_EXT > 8 wrq->u.rts.disabled = (wrq->u.rts.value == 32767);#endif /* WIRELESS_EXT > 8 */ wrq->u.rts.fixed = 1; break; /* Get the current fragmentation threshold */ case SIOCGIWFRAG: wrq->u.frag.value = (local->sparm.b5.a_frag_threshold[0] << 8) + local->sparm.b5.a_frag_threshold[1];#if WIRELESS_EXT > 8 wrq->u.frag.disabled = (wrq->u.frag.value == 32767);#endif /* WIRELESS_EXT > 8 */ wrq->u.frag.fixed = 1; break;#endif /* WIRELESS_EXT > 7 */#if WIRELESS_EXT > 8 /* Get the current mode of operation */ case SIOCGIWMODE: if(local->sparm.b5.a_network_type) wrq->u.mode = IW_MODE_INFRA; else wrq->u.mode = IW_MODE_ADHOC; break;#endif /* WIRELESS_EXT > 8 */#if WIRELESS_EXT > 7 /* ------------------ IWSPY SUPPORT ------------------ */ /* Define the range (variations) of above parameters */ case SIOCGIWRANGE: /* Basic checking... */ if(wrq->u.data.pointer != (caddr_t) 0) { struct iw_range range; memset((char *) &range, 0, sizeof(struct iw_range)); /* Set the length (very important for backward compatibility) */ wrq->u.data.length = sizeof(struct iw_range);#if WIRELESS_EXT > 10 /* Set the Wireless Extension versions */ range.we_version_compiled = WIRELESS_EXT; range.we_version_source = 9;#endif /* WIRELESS_EXT > 10 */ /* Set information in the range struct */ range.throughput = 1.1 * 1000 * 1000; /* Put the right number here */ range.num_channels = hop_pattern_length[(int)country]; range.num_frequency = 0; range.max_qual.qual = 0; range.max_qual.level = 255; /* What's the correct value ? */ range.max_qual.noise = 255; /* Idem */ range.num_bitrates = 2; range.bitrate[0] = 1000000; /* 1 Mb/s */ range.bitrate[1] = 2000000; /* 2 Mb/s */ /* Copy structure to the user buffer */ if(copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) err = -EFAULT; } break;#ifdef WIRELESS_SPY /* Set addresses to spy */ case SIOCSIWSPY: /* Check the number of addresses */ if(wrq->u.data.length > IW_MAX_SPY) { err = -E2BIG; break; } local->spy_number = wrq->u.data.length; /* If there is some addresses to copy */ if(local->spy_number > 0) { struct sockaddr address[IW_MAX_SPY]; int i; /* Copy addresses to the driver */ if(copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * local->spy_number)) { err = -EFAULT; break; } /* Copy addresses to the lp structure */ for(i = 0; i < local->spy_number; i++) memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN); /* Reset structure... */ memset(local->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);#ifdef DEBUG_IOCTL_INFO printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n"); for(i = 0; i < local->spy_number; i++) printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n", local->spy_address[i][0], local->spy_address[i][1], local->spy_address[i][2], local->spy_address[i][3], local->spy_address[i][4], local->spy_address[i][5]);#endif /* DEBUG_IOCTL_INFO */ } break; /* Get the spy list and spy stats */ case SIOCGIWSPY: /* Set the number of addresses */ wrq->u.data.length = local->spy_number; /* If the user want to have the addresses back... */ if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) { struct sockaddr address[IW_MAX_SPY]; int i; /* Copy addresses from the lp structure */ for(i = 0; i < local->spy_number; i++) { memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN); address[i].sa_family = ARPHRD_ETHER; } /* Copy addresses to the user buffer */ if(copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number)) { err = -EFAULT; break; } /* Copy stats to the user buffer (just after) */ if(copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr) * local->spy_number), local->spy_stat, sizeof(iw_qual) * local->spy_number)) { err = -EFAULT; break; } /* Reset updated flags */ for(i = 0; i < local->spy_number; i++) local->spy_stat[i].updated = 0x0; } /* if(pointer != NULL) */ break;#endif /* WIRELESS_SPY */ /* ------------------ PRIVATE IOCTL ------------------ */#ifndef SIOCIWFIRSTPRIV#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE#endif /* SIOCIWFIRSTPRIV */#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ case SIOCSIPFRAMING: if(!capable(CAP_NET_ADMIN)) /* For private IOCTLs, we need to check permissions */ { err = -EPERM; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -