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