s390dyn.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390/kernel/s390dyn.c
  3.  *   S/390 dynamic device attachment
  4.  *
  5.  *  S390 version
  6.  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  7.  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  8.  */
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include <linux/smp_lock.h>
  12. #include <asm/irq.h>
  13. #include <asm/s390io.h>
  14. #include <asm/s390dyn.h>
  15. static struct list_head devreg_anchor = LIST_HEAD_INIT(devreg_anchor);
  16. static spinlock_t  dyn_lock           = SPIN_LOCK_UNLOCKED;
  17. static inline int s390_device_register_internal(devreg_t *drinfo)
  18. {
  19. struct list_head *p;
  20.         list_for_each(p, &devreg_anchor) {
  21.                 devreg_t *pdevreg = list_entry(p, devreg_t, list);
  22.                 
  23.                 if (pdevreg == drinfo)
  24.                         return -EINVAL;
  25.                 /*
  26.                  * We don't allow multiple drivers to register
  27.                  * for the same device number
  28.                  */
  29.                 if (pdevreg->ci.devno == drinfo->ci.devno &&
  30.                     (pdevreg->flag & DEVREG_TYPE_DEVNO) &&
  31.                     (drinfo->flag & DEVREG_TYPE_DEVNO))
  32. return -EBUSY;
  33.                 if (drinfo->flag == (DEVREG_TYPE_DEVCHARS | 
  34.      DEVREG_EXACT_MATCH) &&
  35.                     !memcmp(&drinfo->ci.hc, &pdevreg->ci.hc,
  36.             sizeof(devreg_hc_t))) 
  37. return -EBUSY;
  38.         }
  39.         /*
  40.          * no collision found, enqueue
  41.          */
  42.         list_add (&drinfo->list, &devreg_anchor);
  43. return 0;
  44. }
  45. int s390_device_register( devreg_t *drinfo )
  46. {
  47. unsigned long flags;
  48. int ret;
  49. if (drinfo == NULL ||
  50.             !(drinfo->flag & (DEVREG_TYPE_DEVNO | DEVREG_TYPE_DEVCHARS)))
  51. return -EINVAL;
  52. spin_lock_irqsave (&dyn_lock, flags); 
  53. ret = s390_device_register_internal(drinfo);
  54. spin_unlock_irqrestore( &dyn_lock, flags ); 
  55.  
  56. return ret;
  57. }
  58. static inline int s390_device_unregister_internal(devreg_t *dreg)
  59. {
  60. struct list_head *p;
  61.         list_for_each(p, &devreg_anchor) {
  62.                 devreg_t *pdevreg = list_entry(p, devreg_t, list);
  63. if (pdevreg == dreg) {
  64. list_del (&dreg->list);
  65. return 0;
  66. }
  67.         }
  68. return -EINVAL;
  69. }
  70. int s390_device_unregister(devreg_t *dreg)
  71. {
  72. unsigned long  flags;
  73. int ret;
  74. if (dreg == NULL)
  75. return -EINVAL;
  76. spin_lock_irqsave(&dyn_lock, flags); 
  77. ret = s390_device_unregister_internal(dreg);
  78. spin_unlock_irqrestore(&dyn_lock, flags); 
  79.  
  80. return ret;
  81. }
  82. static inline devreg_t *s390_search_devreg_internal(ioinfo_t *ioinfo)
  83. {
  84. struct list_head *p;
  85.         list_for_each(p, &devreg_anchor) {
  86.                 devreg_t *pdevreg = list_entry(p, devreg_t, list);
  87. senseid_t *sid;
  88. int flag;
  89. flag = pdevreg->flag;
  90. sid = &ioinfo->senseid;
  91. if (flag & DEVREG_TYPE_DEVNO) {
  92.                         if (ioinfo->ui.flags.dval != 1 ||
  93.             ioinfo->devno != pdevreg->ci.devno)
  94. continue;
  95. } else if (flag & DEVREG_TYPE_DEVCHARS) {
  96. if ( (flag & DEVREG_MATCH_CU_TYPE) &&
  97.      pdevreg->ci.hc.ctype != sid->cu_type )
  98. continue;
  99. if ( (flag & DEVREG_MATCH_CU_MODEL) &&
  100.      pdevreg->ci.hc.cmode != sid->cu_model )
  101. continue;
  102. if ( (flag & DEVREG_MATCH_DEV_TYPE) &&
  103.      pdevreg->ci.hc.dtype != sid->dev_type )
  104. continue;
  105. if ( (flag & DEVREG_MATCH_DEV_MODEL) &&
  106.      pdevreg->ci.hc.dmode != sid->dev_model )
  107. continue;
  108. } else {
  109. continue;
  110. }
  111. return pdevreg;
  112. }
  113. return NULL;
  114. }
  115. devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
  116. {
  117. unsigned long  flags;
  118. devreg_t *pdevreg;
  119. if (ioinfo == NULL)
  120. return NULL;
  121. spin_lock_irqsave(&dyn_lock, flags); 
  122. pdevreg = s390_search_devreg_internal(ioinfo);
  123. spin_unlock_irqrestore(&dyn_lock, flags); 
  124.  
  125. return pdevreg;
  126. }
  127. EXPORT_SYMBOL(s390_device_register);
  128. EXPORT_SYMBOL(s390_device_unregister);