patch-2.4.2 linux/drivers/s390/s390dyn.c
Next file: linux/drivers/s390/s390io.c
Previous file: linux/drivers/s390/net/netiucv.c
Back to the patch index
Back to the overall index
- Lines: 214
- Date:
Tue Feb 13 14:13:44 2001
- Orig file:
v2.4.1/linux/drivers/s390/s390dyn.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/s390dyn.c linux/drivers/s390/s390dyn.c
@@ -0,0 +1,213 @@
+/*
+ * arch/s390/kernel/s390dyn.c
+ * S/390 dynamic device attachment
+ *
+ * S390 version
+ * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+
+#include <asm/irq.h>
+#include <asm/s390io.h>
+#include <asm/s390dyn.h>
+
+static devreg_t *devreg_anchor = NULL;
+static spinlock_t dyn_lock = SPIN_LOCK_UNLOCKED;
+
+
+int s390_device_register( devreg_t *drinfo )
+{
+ unsigned long flags;
+ int pdevflag,drflag;
+
+ int ret = 0;
+ devreg_t *pdevreg = devreg_anchor;
+
+ if ( drinfo == NULL )
+ return( -EINVAL );
+
+ drflag = drinfo->flag;
+
+ if ( (drflag & DEVREG_TYPE_DEVNO) == (drflag & DEVREG_TYPE_DEVCHARS) )
+ return( -EINVAL );
+
+ spin_lock_irqsave( &dyn_lock, flags );
+
+ while ( (pdevreg != NULL) && (ret ==0) )
+ {
+ if ( pdevreg == drinfo )
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ pdevflag = pdevreg->flag;
+
+ /*
+ * we don't allow multiple drivers to register
+ * for the same device number
+ */
+ if ( ( (pdevflag & DEVREG_TYPE_DEVNO)
+ && (pdevreg->ci.devno ) )
+ && ( (drflag & DEVREG_TYPE_DEVNO )
+ && (drinfo->ci.devno ) ) )
+ {
+ ret = -EBUSY;
+ }
+ else if ( drflag == ( DEVREG_TYPE_DEVCHARS
+ | DEVREG_EXACT_MATCH ))
+ {
+ if ( !memcmp(&drinfo->ci.hc,
+ &pdevreg->ci.hc,
+ sizeof(devreg_hc_t)))
+ ret=-EBUSY;
+ } /* endif */
+
+ } /* endif */
+
+ pdevreg = pdevreg->next;
+
+ } /* endwhile */
+
+ /*
+ * only enqueue if no collision was found ...
+ */
+ if(ret==0)
+ {
+ drinfo->next = devreg_anchor;
+ drinfo->prev = NULL;
+
+ if ( devreg_anchor != NULL )
+ {
+ devreg_anchor->prev = drinfo;
+
+ } /* endif */
+
+ devreg_anchor=drinfo;
+
+ } /* endif */
+
+ spin_unlock_irqrestore( &dyn_lock, flags );
+
+ return( ret);
+}
+
+
+int s390_device_unregister( devreg_t *dreg )
+{
+ unsigned long flags;
+
+ int ret = -EINVAL;
+ devreg_t *pdevreg = devreg_anchor;
+
+ if ( dreg == NULL )
+ return( -EINVAL );
+
+ spin_lock_irqsave( &dyn_lock, flags );
+
+ while ( (pdevreg != NULL )
+ && ( ret != 0 ) )
+ {
+ if ( pdevreg == dreg )
+ {
+ devreg_t *dprev = pdevreg->prev;
+ devreg_t *dnext = pdevreg->next;
+
+ if ( (dprev != NULL) && (dnext != NULL) )
+ {
+ dnext->prev = dprev;
+ dprev->next = dnext;
+ }
+ if ( (dprev != NULL) && (dnext == NULL) )
+ {
+ dprev->next = NULL;
+ }
+ if ( (dprev == NULL) && (dnext != NULL) )
+ {
+ dnext->prev = NULL;
+
+ } /* else */
+
+ ret = 0;
+ }
+ else
+ {
+ pdevreg = pdevreg->next;
+
+ } /* endif */
+
+ } /* endwhile */
+
+ spin_unlock_irqrestore( &dyn_lock, flags );
+
+ return( ret);
+}
+
+
+devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
+{
+ unsigned long flags;
+ devreg_hc_t match;
+ devreg_t *pdevreg = devreg_anchor;
+
+ if ( ioinfo == NULL )
+ return( NULL );
+
+ spin_lock_irqsave( &dyn_lock, flags );
+
+ while ( pdevreg != NULL )
+ {
+ int flag = pdevreg->flag;
+
+ if ( (flag & DEVREG_TYPE_DEVNO )
+ && (ioinfo->ui.flags.dval == 1 )
+ && (ioinfo->devno == pdevreg->ci.devno) )
+ {
+ break;
+ }
+ else if (flag & DEVREG_TYPE_DEVCHARS )
+ {
+ if ( flag & DEVREG_EXACT_MATCH )
+ {
+ if ( !memcmp( &pdevreg->ci.hc,
+ &ioinfo->senseid.cu_type,
+ sizeof(devreg_hc_t)))
+ break;
+ }
+ else
+ {
+ memcpy( &match, &ioinfo->senseid.cu_type,
+ sizeof(match));
+
+ if( flag & DEVREG_NO_CU_INFO )
+ {
+ match.ctype = pdevreg->ci.hc.ctype;
+ match.cmode = pdevreg->ci.hc.cmode;
+ }
+ if( flag & DEVREG_NO_DEV_INFO )
+ {
+ match.dtype = pdevreg->ci.hc.dtype;
+ match.dmode = pdevreg->ci.hc.dmode;
+ }
+ if ( flag & DEVREG_MATCH_CU_TYPE )
+ match.cmode = pdevreg->ci.hc.cmode;
+ if( flag & DEVREG_MATCH_DEV_TYPE)
+ match.dmode = pdevreg->ci.hc.dmode;
+ if ( !memcmp( &pdevreg->ci.hc,
+ &match, sizeof(match)))
+ break;
+ } /* endif */
+ } /* endif */
+
+ pdevreg = pdevreg->next;
+
+ } /* endwhile */
+
+ spin_unlock_irqrestore( &dyn_lock, flags );
+
+ return( pdevreg);
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)