3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 // TODO: fix comment to add: Module Name: DECODE.C
25 // Global variables defined in this file
27 UNDI_CALL_TABLE api_table
[PXE_OPCODE_LAST_VALID
+1] = { \
28 {PXE_CPBSIZE_NOT_USED
,PXE_DBSIZE_NOT_USED
,0, (UINT16
)(ANY_STATE
),UNDI_GetState
},\
29 {(UINT16
)(DONT_CHECK
),PXE_DBSIZE_NOT_USED
,0,(UINT16
)(ANY_STATE
),UNDI_Start
},\
30 {PXE_CPBSIZE_NOT_USED
,PXE_DBSIZE_NOT_USED
,0,MUST_BE_STARTED
,UNDI_Stop
},\
31 {PXE_CPBSIZE_NOT_USED
,sizeof(PXE_DB_GET_INIT_INFO
),0,MUST_BE_STARTED
, UNDI_GetInitInfo
},\
32 {PXE_CPBSIZE_NOT_USED
,sizeof(PXE_DB_GET_CONFIG_INFO
),0,MUST_BE_STARTED
, UNDI_GetConfigInfo
},\
33 {sizeof(PXE_CPB_INITIALIZE
),(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
),MUST_BE_STARTED
,UNDI_Initialize
},\
34 {PXE_CPBSIZE_NOT_USED
,PXE_DBSIZE_NOT_USED
,(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
,UNDI_Reset
},\
35 {PXE_CPBSIZE_NOT_USED
,PXE_DBSIZE_NOT_USED
,0, MUST_BE_INITIALIZED
,UNDI_Shutdown
},\
36 {PXE_CPBSIZE_NOT_USED
,PXE_DBSIZE_NOT_USED
,(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
,UNDI_Interrupt
},\
37 {(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_RecFilter
},\
38 {(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_StnAddr
},\
39 {PXE_CPBSIZE_NOT_USED
, (UINT16
)(DONT_CHECK
), (UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_Statistics
},\
40 {sizeof(PXE_CPB_MCAST_IP_TO_MAC
),sizeof(PXE_DB_MCAST_IP_TO_MAC
), (UINT16
)(DONT_CHECK
),MUST_BE_INITIALIZED
, UNDI_ip2mac
},\
41 {(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_NVData
},\
42 {PXE_CPBSIZE_NOT_USED
,(UINT16
)(DONT_CHECK
),(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_Status
},\
43 {(UINT16
)(DONT_CHECK
),PXE_DBSIZE_NOT_USED
,(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_FillHeader
},\
44 {(UINT16
)(DONT_CHECK
),PXE_DBSIZE_NOT_USED
,(UINT16
)(DONT_CHECK
), MUST_BE_INITIALIZED
, UNDI_Transmit
},\
45 {sizeof(PXE_CPB_RECEIVE
),sizeof(PXE_DB_RECEIVE
),0,MUST_BE_INITIALIZED
, UNDI_Receive
} \
49 // end of global variables
55 IN NIC_DATA_INSTANCE
*AdapterInfo
60 This routine determines the operational state of the UNDI. It updates the state flags in the
61 Command Descriptor Block based on information derived from the AdapterInfo instance data.
63 To ensure the command has completed successfully, CdbPtr->StatCode will contain the result of
64 the command execution.
66 The CdbPtr->StatFlags will contain a STOPPED, STARTED, or INITIALIZED state once the command
67 has successfully completed.
69 Keep in mind the AdapterInfo->State is the active state of the adapter (based on software
70 interrogation), and the CdbPtr->StateFlags is the passed back information that is reflected
71 to the caller of the UNDI API.
74 CdbPtr - Pointer to the command descriptor block.
75 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
82 CdbPtr
->StatFlags
= (PXE_STATFLAGS
) (CdbPtr
->StatFlags
| AdapterInfo
->State
);
89 IN NIC_DATA_INSTANCE
*AdapterInfo
94 This routine is used to change the operational state of the UNDI from stopped to started.
95 It will do this as long as the adapter's state is PXE_STATFLAGS_GET_STATE_STOPPED, otherwise
96 the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the
97 UNDI as having already been started.
99 This routine is modified to reflect the undi 1.1 specification changes. The
100 changes in the spec are mainly in the callback routines, the new spec adds
101 3 more callbacks and a unique id.
102 Since this UNDI supports both old and new undi specifications,
103 The NIC's data structure is filled in with the callback routines (depending
104 on the version) pointed to in the caller's CpbPtr. This seeds the Delay,
105 Virt2Phys, Block, and Mem_IO for old and new versions and Map_Mem, UnMap_Mem
106 and Sync_Mem routines and a unique id variable for the new version.
107 This is the function which an external entity (SNP, O/S, etc) would call
108 to provide it's I/O abstraction to the UNDI.
110 It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STARTED.
113 CdbPtr - Pointer to the command descriptor block.
114 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
121 PXE_CPB_START_30
*CpbPtr
;
122 PXE_CPB_START_31
*CpbPtr_31
;
125 // check if it is already started.
127 if (AdapterInfo
->State
!= PXE_STATFLAGS_GET_STATE_STOPPED
) {
128 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
129 CdbPtr
->StatCode
= PXE_STATCODE_ALREADY_STARTED
;
133 if (CdbPtr
->CPBsize
!= sizeof(PXE_CPB_START_30
) &&
134 CdbPtr
->CPBsize
!= sizeof(PXE_CPB_START_31
)) {
136 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
137 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
141 CpbPtr
= (PXE_CPB_START_30
*) (UINTN
) (CdbPtr
->CPBaddr
);
142 CpbPtr_31
= (PXE_CPB_START_31
*) (UINTN
) (CdbPtr
->CPBaddr
);
144 if (AdapterInfo
->VersionFlag
== 0x30) {
145 AdapterInfo
->Delay_30
= (bsptr_30
) (UINTN
) CpbPtr
->Delay
;
146 AdapterInfo
->Virt2Phys_30
= (virtphys_30
) (UINTN
) CpbPtr
->Virt2Phys
;
147 AdapterInfo
->Block_30
= (block_30
) (UINTN
) CpbPtr
->Block
;
149 // patch for old buggy 3.0 code:
150 // In EFI1.0 undi used to provide the full (absolute) I/O address to the
151 // i/o calls and SNP used to provide a callback that used GlobalIoFncs and
152 // everything worked fine! In EFI 1.1, UNDI is not using the full
153 // i/o or memory address to access the device, The base values for the i/o
154 // and memory address is abstracted by the device specific PciIoFncs and
155 // UNDI only uses the offset values. Since UNDI3.0 cannot provide any
156 // identification to SNP, SNP cannot use nic specific PciIoFncs callback!
158 // To fix this and make undi3.0 work with SNP in EFI1.1 we
159 // use a TmpMemIo function that is defined in init.c
160 // This breaks the runtime driver feature of undi, but what to do
161 // if we have to provide the 3.0 compatibility (including the 3.0 bugs)
163 // This TmpMemIo function also takes a UniqueId parameter
164 // (as in undi3.1 design) and so initialize the UniqueId as well here
165 // Note: AdapterInfo->Mem_Io_30 is just filled for consistency with other
166 // parameters but never used, we only use Mem_Io field in the In/Out routines
169 AdapterInfo
->Mem_Io_30
= (mem_io_30
) (UINTN
) CpbPtr
->Mem_IO
;
170 AdapterInfo
->Mem_Io
= (mem_io
) (UINTN
) TmpMemIo
;
171 AdapterInfo
->Unique_ID
= (UINT64
) (UINTN
) AdapterInfo
;
174 AdapterInfo
->Delay
= (bsptr
) (UINTN
) CpbPtr_31
->Delay
;
175 AdapterInfo
->Virt2Phys
= (virtphys
) (UINTN
) CpbPtr_31
->Virt2Phys
;
176 AdapterInfo
->Block
= (block
) (UINTN
) CpbPtr_31
->Block
;
177 AdapterInfo
->Mem_Io
= (mem_io
) (UINTN
) CpbPtr_31
->Mem_IO
;
179 AdapterInfo
->Map_Mem
= (map_mem
) (UINTN
) CpbPtr_31
->Map_Mem
;
180 AdapterInfo
->UnMap_Mem
= (unmap_mem
) (UINTN
) CpbPtr_31
->UnMap_Mem
;
181 AdapterInfo
->Sync_Mem
= (sync_mem
) (UINTN
) CpbPtr_31
->Sync_Mem
;
182 AdapterInfo
->Unique_ID
= CpbPtr_31
->Unique_ID
;
185 AdapterInfo
->State
= PXE_STATFLAGS_GET_STATE_STARTED
;
193 IN NIC_DATA_INSTANCE
*AdapterInfo
198 This routine is used to change the operational state of the UNDI from started to stopped.
199 It will not do this if the adapter's state is PXE_STATFLAGS_GET_STATE_INITIALIZED, otherwise
200 the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the
201 UNDI as having already not been shut down.
203 The NIC's data structure will have the Delay, Virt2Phys, and Block, pointers zero'd out..
205 It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STOPPED.
208 CdbPtr - Pointer to the command descriptor block.
209 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
216 if (AdapterInfo
->State
== PXE_STATFLAGS_GET_STATE_INITIALIZED
) {
217 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
218 CdbPtr
->StatCode
= PXE_STATCODE_NOT_SHUTDOWN
;
222 AdapterInfo
->Delay_30
= 0;
223 AdapterInfo
->Virt2Phys_30
= 0;
224 AdapterInfo
->Block_30
= 0;
226 AdapterInfo
->Delay
= 0;
227 AdapterInfo
->Virt2Phys
= 0;
228 AdapterInfo
->Block
= 0;
230 AdapterInfo
->Map_Mem
= 0;
231 AdapterInfo
->UnMap_Mem
= 0;
232 AdapterInfo
->Sync_Mem
= 0;
234 AdapterInfo
->State
= PXE_STATFLAGS_GET_STATE_STOPPED
;
242 IN NIC_DATA_INSTANCE
*AdapterInfo
247 This routine is used to retrieve the initialization information that is needed by drivers and
248 applications to initialize the UNDI. This will fill in data in the Data Block structure that is
249 pointed to by the caller's CdbPtr->DBaddr. The fields filled in are as follows:
251 MemoryRequired, FrameDataLen, LinkSpeeds[0-3], NvCount, NvWidth, MediaHeaderLen, HWaddrLen,
252 MCastFilterCnt, TxBufCnt, TxBufSize, RxBufCnt, RxBufSize, IFtype, Duplex, and LoopBack.
254 In addition, the CdbPtr->StatFlags ORs in that this NIC supports cable detection. (APRIORI knowledge)
257 CdbPtr - Pointer to the command descriptor block.
258 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
265 PXE_DB_GET_INIT_INFO
*DbPtr
;
267 DbPtr
= (PXE_DB_GET_INIT_INFO
*) (UINTN
) (CdbPtr
->DBaddr
);
269 DbPtr
->MemoryRequired
= MEMORY_NEEDED
;
270 DbPtr
->FrameDataLen
= PXE_MAX_TXRX_UNIT_ETHER
;
271 DbPtr
->LinkSpeeds
[0] = 10;
272 DbPtr
->LinkSpeeds
[1] = 100;
273 DbPtr
->LinkSpeeds
[2] = DbPtr
->LinkSpeeds
[3] = 0;
274 DbPtr
->NvCount
= MAX_EEPROM_LEN
;
276 DbPtr
->MediaHeaderLen
= PXE_MAC_HEADER_LEN_ETHER
;
277 DbPtr
->HWaddrLen
= PXE_HWADDR_LEN_ETHER
;
278 DbPtr
->MCastFilterCnt
= MAX_MCAST_ADDRESS_CNT
;
280 DbPtr
->TxBufCnt
= TX_BUFFER_COUNT
;
281 DbPtr
->TxBufSize
= sizeof (TxCB
);
282 DbPtr
->RxBufCnt
= RX_BUFFER_COUNT
;
283 DbPtr
->RxBufSize
= sizeof (RxFD
);
285 DbPtr
->IFtype
= PXE_IFTYPE_ETHERNET
;
286 DbPtr
->SupportedDuplexModes
= PXE_DUPLEX_ENABLE_FULL_SUPPORTED
|
287 PXE_DUPLEX_FORCE_FULL_SUPPORTED
;
288 DbPtr
->SupportedLoopBackModes
= PXE_LOOPBACK_INTERNAL_SUPPORTED
|
289 PXE_LOOPBACK_EXTERNAL_SUPPORTED
;
291 CdbPtr
->StatFlags
|= PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
;
298 IN NIC_DATA_INSTANCE
*AdapterInfo
303 This routine is used to retrieve the configuration information about the NIC being controlled by
304 this driver. This will fill in data in the Data Block structure that is pointed to by the caller's CdbPtr->DBaddr.
305 The fields filled in are as follows:
307 DbPtr->pci.BusType, DbPtr->pci.Bus, DbPtr->pci.Device, and DbPtr->pci.
309 In addition, the DbPtr->pci.Config.Dword[0-63] grabs a copy of this NIC's PCI configuration space.
312 CdbPtr - Pointer to the command descriptor block.
313 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
321 PXE_DB_GET_CONFIG_INFO
*DbPtr
;
323 DbPtr
= (PXE_DB_GET_CONFIG_INFO
*) (UINTN
) (CdbPtr
->DBaddr
);
325 DbPtr
->pci
.BusType
= PXE_BUSTYPE_PCI
;
326 DbPtr
->pci
.Bus
= AdapterInfo
->Bus
;
327 DbPtr
->pci
.Device
= AdapterInfo
->Device
;
328 DbPtr
->pci
.Function
= AdapterInfo
->Function
;
330 for (Index
= 0; Index
< MAX_PCI_CONFIG_LEN
; Index
++) {
331 DbPtr
->pci
.Config
.Dword
[Index
] = AdapterInfo
->Config
[Index
];
340 NIC_DATA_INSTANCE
*AdapterInfo
345 This routine resets the network adapter and initializes the UNDI using the parameters supplied in
346 the CPB. This command must be issued before the network adapter can be setup to transmit and
349 Once the memory requirements of the UNDI are obtained by using the GetInitInfo command, a block
350 of non-swappable memory may need to be allocated. The address of this memory must be passed to
351 UNDI during the Initialize in the CPB. This memory is used primarily for transmit and receive buffers.
353 The fields CableDetect, LinkSpeed, Duplex, LoopBack, MemoryPtr, and MemoryLength are set with information
354 that was passed in the CPB and the NIC is initialized.
356 If the NIC initialization fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED
357 Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_INITIALIZED showing the state of
358 the UNDI is now initialized.
361 CdbPtr - Pointer to the command descriptor block.
362 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
369 PXE_CPB_INITIALIZE
*CpbPtr
;
371 if ((CdbPtr
->OpFlags
!= PXE_OPFLAGS_INITIALIZE_DETECT_CABLE
) &&
372 (CdbPtr
->OpFlags
!= PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
)) {
373 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
374 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
379 // check if it is already initialized
381 if (AdapterInfo
->State
== PXE_STATFLAGS_GET_STATE_INITIALIZED
) {
382 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
383 CdbPtr
->StatCode
= PXE_STATCODE_ALREADY_INITIALIZED
;
387 CpbPtr
= (PXE_CPB_INITIALIZE
*) (UINTN
) CdbPtr
->CPBaddr
;
389 if (CpbPtr
->MemoryLength
< (UINT32
) MEMORY_NEEDED
) {
390 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
391 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CPB
;
396 // default behaviour is to detect the cable, if the 3rd param is 1,
399 AdapterInfo
->CableDetect
= (UINT8
) ((CdbPtr
->OpFlags
== (UINT16
) PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
) ? (UINT8
) 0 : (UINT8
) 1);
400 AdapterInfo
->LinkSpeedReq
= (UINT16
) CpbPtr
->LinkSpeed
;
401 AdapterInfo
->DuplexReq
= CpbPtr
->DuplexMode
;
402 AdapterInfo
->LoopBack
= CpbPtr
->LoopBackMode
;
403 AdapterInfo
->MemoryPtr
= CpbPtr
->MemoryAddr
;
404 AdapterInfo
->MemoryLength
= CpbPtr
->MemoryLength
;
406 CdbPtr
->StatCode
= (PXE_STATCODE
) E100bInit (AdapterInfo
);
408 if (CdbPtr
->StatCode
!= PXE_STATCODE_SUCCESS
) {
409 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
411 AdapterInfo
->State
= PXE_STATFLAGS_GET_STATE_INITIALIZED
;
420 IN NIC_DATA_INSTANCE
*AdapterInfo
425 This routine resets the network adapter and initializes the UNDI using the parameters supplied in
426 the CPB. The transmit and receive queues are emptied and any pending interrupts are cleared.
428 If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED
431 CdbPtr - Pointer to the command descriptor block.
432 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
439 if (CdbPtr
->OpFlags
!= PXE_OPFLAGS_NOT_USED
&&
440 CdbPtr
->OpFlags
!= PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS
&&
441 CdbPtr
->OpFlags
!= PXE_OPFLAGS_RESET_DISABLE_FILTERS
) {
443 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
444 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
448 CdbPtr
->StatCode
= (UINT16
) E100bReset (AdapterInfo
, CdbPtr
->OpFlags
);
450 if (CdbPtr
->StatCode
!= PXE_STATCODE_SUCCESS
) {
451 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
458 IN NIC_DATA_INSTANCE
*AdapterInfo
463 This routine resets the network adapter and leaves it in a safe state for another driver to
464 initialize. Any pending transmits or receives are lost. Receive filters and external
465 interrupt enables are disabled. Once the UNDI has been shutdown, it can then be stopped
466 or initialized again.
468 If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED
470 Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_STARTED showing the state of
471 the NIC as being started.
474 CdbPtr - Pointer to the command descriptor block.
475 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
483 // do the shutdown stuff here
485 CdbPtr
->StatCode
= (UINT16
) E100bShutdown (AdapterInfo
);
487 if (CdbPtr
->StatCode
!= PXE_STATCODE_SUCCESS
) {
488 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
490 AdapterInfo
->State
= PXE_STATFLAGS_GET_STATE_STARTED
;
499 IN NIC_DATA_INSTANCE
*AdapterInfo
504 This routine can be used to read and/or change the current external interrupt enable
505 settings. Disabling an external interrupt enable prevents and external (hardware)
506 interrupt from being signaled by the network device. Internally the interrupt events
507 can still be polled by using the UNDI_GetState command.
509 The resulting information on the interrupt state will be passed back in the CdbPtr->StatFlags.
512 CdbPtr - Pointer to the command descriptor block.
513 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
522 IntMask
= (UINT8
)(UINTN
)(CdbPtr
->OpFlags
& (PXE_OPFLAGS_INTERRUPT_RECEIVE
|
523 PXE_OPFLAGS_INTERRUPT_TRANSMIT
|
524 PXE_OPFLAGS_INTERRUPT_COMMAND
|
525 PXE_OPFLAGS_INTERRUPT_SOFTWARE
));
527 switch (CdbPtr
->OpFlags
& PXE_OPFLAGS_INTERRUPT_OPMASK
) {
528 case PXE_OPFLAGS_INTERRUPT_READ
:
531 case PXE_OPFLAGS_INTERRUPT_ENABLE
:
533 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
534 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
538 AdapterInfo
->int_mask
= IntMask
;
539 E100bSetInterruptState (AdapterInfo
);
542 case PXE_OPFLAGS_INTERRUPT_DISABLE
:
544 AdapterInfo
->int_mask
= (UINT16
) (AdapterInfo
->int_mask
& ~(IntMask
));
545 E100bSetInterruptState (AdapterInfo
);
553 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
554 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
558 if ((AdapterInfo
->int_mask
& PXE_OPFLAGS_INTERRUPT_RECEIVE
) != 0) {
559 CdbPtr
->StatFlags
|= PXE_STATFLAGS_INTERRUPT_RECEIVE
;
563 if ((AdapterInfo
->int_mask
& PXE_OPFLAGS_INTERRUPT_TRANSMIT
) != 0) {
564 CdbPtr
->StatFlags
|= PXE_STATFLAGS_INTERRUPT_TRANSMIT
;
568 if ((AdapterInfo
->int_mask
& PXE_OPFLAGS_INTERRUPT_COMMAND
) != 0) {
569 CdbPtr
->StatFlags
|= PXE_STATFLAGS_INTERRUPT_COMMAND
;
579 IN NIC_DATA_INSTANCE
*AdapterInfo
584 This routine is used to read and change receive filters and, if supported, read
585 and change multicast MAC address filter list.
588 CdbPtr - Pointer to the command descriptor block.
589 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
598 PXE_DB_RECEIVE_FILTERS
*DbPtr
;
605 OpFlags
= CdbPtr
->OpFlags
;
606 NewFilter
= (UINT16
) (OpFlags
& 0x1F);
608 switch (OpFlags
& PXE_OPFLAGS_RECEIVE_FILTER_OPMASK
) {
609 case PXE_OPFLAGS_RECEIVE_FILTER_READ
:
612 // not expecting a cpb, not expecting any filter bits
614 if ((NewFilter
!= 0) || (CdbPtr
->CPBsize
!= 0)) {
619 if ((NewFilter
& PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST
) == 0) {
624 NewFilter
= (UINT16
) (NewFilter
| AdapterInfo
->Rx_Filter
);
626 // all other flags are ignored except mcast_reset
630 case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE
:
632 // there should be atleast one other filter bit set.
634 if (NewFilter
== 0) {
641 if (CdbPtr
->CPBsize
!= 0) {
643 // this must be a multicast address list!
644 // don't accept the list unless selective_mcast is set
645 // don't accept confusing mcast settings with this
647 if (((NewFilter
& PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
) == 0) ||
648 ((NewFilter
& PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST
) != 0) ||
649 ((NewFilter
& PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST
) != 0) ||
650 ((CdbPtr
->CPBsize
% sizeof (PXE_MAC_ADDR
)) != 0) ) {
654 MacAddr
= (UINT8
*) ((UINTN
) (CdbPtr
->CPBaddr
));
655 MacCount
= CdbPtr
->CPBsize
/ sizeof (PXE_MAC_ADDR
);
657 for (; MacCount
-- != 0; MacAddr
+= sizeof (PXE_MAC_ADDR
)) {
658 if (MacAddr
[0] != 0x01 || MacAddr
[1] != 0x00 || MacAddr
[2] != 0x5E || (MacAddr
[3] & 0x80) != 0) {
659 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
660 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CPB
;
667 // check selective mcast case enable case
669 if ((OpFlags
& PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
) != 0) {
670 if (((OpFlags
& PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST
) != 0) ||
671 ((OpFlags
& PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST
) != 0) ) {
676 // if no cpb, make sure we have an old list
678 if ((CdbPtr
->CPBsize
== 0) && (AdapterInfo
->mcast_list
.list_len
== 0)) {
683 // if you want to enable anything, you got to have unicast
684 // and you have what you already enabled!
686 NewFilter
= (UINT16
) (NewFilter
| (PXE_OPFLAGS_RECEIVE_FILTER_UNICAST
| AdapterInfo
->Rx_Filter
));
690 case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE
:
693 // mcast list not expected, i.e. no cpb here!
695 if (CdbPtr
->CPBsize
!= PXE_CPBSIZE_NOT_USED
) {
699 NewFilter
= (UINT16
) ((~(CdbPtr
->OpFlags
& 0x1F)) & AdapterInfo
->Rx_Filter
);
707 if ((OpFlags
& PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST
) != 0) {
708 AdapterInfo
->mcast_list
.list_len
= 0;
709 NewFilter
&= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
);
712 E100bSetfilter (AdapterInfo
, NewFilter
, CdbPtr
->CPBaddr
, CdbPtr
->CPBsize
);
716 // give the current mcast list
718 if ((CdbPtr
->DBsize
!= 0) && (AdapterInfo
->mcast_list
.list_len
!= 0)) {
720 // copy the mc list to db
723 DbPtr
= (PXE_DB_RECEIVE_FILTERS
*) (UINTN
) CdbPtr
->DBaddr
;
724 ptr1
= (UINT8
*) (&DbPtr
->MCastList
[0]);
727 // DbPtr->mc_count = AdapterInfo->mcast_list.list_len;
729 copy_len
= (UINT16
) (AdapterInfo
->mcast_list
.list_len
* PXE_MAC_LENGTH
);
731 if (copy_len
> CdbPtr
->DBsize
) {
732 copy_len
= CdbPtr
->DBsize
;
736 ptr2
= (UINT8
*) (&AdapterInfo
->mcast_list
.mc_list
[0]);
737 for (Index
= 0; Index
< copy_len
; Index
++) {
738 ptr1
[Index
] = ptr2
[Index
];
742 // give the stat flags here
744 if (AdapterInfo
->Receive_Started
) {
745 CdbPtr
->StatFlags
= (PXE_STATFLAGS
) (CdbPtr
->StatFlags
| AdapterInfo
->Rx_Filter
);
752 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
753 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
759 IN NIC_DATA_INSTANCE
*AdapterInfo
764 This routine is used to get the current station and broadcast MAC addresses, and to change the
765 current station MAC address.
768 CdbPtr - Pointer to the command descriptor block.
769 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
776 PXE_CPB_STATION_ADDRESS
*CpbPtr
;
777 PXE_DB_STATION_ADDRESS
*DbPtr
;
780 if (CdbPtr
->OpFlags
== PXE_OPFLAGS_STATION_ADDRESS_RESET
) {
782 // configure the permanent address.
783 // change the AdapterInfo->CurrentNodeAddress field.
786 &AdapterInfo
->CurrentNodeAddress
[0],
787 &AdapterInfo
->PermNodeAddress
[0],
790 for (Index
= 0; Index
< PXE_MAC_LENGTH
; Index
++) {
791 AdapterInfo
->CurrentNodeAddress
[Index
] = AdapterInfo
->PermNodeAddress
[Index
];
794 E100bSetupIAAddr (AdapterInfo
);
798 if (CdbPtr
->CPBaddr
!= (UINT64
) 0) {
799 CpbPtr
= (PXE_CPB_STATION_ADDRESS
*) (UINTN
) (CdbPtr
->CPBaddr
);
801 // configure the new address
803 for (Index
= 0; Index
< PXE_MAC_LENGTH
; Index
++) {
804 AdapterInfo
->CurrentNodeAddress
[Index
] = CpbPtr
->StationAddr
[Index
];
807 E100bSetupIAAddr (AdapterInfo
);
810 if (CdbPtr
->DBaddr
!= (UINT64
) 0) {
811 DbPtr
= (PXE_DB_STATION_ADDRESS
*) (UINTN
) (CdbPtr
->DBaddr
);
813 // fill it with the new values
815 for (Index
= 0; Index
< PXE_MAC_LENGTH
; Index
++) {
816 DbPtr
->StationAddr
[Index
] = AdapterInfo
->CurrentNodeAddress
[Index
];
817 DbPtr
->BroadcastAddr
[Index
] = AdapterInfo
->BroadcastNodeAddress
[Index
];
818 DbPtr
->PermanentAddr
[Index
] = AdapterInfo
->PermNodeAddress
[Index
];
828 IN NIC_DATA_INSTANCE
*AdapterInfo
833 This routine is used to read and clear the NIC traffic statistics. This command is supported only
834 if the !PXE structure's Implementation flags say so.
836 Results will be parsed out in the following manner:
837 CdbPtr->DBaddr.Data[0] R Total Frames (Including frames with errors and dropped frames)
838 CdbPtr->DBaddr.Data[1] R Good Frames (All frames copied into receive buffer)
839 CdbPtr->DBaddr.Data[2] R Undersize Frames (Frames below minimum length for media <64 for ethernet)
840 CdbPtr->DBaddr.Data[4] R Dropped Frames (Frames that were dropped because receive buffers were full)
841 CdbPtr->DBaddr.Data[8] R CRC Error Frames (Frames with alignment or CRC errors)
842 CdbPtr->DBaddr.Data[A] T Total Frames (Including frames with errors and dropped frames)
843 CdbPtr->DBaddr.Data[B] T Good Frames (All frames copied into transmit buffer)
844 CdbPtr->DBaddr.Data[C] T Undersize Frames (Frames below minimum length for media <64 for ethernet)
845 CdbPtr->DBaddr.Data[E] T Dropped Frames (Frames that were dropped because of collisions)
846 CdbPtr->DBaddr.Data[14] T Total Collision Frames (Total collisions on this subnet)
849 CdbPtr - Pointer to the command descriptor block.
850 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
857 if ((CdbPtr
->OpFlags
&~(PXE_OPFLAGS_STATISTICS_RESET
)) != 0) {
858 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
859 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
863 if ((CdbPtr
->OpFlags
& PXE_OPFLAGS_STATISTICS_RESET
) != 0) {
865 // Reset the statistics
867 CdbPtr
->StatCode
= (UINT16
) E100bStatistics (AdapterInfo
, 0, 0);
869 CdbPtr
->StatCode
= (UINT16
) E100bStatistics (AdapterInfo
, CdbPtr
->DBaddr
, CdbPtr
->DBsize
);
878 IN NIC_DATA_INSTANCE
*AdapterInfo
883 This routine is used to translate a multicast IP address to a multicast MAC address.
885 This results in a MAC address composed of 25 bits of fixed data with the upper 23 bits of the IP
886 address being appended to it. Results passed back in the equivalent of CdbPtr->DBaddr->MAC[0-5].
889 CdbPtr - Pointer to the command descriptor block.
890 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
897 PXE_CPB_MCAST_IP_TO_MAC
*CpbPtr
;
898 PXE_DB_MCAST_IP_TO_MAC
*DbPtr
;
901 CpbPtr
= (PXE_CPB_MCAST_IP_TO_MAC
*) (UINTN
) CdbPtr
->CPBaddr
;
902 DbPtr
= (PXE_DB_MCAST_IP_TO_MAC
*) (UINTN
) CdbPtr
->DBaddr
;
904 if ((CdbPtr
->OpFlags
& PXE_OPFLAGS_MCAST_IPV6_TO_MAC
) != 0) {
906 // for now this is not supported
908 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
909 CdbPtr
->StatCode
= PXE_STATCODE_UNSUPPORTED
;
913 TmpPtr
= (UINT8
*) (&CpbPtr
->IP
.IPv4
);
915 // check if the ip given is a mcast IP
917 if ((TmpPtr
[0] & 0xF0) != 0xE0) {
918 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
919 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CPB
;
922 // take the last 23 bits in IP.
923 // be very careful. accessing word on a non-word boundary will hang motherboard codenamed Big Sur
924 // casting the mac array (in the middle) to a UINT32 pointer and accessing
925 // the UINT32 content hung the system...
927 DbPtr
->MAC
[0] = 0x01;
928 DbPtr
->MAC
[1] = 0x00;
929 DbPtr
->MAC
[2] = 0x5e;
930 DbPtr
->MAC
[3] = (UINT8
) (TmpPtr
[1] & 0x7f);
931 DbPtr
->MAC
[4] = (UINT8
) TmpPtr
[2];
932 DbPtr
->MAC
[5] = (UINT8
) TmpPtr
[3];
940 IN NIC_DATA_INSTANCE
*AdapterInfo
945 This routine is used to read and write non-volatile storage on the NIC (if supported). The NVRAM
946 could be EEPROM, FLASH, or battery backed RAM.
948 This is an optional function according to the UNDI specification (or will be......)
951 CdbPtr - Pointer to the command descriptor block.
952 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
959 PXE_DB_NVDATA
*DbPtr
;
962 if ((CdbPtr
->OpFlags
== PXE_OPFLAGS_NVDATA_READ
) != 0) {
964 if ((CdbPtr
->DBsize
== PXE_DBSIZE_NOT_USED
) != 0) {
965 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
966 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
970 DbPtr
= (PXE_DB_NVDATA
*) (UINTN
) CdbPtr
->DBaddr
;
972 for (Index
= 0; Index
< MAX_PCI_CONFIG_LEN
; Index
++) {
973 DbPtr
->Data
.Dword
[Index
] = AdapterInfo
->NVData
[Index
];
981 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
982 CdbPtr
->StatCode
= PXE_STATCODE_UNSUPPORTED
;
991 IN NIC_DATA_INSTANCE
*AdapterInfo
996 This routine returns the current interrupt status and/or the transmitted buffer addresses.
997 If the current interrupt status is returned, pending interrupts will be acknowledged by this
998 command. Transmitted buffer addresses that are written to the DB are removed from the transmit
1001 Normally, this command would be polled with interrupts disabled.
1003 The transmit buffers are returned in CdbPtr->DBaddr->TxBufer[0 - NumEntries].
1004 The interrupt status is returned in CdbPtr->StatFlags.
1007 CdbPtr - Pointer to the command descriptor block.
1008 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
1015 PXE_DB_GET_STATUS
*DbPtr
;
1016 PXE_DB_GET_STATUS TmpGetStatus
;
1023 // Fill in temporary GetStatus storage.
1025 RxPtr
= &AdapterInfo
->rx_ring
[AdapterInfo
->cur_rx_ind
];
1027 if ((RxPtr
->cb_header
.status
& RX_COMPLETE
) != 0) {
1028 TmpGetStatus
.RxFrameLen
= RxPtr
->ActualCount
& 0x3fff;
1030 TmpGetStatus
.RxFrameLen
= 0;
1033 TmpGetStatus
.reserved
= 0;
1036 // Fill in size of next available receive packet and
1037 // reserved field in caller's DB storage.
1039 DbPtr
= (PXE_DB_GET_STATUS
*) (UINTN
) CdbPtr
->DBaddr
;
1041 if (CdbPtr
->DBsize
> 0 && CdbPtr
->DBsize
< sizeof (UINT32
) * 2) {
1042 CopyMem (DbPtr
, &TmpGetStatus
, CdbPtr
->DBsize
);
1044 CopyMem (DbPtr
, &TmpGetStatus
, sizeof (UINT32
) * 2);
1050 if ((CdbPtr
->OpFlags
& PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS
) != 0) {
1052 // DBsize of zero is invalid if Tx buffers are requested.
1054 if (CdbPtr
->DBsize
== 0) {
1055 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1056 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
1061 // remember this b4 we overwrite
1063 NumEntries
= (UINT16
) (CdbPtr
->DBsize
- sizeof (UINT64
));
1066 // We already filled in 2 UINT32s.
1068 CdbPtr
->DBsize
= sizeof (UINT32
) * 2;
1071 // will claim any hanging free CBs
1073 CheckCBList (AdapterInfo
);
1075 if (AdapterInfo
->xmit_done_head
== AdapterInfo
->xmit_done_tail
) {
1076 CdbPtr
->StatFlags
|= PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY
;
1078 for (Index
= 0; NumEntries
>= sizeof (UINT64
); Index
++, NumEntries
-= sizeof (UINT64
)) {
1079 if (AdapterInfo
->xmit_done_head
!= AdapterInfo
->xmit_done_tail
) {
1080 DbPtr
->TxBuffer
[Index
] = AdapterInfo
->xmit_done
[AdapterInfo
->xmit_done_head
];
1081 AdapterInfo
->xmit_done_head
= next (AdapterInfo
->xmit_done_head
);
1082 CdbPtr
->DBsize
+= sizeof (UINT64
);
1089 if (AdapterInfo
->xmit_done_head
!= AdapterInfo
->xmit_done_tail
) {
1090 CdbPtr
->StatFlags
|= PXE_STATFLAGS_DB_WRITE_TRUNCATED
;
1094 // check for a receive buffer and give it's size in db
1100 if ((CdbPtr
->OpFlags
& PXE_OPFLAGS_GET_INTERRUPT_STATUS
) != 0) {
1102 Status
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBStatus
);
1103 AdapterInfo
->Int_Status
= (UINT16
) (AdapterInfo
->Int_Status
| Status
);
1106 // acknoledge the interrupts
1108 OutWord (AdapterInfo
, (UINT16
) (Status
& 0xfc00), (UINT32
) (AdapterInfo
->ioaddr
+ SCBStatus
));
1111 // report all the outstanding interrupts
1113 Status
= AdapterInfo
->Int_Status
;
1114 if ((Status
& SCB_STATUS_FR
) != 0) {
1115 CdbPtr
->StatFlags
|= PXE_STATFLAGS_GET_STATUS_RECEIVE
;
1118 if ((Status
& SCB_STATUS_SWI
) != 0) {
1119 CdbPtr
->StatFlags
|= PXE_STATFLAGS_GET_STATUS_SOFTWARE
;
1129 IN NIC_DATA_INSTANCE
*AdapterInfo
1133 Routine Description:
1134 This routine is used to fill media header(s) in transmit packet(s).
1135 Copies the MAC address into the media header whether it is dealing
1136 with fragmented or non-fragmented packets.
1139 CdbPtr - Pointer to the command descriptor block.
1140 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
1147 PXE_CPB_FILL_HEADER
*Cpb
;
1148 PXE_CPB_FILL_HEADER_FRAGMENTED
*Cpbf
;
1149 EtherHeader
*MacHeader
;
1152 if (CdbPtr
->CPBsize
== PXE_CPBSIZE_NOT_USED
) {
1153 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1154 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
1158 if ((CdbPtr
->OpFlags
& PXE_OPFLAGS_FILL_HEADER_FRAGMENTED
) != 0) {
1159 Cpbf
= (PXE_CPB_FILL_HEADER_FRAGMENTED
*) (UINTN
) CdbPtr
->CPBaddr
;
1162 // assume 1st fragment is big enough for the mac header
1164 if ((Cpbf
->FragCnt
== 0) || (Cpbf
->FragDesc
[0].FragLen
< PXE_MAC_HEADER_LEN_ETHER
)) {
1168 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1169 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
1173 MacHeader
= (EtherHeader
*) (UINTN
) Cpbf
->FragDesc
[0].FragAddr
;
1175 // we don't swap the protocol bytes
1177 MacHeader
->type
= Cpbf
->Protocol
;
1179 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1180 MacHeader
->dest_addr
[Index
] = Cpbf
->DestAddr
[Index
];
1181 MacHeader
->src_addr
[Index
] = Cpbf
->SrcAddr
[Index
];
1184 Cpb
= (PXE_CPB_FILL_HEADER
*) (UINTN
) CdbPtr
->CPBaddr
;
1186 MacHeader
= (EtherHeader
*) (UINTN
) Cpb
->MediaHeader
;
1188 // we don't swap the protocol bytes
1190 MacHeader
->type
= Cpb
->Protocol
;
1192 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1193 MacHeader
->dest_addr
[Index
] = Cpb
->DestAddr
[Index
];
1194 MacHeader
->src_addr
[Index
] = Cpb
->SrcAddr
[Index
];
1204 IN NIC_DATA_INSTANCE
*AdapterInfo
1208 Routine Description:
1209 This routine is used to place a packet into the transmit queue. The data buffers given to
1210 this command are to be considered locked and the application or network driver loses
1211 ownership of these buffers and must not free or relocate them until the ownership returns.
1213 When the packets are transmitted, a transmit complete interrupt is generated (if interrupts
1214 are disabled, the transmit interrupt status is still set and can be checked using the UNDI_Status
1217 Some implementations and adapters support transmitting multiple packets with one transmit
1218 command. If this feature is supported, the transmit CPBs can be linked in one transmit
1221 All UNDIs support fragmented frames, now all network devices or protocols do. If a fragmented
1222 frame CPB is given to UNDI and the network device does not support fragmented frames
1223 (see !PXE.Implementation flag), the UNDI will have to copy the fragments into a local buffer
1224 before transmitting.
1228 CdbPtr - Pointer to the command descriptor block.
1229 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
1237 if (CdbPtr
->CPBsize
== PXE_CPBSIZE_NOT_USED
) {
1238 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1239 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
1243 CdbPtr
->StatCode
= (PXE_STATCODE
) E100bTransmit (AdapterInfo
, CdbPtr
->CPBaddr
, CdbPtr
->OpFlags
);
1245 if (CdbPtr
->StatCode
!= PXE_STATCODE_SUCCESS
) {
1246 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1255 IN NIC_DATA_INSTANCE
*AdapterInfo
1259 Routine Description:
1260 When the network adapter has received a frame, this command is used to copy the frame
1261 into the driver/application storage location. Once a frame has been copied, it is
1262 removed from the receive queue.
1265 CdbPtr - Pointer to the command descriptor block.
1266 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
1275 // check if RU has started...
1277 if (!AdapterInfo
->Receive_Started
) {
1278 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1279 CdbPtr
->StatCode
= PXE_STATCODE_NOT_INITIALIZED
;
1284 CdbPtr
->StatCode
= (UINT16
) E100bReceive (AdapterInfo
, CdbPtr
->CPBaddr
, CdbPtr
->DBaddr
);
1285 if (CdbPtr
->StatCode
!= PXE_STATCODE_SUCCESS
) {
1286 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1300 Routine Description:
1301 This is the main SW UNDI API entry using the newer nii protocol.
1302 The parameter passed in is a 64 bit flat model virtual
1303 address of the cdb. We then jump into the common routine for both old and
1304 new nii protocol entries.
1307 CdbPtr - Pointer to the command descriptor block.
1308 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
1314 // TODO: cdb - add argument and description to function comment
1317 NIC_DATA_INSTANCE
*AdapterInfo
;
1319 if (cdb
== (UINT64
) 0) {
1324 CdbPtr
= (PXE_CDB
*) (UINTN
) cdb
;
1326 if (CdbPtr
->IFnum
>= pxe_31
->IFcnt
) {
1327 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1328 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
1332 AdapterInfo
= &(UNDI32DeviceList
[CdbPtr
->IFnum
]->NicInfo
);
1334 // entering from older entry point
1336 AdapterInfo
->VersionFlag
= 0x31;
1337 UNDI_APIEntry_Common (cdb
);
1341 UNDI_APIEntry_Common (
1346 Routine Description:
1347 This is the common routine for both old and new entry point procedures.
1348 The parameter passed in is a 64 bit flat model virtual
1349 address of the cdb. We then jump into the service routine pointed to by the
1353 CdbPtr - Pointer to the command descriptor block.
1354 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
1360 // TODO: cdb - add argument and description to function comment
1363 NIC_DATA_INSTANCE
*AdapterInfo
;
1364 UNDI_CALL_TABLE
*tab_ptr
;
1366 CdbPtr
= (PXE_CDB
*) (UINTN
) cdb
;
1369 // check the OPCODE range
1371 if ((CdbPtr
->OpCode
> PXE_OPCODE_LAST_VALID
) ||
1372 (CdbPtr
->StatCode
!= PXE_STATCODE_INITIALIZE
) ||
1373 (CdbPtr
->StatFlags
!= PXE_STATFLAGS_INITIALIZE
) ||
1374 (CdbPtr
->IFnum
>= pxe_31
->IFcnt
) ) {
1379 if (CdbPtr
->CPBsize
== PXE_CPBSIZE_NOT_USED
) {
1380 if (CdbPtr
->CPBaddr
!= PXE_CPBADDR_NOT_USED
) {
1383 } else if (CdbPtr
->CPBaddr
== PXE_CPBADDR_NOT_USED
) {
1387 if (CdbPtr
->DBsize
== PXE_DBSIZE_NOT_USED
) {
1388 if (CdbPtr
->DBaddr
!= PXE_DBADDR_NOT_USED
) {
1391 } else if (CdbPtr
->DBaddr
== PXE_DBADDR_NOT_USED
) {
1396 // check if cpbsize and dbsize are as needed
1397 // check if opflags are as expected
1399 tab_ptr
= &api_table
[CdbPtr
->OpCode
];
1401 if (tab_ptr
->cpbsize
!= (UINT16
) (DONT_CHECK
) && tab_ptr
->cpbsize
!= CdbPtr
->CPBsize
) {
1405 if (tab_ptr
->dbsize
!= (UINT16
) (DONT_CHECK
) && tab_ptr
->dbsize
!= CdbPtr
->DBsize
) {
1409 if (tab_ptr
->opflags
!= (UINT16
) (DONT_CHECK
) && tab_ptr
->opflags
!= CdbPtr
->OpFlags
) {
1414 AdapterInfo
= &(UNDI32DeviceList
[CdbPtr
->IFnum
]->NicInfo
);
1417 // check if UNDI_State is valid for this call
1419 if (tab_ptr
->state
!= (UINT16
) (-1)) {
1421 // should atleast be started
1423 if (AdapterInfo
->State
== PXE_STATFLAGS_GET_STATE_STOPPED
) {
1424 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1425 CdbPtr
->StatCode
= PXE_STATCODE_NOT_STARTED
;
1429 // check if it should be initialized
1431 if (tab_ptr
->state
== 2) {
1432 if (AdapterInfo
->State
!= PXE_STATFLAGS_GET_STATE_INITIALIZED
) {
1433 CdbPtr
->StatCode
= PXE_STATCODE_NOT_INITIALIZED
;
1434 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1440 // set the return variable for success case here
1442 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_COMPLETE
;
1443 CdbPtr
->StatCode
= PXE_STATCODE_SUCCESS
;
1445 tab_ptr
->api_ptr (CdbPtr
, AdapterInfo
);
1448 // %% AVL - check for command linking
1451 CdbPtr
->StatFlags
= PXE_STATFLAGS_COMMAND_FAILED
;
1452 CdbPtr
->StatCode
= PXE_STATCODE_INVALID_CDB
;
1464 Routine Description:
1465 This does an 8 bit check sum of the passed in buffer for Len bytes.
1466 This is primarily used to update the check sum in the SW UNDI header.
1469 Buffer - Pointer to the passed in buffer to check sum
1470 Len - Length of buffer to be check summed in bytes.
1481 if ((Bp
= Buffer
) != NULL
) {
1483 Chksum
= (UINT8
) (Chksum
+*Bp
++);
1494 IN NIC_DATA_INSTANCE
*NicPtr
,
1495 IN PXE_SW_UNDI
*PxePtr
1499 Routine Description:
1500 When called with a null NicPtr, this routine decrements the number of NICs
1501 this UNDI is supporting and removes the NIC_DATA_POINTER from the array.
1502 Otherwise, it increments the number of NICs this UNDI is supported and
1503 updates the pxe.Fudge to ensure a proper check sum results.
1506 NicPtr - Pointer to the NIC data structure.
1512 // TODO: PxePtr - add argument and description to function comment
1514 if (NicPtr
== NULL
) {
1515 if (PxePtr
->IFcnt
> 0) {
1517 // number of NICs this undi supports
1522 PxePtr
->Fudge
= (UINT8
) (PxePtr
->Fudge
- ChkSum ((VOID
*) PxePtr
, PxePtr
->Len
));
1527 // number of NICs this undi supports
1530 PxePtr
->Fudge
= (UINT8
) (PxePtr
->Fudge
- ChkSum ((VOID
*) PxePtr
, PxePtr
->Len
));
1537 IN PXE_SW_UNDI
*PxePtr
1541 Routine Description:
1542 Initialize the !PXE structure
1545 RemainingDevicePath - Not used, always produce all possible children.
1548 EFI_SUCCESS - This driver is added to Controller.
1549 other - This driver does not support this device.
1552 // TODO: PxePtr - add argument and description to function comment
1553 // TODO: VersionFlag - add argument and description to function comment
1556 // Initialize the !PXE structure
1558 PxePtr
->Signature
= PXE_ROMID_SIGNATURE
;
1559 PxePtr
->Len
= sizeof (PXE_SW_UNDI
);
1565 // number of NICs this undi supports
1568 PxePtr
->Rev
= PXE_ROMID_REV
;
1569 PxePtr
->MajorVer
= PXE_ROMID_MAJORVER
;
1570 PxePtr
->MinorVer
= PXE_ROMID_MINORVER
;
1571 PxePtr
->reserved1
= 0;
1573 PxePtr
->Implementation
= PXE_ROMID_IMP_SW_VIRT_ADDR
|
1574 PXE_ROMID_IMP_FRAG_SUPPORTED
|
1575 PXE_ROMID_IMP_CMD_LINK_SUPPORTED
|
1576 PXE_ROMID_IMP_NVDATA_READ_ONLY
|
1577 PXE_ROMID_IMP_STATION_ADDR_SETTABLE
|
1578 PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
|
1579 PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
|
1580 PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
|
1581 PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
|
1582 PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED
|
1583 PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED
;
1585 PxePtr
->EntryPoint
= (UINT64
) (UINTN
) UNDI_APIEntry_new
;
1586 PxePtr
->MinorVer
= PXE_ROMID_MINORVER_31
;
1588 PxePtr
->reserved2
[0] = 0;
1589 PxePtr
->reserved2
[1] = 0;
1590 PxePtr
->reserved2
[2] = 0;
1592 PxePtr
->BusType
[0] = PXE_BUSTYPE_PCI
;
1594 PxePtr
->Fudge
= (UINT8
) (PxePtr
->Fudge
- ChkSum ((VOID
*) PxePtr
, PxePtr
->Len
));