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