]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UndiRuntimeDxe/Decode.c
add UndiRuntimeDxe from MdeModulePkg to OptionRomPkg.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UndiRuntimeDxe / Decode.c
CommitLineData
ffa5008a 1/** @file\r
2 Provides the basic UNID functions.\r
40834173 3\r
4Copyright (c) 2006 - 2007, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
ffa5008a 13**/\r
40834173 14\r
40834173 15#include "Undi32.h"\r
16\r
17//\r
18// Global variables defined in this file\r
19//\r
20UNDI_CALL_TABLE api_table[PXE_OPCODE_LAST_VALID+1] = { \\r
21 {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0, (UINT16)(ANY_STATE),UNDI_GetState },\\r
22 {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,0,(UINT16)(ANY_STATE),UNDI_Start },\\r
23 {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0,MUST_BE_STARTED,UNDI_Stop },\\r
24 {PXE_CPBSIZE_NOT_USED,sizeof(PXE_DB_GET_INIT_INFO),0,MUST_BE_STARTED, UNDI_GetInitInfo },\\r
25 {PXE_CPBSIZE_NOT_USED,sizeof(PXE_DB_GET_CONFIG_INFO),0,MUST_BE_STARTED, UNDI_GetConfigInfo },\\r
26 {sizeof(PXE_CPB_INITIALIZE),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),MUST_BE_STARTED,UNDI_Initialize },\\r
27 {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED,UNDI_Reset },\\r
28 {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0, MUST_BE_INITIALIZED,UNDI_Shutdown },\\r
29 {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED,UNDI_Interrupt },\\r
30 {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_RecFilter },\\r
31 {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_StnAddr },\\r
32 {PXE_CPBSIZE_NOT_USED, (UINT16)(DONT_CHECK), (UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Statistics },\\r
33 {sizeof(PXE_CPB_MCAST_IP_TO_MAC),sizeof(PXE_DB_MCAST_IP_TO_MAC), (UINT16)(DONT_CHECK),MUST_BE_INITIALIZED, UNDI_ip2mac },\\r
34 {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_NVData },\\r
35 {PXE_CPBSIZE_NOT_USED,(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Status },\\r
36 {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_FillHeader },\\r
37 {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Transmit },\\r
38 {sizeof(PXE_CPB_RECEIVE),sizeof(PXE_DB_RECEIVE),0,MUST_BE_INITIALIZED, UNDI_Receive } \\r
39};\r
40\r
41//\r
42// end of global variables\r
43//\r
44\r
40834173 45\r
ffa5008a 46/**\r
40834173 47 This routine determines the operational state of the UNDI. It updates the state flags in the\r
48 Command Descriptor Block based on information derived from the AdapterInfo instance data.\r
40834173 49 To ensure the command has completed successfully, CdbPtr->StatCode will contain the result of\r
50 the command execution.\r
40834173 51 The CdbPtr->StatFlags will contain a STOPPED, STARTED, or INITIALIZED state once the command\r
52 has successfully completed.\r
40834173 53 Keep in mind the AdapterInfo->State is the active state of the adapter (based on software\r
54 interrogation), and the CdbPtr->StateFlags is the passed back information that is reflected\r
55 to the caller of the UNDI API.\r
56\r
ffa5008a 57 @param CdbPtr Pointer to the command descriptor block.\r
58 @param AdapterInfo Pointer to the NIC data structure information which\r
59 the UNDI driver is layering on..\r
40834173 60\r
ffa5008a 61 @return None\r
40834173 62\r
ffa5008a 63**/\r
64VOID\r
65UNDI_GetState (\r
66 IN PXE_CDB *CdbPtr,\r
67 IN NIC_DATA_INSTANCE *AdapterInfo\r
68 )\r
40834173 69{\r
70 CdbPtr->StatFlags = (PXE_STATFLAGS) (CdbPtr->StatFlags | AdapterInfo->State);\r
71 return ;\r
72}\r
73\r
40834173 74\r
ffa5008a 75/**\r
40834173 76 This routine is used to change the operational state of the UNDI from stopped to started.\r
77 It will do this as long as the adapter's state is PXE_STATFLAGS_GET_STATE_STOPPED, otherwise\r
78 the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the\r
79 UNDI as having already been started.\r
40834173 80 This routine is modified to reflect the undi 1.1 specification changes. The\r
81 changes in the spec are mainly in the callback routines, the new spec adds\r
82 3 more callbacks and a unique id.\r
83 Since this UNDI supports both old and new undi specifications,\r
84 The NIC's data structure is filled in with the callback routines (depending\r
85 on the version) pointed to in the caller's CpbPtr. This seeds the Delay,\r
86 Virt2Phys, Block, and Mem_IO for old and new versions and Map_Mem, UnMap_Mem\r
87 and Sync_Mem routines and a unique id variable for the new version.\r
88 This is the function which an external entity (SNP, O/S, etc) would call\r
89 to provide it's I/O abstraction to the UNDI.\r
40834173 90 It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STARTED.\r
91\r
ffa5008a 92 @param CdbPtr Pointer to the command descriptor block.\r
93 @param AdapterInfo Pointer to the NIC data structure information which\r
94 the UNDI driver is layering on..\r
40834173 95\r
ffa5008a 96 @return None\r
40834173 97\r
ffa5008a 98**/\r
99VOID\r
100UNDI_Start (\r
101 IN PXE_CDB *CdbPtr,\r
102 IN NIC_DATA_INSTANCE *AdapterInfo\r
103 )\r
40834173 104{\r
105 PXE_CPB_START_30 *CpbPtr;\r
106 PXE_CPB_START_31 *CpbPtr_31;\r
107\r
108 //\r
109 // check if it is already started.\r
110 //\r
111 if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_STOPPED) {\r
112 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
113 CdbPtr->StatCode = PXE_STATCODE_ALREADY_STARTED;\r
114 return ;\r
115 }\r
116\r
117 if (CdbPtr->CPBsize != sizeof(PXE_CPB_START_30) &&\r
118 CdbPtr->CPBsize != sizeof(PXE_CPB_START_31)) {\r
119\r
120 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
121 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
122 return ;\r
123 }\r
124\r
125 CpbPtr = (PXE_CPB_START_30 *) (UINTN) (CdbPtr->CPBaddr);\r
126 CpbPtr_31 = (PXE_CPB_START_31 *) (UINTN) (CdbPtr->CPBaddr);\r
127\r
128 if (AdapterInfo->VersionFlag == 0x30) {\r
129 AdapterInfo->Delay_30 = (bsptr_30) (UINTN) CpbPtr->Delay;\r
130 AdapterInfo->Virt2Phys_30 = (virtphys_30) (UINTN) CpbPtr->Virt2Phys;\r
131 AdapterInfo->Block_30 = (block_30) (UINTN) CpbPtr->Block;\r
132 //\r
133 // patch for old buggy 3.0 code:\r
134 // In EFI1.0 undi used to provide the full (absolute) I/O address to the\r
135 // i/o calls and SNP used to provide a callback that used GlobalIoFncs and\r
136 // everything worked fine! In EFI 1.1, UNDI is not using the full\r
137 // i/o or memory address to access the device, The base values for the i/o\r
138 // and memory address is abstracted by the device specific PciIoFncs and\r
139 // UNDI only uses the offset values. Since UNDI3.0 cannot provide any\r
140 // identification to SNP, SNP cannot use nic specific PciIoFncs callback!\r
141 //\r
142 // To fix this and make undi3.0 work with SNP in EFI1.1 we\r
143 // use a TmpMemIo function that is defined in init.c\r
144 // This breaks the runtime driver feature of undi, but what to do\r
145 // if we have to provide the 3.0 compatibility (including the 3.0 bugs)\r
146 //\r
147 // This TmpMemIo function also takes a UniqueId parameter\r
148 // (as in undi3.1 design) and so initialize the UniqueId as well here\r
149 // Note: AdapterInfo->Mem_Io_30 is just filled for consistency with other\r
150 // parameters but never used, we only use Mem_Io field in the In/Out routines\r
151 // inside e100b.c.\r
152 //\r
153 AdapterInfo->Mem_Io_30 = (mem_io_30) (UINTN) CpbPtr->Mem_IO;\r
154 AdapterInfo->Mem_Io = (mem_io) (UINTN) TmpMemIo;\r
155 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;\r
156\r
157 } else {\r
158 AdapterInfo->Delay = (bsptr) (UINTN) CpbPtr_31->Delay;\r
159 AdapterInfo->Virt2Phys = (virtphys) (UINTN) CpbPtr_31->Virt2Phys;\r
160 AdapterInfo->Block = (block) (UINTN) CpbPtr_31->Block;\r
161 AdapterInfo->Mem_Io = (mem_io) (UINTN) CpbPtr_31->Mem_IO;\r
162\r
163 AdapterInfo->Map_Mem = (map_mem) (UINTN) CpbPtr_31->Map_Mem;\r
164 AdapterInfo->UnMap_Mem = (unmap_mem) (UINTN) CpbPtr_31->UnMap_Mem;\r
165 AdapterInfo->Sync_Mem = (sync_mem) (UINTN) CpbPtr_31->Sync_Mem;\r
166 AdapterInfo->Unique_ID = CpbPtr_31->Unique_ID;\r
167 }\r
168\r
169 AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED;\r
170\r
171 return ;\r
172}\r
173\r
40834173 174\r
ffa5008a 175/**\r
40834173 176 This routine is used to change the operational state of the UNDI from started to stopped.\r
177 It will not do this if the adapter's state is PXE_STATFLAGS_GET_STATE_INITIALIZED, otherwise\r
178 the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the\r
179 UNDI as having already not been shut down.\r
40834173 180 The NIC's data structure will have the Delay, Virt2Phys, and Block, pointers zero'd out..\r
40834173 181 It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STOPPED.\r
182\r
ffa5008a 183 @param CdbPtr Pointer to the command descriptor block.\r
184 @param AdapterInfo Pointer to the NIC data structure information which\r
185 the UNDI driver is layering on..\r
40834173 186\r
ffa5008a 187 @return None\r
40834173 188\r
ffa5008a 189**/\r
190VOID\r
191UNDI_Stop (\r
192 IN PXE_CDB *CdbPtr,\r
193 IN NIC_DATA_INSTANCE *AdapterInfo\r
194 )\r
40834173 195{\r
196 if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {\r
197 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
198 CdbPtr->StatCode = PXE_STATCODE_NOT_SHUTDOWN;\r
199 return ;\r
200 }\r
201\r
202 AdapterInfo->Delay_30 = 0;\r
203 AdapterInfo->Virt2Phys_30 = 0;\r
204 AdapterInfo->Block_30 = 0;\r
205\r
206 AdapterInfo->Delay = 0;\r
207 AdapterInfo->Virt2Phys = 0;\r
208 AdapterInfo->Block = 0;\r
209\r
210 AdapterInfo->Map_Mem = 0;\r
211 AdapterInfo->UnMap_Mem = 0;\r
212 AdapterInfo->Sync_Mem = 0;\r
213\r
214 AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STOPPED;\r
215\r
216 return ;\r
217}\r
218\r
40834173 219\r
ffa5008a 220/**\r
40834173 221 This routine is used to retrieve the initialization information that is needed by drivers and\r
222 applications to initialize the UNDI. This will fill in data in the Data Block structure that is\r
223 pointed to by the caller's CdbPtr->DBaddr. The fields filled in are as follows:\r
40834173 224 MemoryRequired, FrameDataLen, LinkSpeeds[0-3], NvCount, NvWidth, MediaHeaderLen, HWaddrLen,\r
225 MCastFilterCnt, TxBufCnt, TxBufSize, RxBufCnt, RxBufSize, IFtype, Duplex, and LoopBack.\r
40834173 226 In addition, the CdbPtr->StatFlags ORs in that this NIC supports cable detection. (APRIORI knowledge)\r
227\r
ffa5008a 228 @param CdbPtr Pointer to the command descriptor block.\r
229 @param AdapterInfo Pointer to the NIC data structure information which\r
230 the UNDI driver is layering on..\r
40834173 231\r
ffa5008a 232 @return None\r
40834173 233\r
ffa5008a 234**/\r
235VOID\r
236UNDI_GetInitInfo (\r
237 IN PXE_CDB *CdbPtr,\r
238 IN NIC_DATA_INSTANCE *AdapterInfo\r
239 )\r
40834173 240{\r
241 PXE_DB_GET_INIT_INFO *DbPtr;\r
242\r
243 DbPtr = (PXE_DB_GET_INIT_INFO *) (UINTN) (CdbPtr->DBaddr);\r
244\r
245 DbPtr->MemoryRequired = MEMORY_NEEDED;\r
246 DbPtr->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER;\r
247 DbPtr->LinkSpeeds[0] = 10;\r
248 DbPtr->LinkSpeeds[1] = 100;\r
249 DbPtr->LinkSpeeds[2] = DbPtr->LinkSpeeds[3] = 0;\r
250 DbPtr->NvCount = MAX_EEPROM_LEN;\r
251 DbPtr->NvWidth = 4;\r
252 DbPtr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER;\r
253 DbPtr->HWaddrLen = PXE_HWADDR_LEN_ETHER;\r
254 DbPtr->MCastFilterCnt = MAX_MCAST_ADDRESS_CNT;\r
255\r
256 DbPtr->TxBufCnt = TX_BUFFER_COUNT;\r
257 DbPtr->TxBufSize = sizeof (TxCB);\r
258 DbPtr->RxBufCnt = RX_BUFFER_COUNT;\r
259 DbPtr->RxBufSize = sizeof (RxFD);\r
260\r
261 DbPtr->IFtype = PXE_IFTYPE_ETHERNET;\r
262 DbPtr->SupportedDuplexModes = PXE_DUPLEX_ENABLE_FULL_SUPPORTED |\r
263 PXE_DUPLEX_FORCE_FULL_SUPPORTED;\r
264 DbPtr->SupportedLoopBackModes = PXE_LOOPBACK_INTERNAL_SUPPORTED |\r
265 PXE_LOOPBACK_EXTERNAL_SUPPORTED;\r
266\r
267 CdbPtr->StatFlags |= PXE_STATFLAGS_CABLE_DETECT_SUPPORTED;\r
268 return ;\r
269}\r
270\r
40834173 271\r
ffa5008a 272/**\r
40834173 273 This routine is used to retrieve the configuration information about the NIC being controlled by\r
274 this driver. This will fill in data in the Data Block structure that is pointed to by the caller's CdbPtr->DBaddr.\r
275 The fields filled in are as follows:\r
40834173 276 DbPtr->pci.BusType, DbPtr->pci.Bus, DbPtr->pci.Device, and DbPtr->pci.\r
40834173 277 In addition, the DbPtr->pci.Config.Dword[0-63] grabs a copy of this NIC's PCI configuration space.\r
278\r
ffa5008a 279 @param CdbPtr Pointer to the command descriptor block.\r
280 @param AdapterInfo Pointer to the NIC data structure information which\r
281 the UNDI driver is layering on..\r
40834173 282\r
ffa5008a 283 @return None\r
40834173 284\r
ffa5008a 285**/\r
286VOID\r
287UNDI_GetConfigInfo (\r
288 IN PXE_CDB *CdbPtr,\r
289 IN NIC_DATA_INSTANCE *AdapterInfo\r
290 )\r
40834173 291{\r
292 UINT16 Index;\r
293 PXE_DB_GET_CONFIG_INFO *DbPtr;\r
294\r
295 DbPtr = (PXE_DB_GET_CONFIG_INFO *) (UINTN) (CdbPtr->DBaddr);\r
296\r
297 DbPtr->pci.BusType = PXE_BUSTYPE_PCI;\r
298 DbPtr->pci.Bus = AdapterInfo->Bus;\r
299 DbPtr->pci.Device = AdapterInfo->Device;\r
300 DbPtr->pci.Function = AdapterInfo->Function;\r
301\r
302 for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) {\r
303 DbPtr->pci.Config.Dword[Index] = AdapterInfo->Config[Index];\r
304 }\r
305\r
306 return ;\r
307}\r
308\r
40834173 309\r
ffa5008a 310/**\r
40834173 311 This routine resets the network adapter and initializes the UNDI using the parameters supplied in\r
312 the CPB. This command must be issued before the network adapter can be setup to transmit and\r
313 receive packets.\r
40834173 314 Once the memory requirements of the UNDI are obtained by using the GetInitInfo command, a block\r
315 of non-swappable memory may need to be allocated. The address of this memory must be passed to\r
316 UNDI during the Initialize in the CPB. This memory is used primarily for transmit and receive buffers.\r
40834173 317 The fields CableDetect, LinkSpeed, Duplex, LoopBack, MemoryPtr, and MemoryLength are set with information\r
318 that was passed in the CPB and the NIC is initialized.\r
40834173 319 If the NIC initialization fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED\r
320 Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_INITIALIZED showing the state of\r
321 the UNDI is now initialized.\r
322\r
ffa5008a 323 @param CdbPtr Pointer to the command descriptor block.\r
324 @param AdapterInfo Pointer to the NIC data structure information which\r
325 the UNDI driver is layering on..\r
40834173 326\r
ffa5008a 327 @return None\r
40834173 328\r
ffa5008a 329**/\r
330VOID\r
331UNDI_Initialize (\r
332 IN PXE_CDB *CdbPtr,\r
333 NIC_DATA_INSTANCE *AdapterInfo\r
334 )\r
40834173 335{\r
336 PXE_CPB_INITIALIZE *CpbPtr;\r
337\r
338 if ((CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) &&\r
339 (CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) {\r
340 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
341 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
342 return ;\r
343 }\r
344\r
345 //\r
346 // check if it is already initialized\r
347 //\r
348 if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {\r
349 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
350 CdbPtr->StatCode = PXE_STATCODE_ALREADY_INITIALIZED;\r
351 return ;\r
352 }\r
353\r
354 CpbPtr = (PXE_CPB_INITIALIZE *) (UINTN) CdbPtr->CPBaddr;\r
355\r
356 if (CpbPtr->MemoryLength < (UINT32) MEMORY_NEEDED) {\r
357 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
358 CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;\r
359 return ;\r
360 }\r
361\r
362 //\r
363 // default behaviour is to detect the cable, if the 3rd param is 1,\r
364 // do not do that\r
365 //\r
366 AdapterInfo->CableDetect = (UINT8) ((CdbPtr->OpFlags == (UINT16) PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE) ? (UINT8) 0 : (UINT8) 1);\r
367 AdapterInfo->LinkSpeedReq = (UINT16) CpbPtr->LinkSpeed;\r
368 AdapterInfo->DuplexReq = CpbPtr->DuplexMode;\r
369 AdapterInfo->LoopBack = CpbPtr->LoopBackMode;\r
370 AdapterInfo->MemoryPtr = CpbPtr->MemoryAddr;\r
371 AdapterInfo->MemoryLength = CpbPtr->MemoryLength;\r
372\r
373 CdbPtr->StatCode = (PXE_STATCODE) E100bInit (AdapterInfo);\r
374\r
375 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
376 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
377 } else {\r
378 AdapterInfo->State = PXE_STATFLAGS_GET_STATE_INITIALIZED;\r
379 }\r
380\r
381 return ;\r
382}\r
383\r
40834173 384\r
ffa5008a 385/**\r
40834173 386 This routine resets the network adapter and initializes the UNDI using the parameters supplied in\r
387 the CPB. The transmit and receive queues are emptied and any pending interrupts are cleared.\r
40834173 388 If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED\r
389\r
ffa5008a 390 @param CdbPtr Pointer to the command descriptor block.\r
391 @param AdapterInfo Pointer to the NIC data structure information which\r
392 the UNDI driver is layering on..\r
40834173 393\r
ffa5008a 394 @return None\r
40834173 395\r
ffa5008a 396**/\r
397VOID\r
398UNDI_Reset (\r
399 IN PXE_CDB *CdbPtr,\r
400 IN NIC_DATA_INSTANCE *AdapterInfo\r
401 )\r
40834173 402{\r
403 if (CdbPtr->OpFlags != PXE_OPFLAGS_NOT_USED &&\r
404 CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS &&\r
405 CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS ) {\r
406\r
407 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
408 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
409 return ;\r
410 }\r
411\r
412 CdbPtr->StatCode = (UINT16) E100bReset (AdapterInfo, CdbPtr->OpFlags);\r
413\r
414 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
415 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
416 }\r
417}\r
418\r
40834173 419\r
ffa5008a 420/**\r
40834173 421 This routine resets the network adapter and leaves it in a safe state for another driver to\r
422 initialize. Any pending transmits or receives are lost. Receive filters and external\r
423 interrupt enables are disabled. Once the UNDI has been shutdown, it can then be stopped\r
424 or initialized again.\r
40834173 425 If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED\r
40834173 426 Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_STARTED showing the state of\r
427 the NIC as being started.\r
428\r
ffa5008a 429 @param CdbPtr Pointer to the command descriptor block.\r
430 @param AdapterInfo Pointer to the NIC data structure information which\r
431 the UNDI driver is layering on..\r
40834173 432\r
ffa5008a 433 @return None\r
40834173 434\r
ffa5008a 435**/\r
436VOID\r
437UNDI_Shutdown (\r
438 IN PXE_CDB *CdbPtr,\r
439 IN NIC_DATA_INSTANCE *AdapterInfo\r
440 )\r
40834173 441{\r
442 //\r
443 // do the shutdown stuff here\r
444 //\r
445 CdbPtr->StatCode = (UINT16) E100bShutdown (AdapterInfo);\r
446\r
447 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
448 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
449 } else {\r
450 AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED;\r
451 }\r
452\r
453 return ;\r
454}\r
455\r
40834173 456\r
ffa5008a 457/**\r
40834173 458 This routine can be used to read and/or change the current external interrupt enable\r
459 settings. Disabling an external interrupt enable prevents and external (hardware)\r
460 interrupt from being signaled by the network device. Internally the interrupt events\r
461 can still be polled by using the UNDI_GetState command.\r
40834173 462 The resulting information on the interrupt state will be passed back in the CdbPtr->StatFlags.\r
463\r
ffa5008a 464 @param CdbPtr Pointer to the command descriptor block.\r
465 @param AdapterInfo Pointer to the NIC data structure information which\r
466 the UNDI driver is layering on..\r
40834173 467\r
ffa5008a 468 @return None\r
40834173 469\r
ffa5008a 470**/\r
471VOID\r
472UNDI_Interrupt (\r
473 IN PXE_CDB *CdbPtr,\r
474 IN NIC_DATA_INSTANCE *AdapterInfo\r
475 )\r
40834173 476{\r
477 UINT8 IntMask;\r
478\r
479 IntMask = (UINT8)(UINTN)(CdbPtr->OpFlags & (PXE_OPFLAGS_INTERRUPT_RECEIVE |\r
480 PXE_OPFLAGS_INTERRUPT_TRANSMIT |\r
481 PXE_OPFLAGS_INTERRUPT_COMMAND |\r
482 PXE_OPFLAGS_INTERRUPT_SOFTWARE));\r
483\r
484 switch (CdbPtr->OpFlags & PXE_OPFLAGS_INTERRUPT_OPMASK) {\r
485 case PXE_OPFLAGS_INTERRUPT_READ:\r
486 break;\r
487\r
488 case PXE_OPFLAGS_INTERRUPT_ENABLE:\r
489 if (IntMask == 0) {\r
490 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
491 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
492 return ;\r
493 }\r
494\r
495 AdapterInfo->int_mask = IntMask;\r
496 E100bSetInterruptState (AdapterInfo);\r
497 break;\r
498\r
499 case PXE_OPFLAGS_INTERRUPT_DISABLE:\r
500 if (IntMask != 0) {\r
501 AdapterInfo->int_mask = (UINT16) (AdapterInfo->int_mask & ~(IntMask));\r
502 E100bSetInterruptState (AdapterInfo);\r
503 break;\r
504 }\r
505\r
506 //\r
507 // else fall thru.\r
508 //\r
509 default:\r
510 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
511 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
512 return ;\r
513 }\r
514\r
515 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) {\r
516 CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_RECEIVE;\r
517\r
518 }\r
519\r
520 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_TRANSMIT) != 0) {\r
521 CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_TRANSMIT;\r
522\r
523 }\r
524\r
525 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_COMMAND) != 0) {\r
526 CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_COMMAND;\r
527\r
528 }\r
529\r
530 return ;\r
531}\r
532\r
40834173 533\r
ffa5008a 534/**\r
40834173 535 This routine is used to read and change receive filters and, if supported, read\r
536 and change multicast MAC address filter list.\r
537\r
ffa5008a 538 @param CdbPtr Pointer to the command descriptor block.\r
539 @param AdapterInfo Pointer to the NIC data structure information which\r
540 the UNDI driver is layering on..\r
40834173 541\r
ffa5008a 542 @return None\r
40834173 543\r
ffa5008a 544**/\r
545VOID\r
546UNDI_RecFilter (\r
547 IN PXE_CDB *CdbPtr,\r
548 IN NIC_DATA_INSTANCE *AdapterInfo\r
549 )\r
40834173 550{\r
551 UINT16 NewFilter;\r
552 UINT16 OpFlags;\r
553 PXE_DB_RECEIVE_FILTERS *DbPtr;\r
554 UINT8 *MacAddr;\r
555 UINTN MacCount;\r
556 UINT16 Index;\r
557 UINT16 copy_len;\r
558 UINT8 *ptr1;\r
559 UINT8 *ptr2;\r
560 OpFlags = CdbPtr->OpFlags;\r
561 NewFilter = (UINT16) (OpFlags & 0x1F);\r
562\r
563 switch (OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) {\r
564 case PXE_OPFLAGS_RECEIVE_FILTER_READ:\r
565\r
566 //\r
567 // not expecting a cpb, not expecting any filter bits\r
568 //\r
569 if ((NewFilter != 0) || (CdbPtr->CPBsize != 0)) {\r
570 goto BadCdb;\r
571\r
572 }\r
573\r
574 if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == 0) {\r
575 goto JustRead;\r
576\r
577 }\r
578\r
579 NewFilter = (UINT16) (NewFilter | AdapterInfo->Rx_Filter);\r
580 //\r
581 // all other flags are ignored except mcast_reset\r
582 //\r
583 break;\r
584\r
585 case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE:\r
586 //\r
587 // there should be atleast one other filter bit set.\r
588 //\r
589 if (NewFilter == 0) {\r
590 //\r
591 // nothing to enable\r
592 //\r
593 goto BadCdb;\r
594 }\r
595\r
596 if (CdbPtr->CPBsize != 0) {\r
597 //\r
598 // this must be a multicast address list!\r
599 // don't accept the list unless selective_mcast is set\r
600 // don't accept confusing mcast settings with this\r
601 //\r
602 if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) ||\r
603 ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||\r
604 ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ||\r
605 ((CdbPtr->CPBsize % sizeof (PXE_MAC_ADDR)) != 0) ) {\r
606 goto BadCdb;\r
607 }\r
608\r
609 MacAddr = (UINT8 *) ((UINTN) (CdbPtr->CPBaddr));\r
610 MacCount = CdbPtr->CPBsize / sizeof (PXE_MAC_ADDR);\r
611\r
612 for (; MacCount-- != 0; MacAddr += sizeof (PXE_MAC_ADDR)) {\r
613 if (MacAddr[0] != 0x01 || MacAddr[1] != 0x00 || MacAddr[2] != 0x5E || (MacAddr[3] & 0x80) != 0) {\r
614 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
615 CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;\r
616 return ;\r
617 }\r
618 }\r
619 }\r
620\r
621 //\r
622 // check selective mcast case enable case\r
623 //\r
624 if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {\r
625 if (((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||\r
626 ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ) {\r
627 goto BadCdb;\r
628\r
629 }\r
630 //\r
631 // if no cpb, make sure we have an old list\r
632 //\r
633 if ((CdbPtr->CPBsize == 0) && (AdapterInfo->mcast_list.list_len == 0)) {\r
634 goto BadCdb;\r
635 }\r
636 }\r
637 //\r
638 // if you want to enable anything, you got to have unicast\r
639 // and you have what you already enabled!\r
640 //\r
641 NewFilter = (UINT16) (NewFilter | (PXE_OPFLAGS_RECEIVE_FILTER_UNICAST | AdapterInfo->Rx_Filter));\r
642\r
643 break;\r
644\r
645 case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE:\r
646\r
647 //\r
648 // mcast list not expected, i.e. no cpb here!\r
649 //\r
650 if (CdbPtr->CPBsize != PXE_CPBSIZE_NOT_USED) {\r
651 goto BadCdb;\r
652 }\r
653\r
654 NewFilter = (UINT16) ((~(CdbPtr->OpFlags & 0x1F)) & AdapterInfo->Rx_Filter);\r
655\r
656 break;\r
657\r
658 default:\r
659 goto BadCdb;\r
660 }\r
661\r
662 if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) {\r
663 AdapterInfo->mcast_list.list_len = 0;\r
664 NewFilter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);\r
665 }\r
666\r
667 E100bSetfilter (AdapterInfo, NewFilter, CdbPtr->CPBaddr, CdbPtr->CPBsize);\r
668\r
669JustRead:\r
670 //\r
671 // give the current mcast list\r
672 //\r
673 if ((CdbPtr->DBsize != 0) && (AdapterInfo->mcast_list.list_len != 0)) {\r
674 //\r
675 // copy the mc list to db\r
676 //\r
677\r
678 DbPtr = (PXE_DB_RECEIVE_FILTERS *) (UINTN) CdbPtr->DBaddr;\r
679 ptr1 = (UINT8 *) (&DbPtr->MCastList[0]);\r
680\r
681 //\r
682 // DbPtr->mc_count = AdapterInfo->mcast_list.list_len;\r
683 //\r
684 copy_len = (UINT16) (AdapterInfo->mcast_list.list_len * PXE_MAC_LENGTH);\r
685\r
686 if (copy_len > CdbPtr->DBsize) {\r
687 copy_len = CdbPtr->DBsize;\r
688\r
689 }\r
690\r
691 ptr2 = (UINT8 *) (&AdapterInfo->mcast_list.mc_list[0]);\r
692 for (Index = 0; Index < copy_len; Index++) {\r
693 ptr1[Index] = ptr2[Index];\r
694 }\r
695 }\r
696 //\r
697 // give the stat flags here\r
698 //\r
699 if (AdapterInfo->Receive_Started) {\r
700 CdbPtr->StatFlags = (PXE_STATFLAGS) (CdbPtr->StatFlags | AdapterInfo->Rx_Filter);\r
701\r
702 }\r
703\r
704 return ;\r
705\r
706BadCdb:\r
707 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
708 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
709}\r
710\r
40834173 711\r
ffa5008a 712/**\r
40834173 713 This routine is used to get the current station and broadcast MAC addresses, and to change the\r
714 current station MAC address.\r
715\r
ffa5008a 716 @param CdbPtr Pointer to the command descriptor block.\r
717 @param AdapterInfo Pointer to the NIC data structure information which\r
718 the UNDI driver is layering on..\r
40834173 719\r
ffa5008a 720 @return None\r
40834173 721\r
ffa5008a 722**/\r
723VOID\r
724UNDI_StnAddr (\r
725 IN PXE_CDB *CdbPtr,\r
726 IN NIC_DATA_INSTANCE *AdapterInfo\r
727 )\r
40834173 728{\r
729 PXE_CPB_STATION_ADDRESS *CpbPtr;\r
730 PXE_DB_STATION_ADDRESS *DbPtr;\r
731 UINT16 Index;\r
732\r
733 if (CdbPtr->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) {\r
734 //\r
735 // configure the permanent address.\r
736 // change the AdapterInfo->CurrentNodeAddress field.\r
737 //\r
738 if (CompareMem (\r
739 &AdapterInfo->CurrentNodeAddress[0],\r
740 &AdapterInfo->PermNodeAddress[0],\r
741 PXE_MAC_LENGTH\r
742 ) != 0) {\r
743 for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {\r
744 AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];\r
745 }\r
746\r
747 E100bSetupIAAddr (AdapterInfo);\r
748 }\r
749 }\r
750\r
751 if (CdbPtr->CPBaddr != (UINT64) 0) {\r
752 CpbPtr = (PXE_CPB_STATION_ADDRESS *) (UINTN) (CdbPtr->CPBaddr);\r
753 //\r
754 // configure the new address\r
755 //\r
756 for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {\r
757 AdapterInfo->CurrentNodeAddress[Index] = CpbPtr->StationAddr[Index];\r
758 }\r
759\r
760 E100bSetupIAAddr (AdapterInfo);\r
761 }\r
762\r
763 if (CdbPtr->DBaddr != (UINT64) 0) {\r
764 DbPtr = (PXE_DB_STATION_ADDRESS *) (UINTN) (CdbPtr->DBaddr);\r
765 //\r
766 // fill it with the new values\r
767 //\r
768 for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {\r
769 DbPtr->StationAddr[Index] = AdapterInfo->CurrentNodeAddress[Index];\r
770 DbPtr->BroadcastAddr[Index] = AdapterInfo->BroadcastNodeAddress[Index];\r
771 DbPtr->PermanentAddr[Index] = AdapterInfo->PermNodeAddress[Index];\r
772 }\r
773 }\r
774\r
775 return ;\r
776}\r
777\r
40834173 778\r
ffa5008a 779/**\r
40834173 780 This routine is used to read and clear the NIC traffic statistics. This command is supported only\r
781 if the !PXE structure's Implementation flags say so.\r
40834173 782 Results will be parsed out in the following manner:\r
783 CdbPtr->DBaddr.Data[0] R Total Frames (Including frames with errors and dropped frames)\r
784 CdbPtr->DBaddr.Data[1] R Good Frames (All frames copied into receive buffer)\r
785 CdbPtr->DBaddr.Data[2] R Undersize Frames (Frames below minimum length for media <64 for ethernet)\r
786 CdbPtr->DBaddr.Data[4] R Dropped Frames (Frames that were dropped because receive buffers were full)\r
787 CdbPtr->DBaddr.Data[8] R CRC Error Frames (Frames with alignment or CRC errors)\r
788 CdbPtr->DBaddr.Data[A] T Total Frames (Including frames with errors and dropped frames)\r
789 CdbPtr->DBaddr.Data[B] T Good Frames (All frames copied into transmit buffer)\r
790 CdbPtr->DBaddr.Data[C] T Undersize Frames (Frames below minimum length for media <64 for ethernet)\r
791 CdbPtr->DBaddr.Data[E] T Dropped Frames (Frames that were dropped because of collisions)\r
792 CdbPtr->DBaddr.Data[14] T Total Collision Frames (Total collisions on this subnet)\r
793\r
ffa5008a 794 @param CdbPtr Pointer to the command descriptor block.\r
795 @param AdapterInfo Pointer to the NIC data structure information which\r
796 the UNDI driver is layering on..\r
40834173 797\r
ffa5008a 798 @return None\r
40834173 799\r
ffa5008a 800**/\r
801VOID\r
802UNDI_Statistics (\r
803 IN PXE_CDB *CdbPtr,\r
804 IN NIC_DATA_INSTANCE *AdapterInfo\r
805 )\r
40834173 806{\r
807 if ((CdbPtr->OpFlags &~(PXE_OPFLAGS_STATISTICS_RESET)) != 0) {\r
808 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
809 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
810 return ;\r
811 }\r
812\r
813 if ((CdbPtr->OpFlags & PXE_OPFLAGS_STATISTICS_RESET) != 0) {\r
814 //\r
815 // Reset the statistics\r
816 //\r
817 CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, 0, 0);\r
818 } else {\r
819 CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, CdbPtr->DBaddr, CdbPtr->DBsize);\r
820 }\r
821\r
822 return ;\r
823}\r
824\r
40834173 825\r
ffa5008a 826/**\r
40834173 827 This routine is used to translate a multicast IP address to a multicast MAC address.\r
40834173 828 This results in a MAC address composed of 25 bits of fixed data with the upper 23 bits of the IP\r
829 address being appended to it. Results passed back in the equivalent of CdbPtr->DBaddr->MAC[0-5].\r
830\r
ffa5008a 831 @param CdbPtr Pointer to the command descriptor block.\r
832 @param AdapterInfo Pointer to the NIC data structure information which\r
833 the UNDI driver is layering on..\r
40834173 834\r
ffa5008a 835 @return None\r
40834173 836\r
ffa5008a 837**/\r
838VOID\r
839UNDI_ip2mac (\r
840 IN PXE_CDB *CdbPtr,\r
841 IN NIC_DATA_INSTANCE *AdapterInfo\r
842 )\r
40834173 843{\r
844 PXE_CPB_MCAST_IP_TO_MAC *CpbPtr;\r
845 PXE_DB_MCAST_IP_TO_MAC *DbPtr;\r
846 UINT8 *TmpPtr;\r
847\r
848 CpbPtr = (PXE_CPB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->CPBaddr;\r
849 DbPtr = (PXE_DB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->DBaddr;\r
850\r
851 if ((CdbPtr->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) {\r
852 //\r
853 // for now this is not supported\r
854 //\r
855 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
856 CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED;\r
857 return ;\r
858 }\r
859\r
860 TmpPtr = (UINT8 *) (&CpbPtr->IP.IPv4);\r
861 //\r
862 // check if the ip given is a mcast IP\r
863 //\r
864 if ((TmpPtr[0] & 0xF0) != 0xE0) {\r
865 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
866 CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;\r
867 }\r
868 //\r
869 // take the last 23 bits in IP.\r
870 // be very careful. accessing word on a non-word boundary will hang motherboard codenamed Big Sur\r
871 // casting the mac array (in the middle) to a UINT32 pointer and accessing\r
872 // the UINT32 content hung the system...\r
873 //\r
874 DbPtr->MAC[0] = 0x01;\r
875 DbPtr->MAC[1] = 0x00;\r
876 DbPtr->MAC[2] = 0x5e;\r
877 DbPtr->MAC[3] = (UINT8) (TmpPtr[1] & 0x7f);\r
878 DbPtr->MAC[4] = (UINT8) TmpPtr[2];\r
879 DbPtr->MAC[5] = (UINT8) TmpPtr[3];\r
880\r
881 return ;\r
882}\r
883\r
40834173 884\r
ffa5008a 885/**\r
40834173 886 This routine is used to read and write non-volatile storage on the NIC (if supported). The NVRAM\r
887 could be EEPROM, FLASH, or battery backed RAM.\r
40834173 888 This is an optional function according to the UNDI specification (or will be......)\r
889\r
ffa5008a 890 @param CdbPtr Pointer to the command descriptor block.\r
891 @param AdapterInfo Pointer to the NIC data structure information which\r
892 the UNDI driver is layering on..\r
40834173 893\r
ffa5008a 894 @return None\r
40834173 895\r
ffa5008a 896**/\r
897VOID\r
898UNDI_NVData (\r
899 IN PXE_CDB *CdbPtr,\r
900 IN NIC_DATA_INSTANCE *AdapterInfo\r
901 )\r
40834173 902{\r
903 PXE_DB_NVDATA *DbPtr;\r
904 UINT16 Index;\r
905\r
906 if ((CdbPtr->OpFlags == PXE_OPFLAGS_NVDATA_READ) != 0) {\r
907\r
908 if ((CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) != 0) {\r
909 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
910 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
911 return ;\r
912 }\r
913\r
914 DbPtr = (PXE_DB_NVDATA *) (UINTN) CdbPtr->DBaddr;\r
915\r
916 for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) {\r
917 DbPtr->Data.Dword[Index] = AdapterInfo->NVData[Index];\r
918\r
919 }\r
920\r
921 } else {\r
922 //\r
923 // no write for now\r
924 //\r
925 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
926 CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED;\r
927 }\r
928\r
929 return ;\r
930}\r
931\r
40834173 932\r
ffa5008a 933/**\r
40834173 934 This routine returns the current interrupt status and/or the transmitted buffer addresses.\r
935 If the current interrupt status is returned, pending interrupts will be acknowledged by this\r
936 command. Transmitted buffer addresses that are written to the DB are removed from the transmit\r
937 buffer queue.\r
40834173 938 Normally, this command would be polled with interrupts disabled.\r
40834173 939 The transmit buffers are returned in CdbPtr->DBaddr->TxBufer[0 - NumEntries].\r
940 The interrupt status is returned in CdbPtr->StatFlags.\r
941\r
ffa5008a 942 @param CdbPtr Pointer to the command descriptor block.\r
943 @param AdapterInfo Pointer to the NIC data structure information which\r
944 the UNDI driver is layering on..\r
40834173 945\r
ffa5008a 946 @return None\r
40834173 947\r
ffa5008a 948**/\r
949VOID\r
950UNDI_Status (\r
951 IN PXE_CDB *CdbPtr,\r
952 IN NIC_DATA_INSTANCE *AdapterInfo\r
953 )\r
40834173 954{\r
955 PXE_DB_GET_STATUS *DbPtr;\r
956 PXE_DB_GET_STATUS TmpGetStatus;\r
957 UINT16 Index;\r
958 UINT16 Status;\r
959 UINT16 NumEntries;\r
960 RxFD *RxPtr;\r
961\r
962 //\r
963 // Fill in temporary GetStatus storage.\r
964 //\r
965 RxPtr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];\r
966\r
967 if ((RxPtr->cb_header.status & RX_COMPLETE) != 0) {\r
968 TmpGetStatus.RxFrameLen = RxPtr->ActualCount & 0x3fff;\r
969 } else {\r
970 TmpGetStatus.RxFrameLen = 0;\r
971 }\r
972\r
973 TmpGetStatus.reserved = 0;\r
974\r
975 //\r
976 // Fill in size of next available receive packet and\r
977 // reserved field in caller's DB storage.\r
978 //\r
979 DbPtr = (PXE_DB_GET_STATUS *) (UINTN) CdbPtr->DBaddr;\r
980\r
981 if (CdbPtr->DBsize > 0 && CdbPtr->DBsize < sizeof (UINT32) * 2) {\r
982 CopyMem (DbPtr, &TmpGetStatus, CdbPtr->DBsize);\r
983 } else {\r
984 CopyMem (DbPtr, &TmpGetStatus, sizeof (UINT32) * 2);\r
985 }\r
986\r
987 //\r
988 //\r
989 //\r
990 if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) {\r
991 //\r
992 // DBsize of zero is invalid if Tx buffers are requested.\r
993 //\r
994 if (CdbPtr->DBsize == 0) {\r
995 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
996 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
997 return ;\r
998 }\r
999\r
1000 //\r
1001 // remember this b4 we overwrite\r
1002 //\r
1003 NumEntries = (UINT16) (CdbPtr->DBsize - sizeof (UINT64));\r
1004\r
1005 //\r
1006 // We already filled in 2 UINT32s.\r
1007 //\r
1008 CdbPtr->DBsize = sizeof (UINT32) * 2;\r
1009\r
1010 //\r
1011 // will claim any hanging free CBs\r
1012 //\r
1013 CheckCBList (AdapterInfo);\r
1014\r
1015 if (AdapterInfo->xmit_done_head == AdapterInfo->xmit_done_tail) {\r
1016 CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY;\r
1017 } else {\r
1018 for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries -= sizeof (UINT64)) {\r
1019 if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {\r
1020 DbPtr->TxBuffer[Index] = AdapterInfo->xmit_done[AdapterInfo->xmit_done_head];\r
1021 AdapterInfo->xmit_done_head = next (AdapterInfo->xmit_done_head);\r
1022 CdbPtr->DBsize += sizeof (UINT64);\r
1023 } else {\r
1024 break;\r
1025 }\r
1026 }\r
1027 }\r
1028\r
1029 if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {\r
1030 CdbPtr->StatFlags |= PXE_STATFLAGS_DB_WRITE_TRUNCATED;\r
1031\r
1032 }\r
1033 //\r
1034 // check for a receive buffer and give it's size in db\r
1035 //\r
1036 }\r
1037 //\r
1038 //\r
1039 //\r
1040 if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) {\r
1041\r
1042 Status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);\r
1043 AdapterInfo->Int_Status = (UINT16) (AdapterInfo->Int_Status | Status);\r
1044\r
1045 //\r
1046 // acknoledge the interrupts\r
1047 //\r
1048 OutWord (AdapterInfo, (UINT16) (Status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus));\r
1049\r
1050 //\r
1051 // report all the outstanding interrupts\r
1052 //\r
1053 Status = AdapterInfo->Int_Status;\r
1054 if ((Status & SCB_STATUS_FR) != 0) {\r
1055 CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;\r
1056 }\r
1057\r
1058 if ((Status & SCB_STATUS_SWI) != 0) {\r
1059 CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_SOFTWARE;\r
1060 }\r
1061 }\r
1062\r
1063 return ;\r
1064}\r
1065\r
40834173 1066\r
ffa5008a 1067/**\r
40834173 1068 This routine is used to fill media header(s) in transmit packet(s).\r
1069 Copies the MAC address into the media header whether it is dealing\r
1070 with fragmented or non-fragmented packets.\r
1071\r
ffa5008a 1072 @param CdbPtr Pointer to the command descriptor block.\r
1073 @param AdapterInfo Pointer to the NIC data structure information which\r
1074 the UNDI driver is layering on..\r
40834173 1075\r
ffa5008a 1076 @return None\r
40834173 1077\r
ffa5008a 1078**/\r
1079VOID\r
1080UNDI_FillHeader (\r
1081 IN PXE_CDB *CdbPtr,\r
1082 IN NIC_DATA_INSTANCE *AdapterInfo\r
1083 )\r
40834173 1084{\r
1085 PXE_CPB_FILL_HEADER *Cpb;\r
1086 PXE_CPB_FILL_HEADER_FRAGMENTED *Cpbf;\r
1087 EtherHeader *MacHeader;\r
1088 UINTN Index;\r
1089\r
1090 if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {\r
1091 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1092 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1093 return ;\r
1094 }\r
1095\r
1096 if ((CdbPtr->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) {\r
1097 Cpbf = (PXE_CPB_FILL_HEADER_FRAGMENTED *) (UINTN) CdbPtr->CPBaddr;\r
1098\r
1099 //\r
1100 // assume 1st fragment is big enough for the mac header\r
1101 //\r
1102 if ((Cpbf->FragCnt == 0) || (Cpbf->FragDesc[0].FragLen < PXE_MAC_HEADER_LEN_ETHER)) {\r
1103 //\r
1104 // no buffers given\r
1105 //\r
1106 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1107 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1108 return ;\r
1109 }\r
1110\r
1111 MacHeader = (EtherHeader *) (UINTN) Cpbf->FragDesc[0].FragAddr;\r
1112 //\r
1113 // we don't swap the protocol bytes\r
1114 //\r
1115 MacHeader->type = Cpbf->Protocol;\r
1116\r
1117 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {\r
1118 MacHeader->dest_addr[Index] = Cpbf->DestAddr[Index];\r
1119 MacHeader->src_addr[Index] = Cpbf->SrcAddr[Index];\r
1120 }\r
1121 } else {\r
1122 Cpb = (PXE_CPB_FILL_HEADER *) (UINTN) CdbPtr->CPBaddr;\r
1123\r
1124 MacHeader = (EtherHeader *) (UINTN) Cpb->MediaHeader;\r
1125 //\r
1126 // we don't swap the protocol bytes\r
1127 //\r
1128 MacHeader->type = Cpb->Protocol;\r
1129\r
1130 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {\r
1131 MacHeader->dest_addr[Index] = Cpb->DestAddr[Index];\r
1132 MacHeader->src_addr[Index] = Cpb->SrcAddr[Index];\r
1133 }\r
1134 }\r
1135\r
1136 return ;\r
1137}\r
1138\r
40834173 1139\r
ffa5008a 1140/**\r
40834173 1141 This routine is used to place a packet into the transmit queue. The data buffers given to\r
1142 this command are to be considered locked and the application or network driver loses\r
1143 ownership of these buffers and must not free or relocate them until the ownership returns.\r
40834173 1144 When the packets are transmitted, a transmit complete interrupt is generated (if interrupts\r
1145 are disabled, the transmit interrupt status is still set and can be checked using the UNDI_Status\r
1146 command.\r
40834173 1147 Some implementations and adapters support transmitting multiple packets with one transmit\r
1148 command. If this feature is supported, the transmit CPBs can be linked in one transmit\r
1149 command.\r
40834173 1150 All UNDIs support fragmented frames, now all network devices or protocols do. If a fragmented\r
1151 frame CPB is given to UNDI and the network device does not support fragmented frames\r
1152 (see !PXE.Implementation flag), the UNDI will have to copy the fragments into a local buffer\r
1153 before transmitting.\r
1154\r
ffa5008a 1155 @param CdbPtr Pointer to the command descriptor block.\r
1156 @param AdapterInfo Pointer to the NIC data structure information which\r
1157 the UNDI driver is layering on..\r
40834173 1158\r
ffa5008a 1159 @return None\r
40834173 1160\r
ffa5008a 1161**/\r
1162VOID\r
1163UNDI_Transmit (\r
1164 IN PXE_CDB *CdbPtr,\r
1165 IN NIC_DATA_INSTANCE *AdapterInfo\r
1166 )\r
40834173 1167{\r
1168\r
1169 if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {\r
1170 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1171 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1172 return ;\r
1173 }\r
1174\r
1175 CdbPtr->StatCode = (PXE_STATCODE) E100bTransmit (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->OpFlags);\r
1176\r
1177 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
1178 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1179 }\r
1180\r
1181 return ;\r
1182}\r
1183\r
40834173 1184\r
ffa5008a 1185/**\r
40834173 1186 When the network adapter has received a frame, this command is used to copy the frame\r
1187 into the driver/application storage location. Once a frame has been copied, it is\r
1188 removed from the receive queue.\r
1189\r
ffa5008a 1190 @param CdbPtr Pointer to the command descriptor block.\r
1191 @param AdapterInfo Pointer to the NIC data structure information which\r
1192 the UNDI driver is layering on..\r
40834173 1193\r
ffa5008a 1194 @return None\r
40834173 1195\r
ffa5008a 1196**/\r
1197VOID\r
1198UNDI_Receive (\r
1199 IN PXE_CDB *CdbPtr,\r
1200 IN NIC_DATA_INSTANCE *AdapterInfo\r
1201 )\r
40834173 1202{\r
1203\r
1204 //\r
1205 // check if RU has started...\r
1206 //\r
1207 if (!AdapterInfo->Receive_Started) {\r
1208 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1209 CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED;\r
1210 return ;\r
1211 }\r
1212\r
1213\r
1214 CdbPtr->StatCode = (UINT16) E100bReceive (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->DBaddr);\r
1215 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
1216 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1217\r
1218 }\r
1219\r
1220 return ;\r
1221}\r
1222\r
40834173 1223\r
40834173 1224\r
ffa5008a 1225/**\r
40834173 1226 This is the main SW UNDI API entry using the newer nii protocol.\r
1227 The parameter passed in is a 64 bit flat model virtual\r
1228 address of the cdb. We then jump into the common routine for both old and\r
1229 new nii protocol entries.\r
1230\r
ffa5008a 1231 @param CdbPtr Pointer to the command descriptor block.\r
1232 @param AdapterInfo Pointer to the NIC data structure information which\r
1233 the UNDI driver is layering on..\r
40834173 1234\r
ffa5008a 1235 @return None\r
40834173 1236\r
ffa5008a 1237**/\r
40834173 1238// TODO: cdb - add argument and description to function comment\r
ffa5008a 1239VOID\r
1240UNDI_APIEntry_new (\r
1241 IN UINT64 cdb\r
1242 )\r
40834173 1243{\r
1244 PXE_CDB *CdbPtr;\r
1245 NIC_DATA_INSTANCE *AdapterInfo;\r
1246\r
1247 if (cdb == (UINT64) 0) {\r
1248 return ;\r
1249\r
1250 }\r
1251\r
1252 CdbPtr = (PXE_CDB *) (UINTN) cdb;\r
1253\r
1254 if (CdbPtr->IFnum >= pxe_31->IFcnt) {\r
1255 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1256 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1257 return ;\r
1258 }\r
1259\r
1260 AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);\r
1261 //\r
1262 // entering from older entry point\r
1263 //\r
1264 AdapterInfo->VersionFlag = 0x31;\r
1265 UNDI_APIEntry_Common (cdb);\r
1266}\r
1267\r
40834173 1268\r
ffa5008a 1269/**\r
40834173 1270 This is the common routine for both old and new entry point procedures.\r
1271 The parameter passed in is a 64 bit flat model virtual\r
1272 address of the cdb. We then jump into the service routine pointed to by the\r
1273 Api_Table[OpCode].\r
1274\r
ffa5008a 1275 @param CdbPtr Pointer to the command descriptor block.\r
1276 @param AdapterInfo Pointer to the NIC data structure information which\r
1277 the UNDI driver is layering on..\r
40834173 1278\r
ffa5008a 1279 @return None\r
40834173 1280\r
ffa5008a 1281**/\r
40834173 1282// TODO: cdb - add argument and description to function comment\r
ffa5008a 1283VOID\r
1284UNDI_APIEntry_Common (\r
1285 IN UINT64 cdb\r
1286 )\r
40834173 1287{\r
1288 PXE_CDB *CdbPtr;\r
1289 NIC_DATA_INSTANCE *AdapterInfo;\r
1290 UNDI_CALL_TABLE *tab_ptr;\r
1291\r
1292 CdbPtr = (PXE_CDB *) (UINTN) cdb;\r
1293\r
1294 //\r
1295 // check the OPCODE range\r
1296 //\r
1297 if ((CdbPtr->OpCode > PXE_OPCODE_LAST_VALID) ||\r
1298 (CdbPtr->StatCode != PXE_STATCODE_INITIALIZE) ||\r
1299 (CdbPtr->StatFlags != PXE_STATFLAGS_INITIALIZE) ||\r
1300 (CdbPtr->IFnum >= pxe_31->IFcnt) ) {\r
1301 goto badcdb;\r
1302\r
1303 }\r
1304\r
1305 if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {\r
1306 if (CdbPtr->CPBaddr != PXE_CPBADDR_NOT_USED) {\r
1307 goto badcdb;\r
1308 }\r
1309 } else if (CdbPtr->CPBaddr == PXE_CPBADDR_NOT_USED) {\r
1310 goto badcdb;\r
1311 }\r
1312\r
1313 if (CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) {\r
1314 if (CdbPtr->DBaddr != PXE_DBADDR_NOT_USED) {\r
1315 goto badcdb;\r
1316 }\r
1317 } else if (CdbPtr->DBaddr == PXE_DBADDR_NOT_USED) {\r
1318 goto badcdb;\r
1319 }\r
1320\r
1321 //\r
1322 // check if cpbsize and dbsize are as needed\r
1323 // check if opflags are as expected\r
1324 //\r
1325 tab_ptr = &api_table[CdbPtr->OpCode];\r
1326\r
1327 if (tab_ptr->cpbsize != (UINT16) (DONT_CHECK) && tab_ptr->cpbsize != CdbPtr->CPBsize) {\r
1328 goto badcdb;\r
1329 }\r
1330\r
1331 if (tab_ptr->dbsize != (UINT16) (DONT_CHECK) && tab_ptr->dbsize != CdbPtr->DBsize) {\r
1332 goto badcdb;\r
1333 }\r
1334\r
1335 if (tab_ptr->opflags != (UINT16) (DONT_CHECK) && tab_ptr->opflags != CdbPtr->OpFlags) {\r
1336 goto badcdb;\r
1337\r
1338 }\r
1339\r
1340 AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);\r
1341\r
1342 //\r
1343 // check if UNDI_State is valid for this call\r
1344 //\r
1345 if (tab_ptr->state != (UINT16) (-1)) {\r
1346 //\r
1347 // should atleast be started\r
1348 //\r
1349 if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_STOPPED) {\r
1350 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1351 CdbPtr->StatCode = PXE_STATCODE_NOT_STARTED;\r
1352 return ;\r
1353 }\r
1354 //\r
1355 // check if it should be initialized\r
1356 //\r
1357 if (tab_ptr->state == 2) {\r
1358 if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {\r
1359 CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED;\r
1360 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1361 return ;\r
1362 }\r
1363 }\r
1364 }\r
1365 //\r
1366 // set the return variable for success case here\r
1367 //\r
1368 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;\r
1369 CdbPtr->StatCode = PXE_STATCODE_SUCCESS;\r
1370\r
1371 tab_ptr->api_ptr (CdbPtr, AdapterInfo);\r
1372 return ;\r
1373 //\r
1374 // %% AVL - check for command linking\r
1375 //\r
1376badcdb:\r
1377 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1378 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1379 return ;\r
1380}\r
1381\r
40834173 1382\r
ffa5008a 1383/**\r
40834173 1384 When called with a null NicPtr, this routine decrements the number of NICs\r
1385 this UNDI is supporting and removes the NIC_DATA_POINTER from the array.\r
1386 Otherwise, it increments the number of NICs this UNDI is supported and\r
1387 updates the pxe.Fudge to ensure a proper check sum results.\r
1388\r
ffa5008a 1389 @param NicPtr Pointer to the NIC data structure.\r
40834173 1390\r
ffa5008a 1391 @return None\r
40834173 1392\r
ffa5008a 1393**/\r
ffa5008a 1394VOID\r
1395PxeUpdate (\r
1396 IN NIC_DATA_INSTANCE *NicPtr,\r
1397 IN PXE_SW_UNDI *PxePtr\r
1398 )\r
40834173 1399{\r
1400 if (NicPtr == NULL) {\r
1401 if (PxePtr->IFcnt > 0) {\r
1402 //\r
1403 // number of NICs this undi supports\r
1404 //\r
1405 PxePtr->IFcnt--;\r
1406 }\r
1407\r
7e038442 1408 PxePtr->Fudge = (UINT8) (PxePtr->Fudge - CalculateSum8 ((VOID *) PxePtr, PxePtr->Len));\r
40834173 1409 return ;\r
1410 }\r
1411\r
1412 //\r
1413 // number of NICs this undi supports\r
1414 //\r
1415 PxePtr->IFcnt++;\r
7e038442 1416 PxePtr->Fudge = (UINT8) (PxePtr->Fudge - CalculateSum8 ((VOID *) PxePtr, PxePtr->Len));\r
40834173 1417\r
1418 return ;\r
1419}\r
1420\r
40834173 1421\r
ffa5008a 1422/**\r
40834173 1423 Initialize the !PXE structure\r
1424\r
7e038442 1425 @param PxePtr Pointer to SW_UNDI data structure.\r
40834173 1426\r
ffa5008a 1427 @retval EFI_SUCCESS This driver is added to Controller.\r
1428 @retval other This driver does not support this device.\r
40834173 1429\r
ffa5008a 1430**/\r
ffa5008a 1431VOID\r
1432PxeStructInit (\r
1433 IN PXE_SW_UNDI *PxePtr\r
1434 )\r
40834173 1435{\r
1436 //\r
1437 // Initialize the !PXE structure\r
1438 //\r
1439 PxePtr->Signature = PXE_ROMID_SIGNATURE;\r
1440 PxePtr->Len = sizeof (PXE_SW_UNDI);\r
1441 //\r
1442 // cksum\r
1443 //\r
1444 PxePtr->Fudge = 0;\r
1445 //\r
1446 // number of NICs this undi supports\r
1447 //\r
1448 PxePtr->IFcnt = 0;\r
1449 PxePtr->Rev = PXE_ROMID_REV;\r
1450 PxePtr->MajorVer = PXE_ROMID_MAJORVER;\r
1451 PxePtr->MinorVer = PXE_ROMID_MINORVER;\r
1452 PxePtr->reserved1 = 0;\r
1453\r
1454 PxePtr->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR |\r
1455 PXE_ROMID_IMP_FRAG_SUPPORTED |\r
1456 PXE_ROMID_IMP_CMD_LINK_SUPPORTED |\r
1457 PXE_ROMID_IMP_NVDATA_READ_ONLY |\r
1458 PXE_ROMID_IMP_STATION_ADDR_SETTABLE |\r
1459 PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED |\r
1460 PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED |\r
1461 PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED |\r
1462 PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED |\r
1463 PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED |\r
1464 PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED;\r
1465\r
1be0dda6 1466 PxePtr->EntryPoint = (UINT64) (UINTN) UNDI_APIEntry_new;\r
41057d77 1467 PxePtr->MinorVer = PXE_ROMID_MINORVER_31;\r
40834173 1468\r
1469 PxePtr->reserved2[0] = 0;\r
1470 PxePtr->reserved2[1] = 0;\r
1471 PxePtr->reserved2[2] = 0;\r
1472 PxePtr->BusCnt = 1;\r
1473 PxePtr->BusType[0] = PXE_BUSTYPE_PCI;\r
1474\r
7e038442 1475 PxePtr->Fudge = (UINT8) (PxePtr->Fudge - CalculateSum8 ((VOID *) PxePtr, PxePtr->Len));\r
40834173 1476}\r
1477\r