+//\r
+// Simple Network Protocol Driver Global Variables\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = {\r
+ SimpleNetworkDriverSupported,\r
+ SimpleNetworkDriverStart,\r
+ SimpleNetworkDriverStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+\r
+/**\r
+ This routine maps the given CPU address to a Device address. It creates a\r
+ an entry in the map list with the virtual and physical addresses and the\r
+ un map cookie.\r
+\r
+ @param V2p pointer to return a map list node pointer.\r
+ @param Type the direction in which the data flows from the given\r
+ virtual address device->cpu or cpu->device or both\r
+ ways.\r
+ @param VirtualAddress virtual address (or CPU address) to be mapped.\r
+ @param BufferSize size of the buffer to be mapped.\r
+\r
+ @retval EFI_SUCEESS routine has completed the mapping.\r
+ @retval EFI_INVALID_PARAMETER invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES out of resource.\r
+ @retval other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+AddV2P (\r
+ IN OUT V2P **V2p,\r
+ EFI_PCI_IO_PROTOCOL_OPERATION Type,\r
+ VOID *VirtualAddress,\r
+ UINTN BufferSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if ((V2p == NULL) || (VirtualAddress == NULL) || (BufferSize == 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *V2p = AllocatePool (sizeof (V2P ));\r
+ if (*V2p != NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = mPciIo->Map (\r
+ mPciIo,\r
+ Type,\r
+ VirtualAddress,\r
+ &BufferSize,\r
+ &(*V2p)->PhysicalAddress,\r
+ &(*V2p)->Unmap\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ FreePool (*V2p);\r
+ return Status;\r
+ }\r
+ (*V2p)->VirtualAddress = VirtualAddress;\r
+ (*V2p)->BufferSize = BufferSize;\r
+ (*V2p)->Next = mV2p;\r
+ mV2p = *V2p;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This routine searches the linked list of mapped address nodes (for undi3.0\r
+ interface) to find the node that corresponds to the given virtual address and\r
+ returns a pointer to that node.\r
+\r
+ @param V2p pointer to return a map list node pointer.\r
+ @param VirtualAddr virtual address (or CPU address) to be searched in\r
+ the map list\r
+\r
+ @retval EFI_SUCEESS if a match found!\r
+ @retval Other match not found\r
+\r
+**/\r
+EFI_STATUS\r
+FindV2p (\r
+ V2P **V2p,\r
+ VOID *VirtualAddr\r
+ )\r
+{\r
+ V2P *Ptr;\r
+\r
+ if (V2p == NULL || VirtualAddr == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Ptr = mV2p; Ptr != NULL; Ptr = Ptr->Next) {\r
+ if (Ptr->VirtualAddress == VirtualAddr) {\r
+ *V2p = Ptr;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This routine unmaps the given virtual address and frees the memory allocated\r
+ for the map list node corresponding to that address.\r
+\r
+ @param VirtualAddress virtual address (or CPU address) to be unmapped\r
+\r
+ @retval EFI_SUCEESS if successfully unmapped\r
+ @retval Other as indicated by the error\r
+\r
+**/\r
+EFI_STATUS\r
+DelV2p (\r
+ VOID *VirtualAddress\r
+ )\r
+{\r
+ V2P *Current;\r
+ V2P *Next;\r
+ EFI_STATUS Status;\r
+\r
+ if (VirtualAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (mV2p == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Is our node at the head of the list??\r
+ //\r
+ if ((Current = mV2p)->VirtualAddress == VirtualAddress) {\r
+ mV2p = mV2p->Next;\r
+\r
+ Status = mPciIo->Unmap (mPciIo, Current->Unmap);\r
+\r
+ FreePool (Current);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ for (; Current->Next != NULL; Current = Next) {\r
+ if ((Next = Current->Next)->VirtualAddress == VirtualAddress) {\r
+ Current->Next = Next->Next;\r
+ Status = mPciIo->Unmap (mPciIo, Next->Unmap);\r
+ FreePool (Next);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
+ }\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r