[bus] Add child PDO node unit number logic
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Thu, 23 Dec 2010 13:56:12 +0000 (08:56 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Thu, 23 Dec 2010 14:05:42 +0000 (09:05 -0500)
The same kind of effort as we see in WvBusAddChild().
The point is for a move away from WV_S_DEV_T and towards
a bus library that can be used by any driver, so some
things will go in WV_S_BUS_NODE, instead.

src/include/bus.h
src/winvblock/bus/bus.c

index 924ee19..d0232c3 100644 (file)
@@ -64,6 +64,8 @@ typedef struct WV_BUS_NODE {
         LIST_ENTRY Link;
         PDEVICE_OBJECT Pdo;
         WV_SP_BUS_T Bus;
+        /* The child's unit number relative to the parent bus. */
+        winvblock__uint32 Num;
       } BusPrivate_;
   } WV_S_BUS_NODE, * WV_SP_BUS_NODE;
 
index 82fed2d..11c5a6a 100644 (file)
@@ -415,6 +415,53 @@ static WV_SP_BUS_WORK_ITEM_ WvBusGetWorkItem_(
     return CONTAINING_RECORD(list_entry, WV_S_BUS_WORK_ITEM_, Link);
   }
 
+/**
+ * Add a PDO node to a bus' list of children.  Internal.
+ *
+ * @v bus               The bus to add the node to.
+ * @v new_node          The PDO node to add to the bus.
+ *
+ * Don't call this function yourself.  It expects to have exclusive
+ * access to the bus' list of children.
+ */
+static void STDCALL WvBusAddNode_(WV_SP_BUS_T bus, WV_SP_BUS_NODE new_node) {
+    PLIST_ENTRY walker;
+
+    DBG("Adding PDO to bus...\n");
+    ObReferenceObject(new_node->BusPrivate_.Pdo);
+    bus->BusPrivate_.NodeCount++;
+    /* It's too bad about having both linked list and bus ref. */
+    new_node->BusPrivate_.Bus = bus;
+
+    /* Find a slot for the new child. */
+    walker = &bus->BusPrivate_.Nodes;
+    new_node->BusPrivate_.Num = 0;
+    while ((walker = walker->Flink) != &bus->BusPrivate_.Nodes) {
+        WV_SP_BUS_NODE node = CONTAINING_RECORD(
+            walker,
+            WV_S_BUS_NODE,
+            BusPrivate_.Link
+          );
+
+        if (
+            node->BusPrivate_.Num &&
+            (node->BusPrivate_.Link.Blink == &bus->BusPrivate_.Nodes)
+          ) {
+            /* The first node's unit number is != 0.  Insert here. */
+            break;
+          }
+        if (node->BusPrivate_.Num > new_node->BusPrivate_.Num) {
+            /* There is a gap so insert here. */
+            break;
+          }
+        /* Continue trying to find a slot. */
+        new_node->BusPrivate_.Num++;
+      } /* while */
+    /* Insert before walker. */
+    InsertTailList(walker, &new_node->BusPrivate_.Link);
+    return;
+  }
+
 /**
  * Process work items for a bus.
  *
@@ -431,14 +478,8 @@ winvblock__lib_func void WvBusProcessWorkItems(WV_SP_BUS_T Bus) {
     while (work_item = WvBusGetWorkItem_(Bus)) {
         switch (work_item->Cmd) {
             case WvBusWorkItemCmdAddPdo_:
-              DBG("Adding PDO to bus...\n");
-
               node = work_item->Context.Node;
-              /* It's too bad about having both linked list and bus ref. */
-              node->BusPrivate_.Bus = Bus;
-              ObReferenceObject(node->BusPrivate_.Pdo);
-              InsertTailList(&Bus->BusPrivate_.Nodes, &node->BusPrivate_.Link);
-              Bus->BusPrivate_.NodeCount++;
+              WvBusAddNode_(Bus, node);
               break;
 
             case WvBusWorkItemCmdRemovePdo_: