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