Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c
new file mode 100644
index 0000000..68409d9
--- /dev/null
+++ b/drivers/isdn/capi/capilib.c
@@ -0,0 +1,200 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/isdn/capilli.h>
+
+#define DBG(format, arg...) do { \
+printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
+} while (0)
+
+struct capilib_msgidqueue {
+	struct capilib_msgidqueue *next;
+	u16 msgid;
+};
+
+struct capilib_ncci {
+	struct list_head list;
+	u16 applid;
+	u32 ncci;
+	u32 winsize;
+	int   nmsg;
+	struct capilib_msgidqueue *msgidqueue;
+	struct capilib_msgidqueue *msgidlast;
+	struct capilib_msgidqueue *msgidfree;
+	struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
+};
+
+// ---------------------------------------------------------------------------
+// NCCI Handling
+
+static inline void mq_init(struct capilib_ncci * np)
+{
+	u_int i;
+	np->msgidqueue = NULL;
+	np->msgidlast = NULL;
+	np->nmsg = 0;
+	memset(np->msgidpool, 0, sizeof(np->msgidpool));
+	np->msgidfree = &np->msgidpool[0];
+	for (i = 1; i < np->winsize; i++) {
+		np->msgidpool[i].next = np->msgidfree;
+		np->msgidfree = &np->msgidpool[i];
+	}
+}
+
+static inline int mq_enqueue(struct capilib_ncci * np, u16 msgid)
+{
+	struct capilib_msgidqueue *mq;
+	if ((mq = np->msgidfree) == 0)
+		return 0;
+	np->msgidfree = mq->next;
+	mq->msgid = msgid;
+	mq->next = NULL;
+	if (np->msgidlast)
+		np->msgidlast->next = mq;
+	np->msgidlast = mq;
+	if (!np->msgidqueue)
+		np->msgidqueue = mq;
+	np->nmsg++;
+	return 1;
+}
+
+static inline int mq_dequeue(struct capilib_ncci * np, u16 msgid)
+{
+	struct capilib_msgidqueue **pp;
+	for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
+		if ((*pp)->msgid == msgid) {
+			struct capilib_msgidqueue *mq = *pp;
+			*pp = mq->next;
+			if (mq == np->msgidlast)
+				np->msgidlast = NULL;
+			mq->next = np->msgidfree;
+			np->msgidfree = mq;
+			np->nmsg--;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize)
+{
+	struct capilib_ncci *np;
+
+	np = kmalloc(sizeof(*np), GFP_ATOMIC);
+	if (!np) {
+		printk(KERN_WARNING "capilib_new_ncci: no memory.\n");
+		return;
+	}
+	if (winsize > CAPI_MAXDATAWINDOW) {
+		printk(KERN_ERR "capi_new_ncci: winsize %d too big\n",
+		       winsize);
+		winsize = CAPI_MAXDATAWINDOW;
+	}
+	np->applid = applid;
+	np->ncci = ncci;
+	np->winsize = winsize;
+	mq_init(np);
+	list_add_tail(&np->list, head);
+	DBG("kcapi: appl %d ncci 0x%x up", applid, ncci);
+}
+
+EXPORT_SYMBOL(capilib_new_ncci);
+
+void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci)
+{
+	struct list_head *l;
+	struct capilib_ncci *np;
+
+	list_for_each(l, head) {
+		np = list_entry(l, struct capilib_ncci, list);
+		if (np->applid != applid)
+			continue;
+		if (np->ncci != ncci)
+			continue;
+		printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci);
+		list_del(&np->list);
+		kfree(np);
+		return;
+	}
+	printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci);
+}
+
+EXPORT_SYMBOL(capilib_free_ncci);
+
+void capilib_release_appl(struct list_head *head, u16 applid)
+{
+	struct list_head *l, *n;
+	struct capilib_ncci *np;
+
+	list_for_each_safe(l, n, head) {
+		np = list_entry(l, struct capilib_ncci, list);
+		if (np->applid != applid)
+			continue;
+		printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci);
+		list_del(&np->list);
+		kfree(np);
+	}
+}
+
+EXPORT_SYMBOL(capilib_release_appl);
+
+void capilib_release(struct list_head *head)
+{
+	struct list_head *l, *n;
+	struct capilib_ncci *np;
+
+	list_for_each_safe(l, n, head) {
+		np = list_entry(l, struct capilib_ncci, list);
+		printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci);
+		list_del(&np->list);
+		kfree(np);
+	}
+}
+
+EXPORT_SYMBOL(capilib_release);
+
+u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
+{
+	struct list_head *l;
+	struct capilib_ncci *np;
+
+	list_for_each(l, head) {
+		np = list_entry(l, struct capilib_ncci, list);
+		if (np->applid != applid)
+			continue;
+		if (np->ncci != ncci)
+			continue;
+		
+		if (mq_enqueue(np, msgid) == 0)
+			return CAPI_SENDQUEUEFULL;
+
+		return CAPI_NOERROR;
+	}
+	printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci);
+	return CAPI_NOERROR;
+}
+
+EXPORT_SYMBOL(capilib_data_b3_req);
+
+void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
+{
+	struct list_head *l;
+	struct capilib_ncci *np;
+
+	list_for_each(l, head) {
+		np = list_entry(l, struct capilib_ncci, list);
+		if (np->applid != applid)
+			continue;
+		if (np->ncci != ncci)
+			continue;
+		
+		if (mq_dequeue(np, msgid) == 0) {
+			printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
+			       msgid, ncci);
+		}
+		return;
+	}
+	printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci);
+}
+
+EXPORT_SYMBOL(capilib_data_b3_conf);