3 Copyright (c) 2006, 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.
26 static UINT8 basic_config_cmd
[22] = {
36 (UINT8
)0xf2, (UINT8
)0x80, // 0x40=Force full-duplex
41 // How to wait for the command unit to accept a command.
42 // Typically this takes 0 ticks.
44 #define wait_for_cmd_done(cmd_ioaddr) \
46 INT16 wait_count = 2000; \
47 while ((InByte (AdapterInfo, cmd_ioaddr) != 0) && --wait_count >= 0) \
48 DelayIt (AdapterInfo, 10); \
49 if (wait_count == 0) \
50 DelayIt (AdapterInfo, 50); \
55 IN NIC_DATA_INSTANCE
*AdapterInfo
,
61 This function calls the MemIo callback to read a byte from the device's
63 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
64 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
65 to make undi3.0 a special case
68 Port - Which port to read from.
71 Results - The data read from the port.
74 // TODO: AdapterInfo - add argument and description to function comment
78 (*AdapterInfo
->Mem_Io
) (
79 AdapterInfo
->Unique_ID
,
83 (UINT64
) (UINTN
) &Results
90 IN NIC_DATA_INSTANCE
*AdapterInfo
,
96 This function calls the MemIo callback to read a word from the device's
98 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
99 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
100 to make undi3.0 a special case
103 Port - Which port to read from.
106 Results - The data read from the port.
109 // TODO: AdapterInfo - add argument and description to function comment
113 (*AdapterInfo
->Mem_Io
) (
114 AdapterInfo
->Unique_ID
,
118 (UINT64
)(UINTN
)&Results
125 IN NIC_DATA_INSTANCE
*AdapterInfo
,
131 This function calls the MemIo callback to read a dword from the device's
133 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
134 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
135 to make undi3.0 a special case
138 Port - Which port to read from.
141 Results - The data read from the port.
144 // TODO: AdapterInfo - add argument and description to function comment
148 (*AdapterInfo
->Mem_Io
) (
149 AdapterInfo
->Unique_ID
,
153 (UINT64
)(UINTN
)&Results
160 IN NIC_DATA_INSTANCE
*AdapterInfo
,
167 This function calls the MemIo callback to write a byte from the device's
169 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
170 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
171 to make undi3.0 a special case
174 Data - Data to write to Port.
175 Port - Which port to write to.
181 // TODO: AdapterInfo - add argument and description to function comment
186 (*AdapterInfo
->Mem_Io
) (
187 AdapterInfo
->Unique_ID
,
191 (UINT64
)(UINTN
)(UINTN
)&Val
198 IN NIC_DATA_INSTANCE
*AdapterInfo
,
205 This function calls the MemIo callback to write a word from the device's
207 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
208 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
209 to make undi3.0 a special case
212 Data - Data to write to Port.
213 Port - Which port to write to.
219 // TODO: AdapterInfo - add argument and description to function comment
224 (*AdapterInfo
->Mem_Io
) (
225 AdapterInfo
->Unique_ID
,
236 IN NIC_DATA_INSTANCE
*AdapterInfo
,
243 This function calls the MemIo callback to write a dword from the device's
245 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
246 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
247 to make undi3.0 a special case
250 Data - Data to write to Port.
251 Port - Which port to write to.
257 // TODO: AdapterInfo - add argument and description to function comment
262 (*AdapterInfo
->Mem_Io
) (
263 AdapterInfo
->Unique_ID
,
275 IN NIC_DATA_INSTANCE
*AdapterInfo
,
279 OUT UINT64 MappedAddr
285 TODO: Add function description
289 AdapterInfo - TODO: add argument description
290 MemAddr - TODO: add argument description
291 Size - TODO: add argument description
292 Direction - TODO: add argument description
293 MappedAddr - TODO: add argument description
297 TODO: add return values
303 PhyAddr
= (UINT64
*) (UINTN
) MappedAddr
;
305 // mapping is different for theold and new NII protocols
307 if (AdapterInfo
->VersionFlag
== 0x30) {
308 if (AdapterInfo
->Virt2Phys_30
== (VOID
*) NULL
) {
309 *PhyAddr
= (UINT64
) AdapterInfo
->MemoryPtr
;
311 (*AdapterInfo
->Virt2Phys_30
) (MemAddr
, (UINT64
) (UINTN
) PhyAddr
);
314 if (*PhyAddr
> FOUR_GIGABYTE
) {
315 return PXE_STATCODE_INVALID_PARAMETER
;
318 if (AdapterInfo
->Map_Mem
== (VOID
*) NULL
) {
320 // this UNDI cannot handle addresses beyond 4 GB without a map routine
322 if (MemAddr
> FOUR_GIGABYTE
) {
323 return PXE_STATCODE_INVALID_PARAMETER
;
328 (*AdapterInfo
->Map_Mem
) (
329 AdapterInfo
->Unique_ID
,
338 return PXE_STATCODE_SUCCESS
;
344 IN NIC_DATA_INSTANCE
*AdapterInfo
,
354 TODO: Add function description
358 AdapterInfo - TODO: add argument description
359 MemAddr - TODO: add argument description
360 Size - TODO: add argument description
361 Direction - TODO: add argument description
362 MappedAddr - TODO: add argument description
366 TODO: add return values
370 if (AdapterInfo
->VersionFlag
> 0x30) {
372 // no mapping service
374 if (AdapterInfo
->UnMap_Mem
!= (VOID
*) NULL
) {
375 (*AdapterInfo
->UnMap_Mem
) (
376 AdapterInfo
->Unique_ID
,
392 IN NIC_DATA_INSTANCE
*AdapterInfo
,
400 AdapterInfo - Pointer to the NIC data structure information
401 which the UNDI driver is layering on..
406 // TODO: MicroSeconds - add argument and description to function comment
408 if (AdapterInfo
->VersionFlag
== 0x30) {
409 (*AdapterInfo
->Delay_30
) (MicroSeconds
);
411 (*AdapterInfo
->Delay
) (AdapterInfo
->Unique_ID
, MicroSeconds
);
418 IN NIC_DATA_INSTANCE
*AdapterInfo
,
426 AdapterInfo - Pointer to the NIC data structure information
427 which the UNDI driver is layering on..
432 // TODO: flag - add argument and description to function comment
434 if (AdapterInfo
->VersionFlag
== 0x30) {
435 (*AdapterInfo
->Block_30
) (flag
);
437 (*AdapterInfo
->Block
) (AdapterInfo
->Unique_ID
, flag
);
444 NIC_DATA_INSTANCE
*AdapterInfo
450 TODO: Add function description
454 AdapterInfo - TODO: add argument description
458 TODO: add return values
463 // we will use the linear (flat) memory model and fill our base registers
464 // with 0's so that the entire physical address is our offset
467 // we reset the statistics totals here because this is where we are loading stats addr
469 AdapterInfo
->RxTotals
= 0;
470 AdapterInfo
->TxTotals
= 0;
473 // Load the statistics block address.
475 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
476 OutLong (AdapterInfo
, (UINT32
) AdapterInfo
->stat_phy_addr
, AdapterInfo
->ioaddr
+ SCBPointer
);
477 OutByte (AdapterInfo
, CU_STATSADDR
, AdapterInfo
->ioaddr
+ SCBCmd
);
478 AdapterInfo
->statistics
->done_marker
= 0;
480 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
481 OutLong (AdapterInfo
, 0, AdapterInfo
->ioaddr
+ SCBPointer
);
482 OutByte (AdapterInfo
, RX_ADDR_LOAD
, AdapterInfo
->ioaddr
+ SCBCmd
);
484 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
485 OutLong (AdapterInfo
, 0, AdapterInfo
->ioaddr
+ SCBPointer
);
486 OutByte (AdapterInfo
, CU_CMD_BASE
, AdapterInfo
->ioaddr
+ SCBCmd
);
494 NIC_DATA_INSTANCE
*AdapterInfo
,
501 TODO: Add function description
505 AdapterInfo - TODO: add argument description
506 cmd_ptr - TODO: add argument description
510 TODO: add return values
516 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
519 // read the CU status, if it is idle, write the address of cb_ptr
520 // in the scbpointer and issue a cu_start,
521 // if it is suspended, remove the suspend bit in the previous command
522 // block and issue a resume
524 // Ensure that the CU Active Status bit is not on from previous CBs.
526 status
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBStatus
);
529 // Skip acknowledging the interrupt if it is not already set
533 // ack only the cna the integer
535 if ((status
& SCB_STATUS_CNA
) != 0) {
536 OutWord (AdapterInfo
, SCB_STATUS_CNA
, AdapterInfo
->ioaddr
+ SCBStatus
);
540 if ((status
& SCB_STATUS_CU_MASK
) == SCB_STATUS_CU_IDLE
) {
544 OutLong (AdapterInfo
, cmd_ptr
->PhysTCBAddress
, AdapterInfo
->ioaddr
+ SCBPointer
);
545 OutByte (AdapterInfo
, CU_START
, AdapterInfo
->ioaddr
+ SCBCmd
);
548 // either active or suspended, give a resume
551 cmd_ptr
->PrevTCBVirtualLinkPtr
->cb_header
.command
&= ~(CmdSuspend
| CmdIntr
);
552 OutByte (AdapterInfo
, CU_RESUME
, AdapterInfo
->ioaddr
+ SCBCmd
);
561 NIC_DATA_INSTANCE
*AdapterInfo
567 TODO: Add function description
571 AdapterInfo - TODO: add argument description
575 TODO: add return values
580 // all command blocks are of TxCB format
584 volatile INT16 Index
;
587 cmd_ptr
= GetFreeCB (AdapterInfo
);
588 data_ptr
= (UINT8
*) (&cmd_ptr
->PhysTBDArrayAddres
);
591 // start the config data right after the command header
593 for (Index
= 0; Index
< sizeof (basic_config_cmd
); Index
++) {
594 data_ptr
[Index
] = basic_config_cmd
[Index
];
597 my_filter
= (UINT8
) ((AdapterInfo
->Rx_Filter
& PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS
) ? 1 : 0);
598 my_filter
= (UINT8
) ((my_filter
| (AdapterInfo
->Rx_Filter
& PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST
) ? 0 : 2));
600 data_ptr
[15] = (UINT8
) (data_ptr
[15] | my_filter
);
601 data_ptr
[19] = (UINT8
) (AdapterInfo
->Duplex
? 0xC0 : 0x80);
602 data_ptr
[21] = (UINT8
) ((AdapterInfo
->Rx_Filter
& PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST
) ? 0x0D : 0x05);
605 // check if we have to use the AUI port instead
607 if ((AdapterInfo
->PhyRecord
[0] & 0x8000) != 0) {
608 data_ptr
[15] |= 0x80;
612 BlockIt (AdapterInfo
, TRUE
);
613 cmd_ptr
->cb_header
.command
= CmdSuspend
| CmdConfigure
;
615 IssueCB (AdapterInfo
, cmd_ptr
);
616 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
618 BlockIt (AdapterInfo
, FALSE
);
620 CommandWaitForCompletion (cmd_ptr
, AdapterInfo
);
623 // restore the cb values for tx
625 cmd_ptr
->PhysTBDArrayAddres
= cmd_ptr
->PhysArrayAddr
;
626 cmd_ptr
->ByteCount
= cmd_ptr
->Threshold
= cmd_ptr
->TBDCount
= 0;
628 // fields beyond the immediatedata are assumed to be safe
629 // add the CB to the free list again
631 SetFreeCB (AdapterInfo
, cmd_ptr
);
637 NIC_DATA_INSTANCE
*AdapterInfo
643 TODO: Add function description
647 AdapterInfo - TODO: add argument description
651 TODO: add return values
656 // all command blocks are of TxCB format
662 eaddrs
= (UINT16
*) AdapterInfo
->CurrentNodeAddress
;
664 cmd_ptr
= GetFreeCB (AdapterInfo
);
665 data_ptr
= (UINT16
*) (&cmd_ptr
->PhysTBDArrayAddres
);
668 // AVOID a bug (?!) here by marking the command already completed.
670 cmd_ptr
->cb_header
.command
= (CmdSuspend
| CmdIASetup
);
671 cmd_ptr
->cb_header
.status
= 0;
672 data_ptr
[0] = eaddrs
[0];
673 data_ptr
[1] = eaddrs
[1];
674 data_ptr
[2] = eaddrs
[2];
676 BlockIt (AdapterInfo
, TRUE
);
677 IssueCB (AdapterInfo
, cmd_ptr
);
678 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
679 BlockIt (AdapterInfo
, FALSE
);
681 CommandWaitForCompletion (cmd_ptr
, AdapterInfo
);
684 // restore the cb values for tx
686 cmd_ptr
->PhysTBDArrayAddres
= cmd_ptr
->PhysArrayAddr
;
687 cmd_ptr
->ByteCount
= cmd_ptr
->Threshold
= cmd_ptr
->TBDCount
= 0;
689 // fields beyond the immediatedata are assumed to be safe
690 // add the CB to the free list again
692 SetFreeCB (AdapterInfo
, cmd_ptr
);
699 IN NIC_DATA_INSTANCE
*AdapterInfo
704 Instructs the NIC to stop receiving packets.
707 AdapterInfo - Pointer to the NIC data structure information
708 which the UNDI driver is layering on..
713 if (AdapterInfo
->Receive_Started
) {
716 // Todo: verify that we must wait for previous command completion.
718 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
721 // Disable interrupts, and stop the chip's Rx process.
723 OutWord (AdapterInfo
, INT_MASK
, AdapterInfo
->ioaddr
+ SCBCmd
);
724 OutWord (AdapterInfo
, INT_MASK
| RX_ABORT
, AdapterInfo
->ioaddr
+ SCBCmd
);
726 AdapterInfo
->Receive_Started
= FALSE
;
735 NIC_DATA_INSTANCE
*AdapterInfo
740 Instructs the NIC to start receiving packets.
743 AdapterInfo - Pointer to the NIC data structure information
744 which the UNDI driver is layering on..
751 if (AdapterInfo
->Receive_Started
) {
758 AdapterInfo
->cur_rx_ind
= 0;
759 AdapterInfo
->Int_Status
= 0;
761 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
763 OutLong (AdapterInfo
, (UINT32
) AdapterInfo
->rx_phy_addr
, AdapterInfo
->ioaddr
+ SCBPointer
);
764 OutByte (AdapterInfo
, RX_START
, AdapterInfo
->ioaddr
+ SCBCmd
);
766 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
768 AdapterInfo
->Receive_Started
= TRUE
;
774 IN NIC_DATA_INSTANCE
*AdapterInfo
779 Configures the chip. This routine expects the NIC_DATA_INSTANCE structure to be filled in.
782 AdapterInfo - Pointer to the NIC data structure information
783 which the UNDI driver is layering on..
787 PXE_STATCODE_NOT_ENOUGH_MEMORY - Insufficient length of locked memory
788 other - Failure initializing chip
791 PCI_CONFIG_HEADER
*CfgHdr
;
796 if (AdapterInfo
->MemoryLength
< MEMORY_NEEDED
) {
797 return PXE_STATCODE_NOT_ENOUGH_MEMORY
;
802 AdapterInfo
->MemoryPtr
,
803 AdapterInfo
->MemoryLength
,
805 (UINT64
)(UINTN
) &AdapterInfo
->Mapped_MemoryPtr
812 CfgHdr
= (PCI_CONFIG_HEADER
*) &(AdapterInfo
->Config
[0]);
815 // fill in the ioaddr, int... from the config space
817 AdapterInfo
->int_num
= CfgHdr
->int_line
;
820 // we don't need to validate integer number, what if they don't want to assign one?
821 // if (AdapterInfo->int_num == 0 || AdapterInfo->int_num == 0xff)
822 // return PXE_STATCODE_DEVICE_FAILURE;
824 AdapterInfo
->ioaddr
= 0;
825 AdapterInfo
->VendorID
= CfgHdr
->VendorID
;
826 AdapterInfo
->DeviceID
= CfgHdr
->DeviceID
;
827 AdapterInfo
->RevID
= CfgHdr
->RevID
;
828 AdapterInfo
->SubVendorID
= CfgHdr
->SubVendorID
;
829 AdapterInfo
->SubSystemID
= CfgHdr
->SubSystemID
;
830 AdapterInfo
->flash_addr
= 0;
833 // Read the station address EEPROM before doing the reset.
834 // Perhaps this should even be done before accepting the device,
835 // then we wouldn't have a device name with which to report the error.
837 if (E100bReadEepromAndStationAddress (AdapterInfo
) != 0) {
838 return PXE_STATCODE_DEVICE_FAILURE
;
842 // ## calculate the buffer #s depending on memory given
843 // ## calculate the rx and tx ring pointers
846 AdapterInfo
->TxBufCnt
= TX_BUFFER_COUNT
;
847 AdapterInfo
->RxBufCnt
= RX_BUFFER_COUNT
;
848 rx_size
= (AdapterInfo
->RxBufCnt
* sizeof (RxFD
));
849 tx_size
= (AdapterInfo
->TxBufCnt
* sizeof (TxCB
));
850 AdapterInfo
->rx_ring
= (RxFD
*) (UINTN
) (AdapterInfo
->MemoryPtr
);
851 AdapterInfo
->tx_ring
= (TxCB
*) (UINTN
) (AdapterInfo
->MemoryPtr
+ rx_size
);
852 AdapterInfo
->statistics
= (struct speedo_stats
*) (UINTN
) (AdapterInfo
->MemoryPtr
+ rx_size
+ tx_size
);
854 AdapterInfo
->rx_phy_addr
= AdapterInfo
->Mapped_MemoryPtr
;
855 AdapterInfo
->tx_phy_addr
= AdapterInfo
->Mapped_MemoryPtr
+ rx_size
;
856 AdapterInfo
->stat_phy_addr
= AdapterInfo
->tx_phy_addr
+ tx_size
;
861 AdapterInfo
->PhyAddress
= 0xFF;
862 AdapterInfo
->Rx_Filter
= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST
;
863 AdapterInfo
->Receive_Started
= FALSE
;
864 AdapterInfo
->mcast_list
.list_len
= 0;
865 return InitializeChip (AdapterInfo
);
869 E100bSetInterruptState (
870 IN NIC_DATA_INSTANCE
*AdapterInfo
875 Sets the interrupt state for the NIC.
878 AdapterInfo - Pointer to the NIC data structure information
879 which the UNDI driver is layering on..
885 // don't set receive interrupt if receiver is disabled...
889 if ((AdapterInfo
->int_mask
& PXE_OPFLAGS_INTERRUPT_RECEIVE
) != 0) {
890 cmd_word
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBCmd
);
891 cmd_word
&= ~INT_MASK
;
892 OutWord (AdapterInfo
, cmd_word
, AdapterInfo
->ioaddr
+ SCBCmd
);
895 // disable ints, should not be given for SW Int.
897 OutWord (AdapterInfo
, INT_MASK
, AdapterInfo
->ioaddr
+ SCBCmd
);
900 if ((AdapterInfo
->int_mask
& PXE_OPFLAGS_INTERRUPT_SOFTWARE
) != 0) {
902 // reset the bit in our mask, it is only one time!!
904 AdapterInfo
->int_mask
&= ~(PXE_OPFLAGS_INTERRUPT_SOFTWARE
);
905 cmd_word
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBCmd
);
906 cmd_word
|= DRVR_INT
;
907 OutWord (AdapterInfo
, cmd_word
, AdapterInfo
->ioaddr
+ SCBCmd
);
913 // we are not going to disable broadcast for the WOL's sake!
917 NIC_DATA_INSTANCE
*AdapterInfo
,
925 Instructs the NIC to start receiving packets.
928 AdapterInfo - Pointer to the NIC data structure information
929 which the UNDI driver is layering on..
939 PXE_CPB_RECEIVE_FILTERS
*mc_list
= (PXE_CPB_RECEIVE_FILTERS
*) (UINTN
)cpb
;
946 struct MC_CB_STRUCT
*data_ptr
;
949 old_filter
= AdapterInfo
->Rx_Filter
;
952 // only these bits need a change in the configuration
953 // actually change in bcast requires configure but we ignore that change
955 cfg_flt
= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS
|
956 PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST
;
958 if ((old_filter
& cfg_flt
) != (new_filter
& cfg_flt
)) {
959 XmitWaitForCompletion (AdapterInfo
);
961 if (AdapterInfo
->Receive_Started
) {
962 StopRU (AdapterInfo
);
965 AdapterInfo
->Rx_Filter
= (UINT8
) (new_filter
| PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST
);
966 Configure (AdapterInfo
);
970 // check if mcast setting changed
972 if ( ((new_filter
& PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
) !=
973 (old_filter
& PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
) ) ||
974 (mc_list
!= NULL
) ) {
977 if (mc_list
!= NULL
) {
978 mc_count
= AdapterInfo
->mcast_list
.list_len
= (UINT16
) (cpbsize
/ PXE_MAC_LENGTH
);
980 for (Index
= 0; (Index
< mc_count
&& Index
< MAX_MCAST_ADDRESS_CNT
); Index
++) {
981 for (Index2
= 0; Index2
< PXE_MAC_LENGTH
; Index2
++) {
982 AdapterInfo
->mcast_list
.mc_list
[Index
][Index2
] = mc_list
->MCastList
[Index
][Index2
];
988 // are we setting the list or resetting??
990 if ((new_filter
& PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
) != 0) {
992 // we are setting a new list!
994 mc_count
= AdapterInfo
->mcast_list
.list_len
;
996 // count should be the actual # of bytes in the list
997 // so multiply this with 6
999 mc_byte_cnt
= (UINT16
) ((mc_count
<< 2) + (mc_count
<< 1));
1000 AdapterInfo
->Rx_Filter
|= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
;
1003 // disabling the list in the NIC.
1005 mc_byte_cnt
= mc_count
= 0;
1006 AdapterInfo
->Rx_Filter
&= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
);
1010 // before issuing any new command!
1012 XmitWaitForCompletion (AdapterInfo
);
1014 if (AdapterInfo
->Receive_Started
) {
1015 StopRU (AdapterInfo
);
1019 cmd_ptr
= GetFreeCB (AdapterInfo
);
1020 if (cmd_ptr
== NULL
) {
1021 return PXE_STATCODE_QUEUE_FULL
;
1024 // fill the command structure and issue
1026 data_ptr
= (struct MC_CB_STRUCT
*) (&cmd_ptr
->PhysTBDArrayAddres
);
1028 // first 2 bytes are the count;
1030 data_ptr
->count
= mc_byte_cnt
;
1031 for (Index
= 0; Index
< mc_count
; Index
++) {
1032 for (Index2
= 0; Index2
< PXE_HWADDR_LEN_ETHER
; Index2
++) {
1033 data_ptr
->m_list
[Index
][Index2
] = AdapterInfo
->mcast_list
.mc_list
[Index
][Index2
];
1037 cmd_ptr
->cb_header
.command
= CmdSuspend
| CmdMulticastList
;
1038 cmd_ptr
->cb_header
.status
= 0;
1040 BlockIt (AdapterInfo
, TRUE
);
1041 IssueCB (AdapterInfo
, cmd_ptr
);
1042 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
1044 BlockIt (AdapterInfo
, FALSE
);
1046 CommandWaitForCompletion (cmd_ptr
, AdapterInfo
);
1048 cmd_ptr
->PhysTBDArrayAddres
= cmd_ptr
->PhysArrayAddr
;
1049 cmd_ptr
->ByteCount
= cmd_ptr
->Threshold
= cmd_ptr
->TBDCount
= 0;
1051 // fields beyond the immediatedata are assumed to be safe
1052 // add the CB to the free list again
1054 SetFreeCB (AdapterInfo
, cmd_ptr
);
1057 if (new_filter
!= 0) {
1059 // enable unicast and start the RU
1061 AdapterInfo
->Rx_Filter
= (UINT8
) (AdapterInfo
->Rx_Filter
| (new_filter
| PXE_OPFLAGS_RECEIVE_FILTER_UNICAST
));
1062 StartRU (AdapterInfo
);
1065 // may be disabling everything!
1067 if (AdapterInfo
->Receive_Started
) {
1068 StopRU (AdapterInfo
);
1071 AdapterInfo
->Rx_Filter
|= (~PXE_OPFLAGS_RECEIVE_FILTER_UNICAST
);
1079 NIC_DATA_INSTANCE
*AdapterInfo
,
1085 Routine Description:
1087 TODO: Add function description
1091 AdapterInfo - TODO: add argument description
1092 cpb - TODO: add argument description
1093 opflags - TODO: add argument description
1097 TODO: add return values
1101 PXE_CPB_TRANSMIT_FRAGMENTS
*tx_ptr_f
;
1102 PXE_CPB_TRANSMIT
*tx_ptr_1
;
1109 tx_ptr_1
= (PXE_CPB_TRANSMIT
*) (UINTN
) cpb
;
1110 tx_ptr_f
= (PXE_CPB_TRANSMIT_FRAGMENTS
*) (UINTN
) cpb
;
1113 // stop reentrancy here
1115 if (AdapterInfo
->in_transmit
) {
1116 return PXE_STATCODE_BUSY
;
1120 AdapterInfo
->in_transmit
= TRUE
;
1123 // Prevent interrupts from changing the Tx ring from underneath us.
1125 // Calculate the Tx descriptor entry.
1127 if ((tcb_ptr
= GetFreeCB (AdapterInfo
)) == NULL
) {
1128 AdapterInfo
->in_transmit
= FALSE
;
1129 return PXE_STATCODE_QUEUE_FULL
;
1132 AdapterInfo
->TxTotals
++;
1134 tcb_ptr
->cb_header
.command
= (CmdSuspend
| CmdTx
| CmdTxFlex
);
1135 tcb_ptr
->cb_header
.status
= 0;
1138 // no immediate data, set EOF in the ByteCount
1140 tcb_ptr
->ByteCount
= 0x8000;
1143 // The data region is always in one buffer descriptor, Tx FIFO
1144 // threshold of 256.
1145 // 82557 multiplies the threashold value by 8, so give 256/8
1147 tcb_ptr
->Threshold
= 32;
1148 if ((opflags
& PXE_OPFLAGS_TRANSMIT_FRAGMENTED
) != 0) {
1150 if (tx_ptr_f
->FragCnt
> MAX_XMIT_FRAGMENTS
) {
1151 SetFreeCB (AdapterInfo
, tcb_ptr
);
1152 AdapterInfo
->in_transmit
= FALSE
;
1153 return PXE_STATCODE_INVALID_PARAMETER
;
1156 tcb_ptr
->TBDCount
= (UINT8
) tx_ptr_f
->FragCnt
;
1158 for (Index
= 0; Index
< tx_ptr_f
->FragCnt
; Index
++) {
1161 tx_ptr_f
->FragDesc
[Index
].FragAddr
,
1162 tx_ptr_f
->FragDesc
[Index
].FragLen
,
1164 (UINT64
)(UINTN
) &Tmp_ptr
1167 SetFreeCB (AdapterInfo
, tcb_ptr
);
1168 AdapterInfo
->in_transmit
= FALSE
;
1169 return PXE_STATCODE_INVALID_PARAMETER
;
1172 tcb_ptr
->TBDArray
[Index
].phys_buf_addr
= (UINT32
) Tmp_ptr
;
1173 tcb_ptr
->TBDArray
[Index
].buf_len
= tx_ptr_f
->FragDesc
[Index
].FragLen
;
1176 tcb_ptr
->free_data_ptr
= tx_ptr_f
->FragDesc
[0].FragAddr
;
1180 // non fragmented case
1182 tcb_ptr
->TBDCount
= 1;
1185 tx_ptr_1
->FrameAddr
,
1186 tx_ptr_1
->DataLen
+ tx_ptr_1
->MediaheaderLen
,
1188 (UINT64
)(UINTN
) &Tmp_ptr
1191 SetFreeCB (AdapterInfo
, tcb_ptr
);
1192 AdapterInfo
->in_transmit
= FALSE
;
1193 return PXE_STATCODE_INVALID_PARAMETER
;
1196 tcb_ptr
->TBDArray
[0].phys_buf_addr
= (UINT32
) (Tmp_ptr
);
1197 tcb_ptr
->TBDArray
[0].buf_len
= tx_ptr_1
->DataLen
+ tx_ptr_1
->MediaheaderLen
;
1198 tcb_ptr
->free_data_ptr
= tx_ptr_1
->FrameAddr
;
1202 // must wait for previous command completion only if it was a non-transmit
1204 BlockIt (AdapterInfo
, TRUE
);
1205 IssueCB (AdapterInfo
, tcb_ptr
);
1206 BlockIt (AdapterInfo
, FALSE
);
1209 // see if we need to wait for completion here
1211 if ((opflags
& PXE_OPFLAGS_TRANSMIT_BLOCK
) != 0) {
1213 // don't wait for more than 1 second!!!
1216 while (tcb_ptr
->cb_header
.status
== 0) {
1217 DelayIt (AdapterInfo
, 10);
1219 if (wait_sec
== 0) {
1224 // we need to un-map any mapped buffers here
1226 if ((opflags
& PXE_OPFLAGS_TRANSMIT_FRAGMENTED
) != 0) {
1228 for (Index
= 0; Index
< tx_ptr_f
->FragCnt
; Index
++) {
1229 Tmp_ptr
= tcb_ptr
->TBDArray
[Index
].phys_buf_addr
;
1232 tx_ptr_f
->FragDesc
[Index
].FragAddr
,
1233 tx_ptr_f
->FragDesc
[Index
].FragLen
,
1239 Tmp_ptr
= tcb_ptr
->TBDArray
[0].phys_buf_addr
;
1242 tx_ptr_1
->FrameAddr
,
1243 tx_ptr_1
->DataLen
+ tx_ptr_1
->MediaheaderLen
,
1249 if (tcb_ptr
->cb_header
.status
== 0) {
1250 SetFreeCB (AdapterInfo
, tcb_ptr
);
1251 AdapterInfo
->in_transmit
= FALSE
;
1252 return PXE_STATCODE_DEVICE_FAILURE
;
1255 SetFreeCB (AdapterInfo
, tcb_ptr
);
1258 // CB will be set free later in get_status (or when we run out of xmit buffers
1260 AdapterInfo
->in_transmit
= FALSE
;
1267 NIC_DATA_INSTANCE
*AdapterInfo
,
1273 Routine Description:
1275 TODO: Add function description
1279 AdapterInfo - TODO: add argument description
1280 cpb - TODO: add argument description
1281 db - TODO: add argument description
1285 TODO: add return values
1289 PXE_CPB_RECEIVE
*rx_cpbptr
;
1290 PXE_DB_RECEIVE
*rx_dbptr
;
1296 PXE_FRAME_TYPE pkt_type
;
1298 EtherHeader
*hdr_ptr
;
1299 ret_code
= PXE_STATCODE_NO_DATA
;
1300 pkt_type
= PXE_FRAME_TYPE_NONE
;
1301 status
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBStatus
);
1302 AdapterInfo
->Int_Status
= (UINT16
) (AdapterInfo
->Int_Status
| status
);
1304 // acknoledge the interrupts
1306 OutWord (AdapterInfo
, (UINT16
) (status
& 0xfc00), (UINT32
) (AdapterInfo
->ioaddr
+ SCBStatus
));
1309 // include the prev ints as well
1311 status
= AdapterInfo
->Int_Status
;
1312 rx_cpbptr
= (PXE_CPB_RECEIVE
*) (UINTN
) cpb
;
1313 rx_dbptr
= (PXE_DB_RECEIVE
*) (UINTN
) db
;
1315 rx_ptr
= &AdapterInfo
->rx_ring
[AdapterInfo
->cur_rx_ind
];
1318 // be in a loop just in case (we may drop a pkt)
1320 while ((status
= rx_ptr
->cb_header
.status
) & RX_COMPLETE
) {
1322 AdapterInfo
->RxTotals
++;
1324 // If we own the next entry, it's a new packet. Send it up.
1326 if (rx_ptr
->forwarded
) {
1332 // discard bad frames
1336 // crc, align, dma overrun, too short, receive error (v22 no coll)
1338 if ((status
& 0x0D90) != 0) {
1344 // make sure the status is OK
1346 if ((status
& 0x02000) == 0) {
1350 pkt_len
= (UINT16
) (rx_ptr
->ActualCount
& 0x3fff);
1355 if (pkt_len
> rx_cpbptr
->BufferLen
) {
1356 Tmp_len
= (UINT16
) rx_cpbptr
->BufferLen
;
1359 CopyMem ((INT8
*) (UINTN
) rx_cpbptr
->BufferAddr
, (INT8
*) &rx_ptr
->RFDBuffer
, Tmp_len
);
1361 hdr_ptr
= (EtherHeader
*) &rx_ptr
->RFDBuffer
;
1363 // fill the CDB and break the loop
1369 rx_dbptr
->FrameLen
= pkt_len
;
1370 rx_dbptr
->MediaHeaderLen
= PXE_MAC_HEADER_LEN_ETHER
;
1372 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1373 if (hdr_ptr
->dest_addr
[Index
] != AdapterInfo
->CurrentNodeAddress
[Index
]) {
1378 if (Index
>= PXE_HWADDR_LEN_ETHER
) {
1379 pkt_type
= PXE_FRAME_TYPE_UNICAST
;
1381 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1382 if (hdr_ptr
->dest_addr
[Index
] != AdapterInfo
->BroadcastNodeAddress
[Index
]) {
1387 if (Index
>= PXE_HWADDR_LEN_ETHER
) {
1388 pkt_type
= PXE_FRAME_TYPE_BROADCAST
;
1390 if ((hdr_ptr
->dest_addr
[0] & 1) == 1) {
1395 pkt_type
= PXE_FRAME_TYPE_MULTICAST
;
1397 pkt_type
= PXE_FRAME_TYPE_PROMISCUOUS
;
1402 rx_dbptr
->Type
= pkt_type
;
1403 rx_dbptr
->Protocol
= hdr_ptr
->type
;
1405 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1406 rx_dbptr
->SrcAddr
[Index
] = hdr_ptr
->src_addr
[Index
];
1407 rx_dbptr
->DestAddr
[Index
] = hdr_ptr
->dest_addr
[Index
];
1410 rx_ptr
->forwarded
= TRUE
;
1415 Recycle_RFD (AdapterInfo
, AdapterInfo
->cur_rx_ind
);
1416 AdapterInfo
->cur_rx_ind
++;
1417 if (AdapterInfo
->cur_rx_ind
== AdapterInfo
->RxBufCnt
) {
1418 AdapterInfo
->cur_rx_ind
= 0;
1424 Recycle_RFD (AdapterInfo
, AdapterInfo
->cur_rx_ind
);
1425 AdapterInfo
->cur_rx_ind
++;
1426 if (AdapterInfo
->cur_rx_ind
== AdapterInfo
->RxBufCnt
) {
1427 AdapterInfo
->cur_rx_ind
= 0;
1430 rx_ptr
= &AdapterInfo
->rx_ring
[AdapterInfo
->cur_rx_ind
];
1433 if (pkt_type
== PXE_FRAME_TYPE_NONE
) {
1434 AdapterInfo
->Int_Status
&= (~SCB_STATUS_FR
);
1437 status
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBStatus
);
1438 if ((status
& SCB_RUS_NO_RESOURCES
) != 0) {
1440 // start the receive unit here!
1441 // leave all the filled frames,
1443 SetupReceiveQueues (AdapterInfo
);
1444 OutLong (AdapterInfo
, (UINT32
) AdapterInfo
->rx_phy_addr
, AdapterInfo
->ioaddr
+ SCBPointer
);
1445 OutWord (AdapterInfo
, RX_START
, AdapterInfo
->ioaddr
+ SCBCmd
);
1446 AdapterInfo
->cur_rx_ind
= 0;
1453 E100bReadEepromAndStationAddress (
1454 NIC_DATA_INSTANCE
*AdapterInfo
1458 Routine Description:
1460 TODO: Add function description
1464 AdapterInfo - TODO: add argument description
1468 TODO: add return values
1479 eedata
= (UINT16
*) (&AdapterInfo
->NVData
[0]);
1482 addr_len
= E100bGetEepromAddrLen (AdapterInfo
);
1487 AdapterInfo
->NVData_Len
= eeprom_len
= (UINT16
) (1 << addr_len
);
1488 for (Index2
= 0, Index
= 0; Index
< eeprom_len
; Index
++) {
1490 value
= E100bReadEeprom (AdapterInfo
, Index
, addr_len
);
1491 eedata
[Index
] = value
;
1492 sum
= (UINT16
) (sum
+ value
);
1494 AdapterInfo
->PermNodeAddress
[Index2
++] = (UINT8
) value
;
1495 AdapterInfo
->PermNodeAddress
[Index2
++] = (UINT8
) (value
>> 8);
1499 if (sum
!= 0xBABA) {
1503 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1504 AdapterInfo
->CurrentNodeAddress
[Index
] = AdapterInfo
->PermNodeAddress
[Index
];
1507 for (Index
= 0; Index
< PXE_HWADDR_LEN_ETHER
; Index
++) {
1508 AdapterInfo
->BroadcastNodeAddress
[Index
] = 0xff;
1511 for (Index
= PXE_HWADDR_LEN_ETHER
; Index
< PXE_MAC_LENGTH
; Index
++) {
1512 AdapterInfo
->CurrentNodeAddress
[Index
] = 0;
1513 AdapterInfo
->PermNodeAddress
[Index
] = 0;
1514 AdapterInfo
->BroadcastNodeAddress
[Index
] = 0;
1521 // CBList is a circular linked list
1522 // 1) When all are free, Tail->next == Head and FreeCount == # allocated
1523 // 2) When none are free, Tail == Head and FreeCount == 0
1524 // 3) when one is free, Tail == Head and Freecount == 1
1525 // 4) First non-Free frame is always at Tail->next
1529 NIC_DATA_INSTANCE
*AdapterInfo
1533 Routine Description:
1535 TODO: Add function description
1539 AdapterInfo - TODO: add argument description
1543 TODO: add return values
1553 cur_ptr
= &(AdapterInfo
->tx_ring
[0]);
1554 array_off
= (UINTN
) (&cur_ptr
->TBDArray
) - (UINTN
) cur_ptr
;
1555 for (Index
= 0; Index
< AdapterInfo
->TxBufCnt
; Index
++) {
1556 cur_ptr
[Index
].cb_header
.status
= 0;
1557 cur_ptr
[Index
].cb_header
.command
= 0;
1559 cur_ptr
[Index
].PhysTCBAddress
=
1560 (UINT32
) AdapterInfo
->tx_phy_addr
+ (Index
* sizeof (TxCB
));
1562 cur_ptr
[Index
].PhysArrayAddr
= (UINT32
)(cur_ptr
[Index
].PhysTCBAddress
+ array_off
);
1563 cur_ptr
[Index
].PhysTBDArrayAddres
= (UINT32
)(cur_ptr
[Index
].PhysTCBAddress
+ array_off
);
1565 cur_ptr
->free_data_ptr
= (UINT64
) 0;
1567 if (Index
< AdapterInfo
->TxBufCnt
- 1) {
1568 cur_ptr
[Index
].cb_header
.link
= cur_ptr
[Index
].PhysTCBAddress
+ sizeof (TxCB
);
1569 cur_ptr
[Index
].NextTCBVirtualLinkPtr
= &cur_ptr
[Index
+ 1];
1570 cur_ptr
[Index
+ 1].PrevTCBVirtualLinkPtr
= &cur_ptr
[Index
];
1574 head_ptr
= &cur_ptr
[0];
1575 tail_ptr
= &cur_ptr
[AdapterInfo
->TxBufCnt
- 1];
1576 tail_ptr
->cb_header
.link
= head_ptr
->PhysTCBAddress
;
1577 tail_ptr
->NextTCBVirtualLinkPtr
= head_ptr
;
1578 head_ptr
->PrevTCBVirtualLinkPtr
= tail_ptr
;
1580 AdapterInfo
->FreeCBCount
= AdapterInfo
->TxBufCnt
;
1581 AdapterInfo
->FreeTxHeadPtr
= head_ptr
;
1583 // set tail of the free list, next to this would be either in use
1584 // or the head itself
1586 AdapterInfo
->FreeTxTailPtr
= tail_ptr
;
1588 AdapterInfo
->xmit_done_head
= AdapterInfo
->xmit_done_tail
= 0;
1595 NIC_DATA_INSTANCE
*AdapterInfo
1599 Routine Description:
1601 TODO: Add function description
1605 AdapterInfo - TODO: add argument description
1609 TODO: add return values
1616 // claim any hanging free CBs
1618 if (AdapterInfo
->FreeCBCount
<= 1) {
1619 CheckCBList (AdapterInfo
);
1623 // don't use up the last CB problem if the previous CB that the CU used
1624 // becomes the last CB we submit because of the SUSPEND bit we set.
1625 // the CU thinks it was never cleared.
1628 if (AdapterInfo
->FreeCBCount
<= 1) {
1632 BlockIt (AdapterInfo
, TRUE
);
1633 free_cb_ptr
= AdapterInfo
->FreeTxHeadPtr
;
1634 AdapterInfo
->FreeTxHeadPtr
= free_cb_ptr
->NextTCBVirtualLinkPtr
;
1635 --AdapterInfo
->FreeCBCount
;
1636 BlockIt (AdapterInfo
, FALSE
);
1642 IN NIC_DATA_INSTANCE
*AdapterInfo
,
1647 Routine Description:
1649 TODO: Add function description
1653 AdapterInfo - TODO: add argument description
1654 cb_ptr - TODO: add argument description
1658 TODO: add return values
1663 // here we assume cb are returned in the order they are taken out
1664 // and we link the newly freed cb at the tail of free cb list
1666 cb_ptr
->cb_header
.status
= 0;
1667 cb_ptr
->free_data_ptr
= (UINT64
) 0;
1669 AdapterInfo
->FreeTxTailPtr
= cb_ptr
;
1670 ++AdapterInfo
->FreeCBCount
;
1680 Routine Description:
1682 TODO: Add function description
1686 ind - TODO: add argument description
1690 TODO: add return values
1696 Tmp
= (UINT16
) (ind
+ 1);
1697 if (Tmp
>= (TX_BUFFER_COUNT
<< 1)) {
1706 IN NIC_DATA_INSTANCE
*AdapterInfo
1710 Routine Description:
1712 TODO: Add function description
1716 AdapterInfo - TODO: add argument description
1720 TODO: add return values
1729 Tmp_ptr
= AdapterInfo
->FreeTxTailPtr
->NextTCBVirtualLinkPtr
;
1730 if ((Tmp_ptr
->cb_header
.status
& CMD_STATUS_MASK
) != 0) {
1732 // check if Q is full
1734 if (next (AdapterInfo
->xmit_done_tail
) != AdapterInfo
->xmit_done_head
) {
1735 AdapterInfo
->xmit_done
[AdapterInfo
->xmit_done_tail
] = Tmp_ptr
->free_data_ptr
;
1739 Tmp_ptr
->free_data_ptr
,
1740 Tmp_ptr
->TBDArray
[0].buf_len
,
1742 (UINT64
) Tmp_ptr
->TBDArray
[0].phys_buf_addr
1745 AdapterInfo
->xmit_done_tail
= next (AdapterInfo
->xmit_done_tail
);
1748 SetFreeCB (AdapterInfo
, Tmp_ptr
);
1757 // Description : Initialize the RFD list list by linking each element together
1758 // in a circular list. The simplified memory model is used.
1759 // All data is in the RFD. The RFDs are linked together and the
1760 // last one points back to the first one. When the current RFD
1761 // is processed (frame received), its EL bit is set and the EL
1762 // bit in the previous RXFD is cleared.
1763 // Allocation done during INIT, this is making linked list.
1766 SetupReceiveQueues (
1767 IN NIC_DATA_INSTANCE
*AdapterInfo
1771 Routine Description:
1773 TODO: Add function description
1777 AdapterInfo - TODO: add argument description
1781 TODO: add return values
1789 AdapterInfo
->cur_rx_ind
= 0;
1790 rx_ptr
= (&AdapterInfo
->rx_ring
[0]);
1792 for (Index
= 0; Index
< AdapterInfo
->RxBufCnt
; Index
++) {
1793 rx_ptr
[Index
].cb_header
.status
= 0;
1794 rx_ptr
[Index
].cb_header
.command
= 0;
1795 rx_ptr
[Index
].RFDSize
= RX_BUFFER_SIZE
;
1796 rx_ptr
[Index
].ActualCount
= 0;
1798 // RBDs not used, simple memory model
1800 rx_ptr
[Index
].rx_buf_addr
= (UINT32
) (-1);
1803 // RBDs not used, simple memory model
1805 rx_ptr
[Index
].forwarded
= FALSE
;
1808 // don't use Tmp_ptr if it is beyond the last one
1810 if (Index
< AdapterInfo
->RxBufCnt
- 1) {
1811 rx_ptr
[Index
].cb_header
.link
= (UINT32
) AdapterInfo
->rx_phy_addr
+ ((Index
+ 1) * sizeof (RxFD
));
1815 tail_ptr
= (&AdapterInfo
->rx_ring
[AdapterInfo
->RxBufCnt
- 1]);
1816 tail_ptr
->cb_header
.link
= (UINT32
) AdapterInfo
->rx_phy_addr
;
1821 tail_ptr
->cb_header
.command
= 0xC000;
1822 AdapterInfo
->RFDTailPtr
= tail_ptr
;
1828 IN NIC_DATA_INSTANCE
*AdapterInfo
,
1833 Routine Description:
1835 TODO: Add function description
1839 AdapterInfo - TODO: add argument description
1840 rx_index - TODO: add argument description
1844 TODO: add return values
1851 // change the EL bit and change the AdapterInfo->RxTailPtr
1852 // rx_ptr is assumed to be the head of the Q
1853 // AdapterInfo->rx_forwarded[rx_index] = FALSE;
1855 rx_ptr
= &AdapterInfo
->rx_ring
[rx_index
];
1856 tail_ptr
= AdapterInfo
->RFDTailPtr
;
1858 // set el_bit and suspend bit
1860 rx_ptr
->cb_header
.command
= 0xc000;
1861 rx_ptr
->cb_header
.status
= 0;
1862 rx_ptr
->ActualCount
= 0;
1863 rx_ptr
->forwarded
= FALSE
;
1864 AdapterInfo
->RFDTailPtr
= rx_ptr
;
1866 // resetting the el_bit.
1868 tail_ptr
->cb_header
.command
= 0;
1870 // check the receive unit, fix if there is any problem
1875 // Serial EEPROM section.
1877 // EEPROM_Ctrl bits.
1879 #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
1880 #define EE_CS 0x02 /* EEPROM chip select. */
1881 #define EE_DI 0x04 /* EEPROM chip data in. */
1882 #define EE_WRITE_0 0x01
1883 #define EE_WRITE_1 0x05
1884 #define EE_DO 0x08 /* EEPROM chip data out. */
1885 #define EE_ENB (0x4800 | EE_CS)
1888 // Delay between EEPROM clock transitions.
1889 // This will actually work with no delay on 33Mhz PCI.
1891 #define eeprom_delay(nanosec) DelayIt (AdapterInfo, nanosec);
1894 // The EEPROM commands include the alway-set leading bit.
1896 #define EE_WRITE_CMD 5 // 101b
1897 #define EE_READ_CMD 6 // 110b
1898 #define EE_ERASE_CMD (7 << 6)
1903 IN NIC_DATA_INSTANCE
*AdapterInfo
,
1909 Routine Description:
1911 TODO: Add function description
1915 AdapterInfo - TODO: add argument description
1916 val - TODO: add argument description
1917 num_bits - TODO: add argument description
1921 TODO: add return values
1929 EEAddr
= AdapterInfo
->ioaddr
+ SCBeeprom
;
1931 for (Index
= num_bits
; Index
>= 0; Index
--) {
1937 dataval
= (INT16
) ((val
& (1 << Index
)) ? EE_DI
: 0);
1940 // mask off the data_in bit
1942 Tmp
= (UINT8
) (InByte (AdapterInfo
, EEAddr
) &~EE_DI
);
1943 Tmp
= (UINT8
) (Tmp
| dataval
);
1944 OutByte (AdapterInfo
, Tmp
, EEAddr
);
1947 // raise the eeprom clock
1949 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_SHIFT_CLK
), EEAddr
);
1952 // lower the eeprom clock
1954 OutByte (AdapterInfo
, (UINT8
) (Tmp
&~EE_SHIFT_CLK
), EEAddr
);
1962 IN NIC_DATA_INSTANCE
*AdapterInfo
1966 Routine Description:
1968 TODO: Add function description
1972 AdapterInfo - TODO: add argument description
1976 TODO: add return values
1985 EEAddr
= AdapterInfo
->ioaddr
+ SCBeeprom
;
1988 for (Index
= 15; Index
>= 0; Index
--) {
1994 // mask off the data_in bit
1996 Tmp
= InByte (AdapterInfo
, EEAddr
);
1997 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_SHIFT_CLK
), EEAddr
);
1999 Tmp
= InByte (AdapterInfo
, EEAddr
);
2000 retval
= (UINT16
) ((retval
<< 1) | ((Tmp
& EE_DO
) ? 1 : 0));
2004 OutByte (AdapterInfo
, (UINT8
) (Tmp
&~EE_SHIFT_CLK
), EEAddr
);
2013 E100bSetEepromLockOut (
2014 IN NIC_DATA_INSTANCE
*AdapterInfo
2018 Routine Description:
2019 This routine sets the EEPROM lockout bit to gain exclusive access to the
2020 eeprom. the access bit is the most significant bit in the General Control
2021 Register 2 in the SCB space.
2024 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
2027 TRUE - if it got the access
2028 FALSE - if it fails to get the exclusive access
2035 if ((AdapterInfo
->DeviceID
== D102_DEVICE_ID
) ||
2036 (AdapterInfo
->RevID
>= D102_REVID
)) {
2042 tmp
= InByte (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBGenCtrl2
);
2043 tmp
|= GCR2_EEPROM_ACCESS_SEMAPHORE
;
2044 OutByte (AdapterInfo
, tmp
, AdapterInfo
->ioaddr
+ SCBGenCtrl2
);
2046 DelayIt (AdapterInfo
, 50);
2047 tmp
= InByte (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBGenCtrl2
);
2049 if (tmp
& GCR2_EEPROM_ACCESS_SEMAPHORE
) {
2062 E100bReSetEepromLockOut (
2063 IN NIC_DATA_INSTANCE
*AdapterInfo
2067 Routine Description:
2068 This routine Resets the EEPROM lockout bit to giveup access to the
2069 eeprom. the access bit is the most significant bit in the General Control
2070 Register 2 in the SCB space.
2073 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
2082 if ((AdapterInfo
->DeviceID
== D102_DEVICE_ID
) ||
2083 (AdapterInfo
->RevID
>= D102_REVID
)) {
2085 tmp
= InByte (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBGenCtrl2
);
2086 tmp
&= ~(GCR2_EEPROM_ACCESS_SEMAPHORE
);
2087 OutByte (AdapterInfo
, tmp
, AdapterInfo
->ioaddr
+ SCBGenCtrl2
);
2089 DelayIt (AdapterInfo
, 50);
2095 IN NIC_DATA_INSTANCE
*AdapterInfo
,
2101 Routine Description:
2102 Using the NIC data structure information, read the EEPROM to get a Word of data for the MAC address.
2105 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
2106 Location - Word offset into the MAC address to read.
2107 AddrLen - Number of bits of address length.
2110 RetVal - The word read from the EEPROM.
2120 EEAddr
= AdapterInfo
->ioaddr
+ SCBeeprom
;
2121 ReadCmd
= (UINT16
) (Location
| (EE_READ_CMD
<< AddrLen
));
2126 // get exclusive access to the eeprom first!
2128 E100bSetEepromLockOut (AdapterInfo
);
2131 // eeprom control reg bits: x,x,x,x,DO,DI,CS,SK
2132 // to write the opcode+data value out one bit at a time in DI starting at msb
2133 // and then out a 1 to sk, wait, out 0 to SK and wait
2134 // repeat this for all the bits to be written
2140 Tmp
= (UINT8
) (InByte (AdapterInfo
, EEAddr
) & 0xF2);
2141 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_CS
), EEAddr
);
2144 // 3 for the read opcode 110b
2146 shift_bits_out (AdapterInfo
, ReadCmd
, (UINT8
) (3 + AddrLen
));
2149 // read the eeprom word one bit at a time
2151 RetVal
= shift_bits_in (AdapterInfo
);
2154 // Terminate the EEPROM access and leave eeprom in a clean state.
2156 Tmp
= InByte (AdapterInfo
, EEAddr
);
2157 Tmp
&= ~(EE_CS
| EE_DI
);
2158 OutByte (AdapterInfo
, Tmp
, EEAddr
);
2161 // raise the clock and lower the eeprom shift clock
2163 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_SHIFT_CLK
), EEAddr
);
2166 OutByte (AdapterInfo
, (UINT8
) (Tmp
&~EE_SHIFT_CLK
), EEAddr
);
2170 // giveup access to the eeprom
2172 E100bReSetEepromLockOut (AdapterInfo
);
2178 E100bGetEepromAddrLen (
2179 IN NIC_DATA_INSTANCE
*AdapterInfo
2183 Routine Description:
2184 Using the NIC data structure information, read the EEPROM to determine how many bits of address length
2185 this EEPROM is in Words.
2188 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
2191 RetVal - The word read from the EEPROM.
2199 // assume 64word eeprom (so,6 bits of address_length)
2203 EEAddr
= AdapterInfo
->ioaddr
+ SCBeeprom
;
2204 ReadCmd
= (EE_READ_CMD
<< 6);
2207 // get exclusive access to the eeprom first!
2209 E100bSetEepromLockOut (AdapterInfo
);
2212 // address we are trying to read is 0
2213 // eeprom control reg bits: x,x,x,x,DO,,DI,,CS,SK
2214 // to write the opcode+data value out one bit at a time in DI starting at msb
2215 // and then out a 1 to sk, wait, out 0 to SK and wait
2216 // repeat this for all the bits to be written
2218 Tmp
= (UINT8
) (InByte (AdapterInfo
, EEAddr
) & 0xF2);
2221 // enable eeprom access
2223 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_CS
), EEAddr
);
2226 // 3 for opcode, 6 for the default address len
2228 shift_bits_out (AdapterInfo
, ReadCmd
, (UINT8
) (3 + 6));
2231 // (in case of a 64 word eeprom).
2232 // read the "dummy zero" from EE_DO to say that the address we wrote
2233 // (six 0s) is accepted, write more zeros (until 8) to get a "dummy zero"
2237 // assume the smallest
2240 Tmp
= InByte (AdapterInfo
, EEAddr
);
2241 while ((AddrLen
< 8) && ((Tmp
& EE_DO
) != 0)) {
2242 OutByte (AdapterInfo
, (UINT8
) (Tmp
&~EE_DI
), EEAddr
);
2246 // raise the eeprom clock
2248 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_SHIFT_CLK
), EEAddr
);
2252 // lower the eeprom clock
2254 OutByte (AdapterInfo
, (UINT8
) (Tmp
&~EE_SHIFT_CLK
), EEAddr
);
2256 Tmp
= InByte (AdapterInfo
, EEAddr
);
2261 // read the eeprom word, even though we don't need this
2263 shift_bits_in (AdapterInfo
);
2266 // Terminate the EEPROM access.
2268 Tmp
= InByte (AdapterInfo
, EEAddr
);
2269 Tmp
&= ~(EE_CS
| EE_DI
);
2270 OutByte (AdapterInfo
, Tmp
, EEAddr
);
2273 // raise the clock and lower the eeprom shift clock
2275 OutByte (AdapterInfo
, (UINT8
) (Tmp
| EE_SHIFT_CLK
), EEAddr
);
2278 OutByte (AdapterInfo
, (UINT8
) (Tmp
&~EE_SHIFT_CLK
), EEAddr
);
2282 // giveup access to the eeprom!
2284 E100bReSetEepromLockOut (AdapterInfo
);
2291 NIC_DATA_INSTANCE
*AdapterInfo
,
2297 Routine Description:
2299 TODO: Add function description
2303 AdapterInfo - TODO: add argument description
2304 DBaddr - TODO: add argument description
2305 DBsize - TODO: add argument description
2309 TODO: add return values
2313 PXE_DB_STATISTICS db
;
2315 // wait upto one second (each wait is 100 micro s)
2319 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
2322 // Clear statistics done marker.
2324 AdapterInfo
->statistics
->done_marker
= 0;
2327 // Issue statistics dump (or dump w/ reset) command.
2331 (UINT8
) (DBsize
? CU_SHOWSTATS
: CU_DUMPSTATS
),
2332 (UINT32
) (AdapterInfo
->ioaddr
+ SCBCmd
)
2336 // Wait for command to complete.
2338 // zero the db here just to chew up a little more time.
2341 ZeroMem ((VOID
*) &db
, sizeof db
);
2345 // Wait a bit before checking.
2348 DelayIt (AdapterInfo
, 100);
2351 // Look for done marker at end of statistics.
2354 switch (AdapterInfo
->statistics
->done_marker
) {
2365 // if we did not "continue" from the above switch, we are done,
2371 // If this is a reset, we are out of here!
2374 return PXE_STATCODE_SUCCESS
;
2378 // Convert NIC statistics counter format to EFI/UNDI
2379 // specification statistics counter format.
2383 // 54 3210 fedc ba98 7654 3210
2384 // db.Supported = 01 0000 0100 1101 0001 0111;
2386 db
.Supported
= 0x104D17;
2389 // Statistics from the NIC
2392 db
.Data
[0x01] = AdapterInfo
->statistics
->rx_good_frames
;
2394 db
.Data
[0x02] = AdapterInfo
->statistics
->rx_runt_errs
;
2396 db
.Data
[0x08] = AdapterInfo
->statistics
->rx_crc_errs
+
2397 AdapterInfo
->statistics
->rx_align_errs
;
2399 db
.Data
[0x04] = db
.Data
[0x02] +
2401 AdapterInfo
->statistics
->rx_resource_errs
+
2402 AdapterInfo
->statistics
->rx_overrun_errs
;
2404 db
.Data
[0x00] = db
.Data
[0x01] + db
.Data
[0x04];
2406 db
.Data
[0x0B] = AdapterInfo
->statistics
->tx_good_frames
;
2408 db
.Data
[0x0E] = AdapterInfo
->statistics
->tx_coll16_errs
+
2409 AdapterInfo
->statistics
->tx_late_colls
+
2410 AdapterInfo
->statistics
->tx_underruns
+
2411 AdapterInfo
->statistics
->tx_one_colls
+
2412 AdapterInfo
->statistics
->tx_multi_colls
;
2414 db
.Data
[0x14] = AdapterInfo
->statistics
->tx_total_colls
;
2416 db
.Data
[0x0A] = db
.Data
[0x0B] +
2418 AdapterInfo
->statistics
->tx_lost_carrier
;
2420 if (DBsize
> sizeof db
) {
2424 CopyMem ((VOID
*) (UINTN
) DBaddr
, (VOID
*) &db
, (UINTN
) DBsize
);
2426 return PXE_STATCODE_SUCCESS
;
2431 IN NIC_DATA_INSTANCE
*AdapterInfo
,
2436 Routine Description:
2438 TODO: Add function description
2442 AdapterInfo - TODO: add argument description
2443 OpFlags - TODO: add argument description
2447 TODO: add return values
2454 // disable the interrupts
2456 OutWord (AdapterInfo
, INT_MASK
, AdapterInfo
->ioaddr
+ SCBCmd
);
2459 // wait for the tx queue to complete
2461 CheckCBList (AdapterInfo
);
2463 XmitWaitForCompletion (AdapterInfo
);
2465 if (AdapterInfo
->Receive_Started
) {
2466 StopRU (AdapterInfo
);
2469 InitializeChip (AdapterInfo
);
2472 // check the opflags and restart receive filters
2474 if ((OpFlags
& PXE_OPFLAGS_RESET_DISABLE_FILTERS
) == 0) {
2476 save_filter
= AdapterInfo
->Rx_Filter
;
2478 // if we give the filter same as Rx_Filter,
2479 // this routine will not set mcast list (it thinks there is no change)
2480 // to force it, we will reset that flag in the Rx_Filter
2482 AdapterInfo
->Rx_Filter
&= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST
);
2483 E100bSetfilter (AdapterInfo
, save_filter
, (UINT64
) 0, (UINT32
) 0);
2486 if ((OpFlags
& PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS
) != 0) {
2488 // disable the interrupts
2490 AdapterInfo
->int_mask
= 0;
2493 // else leave the interrupt in the pre-set state!!!
2495 E100bSetInterruptState (AdapterInfo
);
2502 IN NIC_DATA_INSTANCE
*AdapterInfo
2506 Routine Description:
2508 TODO: Add function description
2512 AdapterInfo - TODO: add argument description
2516 TODO: add return values
2521 // disable the interrupts
2523 OutWord (AdapterInfo
, INT_MASK
, AdapterInfo
->ioaddr
+ SCBCmd
);
2526 // stop the receive unit
2528 if (AdapterInfo
->Receive_Started
) {
2529 StopRU (AdapterInfo
);
2533 // wait for the tx queue to complete
2535 CheckCBList (AdapterInfo
);
2536 if (AdapterInfo
->FreeCBCount
!= AdapterInfo
->TxBufCnt
) {
2537 wait_for_cmd_done (AdapterInfo
->ioaddr
+ SCBCmd
);
2541 // we do not want to reset the phy, it takes a long time to renegotiate the
2542 // link after that (3-4 seconds)
2544 InitializeChip (AdapterInfo
);
2545 SelectiveReset (AdapterInfo
);
2551 IN NIC_DATA_INSTANCE
*AdapterInfo
,
2552 IN UINT8 RegAddress
,
2553 IN UINT8 PhyAddress
,
2558 Routine Description:
2559 This routine will write a value to the specified MII register
2560 of an external MDI compliant device (e.g. PHY 100). The command will
2561 execute in polled mode.
2564 AdapterInfo - pointer to the structure that contains the NIC's context.
2565 RegAddress - The MII register that we are writing to
2566 PhyAddress - The MDI address of the Phy component.
2567 DataValue - The value that we are writing to the MII register.
2573 UINT32 WriteCommand
;
2575 WriteCommand
= ((UINT32
) DataValue
) |
2576 ((UINT32
)(RegAddress
<< 16)) |
2577 ((UINT32
)(PhyAddress
<< 21)) |
2578 ((UINT32
)(MDI_WRITE
<< 26));
2581 // Issue the write command to the MDI control register.
2583 OutLong (AdapterInfo
, WriteCommand
, AdapterInfo
->ioaddr
+ SCBCtrlMDI
);
2586 // wait 20usec before checking status
2588 DelayIt (AdapterInfo
, 20);
2591 // poll for the mdi write to complete
2592 while ((InLong (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBCtrlMDI
) &
2593 MDI_PHY_READY
) == 0){
2594 DelayIt (AdapterInfo
, 20);
2600 IN NIC_DATA_INSTANCE
*AdapterInfo
,
2601 IN UINT8 RegAddress
,
2602 IN UINT8 PhyAddress
,
2603 IN OUT UINT16
*DataValue
2607 Routine Description:
2608 This routine will read a value from the specified MII register
2609 of an external MDI compliant device (e.g. PHY 100), and return
2610 it to the calling routine. The command will execute in polled mode.
2613 AdapterInfo - pointer to the structure that contains the NIC's context.
2614 RegAddress - The MII register that we are reading from
2615 PhyAddress - The MDI address of the Phy component.
2616 DataValue - pointer to the value that we read from the MII register.
2624 ReadCommand
= ((UINT32
) (RegAddress
<< 16)) |
2625 ((UINT32
) (PhyAddress
<< 21)) |
2626 ((UINT32
) (MDI_READ
<< 26));
2629 // Issue the read command to the MDI control register.
2631 OutLong (AdapterInfo
, ReadCommand
, AdapterInfo
->ioaddr
+ SCBCtrlMDI
);
2634 // wait 20usec before checking status
2636 DelayIt (AdapterInfo
, 20);
2639 // poll for the mdi read to complete
2641 while ((InLong (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBCtrlMDI
) &
2642 MDI_PHY_READY
) == 0) {
2643 DelayIt (AdapterInfo
, 20);
2647 *DataValue
= InWord (AdapterInfo
, AdapterInfo
->ioaddr
+ SCBCtrlMDI
);
2652 NIC_DATA_INSTANCE
*AdapterInfo
2656 Routine Description:
2657 This routine will reset the PHY that the adapter is currently
2661 AdapterInfo - pointer to the structure that contains the NIC's context.
2667 UINT16 MdiControlReg
;
2669 MdiControlReg
= (MDI_CR_AUTO_SELECT
|
2670 MDI_CR_RESTART_AUTO_NEG
|
2674 // Write the MDI control register with our new Phy configuration
2679 AdapterInfo
->PhyAddress
,
2688 NIC_DATA_INSTANCE
*AdapterInfo
2692 Routine Description:
2693 This routine will detect what phy we are using, set the line
2694 speed, FDX or HDX, and configure the phy if necessary.
2696 The following combinations are supported:
2697 - TX or T4 PHY alone at PHY address 1
2698 - T4 or TX PHY at address 1 and MII PHY at address 0
2699 - 82503 alone (10Base-T mode, no full duplex support)
2700 - 82503 and MII PHY (TX or T4) at address 0
2702 The sequence / priority of detection is as follows:
2703 - PHY 1 with cable termination
2704 - PHY 0 with cable termination
2705 - PHY 1 (if found) without cable termination
2708 Additionally auto-negotiation capable (NWAY) and parallel
2709 detection PHYs are supported. The flow-chart is described in
2710 the 82557 software writer's manual.
2712 NOTE: 1. All PHY MDI registers are read in polled mode.
2713 2. The routines assume that the 82557 has been RESET and we have
2714 obtained the virtual memory address of the CSR.
2715 3. PhyDetect will not RESET the PHY.
2716 4. If FORCEFDX is set, SPEED should also be set. The driver will
2717 check the values for inconsistency with the detected PHY
2719 5. PHY 1 (the PHY on the adapter) may have an address in the range
2720 1 through 31 inclusive. The driver will accept addresses in
2722 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface
2726 AdapterInfo - pointer to the structure that contains the NIC's context.
2729 TRUE - If a Phy was detected, and configured correctly.
2730 FALSE - If a valid phy could not be detected and configured.
2735 UINT16 MdiControlReg
;
2736 UINT16 MdiStatusReg
;
2738 UINT8 ReNegotiateTime
;
2740 eedata
= (UINT16
*) (&AdapterInfo
->NVData
[0]);
2743 ReNegotiateTime
= 35;
2745 // EEPROM word [6] contains the Primary PHY record in which the least 3 bits
2746 // indicate the PHY address
2747 // and word [7] contains the secondary PHY record
2749 AdapterInfo
->PhyRecord
[0] = eedata
[6];
2750 AdapterInfo
->PhyRecord
[1] = eedata
[7];
2751 AdapterInfo
->PhyAddress
= (UINT8
) (AdapterInfo
->PhyRecord
[0] & 7);
2754 // Check for a phy address over-ride of 32 which indicates force use of 82503
2755 // not detecting the link in this case
2757 if (AdapterInfo
->PhyAddress
== 32) {
2759 // 503 interface over-ride
2760 // Record the current speed and duplex. We will be in half duplex
2761 // mode unless the user used the force full duplex over-ride.
2763 AdapterInfo
->LinkSpeed
= 10;
2768 // If the Phy Address is between 1-31 then we must first look for phy 1,
2771 if ((AdapterInfo
->PhyAddress
> 0) && (AdapterInfo
->PhyAddress
< 32)) {
2774 // Read the MDI control and status registers at phy 1
2775 // and check if we found a valid phy
2780 AdapterInfo
->PhyAddress
,
2787 AdapterInfo
->PhyAddress
,
2791 if (!((MdiControlReg
== 0xffff) ||
2792 ((MdiStatusReg
== 0) && (MdiControlReg
== 0)))) {
2795 // we have a valid phy1
2796 // Read the status register again because of sticky bits
2802 AdapterInfo
->PhyAddress
,
2807 // If there is a valid link then use this Phy.
2809 if (MdiStatusReg
& MDI_SR_LINK_STATUS
) {
2810 return (SetupPhy(AdapterInfo
));
2816 // Next try to detect a PHY at address 0x00 because there was no Phy 1,
2817 // or Phy 1 didn't have link, or we had a phy 0 over-ride
2821 // Read the MDI control and status registers at phy 0
2823 MdiRead (AdapterInfo
, MDI_CONTROL_REG
, 0, &MdiControlReg
);
2824 MdiRead (AdapterInfo
, MDI_STATUS_REG
, 0, &MdiStatusReg
);
2827 // check if we found a valid phy 0
2829 if (((MdiControlReg
== 0xffff) ||
2830 ((MdiStatusReg
== 0) && (MdiControlReg
== 0)))) {
2833 // we don't have a valid phy at address 0
2834 // if phy address was forced to 0, then error out because we
2835 // didn't find a phy at that address
2837 if (AdapterInfo
->PhyAddress
== 0x0000) {
2841 // at this point phy1 does not have link and there is no phy 0 at all
2842 // if we are forced to detect the cable, error out here!
2844 if (AdapterInfo
->CableDetect
!= 0) {
2851 // no phy 0, but there is a phy 1 (no link I guess), so use phy 1
2853 return SetupPhy (AdapterInfo
);
2856 // didn't find phy 0 or phy 1, so assume a 503 interface
2858 AdapterInfo
->PhyAddress
= 32;
2861 // Record the current speed and duplex. We'll be in half duplex
2862 // mode unless the user used the force full duplex over-ride.
2864 AdapterInfo
->LinkSpeed
= 10;
2870 // We have a valid phy at address 0. If phy 0 has a link then we use
2871 // phy 0. If Phy 0 doesn't have a link then we use Phy 1 (no link)
2872 // if phy 1 is present, or phy 0 if phy 1 is not present
2873 // If phy 1 was present, then we must isolate phy 1 before we enable
2874 // phy 0 to see if Phy 0 has a link.
2883 AdapterInfo
->PhyAddress
,
2888 // wait 100 microseconds for the phy to isolate.
2890 DelayIt (AdapterInfo
, 100);
2894 // Since this Phy is at address 0, we must enable it. So clear
2895 // the isolate bit, and set the auto-speed select bit
2905 // wait 100 microseconds for the phy to be enabled.
2907 DelayIt (AdapterInfo
, 100);
2910 // restart the auto-negotion process
2916 MDI_CR_RESTART_AUTO_NEG
| MDI_CR_AUTO_SELECT
2920 // wait no more than 3.5 seconds for auto-negotiation to complete
2922 while (ReNegotiateTime
) {
2924 // Read the status register twice because of sticky bits
2926 MdiRead (AdapterInfo
, MDI_STATUS_REG
, 0, &MdiStatusReg
);
2927 MdiRead (AdapterInfo
, MDI_STATUS_REG
, 0, &MdiStatusReg
);
2929 if (MdiStatusReg
& MDI_SR_AUTO_NEG_COMPLETE
) {
2933 DelayIt (AdapterInfo
, 100);
2938 // Read the status register again because of sticky bits
2940 MdiRead (AdapterInfo
, MDI_STATUS_REG
, 0, &MdiStatusReg
);
2943 // If the link was not set
2945 if ((MdiStatusReg
& MDI_SR_LINK_STATUS
) == 0) {
2947 // PHY1 does not have a link and phy 0 does not have a link
2948 // do not proceed if we need to detect the link!
2950 if (AdapterInfo
->CableDetect
!= 0) {
2955 // the link wasn't set, so use phy 1 if phy 1 was present
2961 MdiWrite (AdapterInfo
, MDI_CONTROL_REG
, 0, MDI_CR_ISOLATE
);
2964 // wait 100 microseconds for the phy to isolate.
2966 DelayIt (AdapterInfo
, 100);
2969 // Now re-enable PHY 1
2974 AdapterInfo
->PhyAddress
,
2979 // wait 100 microseconds for the phy to be enabled
2981 DelayIt (AdapterInfo
, 100);
2984 // restart the auto-negotion process
2989 AdapterInfo
->PhyAddress
,
2990 MDI_CR_RESTART_AUTO_NEG
| MDI_CR_AUTO_SELECT
2994 // Don't wait for it to complete (we didn't have link earlier)
2996 return (SetupPhy (AdapterInfo
));
3001 // Definitely using Phy 0
3003 AdapterInfo
->PhyAddress
= 0;
3004 return (SetupPhy(AdapterInfo
));
3010 IN NIC_DATA_INSTANCE
*AdapterInfo
3014 Routine Description:
3015 This routine will setup phy 1 or phy 0 so that it is configured
3016 to match a speed and duplex over-ride option. If speed or
3017 duplex mode is not explicitly specified in the registry, the
3018 driver will skip the speed and duplex over-ride code, and
3019 assume the adapter is automatically setting the line speed, and
3020 the duplex mode. At the end of this routine, any truly Phy
3021 specific code will be executed (each Phy has its own quirks,
3022 and some require that certain special bits are set).
3024 NOTE: The driver assumes that SPEED and FORCEFDX are specified at the
3025 same time. If FORCEDPX is set without speed being set, the driver
3026 will encouter a fatal error and log a message into the event viewer.
3029 AdapterInfo - pointer to the structure that contains the NIC's context.
3032 TRUE - If the phy could be configured correctly
3033 FALSE - If the phy couldn't be configured correctly, because an
3034 unsupported over-ride option was used
3038 UINT16 MdiControlReg
;
3039 UINT16 MdiStatusReg
;
3041 UINT16 MdiIdHighReg
;
3044 BOOLEAN ForcePhySetting
;
3046 ForcePhySetting
= FALSE
;
3049 // If we are NOT forcing a setting for line speed or full duplex, then
3050 // we won't force a link setting, and we'll jump down to the phy
3053 if (((AdapterInfo
->LinkSpeedReq
) || (AdapterInfo
->DuplexReq
))) {
3055 // Find out what kind of technology this Phy is capable of.
3060 AdapterInfo
->PhyAddress
,
3065 // Read the MDI control register at our phy
3070 AdapterInfo
->PhyAddress
,
3075 // Now check the validity of our forced option. If the force option is
3076 // valid, then force the setting. If the force option is not valid,
3077 // we'll set a flag indicating that we should error out.
3081 // If speed is forced to 10mb
3083 if (AdapterInfo
->LinkSpeedReq
== 10) {
3085 // If half duplex is forced
3087 if ((AdapterInfo
->DuplexReq
& PXE_FORCE_HALF_DUPLEX
) != 0) {
3088 if (MdiStatusReg
& MDI_SR_10T_HALF_DPX
) {
3090 MdiControlReg
&= ~(MDI_CR_10_100
| MDI_CR_AUTO_SELECT
| MDI_CR_FULL_HALF
);
3091 ForcePhySetting
= TRUE
;
3093 } else if ((AdapterInfo
->DuplexReq
& PXE_FORCE_FULL_DUPLEX
) != 0) {
3096 // If full duplex is forced
3098 if (MdiStatusReg
& MDI_SR_10T_FULL_DPX
) {
3100 MdiControlReg
&= ~(MDI_CR_10_100
| MDI_CR_AUTO_SELECT
);
3101 MdiControlReg
|= MDI_CR_FULL_HALF
;
3102 ForcePhySetting
= TRUE
;
3106 // If auto duplex (we actually set phy to 1/2)
3108 if (MdiStatusReg
& (MDI_SR_10T_FULL_DPX
| MDI_SR_10T_HALF_DPX
)) {
3110 MdiControlReg
&= ~(MDI_CR_10_100
| MDI_CR_AUTO_SELECT
| MDI_CR_FULL_HALF
);
3111 ForcePhySetting
= TRUE
;
3117 // If speed is forced to 100mb
3119 else if (AdapterInfo
->LinkSpeedReq
== 100) {
3121 // If half duplex is forced
3123 if ((AdapterInfo
->DuplexReq
& PXE_FORCE_HALF_DUPLEX
) != 0) {
3124 if (MdiStatusReg
& (MDI_SR_TX_HALF_DPX
| MDI_SR_T4_CAPABLE
)) {
3126 MdiControlReg
&= ~(MDI_CR_AUTO_SELECT
| MDI_CR_FULL_HALF
);
3127 MdiControlReg
|= MDI_CR_10_100
;
3128 ForcePhySetting
= TRUE
;
3130 } else if ((AdapterInfo
->DuplexReq
& PXE_FORCE_FULL_DUPLEX
) != 0) {
3132 // If full duplex is forced
3134 if (MdiStatusReg
& MDI_SR_TX_FULL_DPX
) {
3135 MdiControlReg
&= ~MDI_CR_AUTO_SELECT
;
3136 MdiControlReg
|= (MDI_CR_10_100
| MDI_CR_FULL_HALF
);
3137 ForcePhySetting
= TRUE
;
3141 // If auto duplex (we set phy to 1/2)
3143 if (MdiStatusReg
& (MDI_SR_TX_HALF_DPX
| MDI_SR_T4_CAPABLE
)) {
3145 MdiControlReg
&= ~(MDI_CR_AUTO_SELECT
| MDI_CR_FULL_HALF
);
3146 MdiControlReg
|= MDI_CR_10_100
;
3147 ForcePhySetting
= TRUE
;
3152 if (!ForcePhySetting
) {
3157 // Write the MDI control register with our new Phy configuration
3162 AdapterInfo
->PhyAddress
,
3167 // wait 100 milliseconds for auto-negotiation to complete
3169 DelayIt (AdapterInfo
, 100);
3173 // Find out specifically what Phy this is. We do this because for certain
3174 // phys there are specific bits that must be set so that the phy and the
3175 // 82557 work together properly.
3181 AdapterInfo
->PhyAddress
,
3187 AdapterInfo
->PhyAddress
,
3191 PhyId
= ((UINT32
) MdiIdLowReg
| ((UINT32
) MdiIdHighReg
<< 16));
3194 // And out the revsion field of the Phy ID so that we'll be able to detect
3195 // future revs of the same Phy.
3197 PhyId
&= PHY_MODEL_REV_ID_MASK
;
3200 // Handle the National TX
3202 if (PhyId
== PHY_NSC_TX
) {
3206 NSC_CONG_CONTROL_REG
,
3207 AdapterInfo
->PhyAddress
,
3211 MdiMiscReg
|= (NSC_TX_CONG_TXREADY
| NSC_TX_CONG_F_CONNECT
);
3215 NSC_CONG_CONTROL_REG
,
3216 AdapterInfo
->PhyAddress
,
3221 FindPhySpeedAndDpx (AdapterInfo
, PhyId
);
3224 // We put a hardware fix on to our adapters to work-around the PHY_100 errata
3225 // described below. The following code is only compiled in, if we wanted
3226 // to attempt a software workaround to the PHY_100 A/B step problem.
3233 FindPhySpeedAndDpx (
3234 IN NIC_DATA_INSTANCE
*AdapterInfo
,
3239 Routine Description:
3240 This routine will figure out what line speed and duplex mode
3241 the PHY is currently using.
3244 AdapterInfo - pointer to the structure that contains the NIC's context.
3245 PhyId - The ID of the PHY in question.
3251 UINT16 MdiStatusReg
;
3254 UINT16 MdiLinkPartnerAdReg
;
3257 // If there was a speed and/or duplex override, then set our current
3258 // value accordingly
3260 AdapterInfo
->LinkSpeed
= AdapterInfo
->LinkSpeedReq
;
3261 AdapterInfo
->Duplex
= (UINT8
) ((AdapterInfo
->DuplexReq
& PXE_FORCE_FULL_DUPLEX
) ?
3262 FULL_DUPLEX
: HALF_DUPLEX
);
3265 // If speed and duplex were forced, then we know our current settings, so
3266 // we'll just return. Otherwise, we'll need to figure out what NWAY set
3269 if (AdapterInfo
->LinkSpeed
&& AdapterInfo
->Duplex
) {
3274 // If we didn't have a valid link, then we'll assume that our current
3275 // speed is 10mb half-duplex.
3279 // Read the status register twice because of sticky bits
3284 AdapterInfo
->PhyAddress
,
3290 AdapterInfo
->PhyAddress
,
3295 // If there wasn't a valid link then use default speed & duplex
3297 if (!(MdiStatusReg
& MDI_SR_LINK_STATUS
)) {
3299 AdapterInfo
->LinkSpeed
= 10;
3300 AdapterInfo
->Duplex
= HALF_DUPLEX
;
3305 // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits
3306 // 1 and 0 of extended register 0, to get the current speed and duplex
3309 if ((PhyId
== PHY_100_A
) || (PhyId
== PHY_100_C
) || (PhyId
== PHY_TX_ID
)) {
3311 // Read extended register 0
3316 AdapterInfo
->PhyAddress
,
3321 // Get current speed setting
3323 if (MdiMiscReg
& PHY_100_ER0_SPEED_INDIC
) {
3324 AdapterInfo
->LinkSpeed
= 100;
3326 AdapterInfo
->LinkSpeed
= 10;
3330 // Get current duplex setting -- if bit is set then FDX is enabled
3332 if (MdiMiscReg
& PHY_100_ER0_FDX_INDIC
) {
3333 AdapterInfo
->Duplex
= FULL_DUPLEX
;
3335 AdapterInfo
->Duplex
= HALF_DUPLEX
;
3341 // Read our link partner's advertisement register
3345 AUTO_NEG_LINK_PARTNER_REG
,
3346 AdapterInfo
->PhyAddress
,
3347 &MdiLinkPartnerAdReg
3351 // See if Auto-Negotiation was complete (bit 5, reg 1)
3356 AdapterInfo
->PhyAddress
,
3361 // If a True NWAY connection was made, then we can detect speed/duplex by
3362 // ANDing our adapter's advertised abilities with our link partner's
3363 // advertised ablilities, and then assuming that the highest common
3364 // denominator was chosed by NWAY.
3366 if ((MdiLinkPartnerAdReg
& NWAY_LP_ABILITY
) &&
3367 (MdiStatusReg
& MDI_SR_AUTO_NEG_COMPLETE
)) {
3370 // Read our advertisement register
3374 AUTO_NEG_ADVERTISE_REG
,
3375 AdapterInfo
->PhyAddress
,
3380 // AND the two advertisement registers together, and get rid of any
3383 MdiOwnAdReg
= (UINT16
) (MdiOwnAdReg
& (MdiLinkPartnerAdReg
& NWAY_LP_ABILITY
));
3386 // Get speed setting
3388 if (MdiOwnAdReg
& (NWAY_AD_TX_HALF_DPX
| NWAY_AD_TX_FULL_DPX
| NWAY_AD_T4_CAPABLE
)) {
3389 AdapterInfo
->LinkSpeed
= 100;
3391 AdapterInfo
->LinkSpeed
= 10;