]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c
Initial import.
[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
27//\r
28// Global variables defined outside this file\r
29//\r
30extern PXE_SW_UNDI *pxe; // !pxe structure\r
31extern PXE_SW_UNDI *pxe_31; // !pxe structure for 3.1 drivers\r
32extern UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];\r
33\r
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
92 CdbPtr->StatFlags |= AdapterInfo->State;\r
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
380 PXE_DB_INITIALIZE *DbPtr;\r
381\r
382 if ((CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) &&\r
383 (CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) {\r
384 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
385 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
386 return ;\r
387 }\r
388\r
389 //\r
390 // check if it is already initialized\r
391 //\r
392 if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {\r
393 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
394 CdbPtr->StatCode = PXE_STATCODE_ALREADY_INITIALIZED;\r
395 return ;\r
396 }\r
397\r
398 CpbPtr = (PXE_CPB_INITIALIZE *) (UINTN) CdbPtr->CPBaddr;\r
399 DbPtr = (PXE_DB_INITIALIZE *) (UINTN) CdbPtr->DBaddr;\r
400\r
401 if (CpbPtr->MemoryLength < (UINT32) MEMORY_NEEDED) {\r
402 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
403 CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;\r
404 return ;\r
405 }\r
406\r
407 //\r
408 // default behaviour is to detect the cable, if the 3rd param is 1,\r
409 // do not do that\r
410 //\r
411 AdapterInfo->CableDetect = (UINT8) ((CdbPtr->OpFlags == (UINT16) PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE) ? (UINT8) 0 : (UINT8) 1);\r
412 AdapterInfo->LinkSpeedReq = (UINT16) CpbPtr->LinkSpeed;\r
413 AdapterInfo->DuplexReq = CpbPtr->DuplexMode;\r
414 AdapterInfo->LoopBack = CpbPtr->LoopBackMode;\r
415 AdapterInfo->MemoryPtr = CpbPtr->MemoryAddr;\r
416 AdapterInfo->MemoryLength = CpbPtr->MemoryLength;\r
417\r
418 CdbPtr->StatCode = (PXE_STATCODE) E100bInit (AdapterInfo);\r
419\r
420 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
421 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
422 } else {\r
423 AdapterInfo->State = PXE_STATFLAGS_GET_STATE_INITIALIZED;\r
424 }\r
425\r
426 return ;\r
427}\r
428\r
429VOID\r
430UNDI_Reset (\r
431 IN PXE_CDB *CdbPtr,\r
432 IN NIC_DATA_INSTANCE *AdapterInfo\r
433 )\r
434/*++\r
435\r
436Routine Description:\r
437 This routine resets the network adapter and initializes the UNDI using the parameters supplied in\r
438 the CPB. The transmit and receive queues are emptied and any pending interrupts are cleared.\r
439\r
440 If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED\r
441\r
442Arguments:\r
443 CdbPtr - Pointer to the command descriptor block.\r
444 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
445\r
446Returns:\r
447 None\r
448\r
449--*/\r
450{\r
451 if (CdbPtr->OpFlags != PXE_OPFLAGS_NOT_USED &&\r
452 CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS &&\r
453 CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS ) {\r
454\r
455 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
456 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
457 return ;\r
458 }\r
459\r
460 CdbPtr->StatCode = (UINT16) E100bReset (AdapterInfo, CdbPtr->OpFlags);\r
461\r
462 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
463 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
464 }\r
465}\r
466\r
467VOID\r
468UNDI_Shutdown (\r
469 IN PXE_CDB *CdbPtr,\r
470 IN NIC_DATA_INSTANCE *AdapterInfo\r
471 )\r
472/*++\r
473\r
474Routine Description:\r
475 This routine resets the network adapter and leaves it in a safe state for another driver to\r
476 initialize. Any pending transmits or receives are lost. Receive filters and external\r
477 interrupt enables are disabled. Once the UNDI has been shutdown, it can then be stopped\r
478 or initialized again.\r
479\r
480 If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED\r
481\r
482 Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_STARTED showing the state of\r
483 the NIC as being started.\r
484\r
485Arguments:\r
486 CdbPtr - Pointer to the command descriptor block.\r
487 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
488\r
489Returns:\r
490 None\r
491\r
492--*/\r
493{\r
494 //\r
495 // do the shutdown stuff here\r
496 //\r
497 CdbPtr->StatCode = (UINT16) E100bShutdown (AdapterInfo);\r
498\r
499 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
500 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
501 } else {\r
502 AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED;\r
503 }\r
504\r
505 return ;\r
506}\r
507\r
508VOID\r
509UNDI_Interrupt (\r
510 IN PXE_CDB *CdbPtr,\r
511 IN NIC_DATA_INSTANCE *AdapterInfo\r
512 )\r
513/*++\r
514\r
515Routine Description:\r
516 This routine can be used to read and/or change the current external interrupt enable\r
517 settings. Disabling an external interrupt enable prevents and external (hardware)\r
518 interrupt from being signaled by the network device. Internally the interrupt events\r
519 can still be polled by using the UNDI_GetState command.\r
520\r
521 The resulting information on the interrupt state will be passed back in the CdbPtr->StatFlags.\r
522\r
523Arguments:\r
524 CdbPtr - Pointer to the command descriptor block.\r
525 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
526\r
527Returns:\r
528 None\r
529\r
530--*/\r
531{\r
532 UINT8 IntMask;\r
533\r
534 IntMask = (UINT8)(UINTN)(CdbPtr->OpFlags & (PXE_OPFLAGS_INTERRUPT_RECEIVE |\r
535 PXE_OPFLAGS_INTERRUPT_TRANSMIT |\r
536 PXE_OPFLAGS_INTERRUPT_COMMAND |\r
537 PXE_OPFLAGS_INTERRUPT_SOFTWARE));\r
538\r
539 switch (CdbPtr->OpFlags & PXE_OPFLAGS_INTERRUPT_OPMASK) {\r
540 case PXE_OPFLAGS_INTERRUPT_READ:\r
541 break;\r
542\r
543 case PXE_OPFLAGS_INTERRUPT_ENABLE:\r
544 if (IntMask == 0) {\r
545 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
546 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
547 return ;\r
548 }\r
549\r
550 AdapterInfo->int_mask = IntMask;\r
551 E100bSetInterruptState (AdapterInfo);\r
552 break;\r
553\r
554 case PXE_OPFLAGS_INTERRUPT_DISABLE:\r
555 if (IntMask != 0) {\r
556 AdapterInfo->int_mask &= ~(IntMask);\r
557 E100bSetInterruptState (AdapterInfo);\r
558 break;\r
559 }\r
560\r
561 //\r
562 // else fall thru.\r
563 //\r
564 default:\r
565 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
566 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
567 return ;\r
568 }\r
569\r
570 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) {\r
571 CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_RECEIVE;\r
572\r
573 }\r
574\r
575 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_TRANSMIT) != 0) {\r
576 CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_TRANSMIT;\r
577\r
578 }\r
579\r
580 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_COMMAND) != 0) {\r
581 CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_COMMAND;\r
582\r
583 }\r
584\r
585 return ;\r
586}\r
587\r
588VOID\r
589UNDI_RecFilter (\r
590 IN PXE_CDB *CdbPtr,\r
591 IN NIC_DATA_INSTANCE *AdapterInfo\r
592 )\r
593/*++\r
594\r
595Routine Description:\r
596 This routine is used to read and change receive filters and, if supported, read\r
597 and change multicast MAC address filter list.\r
598\r
599Arguments:\r
600 CdbPtr - Pointer to the command descriptor block.\r
601 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
602\r
603Returns:\r
604 None\r
605\r
606--*/\r
607{\r
608 UINT16 NewFilter;\r
609 UINT16 OpFlags;\r
610 PXE_DB_RECEIVE_FILTERS *DbPtr;\r
611 UINT8 *MacAddr;\r
612 UINTN MacCount;\r
613 UINT16 Index;\r
614 UINT16 copy_len;\r
615 UINT8 *ptr1;\r
616 UINT8 *ptr2;\r
617 OpFlags = CdbPtr->OpFlags;\r
618 NewFilter = (UINT16) (OpFlags & 0x1F);\r
619\r
620 switch (OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) {\r
621 case PXE_OPFLAGS_RECEIVE_FILTER_READ:\r
622\r
623 //\r
624 // not expecting a cpb, not expecting any filter bits\r
625 //\r
626 if ((NewFilter != 0) || (CdbPtr->CPBsize != 0)) {\r
627 goto BadCdb;\r
628\r
629 }\r
630\r
631 if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == 0) {\r
632 goto JustRead;\r
633\r
634 }\r
635\r
636 NewFilter |= AdapterInfo->Rx_Filter;\r
637 //\r
638 // all other flags are ignored except mcast_reset\r
639 //\r
640 break;\r
641\r
642 case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE:\r
643 //\r
644 // there should be atleast one other filter bit set.\r
645 //\r
646 if (NewFilter == 0) {\r
647 //\r
648 // nothing to enable\r
649 //\r
650 goto BadCdb;\r
651 }\r
652\r
653 if (CdbPtr->CPBsize != 0) {\r
654 //\r
655 // this must be a multicast address list!\r
656 // don't accept the list unless selective_mcast is set\r
657 // don't accept confusing mcast settings with this\r
658 //\r
659 if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) ||\r
660 ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||\r
661 ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ||\r
662 ((CdbPtr->CPBsize % sizeof (PXE_MAC_ADDR)) != 0) ) {\r
663 goto BadCdb;\r
664 }\r
665\r
666 MacAddr = (UINT8 *) ((UINTN) (CdbPtr->CPBaddr));\r
667 MacCount = CdbPtr->CPBsize / sizeof (PXE_MAC_ADDR);\r
668\r
669 for (; MacCount-- != 0; MacAddr += sizeof (PXE_MAC_ADDR)) {\r
670 if (MacAddr[0] != 0x01 || MacAddr[1] != 0x00 || MacAddr[2] != 0x5E || (MacAddr[3] & 0x80) != 0) {\r
671 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
672 CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;\r
673 return ;\r
674 }\r
675 }\r
676 }\r
677\r
678 //\r
679 // check selective mcast case enable case\r
680 //\r
681 if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {\r
682 if (((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||\r
683 ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ) {\r
684 goto BadCdb;\r
685\r
686 }\r
687 //\r
688 // if no cpb, make sure we have an old list\r
689 //\r
690 if ((CdbPtr->CPBsize == 0) && (AdapterInfo->mcast_list.list_len == 0)) {\r
691 goto BadCdb;\r
692 }\r
693 }\r
694 //\r
695 // if you want to enable anything, you got to have unicast\r
696 // and you have what you already enabled!\r
697 //\r
698 NewFilter |= (PXE_OPFLAGS_RECEIVE_FILTER_UNICAST | AdapterInfo->Rx_Filter);\r
699\r
700 break;\r
701\r
702 case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE:\r
703\r
704 //\r
705 // mcast list not expected, i.e. no cpb here!\r
706 //\r
707 if (CdbPtr->CPBsize != PXE_CPBSIZE_NOT_USED) {\r
708 goto BadCdb;\r
709 }\r
710\r
711 NewFilter = (UINT16) ((~(CdbPtr->OpFlags & 0x1F)) & AdapterInfo->Rx_Filter);\r
712\r
713 break;\r
714\r
715 default:\r
716 goto BadCdb;\r
717 }\r
718\r
719 if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) {\r
720 AdapterInfo->mcast_list.list_len = 0;\r
721 NewFilter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);\r
722 }\r
723\r
724 E100bSetfilter (AdapterInfo, NewFilter, CdbPtr->CPBaddr, CdbPtr->CPBsize);\r
725\r
726JustRead:\r
727 //\r
728 // give the current mcast list\r
729 //\r
730 if ((CdbPtr->DBsize != 0) && (AdapterInfo->mcast_list.list_len != 0)) {\r
731 //\r
732 // copy the mc list to db\r
733 //\r
734\r
735 DbPtr = (PXE_DB_RECEIVE_FILTERS *) (UINTN) CdbPtr->DBaddr;\r
736 ptr1 = (UINT8 *) (&DbPtr->MCastList[0]);\r
737\r
738 //\r
739 // DbPtr->mc_count = AdapterInfo->mcast_list.list_len;\r
740 //\r
741 copy_len = (UINT16) (AdapterInfo->mcast_list.list_len * PXE_MAC_LENGTH);\r
742\r
743 if (copy_len > CdbPtr->DBsize) {\r
744 copy_len = CdbPtr->DBsize;\r
745\r
746 }\r
747\r
748 ptr2 = (UINT8 *) (&AdapterInfo->mcast_list.mc_list[0]);\r
749 for (Index = 0; Index < copy_len; Index++) {\r
750 ptr1[Index] = ptr2[Index];\r
751 }\r
752 }\r
753 //\r
754 // give the stat flags here\r
755 //\r
756 if (AdapterInfo->Receive_Started) {\r
757 CdbPtr->StatFlags |= AdapterInfo->Rx_Filter;\r
758\r
759 }\r
760\r
761 return ;\r
762\r
763BadCdb:\r
764 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
765 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
766}\r
767\r
768VOID\r
769UNDI_StnAddr (\r
770 IN PXE_CDB *CdbPtr,\r
771 IN NIC_DATA_INSTANCE *AdapterInfo\r
772 )\r
773/*++\r
774\r
775Routine Description:\r
776 This routine is used to get the current station and broadcast MAC addresses, and to change the\r
777 current station MAC address.\r
778\r
779Arguments:\r
780 CdbPtr - Pointer to the command descriptor block.\r
781 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
782\r
783Returns:\r
784 None\r
785\r
786--*/\r
787{\r
788 PXE_CPB_STATION_ADDRESS *CpbPtr;\r
789 PXE_DB_STATION_ADDRESS *DbPtr;\r
790 UINT16 Index;\r
791\r
792 if (CdbPtr->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) {\r
793 //\r
794 // configure the permanent address.\r
795 // change the AdapterInfo->CurrentNodeAddress field.\r
796 //\r
797 if (CompareMem (\r
798 &AdapterInfo->CurrentNodeAddress[0],\r
799 &AdapterInfo->PermNodeAddress[0],\r
800 PXE_MAC_LENGTH\r
801 ) != 0) {\r
802 for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {\r
803 AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];\r
804 }\r
805\r
806 E100bSetupIAAddr (AdapterInfo);\r
807 }\r
808 }\r
809\r
810 if (CdbPtr->CPBaddr != (UINT64) 0) {\r
811 CpbPtr = (PXE_CPB_STATION_ADDRESS *) (UINTN) (CdbPtr->CPBaddr);\r
812 //\r
813 // configure the new address\r
814 //\r
815 for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {\r
816 AdapterInfo->CurrentNodeAddress[Index] = CpbPtr->StationAddr[Index];\r
817 }\r
818\r
819 E100bSetupIAAddr (AdapterInfo);\r
820 }\r
821\r
822 if (CdbPtr->DBaddr != (UINT64) 0) {\r
823 DbPtr = (PXE_DB_STATION_ADDRESS *) (UINTN) (CdbPtr->DBaddr);\r
824 //\r
825 // fill it with the new values\r
826 //\r
827 for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {\r
828 DbPtr->StationAddr[Index] = AdapterInfo->CurrentNodeAddress[Index];\r
829 DbPtr->BroadcastAddr[Index] = AdapterInfo->BroadcastNodeAddress[Index];\r
830 DbPtr->PermanentAddr[Index] = AdapterInfo->PermNodeAddress[Index];\r
831 }\r
832 }\r
833\r
834 return ;\r
835}\r
836\r
837VOID\r
838UNDI_Statistics (\r
839 IN PXE_CDB *CdbPtr,\r
840 IN NIC_DATA_INSTANCE *AdapterInfo\r
841 )\r
842/*++\r
843\r
844Routine Description:\r
845 This routine is used to read and clear the NIC traffic statistics. This command is supported only\r
846 if the !PXE structure's Implementation flags say so.\r
847\r
848 Results will be parsed out in the following manner:\r
849 CdbPtr->DBaddr.Data[0] R Total Frames (Including frames with errors and dropped frames)\r
850 CdbPtr->DBaddr.Data[1] R Good Frames (All frames copied into receive buffer)\r
851 CdbPtr->DBaddr.Data[2] R Undersize Frames (Frames below minimum length for media <64 for ethernet)\r
852 CdbPtr->DBaddr.Data[4] R Dropped Frames (Frames that were dropped because receive buffers were full)\r
853 CdbPtr->DBaddr.Data[8] R CRC Error Frames (Frames with alignment or CRC errors)\r
854 CdbPtr->DBaddr.Data[A] T Total Frames (Including frames with errors and dropped frames)\r
855 CdbPtr->DBaddr.Data[B] T Good Frames (All frames copied into transmit buffer)\r
856 CdbPtr->DBaddr.Data[C] T Undersize Frames (Frames below minimum length for media <64 for ethernet)\r
857 CdbPtr->DBaddr.Data[E] T Dropped Frames (Frames that were dropped because of collisions)\r
858 CdbPtr->DBaddr.Data[14] T Total Collision Frames (Total collisions on this subnet)\r
859\r
860Arguments:\r
861 CdbPtr - Pointer to the command descriptor block.\r
862 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
863\r
864Returns:\r
865 None\r
866\r
867--*/\r
868{\r
869 if ((CdbPtr->OpFlags &~(PXE_OPFLAGS_STATISTICS_RESET)) != 0) {\r
870 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
871 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
872 return ;\r
873 }\r
874\r
875 if ((CdbPtr->OpFlags & PXE_OPFLAGS_STATISTICS_RESET) != 0) {\r
876 //\r
877 // Reset the statistics\r
878 //\r
879 CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, 0, 0);\r
880 } else {\r
881 CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, CdbPtr->DBaddr, CdbPtr->DBsize);\r
882 }\r
883\r
884 return ;\r
885}\r
886\r
887VOID\r
888UNDI_ip2mac (\r
889 IN PXE_CDB *CdbPtr,\r
890 IN NIC_DATA_INSTANCE *AdapterInfo\r
891 )\r
892/*++\r
893\r
894Routine Description:\r
895 This routine is used to translate a multicast IP address to a multicast MAC address.\r
896\r
897 This results in a MAC address composed of 25 bits of fixed data with the upper 23 bits of the IP\r
898 address being appended to it. Results passed back in the equivalent of CdbPtr->DBaddr->MAC[0-5].\r
899\r
900Arguments:\r
901 CdbPtr - Pointer to the command descriptor block.\r
902 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
903\r
904Returns:\r
905 None\r
906\r
907--*/\r
908{\r
909 PXE_CPB_MCAST_IP_TO_MAC *CpbPtr;\r
910 PXE_DB_MCAST_IP_TO_MAC *DbPtr;\r
911 UINT8 *TmpPtr;\r
912\r
913 CpbPtr = (PXE_CPB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->CPBaddr;\r
914 DbPtr = (PXE_DB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->DBaddr;\r
915\r
916 if ((CdbPtr->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) {\r
917 //\r
918 // for now this is not supported\r
919 //\r
920 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
921 CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED;\r
922 return ;\r
923 }\r
924\r
925 TmpPtr = (UINT8 *) (&CpbPtr->IP.IPv4);\r
926 //\r
927 // check if the ip given is a mcast IP\r
928 //\r
929 if ((TmpPtr[0] & 0xF0) != 0xE0) {\r
930 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
931 CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;\r
932 }\r
933 //\r
934 // take the last 23 bits in IP.\r
935 // be very careful. accessing word on a non-word boundary will hang motherboard codenamed Big Sur\r
936 // casting the mac array (in the middle) to a UINT32 pointer and accessing\r
937 // the UINT32 content hung the system...\r
938 //\r
939 DbPtr->MAC[0] = 0x01;\r
940 DbPtr->MAC[1] = 0x00;\r
941 DbPtr->MAC[2] = 0x5e;\r
942 DbPtr->MAC[3] = (UINT8) (TmpPtr[1] & 0x7f);\r
943 DbPtr->MAC[4] = (UINT8) TmpPtr[2];\r
944 DbPtr->MAC[5] = (UINT8) TmpPtr[3];\r
945\r
946 return ;\r
947}\r
948\r
949VOID\r
950UNDI_NVData (\r
951 IN PXE_CDB *CdbPtr,\r
952 IN NIC_DATA_INSTANCE *AdapterInfo\r
953 )\r
954/*++\r
955\r
956Routine Description:\r
957 This routine is used to read and write non-volatile storage on the NIC (if supported). The NVRAM\r
958 could be EEPROM, FLASH, or battery backed RAM.\r
959\r
960 This is an optional function according to the UNDI specification (or will be......)\r
961\r
962Arguments:\r
963 CdbPtr - Pointer to the command descriptor block.\r
964 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
965\r
966Returns:\r
967 None\r
968\r
969--*/\r
970{\r
971 PXE_DB_NVDATA *DbPtr;\r
972 UINT16 Index;\r
973\r
974 if ((CdbPtr->OpFlags == PXE_OPFLAGS_NVDATA_READ) != 0) {\r
975\r
976 if ((CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) != 0) {\r
977 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
978 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
979 return ;\r
980 }\r
981\r
982 DbPtr = (PXE_DB_NVDATA *) (UINTN) CdbPtr->DBaddr;\r
983\r
984 for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) {\r
985 DbPtr->Data.Dword[Index] = AdapterInfo->NVData[Index];\r
986\r
987 }\r
988\r
989 } else {\r
990 //\r
991 // no write for now\r
992 //\r
993 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
994 CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED;\r
995 }\r
996\r
997 return ;\r
998}\r
999\r
1000VOID\r
1001UNDI_Status (\r
1002 IN PXE_CDB *CdbPtr,\r
1003 IN NIC_DATA_INSTANCE *AdapterInfo\r
1004 )\r
1005/*++\r
1006\r
1007Routine Description:\r
1008 This routine returns the current interrupt status and/or the transmitted buffer addresses.\r
1009 If the current interrupt status is returned, pending interrupts will be acknowledged by this\r
1010 command. Transmitted buffer addresses that are written to the DB are removed from the transmit\r
1011 buffer queue.\r
1012\r
1013 Normally, this command would be polled with interrupts disabled.\r
1014\r
1015 The transmit buffers are returned in CdbPtr->DBaddr->TxBufer[0 - NumEntries].\r
1016 The interrupt status is returned in CdbPtr->StatFlags.\r
1017\r
1018Arguments:\r
1019 CdbPtr - Pointer to the command descriptor block.\r
1020 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1021\r
1022Returns:\r
1023 None\r
1024\r
1025--*/\r
1026{\r
1027 PXE_DB_GET_STATUS *DbPtr;\r
1028 PXE_DB_GET_STATUS TmpGetStatus;\r
1029 UINT16 Index;\r
1030 UINT16 Status;\r
1031 UINT16 NumEntries;\r
1032 RxFD *RxPtr;\r
1033\r
1034 //\r
1035 // Fill in temporary GetStatus storage.\r
1036 //\r
1037 RxPtr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];\r
1038\r
1039 if ((RxPtr->cb_header.status & RX_COMPLETE) != 0) {\r
1040 TmpGetStatus.RxFrameLen = RxPtr->ActualCount & 0x3fff;\r
1041 } else {\r
1042 TmpGetStatus.RxFrameLen = 0;\r
1043 }\r
1044\r
1045 TmpGetStatus.reserved = 0;\r
1046\r
1047 //\r
1048 // Fill in size of next available receive packet and\r
1049 // reserved field in caller's DB storage.\r
1050 //\r
1051 DbPtr = (PXE_DB_GET_STATUS *) (UINTN) CdbPtr->DBaddr;\r
1052\r
1053 if (CdbPtr->DBsize > 0 && CdbPtr->DBsize < sizeof (UINT32) * 2) {\r
1054 CopyMem (DbPtr, &TmpGetStatus, CdbPtr->DBsize);\r
1055 } else {\r
1056 CopyMem (DbPtr, &TmpGetStatus, sizeof (UINT32) * 2);\r
1057 }\r
1058\r
1059 //\r
1060 //\r
1061 //\r
1062 if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) {\r
1063 //\r
1064 // DBsize of zero is invalid if Tx buffers are requested.\r
1065 //\r
1066 if (CdbPtr->DBsize == 0) {\r
1067 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1068 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1069 return ;\r
1070 }\r
1071\r
1072 //\r
1073 // remember this b4 we overwrite\r
1074 //\r
1075 NumEntries = (UINT16) (CdbPtr->DBsize - sizeof (UINT64));\r
1076\r
1077 //\r
1078 // We already filled in 2 UINT32s.\r
1079 //\r
1080 CdbPtr->DBsize = sizeof (UINT32) * 2;\r
1081\r
1082 //\r
1083 // will claim any hanging free CBs\r
1084 //\r
1085 CheckCBList (AdapterInfo);\r
1086\r
1087 if (AdapterInfo->xmit_done_head == AdapterInfo->xmit_done_tail) {\r
1088 CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY;\r
1089 } else {\r
1090 for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries -= sizeof (UINT64)) {\r
1091 if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {\r
1092 DbPtr->TxBuffer[Index] = AdapterInfo->xmit_done[AdapterInfo->xmit_done_head];\r
1093 AdapterInfo->xmit_done_head = next (AdapterInfo->xmit_done_head);\r
1094 CdbPtr->DBsize += sizeof (UINT64);\r
1095 } else {\r
1096 break;\r
1097 }\r
1098 }\r
1099 }\r
1100\r
1101 if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {\r
1102 CdbPtr->StatFlags |= PXE_STATFLAGS_DB_WRITE_TRUNCATED;\r
1103\r
1104 }\r
1105 //\r
1106 // check for a receive buffer and give it's size in db\r
1107 //\r
1108 }\r
1109 //\r
1110 //\r
1111 //\r
1112 if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) {\r
1113\r
1114 Status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);\r
1115 AdapterInfo->Int_Status |= Status;\r
1116\r
1117 //\r
1118 // acknoledge the interrupts\r
1119 //\r
1120 OutWord (AdapterInfo, (UINT16) (Status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus));\r
1121\r
1122 //\r
1123 // report all the outstanding interrupts\r
1124 //\r
1125 Status = AdapterInfo->Int_Status;\r
1126 if ((Status & SCB_STATUS_FR) != 0) {\r
1127 CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;\r
1128 }\r
1129\r
1130 if ((Status & SCB_STATUS_SWI) != 0) {\r
1131 CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_SOFTWARE;\r
1132 }\r
1133 }\r
1134\r
1135 return ;\r
1136}\r
1137\r
1138VOID\r
1139UNDI_FillHeader (\r
1140 IN PXE_CDB *CdbPtr,\r
1141 IN NIC_DATA_INSTANCE *AdapterInfo\r
1142 )\r
1143/*++\r
1144\r
1145Routine Description:\r
1146 This routine is used to fill media header(s) in transmit packet(s).\r
1147 Copies the MAC address into the media header whether it is dealing\r
1148 with fragmented or non-fragmented packets.\r
1149\r
1150Arguments:\r
1151 CdbPtr - Pointer to the command descriptor block.\r
1152 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1153\r
1154Returns:\r
1155 None\r
1156\r
1157--*/\r
1158{\r
1159 PXE_CPB_FILL_HEADER *Cpb;\r
1160 PXE_CPB_FILL_HEADER_FRAGMENTED *Cpbf;\r
1161 EtherHeader *MacHeader;\r
1162 UINTN Index;\r
1163\r
1164 if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {\r
1165 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1166 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1167 return ;\r
1168 }\r
1169\r
1170 if ((CdbPtr->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) {\r
1171 Cpbf = (PXE_CPB_FILL_HEADER_FRAGMENTED *) (UINTN) CdbPtr->CPBaddr;\r
1172\r
1173 //\r
1174 // assume 1st fragment is big enough for the mac header\r
1175 //\r
1176 if ((Cpbf->FragCnt == 0) || (Cpbf->FragDesc[0].FragLen < PXE_MAC_HEADER_LEN_ETHER)) {\r
1177 //\r
1178 // no buffers given\r
1179 //\r
1180 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1181 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1182 return ;\r
1183 }\r
1184\r
1185 MacHeader = (EtherHeader *) (UINTN) Cpbf->FragDesc[0].FragAddr;\r
1186 //\r
1187 // we don't swap the protocol bytes\r
1188 //\r
1189 MacHeader->type = Cpbf->Protocol;\r
1190\r
1191 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {\r
1192 MacHeader->dest_addr[Index] = Cpbf->DestAddr[Index];\r
1193 MacHeader->src_addr[Index] = Cpbf->SrcAddr[Index];\r
1194 }\r
1195 } else {\r
1196 Cpb = (PXE_CPB_FILL_HEADER *) (UINTN) CdbPtr->CPBaddr;\r
1197\r
1198 MacHeader = (EtherHeader *) (UINTN) Cpb->MediaHeader;\r
1199 //\r
1200 // we don't swap the protocol bytes\r
1201 //\r
1202 MacHeader->type = Cpb->Protocol;\r
1203\r
1204 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {\r
1205 MacHeader->dest_addr[Index] = Cpb->DestAddr[Index];\r
1206 MacHeader->src_addr[Index] = Cpb->SrcAddr[Index];\r
1207 }\r
1208 }\r
1209\r
1210 return ;\r
1211}\r
1212\r
1213VOID\r
1214UNDI_Transmit (\r
1215 IN PXE_CDB *CdbPtr,\r
1216 IN NIC_DATA_INSTANCE *AdapterInfo\r
1217 )\r
1218/*++\r
1219\r
1220Routine Description:\r
1221 This routine is used to place a packet into the transmit queue. The data buffers given to\r
1222 this command are to be considered locked and the application or network driver loses\r
1223 ownership of these buffers and must not free or relocate them until the ownership returns.\r
1224\r
1225 When the packets are transmitted, a transmit complete interrupt is generated (if interrupts\r
1226 are disabled, the transmit interrupt status is still set and can be checked using the UNDI_Status\r
1227 command.\r
1228\r
1229 Some implementations and adapters support transmitting multiple packets with one transmit\r
1230 command. If this feature is supported, the transmit CPBs can be linked in one transmit\r
1231 command.\r
1232\r
1233 All UNDIs support fragmented frames, now all network devices or protocols do. If a fragmented\r
1234 frame CPB is given to UNDI and the network device does not support fragmented frames\r
1235 (see !PXE.Implementation flag), the UNDI will have to copy the fragments into a local buffer\r
1236 before transmitting.\r
1237\r
1238\r
1239Arguments:\r
1240 CdbPtr - Pointer to the command descriptor block.\r
1241 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1242\r
1243Returns:\r
1244 None\r
1245\r
1246--*/\r
1247{\r
1248\r
1249 if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {\r
1250 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1251 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1252 return ;\r
1253 }\r
1254\r
1255 CdbPtr->StatCode = (PXE_STATCODE) E100bTransmit (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->OpFlags);\r
1256\r
1257 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
1258 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1259 }\r
1260\r
1261 return ;\r
1262}\r
1263\r
1264VOID\r
1265UNDI_Receive (\r
1266 IN PXE_CDB *CdbPtr,\r
1267 IN NIC_DATA_INSTANCE *AdapterInfo\r
1268 )\r
1269/*++\r
1270\r
1271Routine Description:\r
1272 When the network adapter has received a frame, this command is used to copy the frame\r
1273 into the driver/application storage location. Once a frame has been copied, it is\r
1274 removed from the receive queue.\r
1275\r
1276Arguments:\r
1277 CdbPtr - Pointer to the command descriptor block.\r
1278 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1279\r
1280Returns:\r
1281 None\r
1282\r
1283--*/\r
1284{\r
1285 PXE_CPB_RECEIVE *cpbptr;\r
1286\r
1287 //\r
1288 // check if RU has started...\r
1289 //\r
1290 if (!AdapterInfo->Receive_Started) {\r
1291 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1292 CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED;\r
1293 return ;\r
1294 }\r
1295\r
1296 cpbptr = (PXE_CPB_RECEIVE *) (UINTN) CdbPtr->CPBaddr;\r
1297\r
1298 CdbPtr->StatCode = (UINT16) E100bReceive (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->DBaddr);\r
1299 if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {\r
1300 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1301\r
1302 }\r
1303\r
1304 return ;\r
1305}\r
1306\r
1307VOID\r
1308UNDI_APIEntry_old (\r
1309 IN UINT64 cdb\r
1310 )\r
1311/*++\r
1312\r
1313Routine Description:\r
1314 This is the main SW UNDI API entry using the older nii protocol.\r
1315 The parameter passed in is a 64 bit flat model virtual\r
1316 address of the cdb. We then jump into the common routine for both old and\r
1317 new nii protocol entries.\r
1318\r
1319Arguments:\r
1320 CdbPtr - Pointer to the command descriptor block.\r
1321 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1322\r
1323Returns:\r
1324 None\r
1325\r
1326--*/\r
1327// TODO: cdb - add argument and description to function comment\r
1328{\r
1329 PXE_CDB *CdbPtr;\r
1330 NIC_DATA_INSTANCE *AdapterInfo;\r
1331\r
1332 if (cdb == (UINT64) 0) {\r
1333 return ;\r
1334\r
1335 }\r
1336\r
1337 CdbPtr = (PXE_CDB *) (UINTN) cdb;\r
1338\r
1339 if (CdbPtr->IFnum >= pxe->IFcnt) {\r
1340 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1341 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1342 return ;\r
1343 }\r
1344\r
1345 AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);\r
1346 \r
1347 //\r
1348 // entering from older entry point\r
1349 //\r
1350 AdapterInfo->VersionFlag = 0x30;\r
1351 UNDI_APIEntry_Common (cdb);\r
1352}\r
1353\r
1354VOID\r
1355UNDI_APIEntry_new (\r
1356 IN UINT64 cdb\r
1357 )\r
1358/*++\r
1359\r
1360Routine Description:\r
1361 This is the main SW UNDI API entry using the newer nii protocol.\r
1362 The parameter passed in is a 64 bit flat model virtual\r
1363 address of the cdb. We then jump into the common routine for both old and\r
1364 new nii protocol entries.\r
1365\r
1366Arguments:\r
1367 CdbPtr - Pointer to the command descriptor block.\r
1368 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1369\r
1370Returns:\r
1371 None\r
1372\r
1373--*/\r
1374// TODO: cdb - add argument and description to function comment\r
1375{\r
1376 PXE_CDB *CdbPtr;\r
1377 NIC_DATA_INSTANCE *AdapterInfo;\r
1378\r
1379 if (cdb == (UINT64) 0) {\r
1380 return ;\r
1381\r
1382 }\r
1383\r
1384 CdbPtr = (PXE_CDB *) (UINTN) cdb;\r
1385\r
1386 if (CdbPtr->IFnum >= pxe_31->IFcnt) {\r
1387 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1388 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1389 return ;\r
1390 }\r
1391\r
1392 AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);\r
1393 //\r
1394 // entering from older entry point\r
1395 //\r
1396 AdapterInfo->VersionFlag = 0x31;\r
1397 UNDI_APIEntry_Common (cdb);\r
1398}\r
1399\r
1400VOID\r
1401UNDI_APIEntry_Common (\r
1402 IN UINT64 cdb\r
1403 )\r
1404/*++\r
1405\r
1406Routine Description:\r
1407 This is the common routine for both old and new entry point procedures.\r
1408 The parameter passed in is a 64 bit flat model virtual\r
1409 address of the cdb. We then jump into the service routine pointed to by the\r
1410 Api_Table[OpCode].\r
1411\r
1412Arguments:\r
1413 CdbPtr - Pointer to the command descriptor block.\r
1414 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
1415\r
1416Returns:\r
1417 None\r
1418\r
1419--*/\r
1420// TODO: cdb - add argument and description to function comment\r
1421{\r
1422 PXE_CDB *CdbPtr;\r
1423 NIC_DATA_INSTANCE *AdapterInfo;\r
1424 UNDI_CALL_TABLE *tab_ptr;\r
1425\r
1426 CdbPtr = (PXE_CDB *) (UINTN) cdb;\r
1427\r
1428 //\r
1429 // check the OPCODE range\r
1430 //\r
1431 if ((CdbPtr->OpCode > PXE_OPCODE_LAST_VALID) ||\r
1432 (CdbPtr->StatCode != PXE_STATCODE_INITIALIZE) ||\r
1433 (CdbPtr->StatFlags != PXE_STATFLAGS_INITIALIZE) ||\r
1434 (CdbPtr->IFnum >= pxe_31->IFcnt) ) {\r
1435 goto badcdb;\r
1436\r
1437 }\r
1438\r
1439 if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {\r
1440 if (CdbPtr->CPBaddr != PXE_CPBADDR_NOT_USED) {\r
1441 goto badcdb;\r
1442 }\r
1443 } else if (CdbPtr->CPBaddr == PXE_CPBADDR_NOT_USED) {\r
1444 goto badcdb;\r
1445 }\r
1446\r
1447 if (CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) {\r
1448 if (CdbPtr->DBaddr != PXE_DBADDR_NOT_USED) {\r
1449 goto badcdb;\r
1450 }\r
1451 } else if (CdbPtr->DBaddr == PXE_DBADDR_NOT_USED) {\r
1452 goto badcdb;\r
1453 }\r
1454\r
1455 //\r
1456 // check if cpbsize and dbsize are as needed\r
1457 // check if opflags are as expected\r
1458 //\r
1459 tab_ptr = &api_table[CdbPtr->OpCode];\r
1460\r
1461 if (tab_ptr->cpbsize != (UINT16) (DONT_CHECK) && tab_ptr->cpbsize != CdbPtr->CPBsize) {\r
1462 goto badcdb;\r
1463 }\r
1464\r
1465 if (tab_ptr->dbsize != (UINT16) (DONT_CHECK) && tab_ptr->dbsize != CdbPtr->DBsize) {\r
1466 goto badcdb;\r
1467 }\r
1468\r
1469 if (tab_ptr->opflags != (UINT16) (DONT_CHECK) && tab_ptr->opflags != CdbPtr->OpFlags) {\r
1470 goto badcdb;\r
1471\r
1472 }\r
1473\r
1474 AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);\r
1475\r
1476 //\r
1477 // check if UNDI_State is valid for this call\r
1478 //\r
1479 if (tab_ptr->state != (UINT16) (-1)) {\r
1480 //\r
1481 // should atleast be started\r
1482 //\r
1483 if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_STOPPED) {\r
1484 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1485 CdbPtr->StatCode = PXE_STATCODE_NOT_STARTED;\r
1486 return ;\r
1487 }\r
1488 //\r
1489 // check if it should be initialized\r
1490 //\r
1491 if (tab_ptr->state == 2) {\r
1492 if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {\r
1493 CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED;\r
1494 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1495 return ;\r
1496 }\r
1497 }\r
1498 }\r
1499 //\r
1500 // set the return variable for success case here\r
1501 //\r
1502 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;\r
1503 CdbPtr->StatCode = PXE_STATCODE_SUCCESS;\r
1504\r
1505 tab_ptr->api_ptr (CdbPtr, AdapterInfo);\r
1506 return ;\r
1507 //\r
1508 // %% AVL - check for command linking\r
1509 //\r
1510badcdb:\r
1511 CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;\r
1512 CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;\r
1513 return ;\r
1514}\r
1515\r
1516UINT8\r
1517ChkSum (\r
1518 IN VOID *Buffer,\r
1519 IN UINT16 Len\r
1520 )\r
1521/*++\r
1522\r
1523Routine Description:\r
1524 This does an 8 bit check sum of the passed in buffer for Len bytes.\r
1525 This is primarily used to update the check sum in the SW UNDI header.\r
1526\r
1527Arguments:\r
1528 Buffer - Pointer to the passed in buffer to check sum\r
1529 Len - Length of buffer to be check summed in bytes.\r
1530\r
1531Returns:\r
1532 None\r
1533\r
1534--*/\r
1535{\r
1536 UINT8 Chksum;\r
1537 INT8 *Bp;\r
1538\r
1539 Chksum = 0;\r
1540 if ((Bp = Buffer) != NULL) {\r
1541 while (Len--) {\r
1542 Chksum = (UINT8) (Chksum +*Bp++);\r
1543\r
1544 }\r
1545\r
1546 }\r
1547\r
1548 return Chksum;\r
1549}\r
1550\r
1551VOID\r
1552PxeUpdate (\r
1553 IN NIC_DATA_INSTANCE *NicPtr,\r
1554 IN PXE_SW_UNDI *PxePtr\r
1555 )\r
1556/*++\r
1557\r
1558Routine Description:\r
1559 When called with a null NicPtr, this routine decrements the number of NICs\r
1560 this UNDI is supporting and removes the NIC_DATA_POINTER from the array.\r
1561 Otherwise, it increments the number of NICs this UNDI is supported and\r
1562 updates the pxe.Fudge to ensure a proper check sum results.\r
1563\r
1564Arguments:\r
1565 NicPtr - Pointer to the NIC data structure.\r
1566\r
1567Returns:\r
1568 None\r
1569\r
1570--*/\r
1571// TODO: PxePtr - add argument and description to function comment\r
1572{\r
1573 if (NicPtr == NULL) {\r
1574 if (PxePtr->IFcnt > 0) {\r
1575 //\r
1576 // number of NICs this undi supports\r
1577 //\r
1578 PxePtr->IFcnt--;\r
1579 }\r
1580\r
1581 PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len));\r
1582 return ;\r
1583 }\r
1584\r
1585 //\r
1586 // number of NICs this undi supports\r
1587 //\r
1588 PxePtr->IFcnt++;\r
1589 PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len));\r
1590\r
1591 return ;\r
1592}\r
1593\r
1594VOID\r
1595PxeStructInit (\r
1596 IN PXE_SW_UNDI *PxePtr,\r
1597 IN UINTN VersionFlag\r
1598 )\r
1599/*++\r
1600\r
1601Routine Description:\r
1602 Initialize the !PXE structure\r
1603\r
1604Arguments:\r
1605 RemainingDevicePath - Not used, always produce all possible children.\r
1606\r
1607Returns:\r
1608 EFI_SUCCESS - This driver is added to Controller.\r
1609 other - This driver does not support this device.\r
1610\r
1611--*/\r
1612// TODO: PxePtr - add argument and description to function comment\r
1613// TODO: VersionFlag - add argument and description to function comment\r
1614{\r
1615 //\r
1616 // Initialize the !PXE structure\r
1617 //\r
1618 PxePtr->Signature = PXE_ROMID_SIGNATURE;\r
1619 PxePtr->Len = sizeof (PXE_SW_UNDI);\r
1620 //\r
1621 // cksum\r
1622 //\r
1623 PxePtr->Fudge = 0;\r
1624 //\r
1625 // number of NICs this undi supports\r
1626 //\r
1627 PxePtr->IFcnt = 0;\r
1628 PxePtr->Rev = PXE_ROMID_REV;\r
1629 PxePtr->MajorVer = PXE_ROMID_MAJORVER;\r
1630 PxePtr->MinorVer = PXE_ROMID_MINORVER;\r
1631 PxePtr->reserved1 = 0;\r
1632\r
1633 PxePtr->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR |\r
1634 PXE_ROMID_IMP_FRAG_SUPPORTED |\r
1635 PXE_ROMID_IMP_CMD_LINK_SUPPORTED |\r
1636 PXE_ROMID_IMP_NVDATA_READ_ONLY |\r
1637 PXE_ROMID_IMP_STATION_ADDR_SETTABLE |\r
1638 PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED |\r
1639 PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED |\r
1640 PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED |\r
1641 PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED |\r
1642 PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED |\r
1643 PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED;\r
1644\r
1645 if (VersionFlag == 0x30) {\r
1646 PxePtr->EntryPoint = (UINT64) UNDI_APIEntry_old;\r
1647 } else {\r
1648 PxePtr->EntryPoint = (UINT64) UNDI_APIEntry_new;\r
1649 PxePtr->MinorVer = PXE_ROMID_MINORVER_31;\r
1650 }\r
1651\r
1652 PxePtr->reserved2[0] = 0;\r
1653 PxePtr->reserved2[1] = 0;\r
1654 PxePtr->reserved2[2] = 0;\r
1655 PxePtr->BusCnt = 1;\r
1656 PxePtr->BusType[0] = PXE_BUSTYPE_PCI;\r
1657\r
1658 PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len));\r
1659}\r
1660\r
1661#pragma data_seg()\r