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

📄 smc_probe.c

📁 Analog公司的ADSP_BF532上面实现以太网接口的源码
💻 C
字号:
static int smc_probe()
{
   int i, memory, retval;
   static unsigned version_printed = 0;
   unsigned int   bank;

        const char *version_string;

   /*registers */
   word  revision_register;
   word  base_address_register;
   word     memory_info_register;
   /*=> Pramod */
   struct smc_local *lp;
   /*<= Pramod */

   PRINTK2("CARDNAME:smc_probe\n");

   /* Grab the region so that no one else tries to probe our ioports. */
   if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) return -EBUSY;

   /* First, see if the high byte is 0x33 */
   bank = inw( ioaddr + BANK_SELECT );
   if ( (bank & 0xFF00) != 0x3300 ) return -ENODEV;

   /* The above MIGHT indicate a device, but I need to write to further test this.  */
   outw( 0x0, ioaddr + BANK_SELECT );
   bank = inw( ioaddr + BANK_SELECT );
   if ( (bank & 0xFF00 ) != 0x3300 )
   {
      retval = -ENODEV;
      goto err_out;
   }

   /* well, we've already written once, so hopefully another time won't
      hurt.  This time, I need to switch the bank register to bank 1,
      so I can access the base address register */
   SMC_SELECT_BANK(1);
   base_address_register = inw( ioaddr + BASE_REG );
   if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) )
   {
      printk("CARDNAME: IOADDR %x doesn't match configuration (%x)."
         "Probably not a SMC chip\n",
         ioaddr, base_address_register >> 3 & 0x3E0 );
      /* well, the base address register didn't match.  Must not have
         been a SMC chip after all. */
      retval = -ENODEV;
      goto err_out;
   }

   /*  check if the revision register is something that I recognize.
       These might need to be added to later, as future revisions
       could be added.  */
   SMC_SELECT_BANK(3);
   revision_register  = inw( ioaddr + REV_REG );
   if ( !chip_ids[ ( revision_register  >> 4 ) & 0xF  ] )
   {
      /* I don't recognize this chip, so... */
      printk("CARDNAME: IO %x: Unrecognized revision register:"
         " %x, Contact author. \n",
         ioaddr, revision_register );
      retval =  -ENODEV;
      goto err_out;
   }

   /* at this point I'll assume that the chip is an SMC9xxx.
      It might be prudent to check a listing of MAC addresses
      against the hardware address, or do some other tests. */

   if (version_printed++ == 0)
      printk("%s", version);

   /* fill in some of the fields */
   dev->base_addr = ioaddr;

   /*
    . Get the MAC address ( bank 1, regs 4 - 9 )
   */
   SMC_SELECT_BANK( 1 );
   for ( i = 0; i < 6; i += 2 )
   {
      word  address;

      address = inw( ioaddr + ADDR0_REG + i  );
      dev->dev_addr[ i + 1] = address >> 8;
      dev->dev_addr[ i ] = address & 0xFF;
   }

   /* get the memory information */

   SMC_SELECT_BANK( 0 );
   memory_info_register = inw( ioaddr + MIR_REG );
   memory = memory_info_register & (word)0x00ff;
   memory *= LAN91C111_MEMORY_MULTIPLIER;

   /*
    Now, I want to find out more about the chip.  This is sort of
    redundant, but it's cleaner to have it in both, rather than having
    one VERY long probe procedure.
   */
   SMC_SELECT_BANK(3);
   revision_register  = inw( ioaddr + REV_REG );
   version_string = chip_ids[ ( revision_register  >> 4 ) & 0xF  ];
   if ( !version_string )
   {
      /* I shouldn't get here because this call was done before.... */
      retval =  -ENODEV;
      goto err_out;
   }

   /* now, reset the chip, and put it into a known state */
   smc_reset( dev );

   /*
    . If dev->irq is 0, then the device has to be banged on to see
    . what the IRQ is.
    .
    . This banging doesn't always detect the IRQ, for unknown reasons.
    . a workaround is to reset the chip and try again.
    .
    . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
    . be what is requested on the command line.   I don't do that, mostly
    . because the card that I have uses a non-standard method of accessing
    . the IRQs, and because this _should_ work in most configurations.
    .
    . Specifying an IRQ is done with the assumption that the user knows
    . what (s)he is doing.  No checking is done!!!!
    .
   */
   if ( dev->irq < 2 ) {
      int   trials;

      trials = 3;
      while ( trials-- ) {
         dev->irq = smc_findirq( ioaddr );
         if ( dev->irq )
            break;
         /* kick the card and try again */
         smc_reset( dev );
      }
   }
   if (dev->irq == 0 ) {
      printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
         dev->name);
      retval =  -ENODEV;
      goto err_out;
   }

   if (dev->irq == 2) {
      /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
       * or don't know which one to set.
       */
      dev->irq = 9;
   }

   /* now, print out the card info, in a short format.. */

   printk("%s: %s(rev:%d) at %#3x IRQ:%d MEMSIZE:%db NOWAIT:%d ",
      dev->name,
      version_string, revision_register & 0xF, ioaddr, dev->irq,
      memory, dev->dma);
   /*
    . Print the Ethernet address
   */
   printk("ADDR: ");
   for (i = 0; i < 5; i++)
      printk("%2.2x:", dev->dev_addr[i] );
   printk("%2.2x \n", dev->dev_addr[5] );


   /* Initialize the private structure. */
   if (dev->priv == NULL) {
      dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
      if (dev->priv == NULL) {
         retval = -ENOMEM;
         goto err_out;
      }
   }
   /* set the private data to zero by default */
   memset(dev->priv, 0, sizeof(struct smc_local));

   /* Fill in the fields of the device structure with ethernet values. */
   ether_setup(dev);

   /* Grab the IRQ */
    retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
    if (retval) {
           printk("%s: unable to get IRQ %d (irqval=%d).\n",
      dev->name, dev->irq, retval);
        kfree (dev->priv);
        dev->priv = NULL;
        goto err_out;
         }

   dev->open              = smc_open;
   dev->stop              = smc_close;
   dev->hard_start_xmit    = smc_wait_to_send_packet;
   dev->tx_timeout         = smc_timeout;
   dev->get_stats       = smc_query_statistics;
#ifdef   HAVE_MULTICAST
   dev->set_multicast_list    = &smc_set_multicast_list;
#endif

   /* => Store the ChipRevision and ChipID, to be used in resolving the Odd-Byte issue in RevB of LAN91C111; Pramod */
   SMC_SELECT_BANK(3);
   revision_register  = inw( ioaddr + REV_REG );
   lp = (struct smc_local *)dev->priv;
   lp->ChipID = (revision_register >> 4) & 0xF;
   lp->ChipRev = revision_register & 0xF;

   return 0;

err_out:
   release_region (ioaddr, SMC_IO_EXTENT);
   return retval;
}


⌨️ 快捷键说明

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