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

📄 lx_acb.c

📁 liunx 5536 accessBus
💻 C
📖 第 1 页 / 共 2 页
字号:
amd_acb_poll(struct acb_dev *dev){   int status, ret;   unsigned long tmo;   for(;;) {      tmo = jiffies + POLL_TIMEOUT;      while( jiffies < tmo ) {         status = inz(ACBST);         while( (status&(ACBST_BER|ACBST_SDAST|ACBST_NEGACK)) != 0 ) {            ret = amd_acb_machine(dev, status);            if( ret == 0 ) break;            return;         }         yield();      }      acb_reset(dev);      if( dev->msgn != 0 || dev->state != state_address ) break;      if( --dev->retries < 0 ) break;      DEBUG(3,"ACB%d RETRY %d\n",dev->index,dev->retries);      acb_start(dev);   }   DEBUG(0,"ACB%d TIMEOUT\n",dev->index);   dev->state = state_error;}#endif /* POLLED_MODE */static intamd_acb_master_xfer(struct i2c_adapter *adp, struct i2c_msg *msg, int num){   struct acb_dev *dev = adp->algo_data;   DEBUG(2,"ACB%d XFER %d MSGS\n",dev->index,num);   if( num <= 0 ) return 0;   down(&dev->sem);   acb_start(dev);   dev->last = 0;   dev->result = 0;   dev->state = state_address;   dev->count = num;   dev->msgn = 0;   for(;;) {      if( (dev->msgn+1) >= dev->count )         dev->last = 1;      dev->flags = msg->flags;      if( (dev->flags & I2C_M_TEN) != 0 ) {         DEBUG(0,"ACB%d ten bit addresses not supported\n",dev->index);         dev->result = -EIO;         break;      }      dev->bp = msg->buf;      dev->len = msg->len;      dev->addr = msg->addr;      dev->retries = adp->retries;      dev->state = state_address;      DEBUG(2,"ACB%d MSG %d %s %d bytes\n",dev->index,dev->msgn,            (dev->flags&I2C_M_RD)!=0 ? "rd" : "wr", dev->len);#ifdef POLLED_MODE      while( ((1<<dev->state) & STATE_ACTIVE) != 0 ) {         amd_acb_poll(dev);      }#else /* POLLED_MODE */#error Interrupt driven mode not implemented#endif /* POLLED_MODE */      if( dev->state == state_idle )         break;      if( dev->state != state_next ) {         if( dev->result == 0 )            dev->result = -EIO;         acb_dump(dev);	 acb_reset(dev);         break;      }      ++dev->msgn;      ++msg;   }   up(&dev->sem);   return dev->result != 0 ? dev->result : num;}#ifdef MOD_INC_USE_COUNTvoidamd_acb_inc_use(struct i2c_adapter *adapter){#ifdef MODULE   MOD_INC_USE_COUNT;#endif}#endif#ifdef MOD_DEC_USE_COUNTvoidamd_acb_dec_use(struct i2c_adapter *adapter){#ifdef MODULE   MOD_DEC_USE_COUNT;#endif}#endifstatic u32amd_acb_functionality(struct i2c_adapter *adp){   return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;}#ifdef IO_SIOCFG_IN_10#define CFG_INDEX 0x002E#define CFG_DATA  0x002F#else#define CFG_INDEX 0x015C   /* Cygnus/Krill... */#define CFG_DATA  0x015D#endif#define CFG_IDX_LDN  7#define CFG_IDX_ACBH 60#define CFG_IDX_ACBL 61#define LDN_ACB1 5         /* ACB1 (LDN 5) */#define LDN_ACB2 6         /* ACB2 (LDN 6) */static intdetect_addr_ldn(struct amd_acb_driver *s){   int i, addr, ldn, io[MAX_DEVICES];   unsigned long flags;   ldn = LDN_ACB1;   s->n_dev = 2;   /* probe addresses */   spin_lock_irqsave(&s->lock, flags);   for( i=0; i<s->n_dev; ++i ) {      outz(CFG_IDX_LDN,CFG_INDEX);      outz(ldn,CFG_DATA);      outz(CFG_IDX_ACBH,CFG_INDEX);      addr = inz(CFG_DATA) << 8;      outz(CFG_IDX_ACBL,CFG_INDEX);      addr |= inz(CFG_DATA);      if( addr == 0 ) break;      io[i] = addr;      ++ldn;   }   spin_unlock_irqrestore(&s->lock, flags);   /* check addresses */   for( i=0; i<s->n_dev; ++i ) {      DEBUG(1,"bus %d addr %04x\n",i,io[i]);      if( io[i] == 0 ) return -ENODEV;   }   /* load algo_data */   for( i=0; i<s->n_dev; ++i ) {      struct acb_dev *dev = &s->dev[i];      dev->io = io[i];   }   return 0;}static intdetect_addr_bar(struct amd_acb_driver *s){   unsigned long addr;   struct acb_dev *dev;   /* check addresses */   if( s->pci == NULL ) return -ENODEV;   addr = pci_resource_start(s->pci,0);   if( addr == 0 ) return -ENODEV;   s->n_dev = 1;   /* load algo_data */   dev = &s->dev[0];   dev->io = addr;   DEBUG(1,"bus addr %04lx\n",addr);   return 0;}/* pci vendor and device id for pci to isa bridge */#define PCI_DEVICE_ID_CYRIX_SC1400_BRIDGE       0x0405 #define PCI_DEVICE_ID_NS_SC1200_BRIDGE          0x0505 #define PCI_DEVICE_ID_NS_LX_BRIDGE              0x002b #define PCI_DEVICE_ID_AMD_LX_BRIDGE             0x2090#ifndef I2C_HW_ACB_SC1200  #define I2C_HW_ACB_SC1200 (I2C_ALGO_ACB | 0)#endif#ifndef I2C_HW_ACB_SC1400  #define I2C_HW_ACB_SC1400 (I2C_ALGO_ACB | 1)#endif#ifndef I2C_HW_ACB_LX  #define I2C_HW_ACB_LX     (I2C_ALGO_ACB | 2)#endif#define MODEL(vendor,name,model,probe,n) { \  #name, I2C_HW_ACB_##name, 0x##model, detect_addr_##probe, n, \  PCI_VENDOR_ID_##vendor, PCI_DEVICE_ID_##vendor##_##name##_BRIDGE }static struct pci_id {   char *name;   int id;   int model;   int (*probe)(struct amd_acb_driver *s);   int n_dev;   int vendor;   int devid;} pci_isa_devids[] = {   MODEL(AMD  , LX    , 5536, bar, 1),   MODEL(NS   , LX    , 5535, bar, 1),   MODEL(NS   , SC1200, 1200, ldn, 2),   MODEL(CYRIX, SC1400, 1400, ldn, 1),};static intdetect_addr(struct amd_acb_driver *s){   int i, rc;   struct acb_dev *dev;   struct i2c_adapter *adp;   struct i2c_algorithm *algo;   struct pci_dev *dp;   struct pci_id *idp = &pci_isa_devids[0];   rc = 0;   for( i=LENGTH(pci_isa_devids); --i>=0; ++idp ) {      dp = pci_find_device(idp->vendor,idp->devid,NULL);      if( dp != NULL ) break;   }   if( i < 0 ) {      rc = -ENODEV;      goto xit;   }   if( (rc=pci_request_region(dp,0,"amd_acb")) != 0 )      goto xit;   s->pci = dp;   s->model = idp->model;   DEBUG(0,"model %04x/id %08x\n",idp->model,idp->id);   rc = idp->probe(s);   if( rc != 0 ) goto xit;   s->n_dev = idp->n_dev;   spin_lock_init(&s->lock);   for( i=0; i<s->n_dev; ++i ) {      dev = &s->dev[i];      dev->index = i;      init_MUTEX(&dev->sem);      algo = &dev->algo;      strcpy(&algo->name[0],"ACCESS.bus (ACB) algorithm");      algo->id = I2C_ALGO_ACB;      algo->master_xfer = amd_acb_master_xfer;      algo->functionality = amd_acb_functionality;      adp = &dev->adp;      sprintf(&adp->name[0],"%s (ACB%d)",idp->name,i+1);      adp->id = idp->id;      adp->algo = algo;      adp->algo_data = dev;#ifdef MOD_IEC_USE_COUNT      adp->inc_use = amd_acb_inc_use;#endif#ifdef MOD_DEC_USE_COUNT      adp->dec_use = amd_acb_dec_use;#endif      DEBUG(3,"ACB%d ADD %08lx\n",dev->index,(unsigned long)adp);      rc = i2c_add_adapter(adp);      if( rc != 0 ) {         DEBUG(0,"Adapter %d registration failed: %d\n",i+1,rc);         rc = -ENODEV;         goto xit;      }      rc = acb_probe(dev);      if( rc != 0 ) goto xit;   }   return 0;xit:   if( s->pci != NULL )      pci_release_region(s->pci,0);   return rc;}static int __initamd_acb_init(void){   int rc;   DEBUG(0,"AMD ACCESS.bus Driver\n");   s = kmalloc(sizeof(*s),GFP_KERNEL);   if( s == NULL ) return -ENOMEM;   memset(s,0,sizeof(*s));   rc = detect_addr(s);   if( rc != 0 ) {      kfree(s);      s = NULL;   }   return rc;}static void __exitamd_acb_cleanup(void){   int i;   struct acb_dev *dev;   struct i2c_adapter *adp;   DEBUG(0,"removing ACCESS.bus Driver\n");   if( s == NULL ) return;   for( i=0; i<s->n_dev; ++i ) {      dev = &s->dev[i];      adp = &dev->adp;      DEBUG(3,"ACB%d DELETE %08lx\n",dev->index,(unsigned long)adp);      i2c_del_adapter(adp);      pci_release_region(s->pci,0);   }   kfree(s);   s = NULL;}#ifdef EXPORT_NO_SYMBOLSEXPORT_NO_SYMBOLS;#endifmodule_init(amd_acb_init);module_exit(amd_acb_cleanup);

⌨️ 快捷键说明

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