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

📄 wavelan.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
      break;    case SIOCGIWNWID:      /* Read the NWID */      psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,	       (unsigned char *)psa.psa_nwid, 3);      wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];      wrq->u.nwid.on = psa.psa_nwid_select;      break;    case SIOCSIWFREQ:      /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */      if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &	   (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))	ret = wv_set_frequency(ioaddr, &(wrq->u.freq));      else	ret = -EOPNOTSUPP;      break;    case SIOCGIWFREQ:      /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)       * (does it work for everybody ??? - especially old cards...) */      if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &	   (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))	{	  unsigned short	freq;	  /* Ask the EEPROM to read the frequency from the first area */	  fee_read(ioaddr, 0x00 /* 1st area - frequency... */,		   &freq, 1);	  wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;	  wrq->u.freq.e = 1;	}      else	{	  int	bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };	  psa_read(ioaddr, lp->hacr, (char *)&psa.psa_subband - (char *)&psa,		   (unsigned char *)&psa.psa_subband, 1);	  if(psa.psa_subband <= 4)	    {	      wrq->u.freq.m = bands[psa.psa_subband];	      wrq->u.freq.e = (psa.psa_subband != 0);	    }	  else	    ret = -EOPNOTSUPP;	}      break;    case SIOCSIWSENS:      /* Set the level threshold */      if(!suser())	return -EPERM;      psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,	       (unsigned char *) &psa.psa_thr_pre_set, 1);      mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);      break;    case SIOCGIWSENS:      /* Read the level threshold */      psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,	       (unsigned char *) &psa.psa_thr_pre_set, 1);      wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;      break;     case SIOCSIWENCODE:       /* Set encryption key */       if(!mmc_encr(ioaddr))	 {	   ret = -EOPNOTSUPP;	   break;	 }       if(wrq->u.encoding.method)	 {	/* enable encryption */	   int		i;	   long long	key = wrq->u.encoding.code;	   for(i = 7; i >= 0; i--)	     {	       psa.psa_encryption_key[i] = key & 0xFF;	       key >>= 8;	     }           psa.psa_encryption_select = 1;	   psa_write(ioaddr, lp->hacr,		     (char *) &psa.psa_encryption_select - (char *) &psa,		     (unsigned char *) &psa.psa_encryption_select, 8+1);           mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),		   MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);           mmc_write(ioaddr, mmwoff(0, mmw_encr_key),		     (unsigned char *) &psa.psa_encryption_key, 8);	 }       else	 {	/* disable encryption */	   psa.psa_encryption_select = 0;	   psa_write(ioaddr, lp->hacr,		     (char *) &psa.psa_encryption_select - (char *) &psa,		     (unsigned char *) &psa.psa_encryption_select, 1);	   mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);	 }       break;     case SIOCGIWENCODE:       /* Read the encryption key */       if(!mmc_encr(ioaddr))	 {	   ret = -EOPNOTSUPP;	   break;	 }       /* only super-user can see encryption key */       if(!suser())	 {	   ret = -EPERM;	   break;	 }       else	 {	   int		i;	   long long	key = 0;	   psa_read(ioaddr, lp->hacr,		    (char *) &psa.psa_encryption_select - (char *) &psa,		    (unsigned char *) &psa.psa_encryption_select, 1+8);	   for(i = 0; i < 8; i++)	     {	       key <<= 8;	       key += psa.psa_encryption_key[i];	     }	   wrq->u.encoding.code = key;	   /* encryption is enabled */	   if(psa.psa_encryption_select)	     wrq->u.encoding.method = mmc_encr(ioaddr);	   else	     wrq->u.encoding.method = 0;	 }       break;    case SIOCGIWRANGE:      /* basic checking */      if(wrq->u.data.pointer != (caddr_t) 0)	{	  struct iw_range	range;	  /* Verify the user buffer */	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,			    sizeof(struct iw_range));	  if(ret)	    break;	  /* Set the length (useless : its constant...) */	  wrq->u.data.length = sizeof(struct iw_range);	  /* Set information in the range struct */	  range.throughput = 1.6 * 1024 * 1024;	/* don't argue on this ! */	  range.min_nwid = 0x0000;	  range.max_nwid = 0xFFFF;	  /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */	  if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &	       (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))	    {	      range.num_channels = 10;	      range.num_frequency = wv_frequency_list(ioaddr, range.freq,						      IW_MAX_FREQUENCIES);	    }	  else	    range.num_channels = range.num_frequency = 0;	  range.sensitivity = 0x3F;	  range.max_qual.qual = MMR_SGNL_QUAL;	  range.max_qual.level = MMR_SIGNAL_LVL;	  range.max_qual.noise = MMR_SILENCE_LVL;	  /* Copy structure to the user buffer */	  copy_to_user(wrq->u.data.pointer, &range,		       sizeof(struct iw_range));	}      break;    case SIOCGIWPRIV:      /* Basic checking... */      if(wrq->u.data.pointer != (caddr_t) 0)	{	  struct iw_priv_args	priv[] =	  {	/* cmd,		set_args,	get_args,	name */	    { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },	    { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },	    { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,	0, "sethisto" },	    { SIOCGIPHISTO, 0,	    IW_PRIV_TYPE_INT | 16, "gethisto" },	  };	  /* Verify the user buffer */	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,			    sizeof(priv));	  if(ret)	    break;	  /* Set the number of ioctl available */	  wrq->u.data.length = 4;	  /* Copy structure to the user buffer */	  copy_to_user(wrq->u.data.pointer, (u_char *) priv,		       sizeof(priv));	}      break;#ifdef WIRELESS_SPY    case SIOCSIWSPY:      /* Set the spy list */      /* Check the number of addresses */      if(wrq->u.data.length > IW_MAX_SPY)	{	  ret = -E2BIG;	  break;	}      lp->spy_number = wrq->u.data.length;      /* If there is some addresses to copy */      if(lp->spy_number > 0)	{	  struct sockaddr	address[IW_MAX_SPY];	  int			i;	  /* Verify where the user has set his addresses */	  ret = verify_area(VERIFY_READ, wrq->u.data.pointer,			    sizeof(struct sockaddr) * lp->spy_number);	  if(ret)	    break;	  /* Copy addresses to the driver */	  copy_from_user(address, wrq->u.data.pointer,			 sizeof(struct sockaddr) * lp->spy_number);	  /* Copy addresses to the lp structure */	  for(i = 0; i < lp->spy_number; i++)	    {	      memcpy(lp->spy_address[i], address[i].sa_data,		     WAVELAN_ADDR_SIZE);	    }	  /* Reset structure... */	  memset(lp->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 < wrq->u.data.length; i++)	    printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n",		   lp->spy_address[i][0],		   lp->spy_address[i][1],		   lp->spy_address[i][2],		   lp->spy_address[i][3],		   lp->spy_address[i][4],		   lp->spy_address[i][5]);#endif	/* DEBUG_IOCTL_INFO */	}      break;    case SIOCGIWSPY:      /* Get the spy list and spy stats */      /* Set the number of addresses */      wrq->u.data.length = lp->spy_number;      /* If the user want to have the addresses back... */      if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))	{	  struct sockaddr	address[IW_MAX_SPY];	  int			i;	  /* Verify the user buffer */	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,			    (sizeof(iw_qual) + sizeof(struct sockaddr))			    * IW_MAX_SPY);	  if(ret)	    break;	  /* Copy addresses from the lp structure */	  for(i = 0; i < lp->spy_number; i++)	    {	      memcpy(address[i].sa_data, lp->spy_address[i],		     WAVELAN_ADDR_SIZE);	      address[i].sa_family = AF_UNIX;	    }	  /* Copy addresses to the user buffer */	  copy_to_user(wrq->u.data.pointer, address,		       sizeof(struct sockaddr) * lp->spy_number);	  /* Copy stats to the user buffer (just after) */	  copy_to_user(wrq->u.data.pointer +		       (sizeof(struct sockaddr) * lp->spy_number),		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);	  /* Reset updated flags */	  for(i = 0; i < lp->spy_number; i++)	    lp->spy_stat[i].updated = 0x0;	}	/* if(pointer != NULL) */      break;#endif	/* WIRELESS_SPY */      /* ------------------ PRIVATE IOCTL ------------------ */    case SIOCSIPQTHR:      if(!suser())	return -EPERM;      psa.psa_quality_thr = *(wrq->u.name) & 0x0F;      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,	       (unsigned char *)&psa.psa_quality_thr, 1);      mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);      break;    case SIOCGIPQTHR:      psa_read(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,	       (unsigned char *)&psa.psa_quality_thr, 1);      *(wrq->u.name) = psa.psa_quality_thr & 0x0F;      break;#ifdef HISTOGRAM    case SIOCSIPHISTO:      /* Verif if the user is root */      if(!suser())	return -EPERM;      /* Check the number of intervals */      if(wrq->u.data.length > 16)	{	  ret = -E2BIG;	  break;	}      lp->his_number = wrq->u.data.length;      /* If there is some addresses to copy */      if(lp->his_number > 0)	{	  /* Verify where the user has set his addresses */	  ret = verify_area(VERIFY_READ, wrq->u.data.pointer,			    sizeof(char) * lp->his_number);	  if(ret)	    break;	  /* Copy interval ranges to the driver */	  copy_from_user(lp->his_range, wrq->u.data.pointer,			 sizeof(char) * lp->his_number);	  /* Reset structure... */	  memset(lp->his_sum, 0x00, sizeof(long) * 16);	}      break;    case SIOCGIPHISTO:      /* Set the number of intervals */      wrq->u.data.length = lp->his_number;      /* Give back the distribution statistics */      if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))	{	  /* Verify the user buffer */	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,			    sizeof(long) * 16);	  if(ret)	    break;	  /* Copy data to the user buffer */	  copy_to_user(wrq->u.data.pointer, lp->his_sum,		       sizeof(long) * lp->his_number);	}	/* if(pointer != NULL) */      break;#endif	/* HISTOGRAM */      /* ------------------- OTHER IOCTL ------------------- */    default:      ret = -EOPNOTSUPP;    }  /* Enable interrupts, restore flags */  wv_splx(x);#ifdef DEBUG_IOCTL_TRACE  printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);#endif  return ret;}/*------------------------------------------------------------------*//* * Get wireless statistics * Called by /proc/net/wireless */static iw_stats *wavelan_get_wireless_stats(device *	dev){  u_long		ioaddr = dev->base_addr;  net_local *		lp = (net_local *) dev->priv;  mmr_t			m;  iw_stats *		wstats;  unsigned long		x;#ifdef DEBUG_IOCTL_TRACE  printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);#endif  /* Disable interrupts & save flags */  x = wv_splhi();  if(lp == (net_local *) NULL)    return (iw_stats *) NULL;  wstats = &lp->wstats;  /* Get data from the mmc */  mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);  mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1);  mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2);  mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4);  mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);  /* Copy data to wireless stuff */  wstats->status = m.mmr_dce_status;  wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;  wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;  wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;  wstats->qual.updated = (((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) |			  ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) |			  ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5));  wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;  wstats->discard.code = 0L;  wstats->discard.misc = 0L;  /* Enable interrupts & restore flags */  wv_splx(x);#ifdef DEBUG_IOCTL_TRACE  printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);#endif  return &lp->wstats;}#endif	/* WIRELESS_EXT *//************************* PACKET RECEPTION *************************//* * This part deals with receiving the packets. * The interrupt handler gets an interrupt when a packet has been * successfully received and calls this part. *//*------------------------------------------------------------------*//* * This routine does the actual copying of data (including the Ethernet * header structure) from the WaveLAN card to an sk_buff chain that * will be passed up to the network interface layer. NOTE: we * currently don't handle trailer protocols (neither does the rest of * the network interface), so if that is needed, it will (at least in * part) be added here.  The contents of the receive ring buffer are * copied to a message chain that is then passed to the kernel. * * Note: if any errors occur, the packet is "dropped on the floor" * (called by wv_packet_rcv()) */static inline voidwv_packet_read(device *		dev,	       u_short		buf_off,	       int		sksize){  net_local *		lp = (net_local *) dev->priv;  u_long		ioaddr = dev->base_addr;

⌨️ 快捷键说明

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