me8100.c
changeset 12 67e56b4bce81
parent 11 a60ff25672a0
child 13 f7fb771d7842
equal deleted inserted replaced
11:a60ff25672a0 12:67e56b4bce81
   123 
   123 
   124 
   124 
   125 /* Major Device Number. 0 means to get it automatically from the System */
   125 /* Major Device Number. 0 means to get it automatically from the System */
   126 static unsigned int major = 0;
   126 static unsigned int major = 0;
   127 
   127 
       
   128 /* The queue all the readers are on. */
       
   129 DECLARE_WAIT_QUEUE_HEAD(me8100_readq);
       
   130 
       
   131 
   128 
   132 
   129 /* Prototypes */
   133 /* Prototypes */
   130 static int me8100_open(struct inode *, struct file *);
   134 static int me8100_open(struct inode *, struct file *);
   131 static int me8100_release(struct inode *, struct file *);
   135 static int me8100_release(struct inode *, struct file *);
   132 static int me8100_ioctl(struct inode *, struct file *, 
   136 static int me8100_ioctl(struct inode *, struct file *, 
   338  *             for compatibility. (GG)
   342  *             for compatibility. (GG)
   339  *
   343  *
   340  */
   344  */
   341 static int me8100_init_board(me8100_info_type *info, 
   345 static int me8100_init_board(me8100_info_type *info, 
   342 			     struct pci_dev *pci_dev_ptr){
   346 			     struct pci_dev *pci_dev_ptr){
       
   347   int i;
   343   int result = 0;
   348   int result = 0;
   344   unsigned int plx_regbase_tmp;
   349   unsigned int plx_regbase_tmp;
   345   unsigned int me8100_regbase_tmp;
   350   unsigned int me8100_regbase_tmp;
   346   unsigned int swap_regbase_tmp;
   351   unsigned int swap_regbase_tmp;
   347   unsigned int regbase_tmp;
   352   unsigned int regbase_tmp;
   435   }
   440   }
   436   info->me8100_regbase_size = ME8100_BASE_SIZE;
   441   info->me8100_regbase_size = ME8100_BASE_SIZE;
   437   info->me8100_regbase = me8100_regbase_tmp & PCI_BASE_ADDRESS_IO_MASK;
   442   info->me8100_regbase = me8100_regbase_tmp & PCI_BASE_ADDRESS_IO_MASK;
   438   PDEBUG("me8100_init_board():IO at 0x%04X\n", info->me8100_regbase);
   443   PDEBUG("me8100_init_board():IO at 0x%04X\n", info->me8100_regbase);
   439 
   444 
   440   info->subinfo[0].regbase = info->me8100_regbase;
       
   441   info->subinfo[1].regbase = info->me8100_regbase + 0x0C;
       
   442   
       
   443 
       
   444   /*--------------------------- init device info ----------------------------*/
   445   /*--------------------------- init device info ----------------------------*/
   445 
   446 
   446   result = pci_read_config_dword(pci_dev_ptr, 0x2C, &info->serial_no);
   447   result = pci_read_config_dword(pci_dev_ptr, 0x2C, &info->serial_no);
   447   if(result != PCIBIOS_SUCCESSFUL){
   448   if(result != PCIBIOS_SUCCESSFUL){
   448     printk(KERN_ERR"ME8100:me8100_init_board:Can't get serial_no\n");
   449     printk(KERN_ERR"ME8100:me8100_init_board:Can't get serial_no\n");
   473   PDEBUG("me8100_init_board():pci_bus_no = 0x%02X\n", info->pci_bus_no);
   474   PDEBUG("me8100_init_board():pci_bus_no = 0x%02X\n", info->pci_bus_no);
   474 
   475 
   475   info->int_line = pci_dev_ptr->irq;
   476   info->int_line = pci_dev_ptr->irq;
   476   PDEBUG("me8100_init_board():int_line = %d\n", info->int_line);
   477   PDEBUG("me8100_init_board():int_line = %d\n", info->int_line);
   477 
   478 
   478   info->int_count_1 = 0;
       
   479   info->int_count_2 = 0;
       
   480   info->int1 = 0;
       
   481   info->int2 = 0;
       
   482   info->file_ptr = NULL;
   479   info->file_ptr = NULL;
   483   info->fasync_ptr = NULL;
       
   484   info->board_in_use = 0;
   480   info->board_in_use = 0;
       
   481 
       
   482   info->subinfo[0].regbase = info->me8100_regbase;
       
   483   info->subinfo[1].regbase = info->me8100_regbase + 0x0C;
       
   484 
       
   485   for (i = 0; i <= 1; ++i) {
       
   486     info->subinfo[i].int_seen = 0;
       
   487     info->subinfo[i].int_count = 0;
       
   488     info->subinfo[i].fasync_ptr = NULL;
       
   489   }
       
   490   
   485   
   491   
   486   /*--------------------------- Reset the board -----------------------------*/
   492   /*--------------------------- Reset the board -----------------------------*/
   487 
   493 
   488   result = me8100_reset_board(info);
   494   result = me8100_reset_board(info);
   489   if(result){
   495   if(result){
   579 
   585 
   580   device = DEVICE(MINOR(inode_ptr->i_rdev));
   586   device = DEVICE(MINOR(inode_ptr->i_rdev));
   581   subdevice = SUBDEVICE(MINOR(inode_ptr->i_rdev));
   587   subdevice = SUBDEVICE(MINOR(inode_ptr->i_rdev));
   582   PDEBUG("*** device: %d, subdevice %d\n", device, subdevice);
   588   PDEBUG("*** device: %d, subdevice %d\n", device, subdevice);
   583 
   589 
   584   info = &info_vec[device];
   590   if(device >= me8100_board_count){
   585   subinfo = &info->subinfo[subdevice];
   591     printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", device);
       
   592     return -ENODEV;
       
   593   }
   586 
   594 
   587   /* Currently we can't support the old style minor numbers. */
   595   /* Currently we can't support the old style minor numbers. */
   588   if (subdevice < 0) {
   596   if (subdevice < 0) {
   589     printk(KERN_ERR "ME8100:me8100_open(): Bad subdevice %d\n", subdevice);
   597     printk(KERN_ERR "ME8100:me8100_open(): Bad subdevice %d\n", subdevice);
   590     return -ENODEV;
   598     return -ENODEV;
   591   }
   599   }
   592 
   600 
   593 
   601   info = &info_vec[device];
   594   if(device >= me8100_board_count){
   602   subinfo = &info->subinfo[subdevice];
   595     printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", device);
       
   596     return -ENODEV;
       
   597   }
       
   598 
   603 
   599   MOD_INC_USE_COUNT;
   604   MOD_INC_USE_COUNT;
   600 
   605 
   601   if (file_ptr->f_mode & FMODE_WRITE) {
   606   if (file_ptr->f_mode & FMODE_WRITE) {
   602     /* If we're the first write, the control register has to be
   607     /* If we're the first writer, the control register has to be
   603      * setup properly. */
   608      * setup properly. */
   604 
   609 
   605     PDEBUG("*** open for writing\n");
   610     PDEBUG("*** open for writing\n");
   606 
   611 
   607     if (0 == subinfo->num_writer++) {
   612     if (0 == subinfo->num_writer++) {
   608       subinfo->ctrl_reg |= ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE;
   613       PDEBUG("*** first writer\n");
   609       PDEBUG("*** adding %0x to ctrl: 0x%04x\n",
   614       subinfo->ctrl_wflags = ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE;
   610 	ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE, subinfo->ctrl_reg);
   615       subinfo->ctrl_reg |= subinfo->ctrl_wflags;
       
   616       PDEBUG("*** adding 0x%0x to ctrl => 0x%04x\n",
       
   617 	subinfo->ctrl_wflags, subinfo->ctrl_reg);
   611       outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
   618       outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
   612     }
   619     }
   613   }
   620   }
   614 
   621 
   615 
   622 
   621 
   628 
   622     struct me8100_private_data *priv;
   629     struct me8100_private_data *priv;
   623 
   630 
   624     PDEBUG("*** open for reading\n");
   631     PDEBUG("*** open for reading\n");
   625 
   632 
       
   633     /* The first reader should setup the IRQs (enabling IRQ handling
       
   634      * with the full bit mask.  It might be modified later. */
   626     if (0 == subinfo->num_reader++) {
   635     if (0 == subinfo->num_reader++) {
   627       
   636       int mask = 0xffff;
       
   637       unsigned short icsr = PCI_INT_EN
       
   638 	| ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice));
   628       PDEBUG("*** first reader...\n");
   639       PDEBUG("*** first reader...\n");
   629 
   640       subinfo->ctrl_rflags = 0;
   630       if (!(priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {	  
   641 
       
   642       /* Allocate memory for the private data.  If allocating fails,
       
   643        * call m8100_release() (which in turn decrements the mod-in-use-count)
       
   644        * and return IO error. */
       
   645       if (NULL == (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {	  
   631 	printk(KERN_ERR"ME8100:me8100_open: kmalloc() failed.\n");
   646 	printk(KERN_ERR"ME8100:me8100_open: kmalloc() failed.\n");
   632 	me8100_release(inode_ptr, file_ptr); 
   647 	me8100_release(inode_ptr, file_ptr);  
   633 	return -EIO;
   648 	return -EIO;
   634       }
   649       }
   635 
   650 
   636       priv->last_read = 0;
   651       priv->last_read = 0;
   637       file_ptr->private_data = priv;
   652       file_ptr->private_data = priv;
   638 
   653 
   639       /* Now we've to setup the IRQ line.  We suppose that it should be done
   654       /* 1) setup the PLX register */
   640        * in "mask" manner.  If somebody wishes to do it the otherway or if somebody
   655       PDEBUG("*** plx = 0x%0x\n", icsr);
   641        * wants to change the mask, ioctl() should be used. */
   656       outb(icsr, info->plx_regbase + PLX_ICSR);
   642       {
   657 
   643 	int mask = 0xffff;
   658       /* 2) setup the irq flags in regbase */
   644 	unsigned short icsr = PCI_INT_EN | ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice)); 
   659       subinfo->ctrl_rflags = ME8100_CTRL_IRQ_MASK;
   645 
   660       subinfo->ctrl_reg |= subinfo->ctrl_rflags;
   646 
   661       PDEBUG("*** adding 0x%0x to ctrl => 0x%04x\n", 
   647 	/* 1) setup the PLX register */
   662 	subinfo->ctrl_rflags, subinfo->ctrl_reg);
   648 	PDEBUG("*** plx = 0x%0x\n", icsr);
   663       outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
   649 	outb(icsr, info->plx_regbase + PLX_ICSR);
   664 
   650 
   665       /* 3) setup the interrupt mask */
   651 	/* 2) setup the irq flags in regbase */
   666       PDEBUG("*** irqmask = 0x%04x\n", mask);
   652 	subinfo->ctrl_reg |= ME8100_CTRL_IRQ_MASK;
   667       outw(mask, subinfo->regbase + ME8100_MASK_REG);
   653 	PDEBUG("*** adding %0x to ctrl: 0x%04x\n", ME8100_CTRL_IRQ_MASK, 
   668 
   654 	  subinfo->ctrl_reg);
       
   655 	outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
       
   656 
       
   657 	/* 3) setup the interrupt mask */
       
   658 	PDEBUG("*** irqmask = 0x%04x\n", mask);
       
   659 	outw(mask, subinfo->regbase + ME8100_MASK_REG);
       
   660 
       
   661       }
       
   662     } /* first reader */
   669     } /* first reader */
   663   } /* reader */    
   670   } /* reader */    
   664 
   671 
   665 
   672 
   666   return 0;
   673   return 0;
   709 
   716 
   710   /* Resetting write mode if last writer is gone */
   717   /* Resetting write mode if last writer is gone */
   711   if (file_ptr->f_mode & FMODE_WRITE) {
   718   if (file_ptr->f_mode & FMODE_WRITE) {
   712     PDEBUG("*** writer closes\n");
   719     PDEBUG("*** writer closes\n");
   713     if (0 == --subinfo->num_writer) {
   720     if (0 == --subinfo->num_writer) {
   714 	subinfo->ctrl_reg &= !ME8100_CTRL_ENIO;
   721 	/*
   715 	PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg);
   722 	PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg);
       
   723 	subinfo->ctrl_reg &= !subinfo->ctrl_wflags;
       
   724 	subinfo->ctrl_wflags = 0;
   716 	outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
   725 	outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
       
   726 	*/
   717     }
   727     }
   718   }
   728   }
   719 
   729 
   720   if (file_ptr->f_mode & FMODE_READ) {
   730   if (file_ptr->f_mode & FMODE_READ) {
   721     PDEBUG("*** reader close\n");
   731     PDEBUG("*** reader close\n");
   722     if (0 == --subinfo->num_reader) {
   732     if (0 == --subinfo->num_reader) {
   723       PDEBUG("*** last reader...\n");
   733       PDEBUG("*** last reader...\n");
   724       subinfo->ctrl_reg &= !ME8100_CTRL_IRQ_MASK; /* 11 */
   734       subinfo->ctrl_reg &= !subinfo->ctrl_rflags;
       
   735       subinfo->ctrl_rflags = 0;
   725       PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg);
   736       PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg);
   726       outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
   737       outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
   727      }
   738      }
   728   }
   739   }
   729 
   740 
   735     if(err){
   746     if(err){
   736       printk(KERN_ERR"ME8100:me8100_release():Can't reset");
   747       printk(KERN_ERR"ME8100:me8100_release():Can't reset");
   737       return err;
   748       return err;
   738     }
   749     }
   739   }
   750   }
       
   751 
       
   752   /* Cleanup all async notification queues associated to the 
       
   753    * current file handle as well as free any allocated memory. */
   740   me8100_fasync(-1, file_ptr, 0);
   754   me8100_fasync(-1, file_ptr, 0);
   741   if (file_ptr->private_data) kfree(file_ptr->private_data);
   755   if (file_ptr->private_data) kfree(file_ptr->private_data);
   742   file_ptr->private_data = NULL;
   756   file_ptr->private_data = NULL;
   743 
   757 
   744   MOD_DEC_USE_COUNT;
   758   MOD_DEC_USE_COUNT;
   895  * Author: GG                                                               
   909  * Author: GG                                                               
   896  * Modufication:                                                            
   910  * Modufication:                                                            
   897  */
   911  */
   898 static int me8100_fasync(int fd, struct file *file_ptr, int mode){
   912 static int me8100_fasync(int fd, struct file *file_ptr, int mode){
   899   int val;
   913   int val;
   900   int device;
   914   int device, subdevice;
   901   me8100_info_type *info;
   915   me8100_info_type *info;
       
   916   struct me8100_subinfo *subinfo;
   902 
   917 
   903   device = DEVICE(MINOR(file_ptr->f_dentry->d_inode->i_rdev));
   918   device = DEVICE(MINOR(file_ptr->f_dentry->d_inode->i_rdev));
       
   919   subdevice = SUBDEVICE(MINOR(file_ptr->f_dentry->d_inode->i_rdev));
   904   info = &info_vec[device];
   920   info = &info_vec[device];
       
   921   subinfo = &info_vec[device].subinfo[subdevice];
   905 
   922 
   906   PDEBUG("me8100_fasync() is executed\n");
   923   PDEBUG("me8100_fasync() is executed\n");
   907   PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr);
   924   PDEBUG("** fasync_ptr: %p\n", subinfo->fasync_ptr);
   908   val = fasync_helper(fd, file_ptr, mode, &info->fasync_ptr);
   925   val = fasync_helper(fd, file_ptr, mode, &subinfo->fasync_ptr);
   909   PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr);
   926   PDEBUG("** fasync_ptr: %p\n", subinfo->fasync_ptr);
   910   return val;
   927   return val;
   911 }
   928 }
   912 
   929 
   913 
   930 
   914 
   931 
  1929 
  1946 
  1930   PDEBUG("me8100_read_int_occur() is executed\n");
  1947   PDEBUG("me8100_read_int_occur() is executed\n");
  1931 
  1948 
  1932   save_flags(flags);
  1949   save_flags(flags);
  1933   cli();
  1950   cli();
  1934   int_occur.int1 = info->int1;
  1951   int_occur.int1 = info->subinfo[0].int_seen;
  1935   int_occur.int2 = info->int2;
  1952   int_occur.int2 = info->subinfo[1].int_seen;
  1936   restore_flags(flags);
  1953   restore_flags(flags);
  1937 
  1954 
  1938   err = copy_to_user(arg, &int_occur, sizeof(int_occur));
  1955   err = copy_to_user(arg, &int_occur, sizeof(int_occur));
  1939   if(err)
  1956   if(err)
  1940     return err;
  1957     return err;
  2047 
  2064 
  2048   PDEBUG("me8100_get_int_count() is executed\n");
  2065   PDEBUG("me8100_get_int_count() is executed\n");
  2049 
  2066 
  2050   save_flags(flags);
  2067   save_flags(flags);
  2051   cli();
  2068   cli();
  2052   int_count.int1 = info->int_count_1;
  2069   int_count.int1 = info->subinfo[0].int_count;
  2053   int_count.int2 = info->int_count_2;
  2070   int_count.int2 = info->subinfo[1].int_count;
  2054   restore_flags(flags);
  2071   restore_flags(flags);
  2055 
  2072 
  2056   if(copy_to_user(arg, &int_count, sizeof(int_count)))
  2073   if(copy_to_user(arg, &int_count, sizeof(int_count)))
  2057     return -EFAULT;
  2074     return -EFAULT;
  2058   return 0;
  2075   return 0;
  2091 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){
  2108 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){
  2092   unsigned char icsr;
  2109   unsigned char icsr;
  2093   unsigned short dummy;
  2110   unsigned short dummy;
  2094   me8100_info_type *info;
  2111   me8100_info_type *info;
  2095 
  2112 
  2096   PDEBUG("*** => me8100_isr() is executed\n");
  2113   PDEBUG("=====> me8100_isr() is executed\n");
  2097 
  2114 
  2098   info = (me8100_info_type *) dev_id;
  2115   info = (me8100_info_type *) dev_id;
  2099 
  2116 
  2100   if(irq != info->int_line){
  2117   if(irq != info->int_line){
  2101     PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq);
  2118     PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq);
  2102     return;
  2119     return;
  2103   }
  2120   }
  2104 
  2121 
  2105   info->int1 = 0;
  2122   info->subinfo[0].int_seen = 0;
  2106   info->int2 = 0;
  2123   info->subinfo[1].int_seen = 0;
  2107 
  2124 
  2108   icsr = inb(info->plx_regbase + PLX_ICSR);
  2125   icsr = inb(info->plx_regbase + PLX_ICSR);
  2109 
  2126   PDEBUG("== ICSR: 0x%04x\n", icsr);
  2110   if((icsr & 0x04)&&(icsr & 0x40)&&(icsr & 0x01)){
  2127 
       
  2128 
       
  2129   /* A: 0x04 & 0x40 & 0x01 */
       
  2130   /* B: 0x20 & 0x40 & 0x08 */
       
  2131   if((icsr & 0x45) == 0x45) {
       
  2132     struct me8100_subinfo *subinfo = &info->subinfo[0];
  2111     PDEBUG("me8100_isr():Int1 occured\n");
  2133     PDEBUG("me8100_isr():Int1 occured\n");
  2112     info->int1 = 1;
  2134     subinfo->int_seen = 1;
  2113     info->int_count_1++;
  2135     subinfo->int_count++;
  2114     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); 
  2136     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); 
  2115   }
  2137     if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN);
  2116 
  2138 
  2117   if((icsr & 0x20)&&(icsr & 0x40)&&(icsr & 0x08)){
  2139   } else if((icsr & 0x68) == 0x68) {
       
  2140     struct me8100_subinfo *subinfo = &info->subinfo[1];
  2118     PDEBUG("me8100_isr():Int2 occured\n");
  2141     PDEBUG("me8100_isr():Int2 occured\n");
  2119     info->int2 = 1;
  2142     subinfo->int_seen = 1;
  2120     info->int_count_2++;
  2143     subinfo->int_count++;
  2121     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); 
  2144     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); 
  2122   }
  2145     if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN);
  2123 
  2146 
  2124   if(!(info->int1 || info->int2)){
  2147   } else {
  2125     PDEBUG("me8100_isr():Not this Board\n");
  2148     PDEBUG("me8100_isr():Not this Board\n");
  2126     return;
  2149     return;
  2127   }
  2150   }
  2128 
  2151 
  2129   if(info->fasync_ptr){
  2152   PDEBUG("*** wake up sleeper\n");
  2130     PDEBUG("*** me8100_isr():send signal to process %p->%d\n", 
  2153   /* should be splitted too (one queue for each channel) */
  2131       info->fasync_ptr, info->fasync_ptr->fa_file->f_owner.pid);
  2154   wake_up_interruptible(&me8100_readq);
  2132     kill_fasync(&info->fasync_ptr, SIGIO, POLL_IN);
       
  2133   }
       
  2134 } 
  2155 } 
  2135 
  2156 
  2136 
  2157 
  2137 
  2158 
  2138 
  2159 
  2195   minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev);
  2216   minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev);
  2196   subinfo = &info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)];
  2217   subinfo = &info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)];
  2197   
  2218   
  2198   if (len == 0) return 0;	/* do we really need this check? */
  2219   if (len == 0) return 0;	/* do we really need this check? */
  2199   if (len < 0) return -EINVAL;	/* do we really need this check? */
  2220   if (len < 0) return -EINVAL;	/* do we really need this check? */
  2200   if (priv->last_read >= subinfo->last_change) return 0;  /* nothing has changed */
  2221   if (priv->last_read > subinfo->last_change) {
       
  2222     PDEBUG("*** going to sleep\n");
       
  2223     interruptible_sleep_on(&me8100_readq);
       
  2224   }
       
  2225   priv->last_read = jiffies;
  2201 
  2226 
  2202   val = inw(subinfo->regbase + ME8100_DI_REG);
  2227   val = inw(subinfo->regbase + ME8100_DI_REG);
  2203   PDEBUG("me8100_read: val=0x%04x\n", val);
  2228   PDEBUG("me8100_read: val=0x%04x\n", val);
  2204 
  2229 
  2205   if (len >= sizeof(val)) {
  2230   if (len >= sizeof(val)) {