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