]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/UndiRuntimeDxe/E100b.c
6612d46041102017930d69b8b601a7aa2a72215b
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UndiRuntimeDxe / E100b.c
1 /** @file
2 Provides basic function upon network adapter card.
3
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Undi32.h"
16
17 static UINT8 basic_config_cmd[22] = {
18 22, 0x08,
19 0, 0,
20 0, (UINT8)0x80,
21 0x32, 0x03,
22 1, 0,
23 0x2E, 0,
24 0x60, 0,
25 (UINT8)0xf2, 0x48,
26 0, 0x40,
27 (UINT8)0xf2, (UINT8)0x80, // 0x40=Force full-duplex
28 0x3f, 0x05,
29 };
30
31 //
32 // How to wait for the command unit to accept a command.
33 // Typically this takes 0 ticks.
34 //
35 #define wait_for_cmd_done(cmd_ioaddr) \
36 { \
37 INT16 wait_count = 2000; \
38 while ((InByte (AdapterInfo, cmd_ioaddr) != 0) && --wait_count >= 0) \
39 DelayIt (AdapterInfo, 10); \
40 if (wait_count == 0) \
41 DelayIt (AdapterInfo, 50); \
42 }
43
44
45 /**
46 This function calls the MemIo callback to read a byte from the device's
47 address space
48 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
49 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
50 to make undi3.0 a special case
51
52 @param Port Which port to read from.
53
54 @retval Results The data read from the port.
55
56 **/
57 // TODO: AdapterInfo - add argument and description to function comment
58 UINT8
59 InByte (
60 IN NIC_DATA_INSTANCE *AdapterInfo,
61 IN UINT32 Port
62 )
63 {
64 UINT8 Results;
65
66 (*AdapterInfo->Mem_Io) (
67 AdapterInfo->Unique_ID,
68 PXE_MEM_READ,
69 1,
70 (UINT64)Port,
71 (UINT64) (UINTN) &Results
72 );
73 return Results;
74 }
75
76
77 /**
78 This function calls the MemIo callback to read a word from the device's
79 address space
80 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
81 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
82 to make undi3.0 a special case
83
84 @param Port Which port to read from.
85
86 @retval Results The data read from the port.
87
88 **/
89 // TODO: AdapterInfo - add argument and description to function comment
90 UINT16
91 InWord (
92 IN NIC_DATA_INSTANCE *AdapterInfo,
93 IN UINT32 Port
94 )
95 {
96 UINT16 Results;
97
98 (*AdapterInfo->Mem_Io) (
99 AdapterInfo->Unique_ID,
100 PXE_MEM_READ,
101 2,
102 (UINT64)Port,
103 (UINT64)(UINTN)&Results
104 );
105 return Results;
106 }
107
108
109 /**
110 This function calls the MemIo callback to read a dword from the device's
111 address space
112 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
113 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
114 to make undi3.0 a special case
115
116 @param Port Which port to read from.
117
118 @retval Results The data read from the port.
119
120 **/
121 // TODO: AdapterInfo - add argument and description to function comment
122 UINT32
123 InLong (
124 IN NIC_DATA_INSTANCE *AdapterInfo,
125 IN UINT32 Port
126 )
127 {
128 UINT32 Results;
129
130 (*AdapterInfo->Mem_Io) (
131 AdapterInfo->Unique_ID,
132 PXE_MEM_READ,
133 4,
134 (UINT64)Port,
135 (UINT64)(UINTN)&Results
136 );
137 return Results;
138 }
139
140
141 /**
142 This function calls the MemIo callback to write a byte from the device's
143 address space
144 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
145 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
146 to make undi3.0 a special case
147
148 @param Data Data to write to Port.
149 @param Port Which port to write to.
150
151 @return none
152
153 **/
154 // TODO: AdapterInfo - add argument and description to function comment
155 VOID
156 OutByte (
157 IN NIC_DATA_INSTANCE *AdapterInfo,
158 IN UINT8 Data,
159 IN UINT32 Port
160 )
161 {
162 UINT8 Val;
163
164 Val = Data;
165 (*AdapterInfo->Mem_Io) (
166 AdapterInfo->Unique_ID,
167 PXE_MEM_WRITE,
168 1,
169 (UINT64)Port,
170 (UINT64)(UINTN)(UINTN)&Val
171 );
172 return ;
173 }
174
175
176 /**
177 This function calls the MemIo callback to write a word from the device's
178 address space
179 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
180 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
181 to make undi3.0 a special case
182
183 @param Data Data to write to Port.
184 @param Port Which port to write to.
185
186 @return none
187
188 **/
189 // TODO: AdapterInfo - add argument and description to function comment
190 VOID
191 OutWord (
192 IN NIC_DATA_INSTANCE *AdapterInfo,
193 IN UINT16 Data,
194 IN UINT32 Port
195 )
196 {
197 UINT16 Val;
198
199 Val = Data;
200 (*AdapterInfo->Mem_Io) (
201 AdapterInfo->Unique_ID,
202 PXE_MEM_WRITE,
203 2,
204 (UINT64)Port,
205 (UINT64)(UINTN)&Val
206 );
207 return ;
208 }
209
210
211 /**
212 This function calls the MemIo callback to write a dword from the device's
213 address space
214 Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
215 which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
216 to make undi3.0 a special case
217
218 @param Data Data to write to Port.
219 @param Port Which port to write to.
220
221 @return none
222
223 **/
224 // TODO: AdapterInfo - add argument and description to function comment
225 VOID
226 OutLong (
227 IN NIC_DATA_INSTANCE *AdapterInfo,
228 IN UINT32 Data,
229 IN UINT32 Port
230 )
231 {
232 UINT32 Val;
233
234 Val = Data;
235 (*AdapterInfo->Mem_Io) (
236 AdapterInfo->Unique_ID,
237 PXE_MEM_WRITE,
238 4,
239 (UINT64)Port,
240 (UINT64)(UINTN)&Val
241 );
242 return ;
243 }
244
245
246 /**
247 TODO: Add function description
248
249 @param AdapterInfo TODO: add argument description
250 @param MemAddr TODO: add argument description
251 @param Size TODO: add argument description
252 @param Direction TODO: add argument description
253 @param MappedAddr TODO: add argument description
254
255 @return TODO: add return values
256
257 **/
258 STATIC
259 UINTN
260 MapIt (
261 IN NIC_DATA_INSTANCE *AdapterInfo,
262 IN UINT64 MemAddr,
263 IN UINT32 Size,
264 IN UINT32 Direction,
265 OUT UINT64 MappedAddr
266 )
267 {
268 UINT64 *PhyAddr;
269
270 PhyAddr = (UINT64 *) (UINTN) MappedAddr;
271 //
272 // mapping is different for theold and new NII protocols
273 //
274 if (AdapterInfo->VersionFlag == 0x30) {
275 if (AdapterInfo->Virt2Phys_30 == (VOID *) NULL) {
276 *PhyAddr = (UINT64) AdapterInfo->MemoryPtr;
277 } else {
278 (*AdapterInfo->Virt2Phys_30) (MemAddr, (UINT64) (UINTN) PhyAddr);
279 }
280
281 if (*PhyAddr > FOUR_GIGABYTE) {
282 return PXE_STATCODE_INVALID_PARAMETER;
283 }
284 } else {
285 if (AdapterInfo->Map_Mem == (VOID *) NULL) {
286 //
287 // this UNDI cannot handle addresses beyond 4 GB without a map routine
288 //
289 if (MemAddr > FOUR_GIGABYTE) {
290 return PXE_STATCODE_INVALID_PARAMETER;
291 } else {
292 *PhyAddr = MemAddr;
293 }
294 } else {
295 (*AdapterInfo->Map_Mem) (
296 AdapterInfo->Unique_ID,
297 MemAddr,
298 Size,
299 Direction,
300 MappedAddr
301 );
302 }
303 }
304
305 return PXE_STATCODE_SUCCESS;
306 }
307
308
309 /**
310 TODO: Add function description
311
312 @param AdapterInfo TODO: add argument description
313 @param MemAddr TODO: add argument description
314 @param Size TODO: add argument description
315 @param Direction TODO: add argument description
316 @param MappedAddr TODO: add argument description
317
318 @return TODO: add return values
319
320 **/
321 STATIC
322 VOID
323 UnMapIt (
324 IN NIC_DATA_INSTANCE *AdapterInfo,
325 IN UINT64 MemAddr,
326 IN UINT32 Size,
327 IN UINT32 Direction,
328 IN UINT64 MappedAddr
329 )
330 {
331 if (AdapterInfo->VersionFlag > 0x30) {
332 //
333 // no mapping service
334 //
335 if (AdapterInfo->UnMap_Mem != (VOID *) NULL) {
336 (*AdapterInfo->UnMap_Mem) (
337 AdapterInfo->Unique_ID,
338 MemAddr,
339 Size,
340 Direction,
341 MappedAddr
342 );
343
344 }
345 }
346
347 return ;
348 }
349
350
351 /**
352
353 @param AdapterInfo Pointer to the NIC data structure
354 information which the UNDI driver is
355 layering on..
356
357
358 **/
359 // TODO: MicroSeconds - add argument and description to function comment
360 STATIC
361 VOID
362 DelayIt (
363 IN NIC_DATA_INSTANCE *AdapterInfo,
364 UINT16 MicroSeconds
365 )
366 {
367 if (AdapterInfo->VersionFlag == 0x30) {
368 (*AdapterInfo->Delay_30) (MicroSeconds);
369 } else {
370 (*AdapterInfo->Delay) (AdapterInfo->Unique_ID, MicroSeconds);
371 }
372 }
373
374
375 /**
376
377 @param AdapterInfo Pointer to the NIC data structure
378 information which the UNDI driver is
379 layering on..
380
381
382 **/
383 // TODO: flag - add argument and description to function comment
384 STATIC
385 VOID
386 BlockIt (
387 IN NIC_DATA_INSTANCE *AdapterInfo,
388 UINT32 flag
389 )
390 {
391 if (AdapterInfo->VersionFlag == 0x30) {
392 (*AdapterInfo->Block_30) (flag);
393 } else {
394 (*AdapterInfo->Block) (AdapterInfo->Unique_ID, flag);
395 }
396 }
397
398
399 /**
400 TODO: Add function description
401
402 @param AdapterInfo TODO: add argument description
403
404 @return TODO: add return values
405
406 **/
407 STATIC
408 UINT8
409 Load_Base_Regs (
410 NIC_DATA_INSTANCE *AdapterInfo
411 )
412 {
413 //
414 // we will use the linear (flat) memory model and fill our base registers
415 // with 0's so that the entire physical address is our offset
416 //
417 //
418 // we reset the statistics totals here because this is where we are loading stats addr
419 //
420 AdapterInfo->RxTotals = 0;
421 AdapterInfo->TxTotals = 0;
422
423 //
424 // Load the statistics block address.
425 //
426 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
427 OutLong (AdapterInfo, (UINT32) AdapterInfo->stat_phy_addr, AdapterInfo->ioaddr + SCBPointer);
428 OutByte (AdapterInfo, CU_STATSADDR, AdapterInfo->ioaddr + SCBCmd);
429 AdapterInfo->statistics->done_marker = 0;
430
431 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
432 OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer);
433 OutByte (AdapterInfo, RX_ADDR_LOAD, AdapterInfo->ioaddr + SCBCmd);
434
435 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
436 OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer);
437 OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd);
438
439 return 0;
440 }
441
442
443 /**
444 TODO: Add function description
445
446 @param AdapterInfo TODO: add argument description
447 @param cmd_ptr TODO: add argument description
448
449 @return TODO: add return values
450
451 **/
452 STATIC
453 UINT8
454 IssueCB (
455 NIC_DATA_INSTANCE *AdapterInfo,
456 TxCB *cmd_ptr
457 )
458 {
459 UINT16 status;
460
461 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
462
463 //
464 // read the CU status, if it is idle, write the address of cb_ptr
465 // in the scbpointer and issue a cu_start,
466 // if it is suspended, remove the suspend bit in the previous command
467 // block and issue a resume
468 //
469 // Ensure that the CU Active Status bit is not on from previous CBs.
470 //
471 status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
472
473 //
474 // Skip acknowledging the interrupt if it is not already set
475 //
476
477 //
478 // ack only the cna the integer
479 //
480 if ((status & SCB_STATUS_CNA) != 0) {
481 OutWord (AdapterInfo, SCB_STATUS_CNA, AdapterInfo->ioaddr + SCBStatus);
482
483 }
484
485 if ((status & SCB_STATUS_CU_MASK) == SCB_STATUS_CU_IDLE) {
486 //
487 // give a cu_start
488 //
489 OutLong (AdapterInfo, cmd_ptr->PhysTCBAddress, AdapterInfo->ioaddr + SCBPointer);
490 OutByte (AdapterInfo, CU_START, AdapterInfo->ioaddr + SCBCmd);
491 } else {
492 //
493 // either active or suspended, give a resume
494 //
495
496 cmd_ptr->PrevTCBVirtualLinkPtr->cb_header.command &= ~(CmdSuspend | CmdIntr);
497 OutByte (AdapterInfo, CU_RESUME, AdapterInfo->ioaddr + SCBCmd);
498 }
499
500 return 0;
501 }
502
503
504 /**
505 TODO: Add function description
506
507 @param AdapterInfo TODO: add argument description
508
509 @return TODO: add return values
510
511 **/
512 STATIC
513 UINT8
514 Configure (
515 NIC_DATA_INSTANCE *AdapterInfo
516 )
517 {
518 //
519 // all command blocks are of TxCB format
520 //
521 TxCB *cmd_ptr;
522 UINT8 *data_ptr;
523 volatile INT16 Index;
524 UINT8 my_filter;
525
526 cmd_ptr = GetFreeCB (AdapterInfo);
527 data_ptr = (UINT8 *) (&cmd_ptr->PhysTBDArrayAddres);
528
529 //
530 // start the config data right after the command header
531 //
532 for (Index = 0; Index < sizeof (basic_config_cmd); Index++) {
533 data_ptr[Index] = basic_config_cmd[Index];
534 }
535
536 my_filter = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS) ? 1 : 0);
537 my_filter = (UINT8) (my_filter | ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST) ? 0 : 2));
538
539 data_ptr[15] = (UINT8) (data_ptr[15] | my_filter);
540 data_ptr[19] = (UINT8) (AdapterInfo->Duplex ? 0xC0 : 0x80);
541 data_ptr[21] = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) ? 0x0D : 0x05);
542
543 //
544 // check if we have to use the AUI port instead
545 //
546 if ((AdapterInfo->PhyRecord[0] & 0x8000) != 0) {
547 data_ptr[15] |= 0x80;
548 data_ptr[8] = 0;
549 }
550
551 BlockIt (AdapterInfo, TRUE);
552 cmd_ptr->cb_header.command = CmdSuspend | CmdConfigure;
553
554 IssueCB (AdapterInfo, cmd_ptr);
555 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
556
557 BlockIt (AdapterInfo, FALSE);
558
559 CommandWaitForCompletion (cmd_ptr, AdapterInfo);
560
561 //
562 // restore the cb values for tx
563 //
564 cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr;
565 cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0;
566 //
567 // fields beyond the immediatedata are assumed to be safe
568 // add the CB to the free list again
569 //
570 SetFreeCB (AdapterInfo, cmd_ptr);
571 return 0;
572 }
573
574
575 /**
576 TODO: Add function description
577
578 @param AdapterInfo TODO: add argument description
579
580 @return TODO: add return values
581
582 **/
583 UINT8
584 E100bSetupIAAddr (
585 NIC_DATA_INSTANCE *AdapterInfo
586 )
587 {
588 //
589 // all command blocks are of TxCB format
590 //
591 TxCB *cmd_ptr;
592 UINT16 *data_ptr;
593 UINT16 *eaddrs;
594
595 eaddrs = (UINT16 *) AdapterInfo->CurrentNodeAddress;
596
597 cmd_ptr = GetFreeCB (AdapterInfo);
598 data_ptr = (UINT16 *) (&cmd_ptr->PhysTBDArrayAddres);
599
600 //
601 // AVOID a bug (?!) here by marking the command already completed.
602 //
603 cmd_ptr->cb_header.command = (CmdSuspend | CmdIASetup);
604 cmd_ptr->cb_header.status = 0;
605 data_ptr[0] = eaddrs[0];
606 data_ptr[1] = eaddrs[1];
607 data_ptr[2] = eaddrs[2];
608
609 BlockIt (AdapterInfo, TRUE);
610 IssueCB (AdapterInfo, cmd_ptr);
611 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
612 BlockIt (AdapterInfo, FALSE);
613
614 CommandWaitForCompletion (cmd_ptr, AdapterInfo);
615
616 //
617 // restore the cb values for tx
618 //
619 cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr;
620 cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0;
621 //
622 // fields beyond the immediatedata are assumed to be safe
623 // add the CB to the free list again
624 //
625 SetFreeCB (AdapterInfo, cmd_ptr);
626 return 0;
627 }
628
629
630 /**
631 Instructs the NIC to stop receiving packets.
632
633 @param AdapterInfo Pointer to the NIC data structure
634 information which the UNDI driver is
635 layering on..
636
637
638 **/
639 STATIC
640 VOID
641 StopRU (
642 IN NIC_DATA_INSTANCE *AdapterInfo
643 )
644 {
645 if (AdapterInfo->Receive_Started) {
646
647 //
648 // Todo: verify that we must wait for previous command completion.
649 //
650 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
651
652 //
653 // Disable interrupts, and stop the chip's Rx process.
654 //
655 OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
656 OutWord (AdapterInfo, INT_MASK | RX_ABORT, AdapterInfo->ioaddr + SCBCmd);
657
658 AdapterInfo->Receive_Started = FALSE;
659 }
660
661 return ;
662 }
663
664
665 /**
666 Instructs the NIC to start receiving packets.
667
668 @param AdapterInfo Pointer to the NIC data structure
669 information which the UNDI driver is
670 layering on..
671
672 @retval 0 Successful
673 @retval -1 Already Started
674
675 **/
676 STATIC
677 INT8
678 StartRU (
679 NIC_DATA_INSTANCE *AdapterInfo
680 )
681 {
682
683 if (AdapterInfo->Receive_Started) {
684 //
685 // already started
686 //
687 return -1;
688 }
689
690 AdapterInfo->cur_rx_ind = 0;
691 AdapterInfo->Int_Status = 0;
692
693 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
694
695 OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer);
696 OutByte (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd);
697
698 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
699
700 AdapterInfo->Receive_Started = TRUE;
701 return 0;
702 }
703
704
705 /**
706 Configures the chip. This routine expects the NIC_DATA_INSTANCE structure to be filled in.
707
708 @param AdapterInfo Pointer to the NIC data structure
709 information which the UNDI driver is
710 layering on..
711
712 @retval 0 Successful
713 @retval PXE_STATCODE_NOT_ENOUGH_MEMORY Insufficient length of locked memory
714 @retval other Failure initializing chip
715
716 **/
717 UINTN
718 E100bInit (
719 IN NIC_DATA_INSTANCE *AdapterInfo
720 )
721 {
722 PCI_CONFIG_HEADER *CfgHdr;
723 UINTN stat;
724 UINTN rx_size;
725 UINTN tx_size;
726
727 if (AdapterInfo->MemoryLength < MEMORY_NEEDED) {
728 return PXE_STATCODE_NOT_ENOUGH_MEMORY;
729 }
730
731 stat = MapIt (
732 AdapterInfo,
733 AdapterInfo->MemoryPtr,
734 AdapterInfo->MemoryLength,
735 TO_AND_FROM_DEVICE,
736 (UINT64)(UINTN) &AdapterInfo->Mapped_MemoryPtr
737 );
738
739 if (stat != 0) {
740 return stat;
741 }
742
743 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);
744
745 //
746 // fill in the ioaddr, int... from the config space
747 //
748 AdapterInfo->int_num = CfgHdr->int_line;
749
750 //
751 // we don't need to validate integer number, what if they don't want to assign one?
752 // if (AdapterInfo->int_num == 0 || AdapterInfo->int_num == 0xff)
753 // return PXE_STATCODE_DEVICE_FAILURE;
754 //
755 AdapterInfo->ioaddr = 0;
756 AdapterInfo->VendorID = CfgHdr->VendorID;
757 AdapterInfo->DeviceID = CfgHdr->DeviceID;
758 AdapterInfo->RevID = CfgHdr->RevID;
759 AdapterInfo->SubVendorID = CfgHdr->SubVendorID;
760 AdapterInfo->SubSystemID = CfgHdr->SubSystemID;
761 AdapterInfo->flash_addr = 0;
762
763 //
764 // Read the station address EEPROM before doing the reset.
765 // Perhaps this should even be done before accepting the device,
766 // then we wouldn't have a device name with which to report the error.
767 //
768 if (E100bReadEepromAndStationAddress (AdapterInfo) != 0) {
769 return PXE_STATCODE_DEVICE_FAILURE;
770
771 }
772 //
773 // ## calculate the buffer #s depending on memory given
774 // ## calculate the rx and tx ring pointers
775 //
776
777 AdapterInfo->TxBufCnt = TX_BUFFER_COUNT;
778 AdapterInfo->RxBufCnt = RX_BUFFER_COUNT;
779 rx_size = (AdapterInfo->RxBufCnt * sizeof (RxFD));
780 tx_size = (AdapterInfo->TxBufCnt * sizeof (TxCB));
781 AdapterInfo->rx_ring = (RxFD *) (UINTN) (AdapterInfo->MemoryPtr);
782 AdapterInfo->tx_ring = (TxCB *) (UINTN) (AdapterInfo->MemoryPtr + rx_size);
783 AdapterInfo->statistics = (struct speedo_stats *) (UINTN) (AdapterInfo->MemoryPtr + rx_size + tx_size);
784
785 AdapterInfo->rx_phy_addr = AdapterInfo->Mapped_MemoryPtr;
786 AdapterInfo->tx_phy_addr = AdapterInfo->Mapped_MemoryPtr + rx_size;
787 AdapterInfo->stat_phy_addr = AdapterInfo->tx_phy_addr + tx_size;
788
789 //
790 // auto detect.
791 //
792 AdapterInfo->PhyAddress = 0xFF;
793 AdapterInfo->Rx_Filter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
794 AdapterInfo->Receive_Started = FALSE;
795 AdapterInfo->mcast_list.list_len = 0;
796 return InitializeChip (AdapterInfo);
797 }
798
799
800 /**
801 Sets the interrupt state for the NIC.
802
803 @param AdapterInfo Pointer to the NIC data structure
804 information which the UNDI driver is
805 layering on..
806
807 @retval 0 Successful
808
809 **/
810 UINT8
811 E100bSetInterruptState (
812 IN NIC_DATA_INSTANCE *AdapterInfo
813 )
814 {
815 //
816 // don't set receive interrupt if receiver is disabled...
817 //
818 UINT16 cmd_word;
819
820 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) {
821 cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd);
822 cmd_word &= ~INT_MASK;
823 OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd);
824 } else {
825 //
826 // disable ints, should not be given for SW Int.
827 //
828 OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
829 }
830
831 if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_SOFTWARE) != 0) {
832 //
833 // reset the bit in our mask, it is only one time!!
834 //
835 AdapterInfo->int_mask &= ~(PXE_OPFLAGS_INTERRUPT_SOFTWARE);
836 cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd);
837 cmd_word |= DRVR_INT;
838 OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd);
839 }
840
841 return 0;
842 }
843 //
844 // we are not going to disable broadcast for the WOL's sake!
845 //
846
847 /**
848 Instructs the NIC to start receiving packets.
849
850 @param AdapterInfo Pointer to the NIC data structure
851 information which the UNDI driver is
852 layering on.. new_filter
853 - cpb -
854 cpbsize -
855
856 @retval 0 Successful
857 @retval -1 Already Started
858
859 **/
860 UINTN
861 E100bSetfilter (
862 NIC_DATA_INSTANCE *AdapterInfo,
863 UINT16 new_filter,
864 UINT64 cpb,
865 UINT32 cpbsize
866 )
867 {
868 PXE_CPB_RECEIVE_FILTERS *mc_list = (PXE_CPB_RECEIVE_FILTERS *) (UINTN)cpb;
869 UINT16 cfg_flt;
870 UINT16 old_filter;
871 UINT16 Index;
872 UINT16 Index2;
873 UINT16 mc_count;
874 TxCB *cmd_ptr;
875 struct MC_CB_STRUCT *data_ptr;
876 UINT16 mc_byte_cnt;
877
878 old_filter = AdapterInfo->Rx_Filter;
879
880 //
881 // only these bits need a change in the configuration
882 // actually change in bcast requires configure but we ignore that change
883 //
884 cfg_flt = PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS |
885 PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
886
887 if ((old_filter & cfg_flt) != (new_filter & cfg_flt)) {
888 XmitWaitForCompletion (AdapterInfo);
889
890 if (AdapterInfo->Receive_Started) {
891 StopRU (AdapterInfo);
892 }
893
894 AdapterInfo->Rx_Filter = (UINT8) (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST);
895 Configure (AdapterInfo);
896 }
897
898 //
899 // check if mcast setting changed
900 //
901 if ( ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=
902 (old_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) ) ||
903 (mc_list != NULL) ) {
904
905
906 if (mc_list != NULL) {
907 mc_count = AdapterInfo->mcast_list.list_len = (UINT16) (cpbsize / PXE_MAC_LENGTH);
908
909 for (Index = 0; (Index < mc_count && Index < MAX_MCAST_ADDRESS_CNT); Index++) {
910 for (Index2 = 0; Index2 < PXE_MAC_LENGTH; Index2++) {
911 AdapterInfo->mcast_list.mc_list[Index][Index2] = mc_list->MCastList[Index][Index2];
912 }
913 }
914 }
915
916 //
917 // are we setting the list or resetting??
918 //
919 if ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
920 //
921 // we are setting a new list!
922 //
923 mc_count = AdapterInfo->mcast_list.list_len;
924 //
925 // count should be the actual # of bytes in the list
926 // so multiply this with 6
927 //
928 mc_byte_cnt = (UINT16) ((mc_count << 2) + (mc_count << 1));
929 AdapterInfo->Rx_Filter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
930 } else {
931 //
932 // disabling the list in the NIC.
933 //
934 mc_byte_cnt = mc_count = 0;
935 AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);
936 }
937
938 //
939 // before issuing any new command!
940 //
941 XmitWaitForCompletion (AdapterInfo);
942
943 if (AdapterInfo->Receive_Started) {
944 StopRU (AdapterInfo);
945
946 }
947
948 cmd_ptr = GetFreeCB (AdapterInfo);
949 if (cmd_ptr == NULL) {
950 return PXE_STATCODE_QUEUE_FULL;
951 }
952 //
953 // fill the command structure and issue
954 //
955 data_ptr = (struct MC_CB_STRUCT *) (&cmd_ptr->PhysTBDArrayAddres);
956 //
957 // first 2 bytes are the count;
958 //
959 data_ptr->count = mc_byte_cnt;
960 for (Index = 0; Index < mc_count; Index++) {
961 for (Index2 = 0; Index2 < PXE_HWADDR_LEN_ETHER; Index2++) {
962 data_ptr->m_list[Index][Index2] = AdapterInfo->mcast_list.mc_list[Index][Index2];
963 }
964 }
965
966 cmd_ptr->cb_header.command = CmdSuspend | CmdMulticastList;
967 cmd_ptr->cb_header.status = 0;
968
969 BlockIt (AdapterInfo, TRUE);
970 IssueCB (AdapterInfo, cmd_ptr);
971 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
972
973 BlockIt (AdapterInfo, FALSE);
974
975 CommandWaitForCompletion (cmd_ptr, AdapterInfo);
976
977 cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr;
978 cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0;
979 //
980 // fields beyond the immediatedata are assumed to be safe
981 // add the CB to the free list again
982 //
983 SetFreeCB (AdapterInfo, cmd_ptr);
984 }
985
986 if (new_filter != 0) {
987 //
988 // enable unicast and start the RU
989 //
990 AdapterInfo->Rx_Filter = (UINT8) (AdapterInfo->Rx_Filter | (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_UNICAST));
991 StartRU (AdapterInfo);
992 } else {
993 //
994 // may be disabling everything!
995 //
996 if (AdapterInfo->Receive_Started) {
997 StopRU (AdapterInfo);
998 }
999
1000 AdapterInfo->Rx_Filter |= (~PXE_OPFLAGS_RECEIVE_FILTER_UNICAST);
1001 }
1002
1003 return 0;
1004 }
1005
1006
1007 /**
1008 TODO: Add function description
1009
1010 @param AdapterInfo TODO: add argument description
1011 @param cpb TODO: add argument description
1012 @param opflags TODO: add argument description
1013
1014 @return TODO: add return values
1015
1016 **/
1017 UINTN
1018 E100bTransmit (
1019 NIC_DATA_INSTANCE *AdapterInfo,
1020 UINT64 cpb,
1021 UINT16 opflags
1022 )
1023 {
1024 PXE_CPB_TRANSMIT_FRAGMENTS *tx_ptr_f;
1025 PXE_CPB_TRANSMIT *tx_ptr_1;
1026 TxCB *tcb_ptr;
1027 UINT64 Tmp_ptr;
1028 UINTN stat;
1029 INT32 Index;
1030 UINT16 wait_sec;
1031
1032 tx_ptr_1 = (PXE_CPB_TRANSMIT *) (UINTN) cpb;
1033 tx_ptr_f = (PXE_CPB_TRANSMIT_FRAGMENTS *) (UINTN) cpb;
1034
1035 //
1036 // stop reentrancy here
1037 //
1038 if (AdapterInfo->in_transmit) {
1039 return PXE_STATCODE_BUSY;
1040
1041 }
1042
1043 AdapterInfo->in_transmit = TRUE;
1044
1045 //
1046 // Prevent interrupts from changing the Tx ring from underneath us.
1047 //
1048 // Calculate the Tx descriptor entry.
1049 //
1050 if ((tcb_ptr = GetFreeCB (AdapterInfo)) == NULL) {
1051 AdapterInfo->in_transmit = FALSE;
1052 return PXE_STATCODE_QUEUE_FULL;
1053 }
1054
1055 AdapterInfo->TxTotals++;
1056
1057 tcb_ptr->cb_header.command = (CmdSuspend | CmdTx | CmdTxFlex);
1058 tcb_ptr->cb_header.status = 0;
1059
1060 //
1061 // no immediate data, set EOF in the ByteCount
1062 //
1063 tcb_ptr->ByteCount = 0x8000;
1064
1065 //
1066 // The data region is always in one buffer descriptor, Tx FIFO
1067 // threshold of 256.
1068 // 82557 multiplies the threashold value by 8, so give 256/8
1069 //
1070 tcb_ptr->Threshold = 32;
1071 if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) {
1072
1073 if (tx_ptr_f->FragCnt > MAX_XMIT_FRAGMENTS) {
1074 SetFreeCB (AdapterInfo, tcb_ptr);
1075 AdapterInfo->in_transmit = FALSE;
1076 return PXE_STATCODE_INVALID_PARAMETER;
1077 }
1078
1079 tcb_ptr->TBDCount = (UINT8) tx_ptr_f->FragCnt;
1080
1081 for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) {
1082 stat = MapIt (
1083 AdapterInfo,
1084 tx_ptr_f->FragDesc[Index].FragAddr,
1085 tx_ptr_f->FragDesc[Index].FragLen,
1086 TO_DEVICE,
1087 (UINT64)(UINTN) &Tmp_ptr
1088 );
1089 if (stat != 0) {
1090 SetFreeCB (AdapterInfo, tcb_ptr);
1091 AdapterInfo->in_transmit = FALSE;
1092 return PXE_STATCODE_INVALID_PARAMETER;
1093 }
1094
1095 tcb_ptr->TBDArray[Index].phys_buf_addr = (UINT32) Tmp_ptr;
1096 tcb_ptr->TBDArray[Index].buf_len = tx_ptr_f->FragDesc[Index].FragLen;
1097 }
1098
1099 tcb_ptr->free_data_ptr = tx_ptr_f->FragDesc[0].FragAddr;
1100
1101 } else {
1102 //
1103 // non fragmented case
1104 //
1105 tcb_ptr->TBDCount = 1;
1106 stat = MapIt (
1107 AdapterInfo,
1108 tx_ptr_1->FrameAddr,
1109 tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen,
1110 TO_DEVICE,
1111 (UINT64)(UINTN) &Tmp_ptr
1112 );
1113 if (stat != 0) {
1114 SetFreeCB (AdapterInfo, tcb_ptr);
1115 AdapterInfo->in_transmit = FALSE;
1116 return PXE_STATCODE_INVALID_PARAMETER;
1117 }
1118
1119 tcb_ptr->TBDArray[0].phys_buf_addr = (UINT32) (Tmp_ptr);
1120 tcb_ptr->TBDArray[0].buf_len = tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen;
1121 tcb_ptr->free_data_ptr = tx_ptr_1->FrameAddr;
1122 }
1123
1124 //
1125 // must wait for previous command completion only if it was a non-transmit
1126 //
1127 BlockIt (AdapterInfo, TRUE);
1128 IssueCB (AdapterInfo, tcb_ptr);
1129 BlockIt (AdapterInfo, FALSE);
1130
1131 //
1132 // see if we need to wait for completion here
1133 //
1134 if ((opflags & PXE_OPFLAGS_TRANSMIT_BLOCK) != 0) {
1135 //
1136 // don't wait for more than 1 second!!!
1137 //
1138 wait_sec = 1000;
1139 while (tcb_ptr->cb_header.status == 0) {
1140 DelayIt (AdapterInfo, 10);
1141 wait_sec--;
1142 if (wait_sec == 0) {
1143 break;
1144 }
1145 }
1146 //
1147 // we need to un-map any mapped buffers here
1148 //
1149 if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) {
1150
1151 for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) {
1152 Tmp_ptr = tcb_ptr->TBDArray[Index].phys_buf_addr;
1153 UnMapIt (
1154 AdapterInfo,
1155 tx_ptr_f->FragDesc[Index].FragAddr,
1156 tx_ptr_f->FragDesc[Index].FragLen,
1157 TO_DEVICE,
1158 (UINT64) Tmp_ptr
1159 );
1160 }
1161 } else {
1162 Tmp_ptr = tcb_ptr->TBDArray[0].phys_buf_addr;
1163 UnMapIt (
1164 AdapterInfo,
1165 tx_ptr_1->FrameAddr,
1166 tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen,
1167 TO_DEVICE,
1168 (UINT64) Tmp_ptr
1169 );
1170 }
1171
1172 if (tcb_ptr->cb_header.status == 0) {
1173 SetFreeCB (AdapterInfo, tcb_ptr);
1174 AdapterInfo->in_transmit = FALSE;
1175 return PXE_STATCODE_DEVICE_FAILURE;
1176 }
1177
1178 SetFreeCB (AdapterInfo, tcb_ptr);
1179 }
1180 //
1181 // CB will be set free later in get_status (or when we run out of xmit buffers
1182 //
1183 AdapterInfo->in_transmit = FALSE;
1184
1185 return 0;
1186 }
1187
1188
1189 /**
1190 TODO: Add function description
1191
1192 @param AdapterInfo TODO: add argument description
1193 @param cpb TODO: add argument description
1194 @param db TODO: add argument description
1195
1196 @return TODO: add return values
1197
1198 **/
1199 UINTN
1200 E100bReceive (
1201 NIC_DATA_INSTANCE *AdapterInfo,
1202 UINT64 cpb,
1203 UINT64 db
1204 )
1205 {
1206 PXE_CPB_RECEIVE *rx_cpbptr;
1207 PXE_DB_RECEIVE *rx_dbptr;
1208 RxFD *rx_ptr;
1209 INT32 status;
1210 INT32 Index;
1211 UINT16 pkt_len;
1212 UINT16 ret_code;
1213 PXE_FRAME_TYPE pkt_type;
1214 UINT16 Tmp_len;
1215 EtherHeader *hdr_ptr;
1216 ret_code = PXE_STATCODE_NO_DATA;
1217 pkt_type = PXE_FRAME_TYPE_NONE;
1218 status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
1219 AdapterInfo->Int_Status = (UINT16) (AdapterInfo->Int_Status | status);
1220 //
1221 // acknoledge the interrupts
1222 //
1223 OutWord (AdapterInfo, (UINT16) (status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus));
1224
1225 //
1226 // include the prev ints as well
1227 //
1228 status = AdapterInfo->Int_Status;
1229 rx_cpbptr = (PXE_CPB_RECEIVE *) (UINTN) cpb;
1230 rx_dbptr = (PXE_DB_RECEIVE *) (UINTN) db;
1231
1232 rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];
1233
1234 //
1235 // be in a loop just in case (we may drop a pkt)
1236 //
1237 while ((status = rx_ptr->cb_header.status) & RX_COMPLETE) {
1238
1239 AdapterInfo->RxTotals++;
1240 //
1241 // If we own the next entry, it's a new packet. Send it up.
1242 //
1243 if (rx_ptr->forwarded) {
1244 goto FreeRFD;
1245
1246 }
1247
1248 //
1249 // discard bad frames
1250 //
1251
1252 //
1253 // crc, align, dma overrun, too short, receive error (v22 no coll)
1254 //
1255 if ((status & 0x0D90) != 0) {
1256 goto FreeRFD;
1257
1258 }
1259
1260 //
1261 // make sure the status is OK
1262 //
1263 if ((status & 0x02000) == 0) {
1264 goto FreeRFD;
1265 }
1266
1267 pkt_len = (UINT16) (rx_ptr->ActualCount & 0x3fff);
1268
1269 if (pkt_len != 0) {
1270
1271 Tmp_len = pkt_len;
1272 if (pkt_len > rx_cpbptr->BufferLen) {
1273 Tmp_len = (UINT16) rx_cpbptr->BufferLen;
1274 }
1275
1276 CopyMem ((INT8 *) (UINTN) rx_cpbptr->BufferAddr, (INT8 *) &rx_ptr->RFDBuffer, Tmp_len);
1277
1278 hdr_ptr = (EtherHeader *) &rx_ptr->RFDBuffer;
1279 //
1280 // fill the CDB and break the loop
1281 //
1282
1283 //
1284 // includes header
1285 //
1286 rx_dbptr->FrameLen = pkt_len;
1287 rx_dbptr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER;
1288
1289 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
1290 if (hdr_ptr->dest_addr[Index] != AdapterInfo->CurrentNodeAddress[Index]) {
1291 break;
1292 }
1293 }
1294
1295 if (Index >= PXE_HWADDR_LEN_ETHER) {
1296 pkt_type = PXE_FRAME_TYPE_UNICAST;
1297 } else {
1298 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
1299 if (hdr_ptr->dest_addr[Index] != AdapterInfo->BroadcastNodeAddress[Index]) {
1300 break;
1301 }
1302 }
1303
1304 if (Index >= PXE_HWADDR_LEN_ETHER) {
1305 pkt_type = PXE_FRAME_TYPE_BROADCAST;
1306 } else {
1307 if ((hdr_ptr->dest_addr[0] & 1) == 1) {
1308 //
1309 // mcast
1310 //
1311
1312 pkt_type = PXE_FRAME_TYPE_FILTERED_MULTICAST;
1313 } else {
1314 pkt_type = PXE_FRAME_TYPE_PROMISCUOUS;
1315 }
1316 }
1317 }
1318
1319 rx_dbptr->Type = pkt_type;
1320 rx_dbptr->Protocol = hdr_ptr->type;
1321
1322 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
1323 rx_dbptr->SrcAddr[Index] = hdr_ptr->src_addr[Index];
1324 rx_dbptr->DestAddr[Index] = hdr_ptr->dest_addr[Index];
1325 }
1326
1327 rx_ptr->forwarded = TRUE;
1328 //
1329 // success
1330 //
1331 ret_code = 0;
1332 Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind);
1333 AdapterInfo->cur_rx_ind++;
1334 if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) {
1335 AdapterInfo->cur_rx_ind = 0;
1336 }
1337 break;
1338 }
1339
1340 FreeRFD:
1341 Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind);
1342 AdapterInfo->cur_rx_ind++;
1343 if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) {
1344 AdapterInfo->cur_rx_ind = 0;
1345 }
1346
1347 rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];
1348 }
1349
1350 if (pkt_type == PXE_FRAME_TYPE_NONE) {
1351 AdapterInfo->Int_Status &= (~SCB_STATUS_FR);
1352 }
1353
1354 status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
1355 if ((status & SCB_RUS_NO_RESOURCES) != 0) {
1356 //
1357 // start the receive unit here!
1358 // leave all the filled frames,
1359 //
1360 SetupReceiveQueues (AdapterInfo);
1361 OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer);
1362 OutWord (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd);
1363 AdapterInfo->cur_rx_ind = 0;
1364 }
1365
1366 return ret_code;
1367 }
1368
1369
1370 /**
1371 TODO: Add function description
1372
1373 @param AdapterInfo TODO: add argument description
1374
1375 @return TODO: add return values
1376
1377 **/
1378 INT16
1379 E100bReadEepromAndStationAddress (
1380 NIC_DATA_INSTANCE *AdapterInfo
1381 )
1382 {
1383 INT32 Index;
1384 INT32 Index2;
1385 UINT16 sum;
1386 UINT16 eeprom_len;
1387 UINT8 addr_len;
1388 UINT16 *eedata;
1389
1390 eedata = (UINT16 *) (&AdapterInfo->NVData[0]);
1391
1392 sum = 0;
1393 addr_len = E100bGetEepromAddrLen (AdapterInfo);
1394
1395 //
1396 // in words
1397 //
1398 AdapterInfo->NVData_Len = eeprom_len = (UINT16) (1 << addr_len);
1399 for (Index2 = 0, Index = 0; Index < eeprom_len; Index++) {
1400 UINT16 value;
1401 value = E100bReadEeprom (AdapterInfo, Index, addr_len);
1402 eedata[Index] = value;
1403 sum = (UINT16) (sum + value);
1404 if (Index < 3) {
1405 AdapterInfo->PermNodeAddress[Index2++] = (UINT8) value;
1406 AdapterInfo->PermNodeAddress[Index2++] = (UINT8) (value >> 8);
1407 }
1408 }
1409
1410 if (sum != 0xBABA) {
1411 return -1;
1412 }
1413
1414 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
1415 AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];
1416 }
1417
1418 for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
1419 AdapterInfo->BroadcastNodeAddress[Index] = 0xff;
1420 }
1421
1422 for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) {
1423 AdapterInfo->CurrentNodeAddress[Index] = 0;
1424 AdapterInfo->PermNodeAddress[Index] = 0;
1425 AdapterInfo->BroadcastNodeAddress[Index] = 0;
1426 }
1427
1428 return 0;
1429 }
1430
1431 //
1432 // CBList is a circular linked list
1433 // 1) When all are free, Tail->next == Head and FreeCount == # allocated
1434 // 2) When none are free, Tail == Head and FreeCount == 0
1435 // 3) when one is free, Tail == Head and Freecount == 1
1436 // 4) First non-Free frame is always at Tail->next
1437 //
1438
1439 /**
1440 TODO: Add function description
1441
1442 @param AdapterInfo TODO: add argument description
1443
1444 @return TODO: add return values
1445
1446 **/
1447 UINT8
1448 SetupCBlink (
1449 NIC_DATA_INSTANCE *AdapterInfo
1450 )
1451 {
1452 TxCB *head_ptr;
1453 TxCB *tail_ptr;
1454 TxCB *cur_ptr;
1455 INT32 Index;
1456 UINTN array_off;
1457
1458 cur_ptr = &(AdapterInfo->tx_ring[0]);
1459 array_off = (UINTN) (&cur_ptr->TBDArray) - (UINTN) cur_ptr;
1460 for (Index = 0; Index < AdapterInfo->TxBufCnt; Index++) {
1461 cur_ptr[Index].cb_header.status = 0;
1462 cur_ptr[Index].cb_header.command = 0;
1463
1464 cur_ptr[Index].PhysTCBAddress =
1465 (UINT32) AdapterInfo->tx_phy_addr + (Index * sizeof (TxCB));
1466
1467 cur_ptr[Index].PhysArrayAddr = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off);
1468 cur_ptr[Index].PhysTBDArrayAddres = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off);
1469
1470 cur_ptr->free_data_ptr = (UINT64) 0;
1471
1472 if (Index < AdapterInfo->TxBufCnt - 1) {
1473 cur_ptr[Index].cb_header.link = cur_ptr[Index].PhysTCBAddress + sizeof (TxCB);
1474 cur_ptr[Index].NextTCBVirtualLinkPtr = &cur_ptr[Index + 1];
1475 cur_ptr[Index + 1].PrevTCBVirtualLinkPtr = &cur_ptr[Index];
1476 }
1477 }
1478
1479 head_ptr = &cur_ptr[0];
1480 tail_ptr = &cur_ptr[AdapterInfo->TxBufCnt - 1];
1481 tail_ptr->cb_header.link = head_ptr->PhysTCBAddress;
1482 tail_ptr->NextTCBVirtualLinkPtr = head_ptr;
1483 head_ptr->PrevTCBVirtualLinkPtr = tail_ptr;
1484
1485 AdapterInfo->FreeCBCount = AdapterInfo->TxBufCnt;
1486 AdapterInfo->FreeTxHeadPtr = head_ptr;
1487 //
1488 // set tail of the free list, next to this would be either in use
1489 // or the head itself
1490 //
1491 AdapterInfo->FreeTxTailPtr = tail_ptr;
1492
1493 AdapterInfo->xmit_done_head = AdapterInfo->xmit_done_tail = 0;
1494
1495 return 0;
1496 }
1497
1498
1499 /**
1500 TODO: Add function description
1501
1502 @param AdapterInfo TODO: add argument description
1503
1504 @return TODO: add return values
1505
1506 **/
1507 TxCB *
1508 GetFreeCB (
1509 NIC_DATA_INSTANCE *AdapterInfo
1510 )
1511 {
1512 TxCB *free_cb_ptr;
1513
1514 //
1515 // claim any hanging free CBs
1516 //
1517 if (AdapterInfo->FreeCBCount <= 1) {
1518 CheckCBList (AdapterInfo);
1519 }
1520
1521 //
1522 // don't use up the last CB problem if the previous CB that the CU used
1523 // becomes the last CB we submit because of the SUSPEND bit we set.
1524 // the CU thinks it was never cleared.
1525 //
1526
1527 if (AdapterInfo->FreeCBCount <= 1) {
1528 return NULL;
1529 }
1530
1531 BlockIt (AdapterInfo, TRUE);
1532 free_cb_ptr = AdapterInfo->FreeTxHeadPtr;
1533 AdapterInfo->FreeTxHeadPtr = free_cb_ptr->NextTCBVirtualLinkPtr;
1534 --AdapterInfo->FreeCBCount;
1535 BlockIt (AdapterInfo, FALSE);
1536 return free_cb_ptr;
1537 }
1538
1539
1540 /**
1541 TODO: Add function description
1542
1543 @param AdapterInfo TODO: add argument description
1544 @param cb_ptr TODO: add argument description
1545
1546 @return TODO: add return values
1547
1548 **/
1549 VOID
1550 SetFreeCB (
1551 IN NIC_DATA_INSTANCE *AdapterInfo,
1552 IN TxCB *cb_ptr
1553 )
1554 {
1555 //
1556 // here we assume cb are returned in the order they are taken out
1557 // and we link the newly freed cb at the tail of free cb list
1558 //
1559 cb_ptr->cb_header.status = 0;
1560 cb_ptr->free_data_ptr = (UINT64) 0;
1561
1562 AdapterInfo->FreeTxTailPtr = cb_ptr;
1563 ++AdapterInfo->FreeCBCount;
1564 return ;
1565 }
1566
1567
1568 /**
1569 TODO: Add function description
1570
1571 @param ind TODO: add argument description
1572
1573 @return TODO: add return values
1574
1575 **/
1576 UINT16
1577 next (
1578 IN UINT16 ind
1579 )
1580 {
1581 UINT16 Tmp;
1582
1583 Tmp = (UINT16) (ind + 1);
1584 if (Tmp >= (TX_BUFFER_COUNT << 1)) {
1585 Tmp = 0;
1586 }
1587
1588 return Tmp;
1589 }
1590
1591
1592 /**
1593 TODO: Add function description
1594
1595 @param AdapterInfo TODO: add argument description
1596
1597 @return TODO: add return values
1598
1599 **/
1600 UINT16
1601 CheckCBList (
1602 IN NIC_DATA_INSTANCE *AdapterInfo
1603 )
1604 {
1605 TxCB *Tmp_ptr;
1606 UINT16 cnt;
1607
1608 cnt = 0;
1609 while (1) {
1610 Tmp_ptr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr;
1611 if ((Tmp_ptr->cb_header.status & CMD_STATUS_MASK) != 0) {
1612 //
1613 // check if Q is full
1614 //
1615 if (next (AdapterInfo->xmit_done_tail) != AdapterInfo->xmit_done_head) {
1616 AdapterInfo->xmit_done[AdapterInfo->xmit_done_tail] = Tmp_ptr->free_data_ptr;
1617
1618 UnMapIt (
1619 AdapterInfo,
1620 Tmp_ptr->free_data_ptr,
1621 Tmp_ptr->TBDArray[0].buf_len,
1622 TO_DEVICE,
1623 (UINT64) Tmp_ptr->TBDArray[0].phys_buf_addr
1624 );
1625
1626 AdapterInfo->xmit_done_tail = next (AdapterInfo->xmit_done_tail);
1627 }
1628
1629 SetFreeCB (AdapterInfo, Tmp_ptr);
1630 } else {
1631 break;
1632 }
1633 }
1634
1635 return cnt;
1636 }
1637 //
1638 // Description : Initialize the RFD list list by linking each element together
1639 // in a circular list. The simplified memory model is used.
1640 // All data is in the RFD. The RFDs are linked together and the
1641 // last one points back to the first one. When the current RFD
1642 // is processed (frame received), its EL bit is set and the EL
1643 // bit in the previous RXFD is cleared.
1644 // Allocation done during INIT, this is making linked list.
1645 //
1646
1647 /**
1648 TODO: Add function description
1649
1650 @param AdapterInfo TODO: add argument description
1651
1652 @return TODO: add return values
1653
1654 **/
1655 UINT8
1656 SetupReceiveQueues (
1657 IN NIC_DATA_INSTANCE *AdapterInfo
1658 )
1659 {
1660 RxFD *rx_ptr;
1661 RxFD *tail_ptr;
1662 UINT16 Index;
1663
1664 AdapterInfo->cur_rx_ind = 0;
1665 rx_ptr = (&AdapterInfo->rx_ring[0]);
1666
1667 for (Index = 0; Index < AdapterInfo->RxBufCnt; Index++) {
1668 rx_ptr[Index].cb_header.status = 0;
1669 rx_ptr[Index].cb_header.command = 0;
1670 rx_ptr[Index].RFDSize = RX_BUFFER_SIZE;
1671 rx_ptr[Index].ActualCount = 0;
1672 //
1673 // RBDs not used, simple memory model
1674 //
1675 rx_ptr[Index].rx_buf_addr = (UINT32) (-1);
1676
1677 //
1678 // RBDs not used, simple memory model
1679 //
1680 rx_ptr[Index].forwarded = FALSE;
1681
1682 //
1683 // don't use Tmp_ptr if it is beyond the last one
1684 //
1685 if (Index < AdapterInfo->RxBufCnt - 1) {
1686 rx_ptr[Index].cb_header.link = (UINT32) AdapterInfo->rx_phy_addr + ((Index + 1) * sizeof (RxFD));
1687 }
1688 }
1689
1690 tail_ptr = (&AdapterInfo->rx_ring[AdapterInfo->RxBufCnt - 1]);
1691 tail_ptr->cb_header.link = (UINT32) AdapterInfo->rx_phy_addr;
1692
1693 //
1694 // set the EL bit
1695 //
1696 tail_ptr->cb_header.command = 0xC000;
1697 AdapterInfo->RFDTailPtr = tail_ptr;
1698 return 0;
1699 }
1700
1701
1702 /**
1703 TODO: Add function description
1704
1705 @param AdapterInfo TODO: add argument description
1706 @param rx_index TODO: add argument description
1707
1708 @return TODO: add return values
1709
1710 **/
1711 VOID
1712 Recycle_RFD (
1713 IN NIC_DATA_INSTANCE *AdapterInfo,
1714 IN UINT16 rx_index
1715 )
1716 {
1717 RxFD *rx_ptr;
1718 RxFD *tail_ptr;
1719 //
1720 // change the EL bit and change the AdapterInfo->RxTailPtr
1721 // rx_ptr is assumed to be the head of the Q
1722 // AdapterInfo->rx_forwarded[rx_index] = FALSE;
1723 //
1724 rx_ptr = &AdapterInfo->rx_ring[rx_index];
1725 tail_ptr = AdapterInfo->RFDTailPtr;
1726 //
1727 // set el_bit and suspend bit
1728 //
1729 rx_ptr->cb_header.command = 0xc000;
1730 rx_ptr->cb_header.status = 0;
1731 rx_ptr->ActualCount = 0;
1732 rx_ptr->forwarded = FALSE;
1733 AdapterInfo->RFDTailPtr = rx_ptr;
1734 //
1735 // resetting the el_bit.
1736 //
1737 tail_ptr->cb_header.command = 0;
1738 //
1739 // check the receive unit, fix if there is any problem
1740 //
1741 return ;
1742 }
1743 //
1744 // Serial EEPROM section.
1745 //
1746 // EEPROM_Ctrl bits.
1747 //
1748 #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
1749 #define EE_CS 0x02 /* EEPROM chip select. */
1750 #define EE_DI 0x04 /* EEPROM chip data in. */
1751 #define EE_WRITE_0 0x01
1752 #define EE_WRITE_1 0x05
1753 #define EE_DO 0x08 /* EEPROM chip data out. */
1754 #define EE_ENB (0x4800 | EE_CS)
1755
1756 //
1757 // Delay between EEPROM clock transitions.
1758 // This will actually work with no delay on 33Mhz PCI.
1759 //
1760 #define eeprom_delay(nanosec) DelayIt (AdapterInfo, nanosec);
1761
1762 //
1763 // The EEPROM commands include the alway-set leading bit.
1764 //
1765 #define EE_WRITE_CMD 5 // 101b
1766 #define EE_READ_CMD 6 // 110b
1767 #define EE_ERASE_CMD (7 << 6)
1768
1769 STATIC
1770 VOID
1771 shift_bits_out (
1772 IN NIC_DATA_INSTANCE *AdapterInfo,
1773 IN UINT16 val,
1774 IN UINT8 num_bits
1775 )
1776 /*++
1777
1778 Routine Description:
1779
1780 TODO: Add function description
1781
1782 Arguments:
1783
1784 AdapterInfo - TODO: add argument description
1785 val - TODO: add argument description
1786 num_bits - TODO: add argument description
1787
1788 Returns:
1789
1790 TODO: add return values
1791
1792 --*/
1793 {
1794 INT32 Index;
1795 UINT8 Tmp;
1796 UINT32 EEAddr;
1797
1798 EEAddr = AdapterInfo->ioaddr + SCBeeprom;
1799
1800 for (Index = num_bits; Index >= 0; Index--) {
1801 INT16 dataval;
1802
1803 //
1804 // will be 0 or 4
1805 //
1806 dataval = (INT16) ((val & (1 << Index)) ? EE_DI : 0);
1807
1808 //
1809 // mask off the data_in bit
1810 //
1811 Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) &~EE_DI);
1812 Tmp = (UINT8) (Tmp | dataval);
1813 OutByte (AdapterInfo, Tmp, EEAddr);
1814 eeprom_delay (100);
1815 //
1816 // raise the eeprom clock
1817 //
1818 OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
1819 eeprom_delay (150);
1820 //
1821 // lower the eeprom clock
1822 //
1823 OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
1824 eeprom_delay (150);
1825 }
1826 }
1827
1828
1829 /**
1830 TODO: Add function description
1831
1832 @param AdapterInfo TODO: add argument description
1833
1834 @return TODO: add return values
1835
1836 **/
1837 STATIC
1838 UINT16
1839 shift_bits_in (
1840 IN NIC_DATA_INSTANCE *AdapterInfo
1841 )
1842 {
1843 UINT8 Tmp;
1844 INT32 Index;
1845 UINT16 retval;
1846 UINT32 EEAddr;
1847
1848 EEAddr = AdapterInfo->ioaddr + SCBeeprom;
1849
1850 retval = 0;
1851 for (Index = 15; Index >= 0; Index--) {
1852 //
1853 // raise the clock
1854 //
1855
1856 //
1857 // mask off the data_in bit
1858 //
1859 Tmp = InByte (AdapterInfo, EEAddr);
1860 OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
1861 eeprom_delay (100);
1862 Tmp = InByte (AdapterInfo, EEAddr);
1863 retval = (UINT16) ((retval << 1) | ((Tmp & EE_DO) ? 1 : 0));
1864 //
1865 // lower the clock
1866 //
1867 OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
1868 eeprom_delay (100);
1869 }
1870
1871 return retval;
1872 }
1873
1874
1875 /**
1876 This routine sets the EEPROM lockout bit to gain exclusive access to the
1877 eeprom. the access bit is the most significant bit in the General Control
1878 Register 2 in the SCB space.
1879
1880 @param AdapterInfo Pointer to the NIC data structure
1881 information which the UNDI driver is
1882 layering on..
1883
1884 @retval TRUE if it got the access
1885 @retval FALSE if it fails to get the exclusive access
1886
1887 **/
1888 STATIC
1889 BOOLEAN
1890 E100bSetEepromLockOut (
1891 IN NIC_DATA_INSTANCE *AdapterInfo
1892 )
1893 {
1894 UINTN wait;
1895 UINT8 tmp;
1896
1897 if ((AdapterInfo->DeviceID == D102_DEVICE_ID) ||
1898 (AdapterInfo->RevID >= D102_REVID)) {
1899
1900 wait = 500;
1901
1902 while (wait--) {
1903
1904 tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2);
1905 tmp |= GCR2_EEPROM_ACCESS_SEMAPHORE;
1906 OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2);
1907
1908 DelayIt (AdapterInfo, 50);
1909 tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2);
1910
1911 if (tmp & GCR2_EEPROM_ACCESS_SEMAPHORE) {
1912 return TRUE;
1913 }
1914 }
1915
1916 return FALSE;
1917 }
1918
1919 return TRUE;
1920 }
1921
1922
1923 /**
1924 This routine Resets the EEPROM lockout bit to giveup access to the
1925 eeprom. the access bit is the most significant bit in the General Control
1926 Register 2 in the SCB space.
1927
1928 @param AdapterInfo Pointer to the NIC data structure
1929 information which the UNDI driver is
1930 layering on..
1931
1932 @return None
1933
1934 **/
1935 STATIC
1936 VOID
1937 E100bReSetEepromLockOut (
1938 IN NIC_DATA_INSTANCE *AdapterInfo
1939 )
1940 {
1941 UINT8 tmp;
1942
1943 if ((AdapterInfo->DeviceID == D102_DEVICE_ID) ||
1944 (AdapterInfo->RevID >= D102_REVID)) {
1945
1946 tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2);
1947 tmp &= ~(GCR2_EEPROM_ACCESS_SEMAPHORE);
1948 OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2);
1949
1950 DelayIt (AdapterInfo, 50);
1951 }
1952 }
1953
1954
1955 /**
1956 Using the NIC data structure information, read the EEPROM to get a Word of data for the MAC address.
1957
1958 @param AdapterInfo Pointer to the NIC data structure
1959 information which the UNDI driver is
1960 layering on..
1961 @param Location Word offset into the MAC address to read.
1962 @param AddrLen Number of bits of address length.
1963
1964 @retval RetVal The word read from the EEPROM.
1965
1966 **/
1967 UINT16
1968 E100bReadEeprom (
1969 IN NIC_DATA_INSTANCE *AdapterInfo,
1970 IN INT32 Location,
1971 IN UINT8 AddrLen
1972 )
1973 {
1974 UINT16 RetVal;
1975 UINT8 Tmp;
1976
1977 UINT32 EEAddr;
1978 UINT16 ReadCmd;
1979
1980 EEAddr = AdapterInfo->ioaddr + SCBeeprom;
1981 ReadCmd = (UINT16) (Location | (EE_READ_CMD << AddrLen));
1982
1983 RetVal = 0;
1984
1985 //
1986 // get exclusive access to the eeprom first!
1987 //
1988 E100bSetEepromLockOut (AdapterInfo);
1989
1990 //
1991 // eeprom control reg bits: x,x,x,x,DO,DI,CS,SK
1992 // to write the opcode+data value out one bit at a time in DI starting at msb
1993 // and then out a 1 to sk, wait, out 0 to SK and wait
1994 // repeat this for all the bits to be written
1995 //
1996
1997 //
1998 // 11110010b
1999 //
2000 Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2);
2001 OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr);
2002
2003 //
2004 // 3 for the read opcode 110b
2005 //
2006 shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + AddrLen));
2007
2008 //
2009 // read the eeprom word one bit at a time
2010 //
2011 RetVal = shift_bits_in (AdapterInfo);
2012
2013 //
2014 // Terminate the EEPROM access and leave eeprom in a clean state.
2015 //
2016 Tmp = InByte (AdapterInfo, EEAddr);
2017 Tmp &= ~(EE_CS | EE_DI);
2018 OutByte (AdapterInfo, Tmp, EEAddr);
2019
2020 //
2021 // raise the clock and lower the eeprom shift clock
2022 //
2023 OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
2024 eeprom_delay (100);
2025
2026 OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
2027 eeprom_delay (100);
2028
2029 //
2030 // giveup access to the eeprom
2031 //
2032 E100bReSetEepromLockOut (AdapterInfo);
2033
2034 return RetVal;
2035 }
2036
2037
2038 /**
2039 Using the NIC data structure information, read the EEPROM to determine how many bits of address length
2040 this EEPROM is in Words.
2041
2042 @param AdapterInfo Pointer to the NIC data structure
2043 information which the UNDI driver is
2044 layering on..
2045
2046 @retval RetVal The word read from the EEPROM.
2047
2048 **/
2049 UINT8
2050 E100bGetEepromAddrLen (
2051 IN NIC_DATA_INSTANCE *AdapterInfo
2052 )
2053 {
2054 UINT8 Tmp;
2055 UINT8 AddrLen;
2056 UINT32 EEAddr;
2057 //
2058 // assume 64word eeprom (so,6 bits of address_length)
2059 //
2060 UINT16 ReadCmd;
2061
2062 EEAddr = AdapterInfo->ioaddr + SCBeeprom;
2063 ReadCmd = (EE_READ_CMD << 6);
2064
2065 //
2066 // get exclusive access to the eeprom first!
2067 //
2068 E100bSetEepromLockOut (AdapterInfo);
2069
2070 //
2071 // address we are trying to read is 0
2072 // eeprom control reg bits: x,x,x,x,DO,,DI,,CS,SK
2073 // to write the opcode+data value out one bit at a time in DI starting at msb
2074 // and then out a 1 to sk, wait, out 0 to SK and wait
2075 // repeat this for all the bits to be written
2076 //
2077 Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2);
2078
2079 //
2080 // enable eeprom access
2081 //
2082 OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr);
2083
2084 //
2085 // 3 for opcode, 6 for the default address len
2086 //
2087 shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + 6));
2088
2089 //
2090 // (in case of a 64 word eeprom).
2091 // read the "dummy zero" from EE_DO to say that the address we wrote
2092 // (six 0s) is accepted, write more zeros (until 8) to get a "dummy zero"
2093 //
2094
2095 //
2096 // assume the smallest
2097 //
2098 AddrLen = 6;
2099 Tmp = InByte (AdapterInfo, EEAddr);
2100 while ((AddrLen < 8) && ((Tmp & EE_DO) != 0)) {
2101 OutByte (AdapterInfo, (UINT8) (Tmp &~EE_DI), EEAddr);
2102 eeprom_delay (100);
2103
2104 //
2105 // raise the eeprom clock
2106 //
2107 OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
2108 eeprom_delay (150);
2109
2110 //
2111 // lower the eeprom clock
2112 //
2113 OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
2114 eeprom_delay (150);
2115 Tmp = InByte (AdapterInfo, EEAddr);
2116 AddrLen++;
2117 }
2118
2119 //
2120 // read the eeprom word, even though we don't need this
2121 //
2122 shift_bits_in (AdapterInfo);
2123
2124 //
2125 // Terminate the EEPROM access.
2126 //
2127 Tmp = InByte (AdapterInfo, EEAddr);
2128 Tmp &= ~(EE_CS | EE_DI);
2129 OutByte (AdapterInfo, Tmp, EEAddr);
2130
2131 //
2132 // raise the clock and lower the eeprom shift clock
2133 //
2134 OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
2135 eeprom_delay (100);
2136
2137 OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
2138 eeprom_delay (100);
2139
2140 //
2141 // giveup access to the eeprom!
2142 //
2143 E100bReSetEepromLockOut (AdapterInfo);
2144
2145 return AddrLen;
2146 }
2147
2148
2149 /**
2150 TODO: Add function description
2151
2152 @param AdapterInfo TODO: add argument description
2153 @param DBaddr TODO: add argument description
2154 @param DBsize TODO: add argument description
2155
2156 @return TODO: add return values
2157
2158 **/
2159 UINTN
2160 E100bStatistics (
2161 NIC_DATA_INSTANCE *AdapterInfo,
2162 UINT64 DBaddr,
2163 UINT16 DBsize
2164 )
2165 {
2166 PXE_DB_STATISTICS db;
2167 //
2168 // wait upto one second (each wait is 100 micro s)
2169 //
2170 UINT32 Wait;
2171 Wait = 10000;
2172 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
2173
2174 //
2175 // Clear statistics done marker.
2176 //
2177 AdapterInfo->statistics->done_marker = 0;
2178
2179 //
2180 // Issue statistics dump (or dump w/ reset) command.
2181 //
2182 OutByte (
2183 AdapterInfo,
2184 (UINT8) (DBsize ? CU_SHOWSTATS : CU_DUMPSTATS),
2185 (UINT32) (AdapterInfo->ioaddr + SCBCmd)
2186 );
2187
2188 //
2189 // Wait for command to complete.
2190 //
2191 // zero the db here just to chew up a little more time.
2192 //
2193
2194 ZeroMem ((VOID *) &db, sizeof db);
2195
2196 while (Wait != 0) {
2197 //
2198 // Wait a bit before checking.
2199 //
2200
2201 DelayIt (AdapterInfo, 100);
2202
2203 //
2204 // Look for done marker at end of statistics.
2205 //
2206
2207 switch (AdapterInfo->statistics->done_marker) {
2208 case 0xA005:
2209 case 0xA007:
2210 break;
2211
2212 default:
2213 Wait--;
2214 continue;
2215 }
2216
2217 //
2218 // if we did not "continue" from the above switch, we are done,
2219 //
2220 break;
2221 }
2222
2223 //
2224 // If this is a reset, we are out of here!
2225 //
2226 if (DBsize == 0) {
2227 return PXE_STATCODE_SUCCESS;
2228 }
2229
2230 //
2231 // Convert NIC statistics counter format to EFI/UNDI
2232 // specification statistics counter format.
2233 //
2234
2235 //
2236 // 54 3210 fedc ba98 7654 3210
2237 // db.Supported = 01 0000 0100 1101 0001 0111;
2238 //
2239 db.Supported = 0x104D17;
2240
2241 //
2242 // Statistics from the NIC
2243 //
2244
2245 db.Data[0x01] = AdapterInfo->statistics->rx_good_frames;
2246
2247 db.Data[0x02] = AdapterInfo->statistics->rx_runt_errs;
2248
2249 db.Data[0x08] = AdapterInfo->statistics->rx_crc_errs +
2250 AdapterInfo->statistics->rx_align_errs;
2251
2252 db.Data[0x04] = db.Data[0x02] +
2253 db.Data[0x08] +
2254 AdapterInfo->statistics->rx_resource_errs +
2255 AdapterInfo->statistics->rx_overrun_errs;
2256
2257 db.Data[0x00] = db.Data[0x01] + db.Data[0x04];
2258
2259 db.Data[0x0B] = AdapterInfo->statistics->tx_good_frames;
2260
2261 db.Data[0x0E] = AdapterInfo->statistics->tx_coll16_errs +
2262 AdapterInfo->statistics->tx_late_colls +
2263 AdapterInfo->statistics->tx_underruns +
2264 AdapterInfo->statistics->tx_one_colls +
2265 AdapterInfo->statistics->tx_multi_colls;
2266
2267 db.Data[0x14] = AdapterInfo->statistics->tx_total_colls;
2268
2269 db.Data[0x0A] = db.Data[0x0B] +
2270 db.Data[0x0E] +
2271 AdapterInfo->statistics->tx_lost_carrier;
2272
2273 if (DBsize > sizeof db) {
2274 DBsize = sizeof db;
2275 }
2276
2277 CopyMem ((VOID *) (UINTN) DBaddr, (VOID *) &db, (UINTN) DBsize);
2278
2279 return PXE_STATCODE_SUCCESS;
2280 }
2281
2282
2283 /**
2284 TODO: Add function description
2285
2286 @param AdapterInfo TODO: add argument description
2287 @param OpFlags TODO: add argument description
2288
2289 @return TODO: add return values
2290
2291 **/
2292 UINTN
2293 E100bReset (
2294 IN NIC_DATA_INSTANCE *AdapterInfo,
2295 IN INT32 OpFlags
2296 )
2297 {
2298
2299 UINT16 save_filter;
2300 //
2301 // disable the interrupts
2302 //
2303 OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
2304
2305 //
2306 // wait for the tx queue to complete
2307 //
2308 CheckCBList (AdapterInfo);
2309
2310 XmitWaitForCompletion (AdapterInfo);
2311
2312 if (AdapterInfo->Receive_Started) {
2313 StopRU (AdapterInfo);
2314 }
2315
2316 InitializeChip (AdapterInfo);
2317
2318 //
2319 // check the opflags and restart receive filters
2320 //
2321 if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) {
2322
2323 save_filter = AdapterInfo->Rx_Filter;
2324 //
2325 // if we give the filter same as Rx_Filter,
2326 // this routine will not set mcast list (it thinks there is no change)
2327 // to force it, we will reset that flag in the Rx_Filter
2328 //
2329 AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);
2330 E100bSetfilter (AdapterInfo, save_filter, (UINT64) 0, (UINT32) 0);
2331 }
2332
2333 if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) {
2334 //
2335 // disable the interrupts
2336 //
2337 AdapterInfo->int_mask = 0;
2338 }
2339 //
2340 // else leave the interrupt in the pre-set state!!!
2341 //
2342 E100bSetInterruptState (AdapterInfo);
2343
2344 return 0;
2345 }
2346
2347
2348 /**
2349 TODO: Add function description
2350
2351 @param AdapterInfo TODO: add argument description
2352
2353 @return TODO: add return values
2354
2355 **/
2356 UINTN
2357 E100bShutdown (
2358 IN NIC_DATA_INSTANCE *AdapterInfo
2359 )
2360 {
2361 //
2362 // disable the interrupts
2363 //
2364 OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
2365
2366 //
2367 // stop the receive unit
2368 //
2369 if (AdapterInfo->Receive_Started) {
2370 StopRU (AdapterInfo);
2371 }
2372
2373 //
2374 // wait for the tx queue to complete
2375 //
2376 CheckCBList (AdapterInfo);
2377 if (AdapterInfo->FreeCBCount != AdapterInfo->TxBufCnt) {
2378 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
2379 }
2380
2381 //
2382 // we do not want to reset the phy, it takes a long time to renegotiate the
2383 // link after that (3-4 seconds)
2384 //
2385 InitializeChip (AdapterInfo);
2386 SelectiveReset (AdapterInfo);
2387 return 0;
2388 }
2389
2390
2391 /**
2392 This routine will write a value to the specified MII register
2393 of an external MDI compliant device (e.g. PHY 100). The command will
2394 execute in polled mode.
2395
2396 @param AdapterInfo pointer to the structure that contains
2397 the NIC's context.
2398 @param RegAddress The MII register that we are writing to
2399 @param PhyAddress The MDI address of the Phy component.
2400 @param DataValue The value that we are writing to the MII
2401 register.
2402
2403 @return nothing
2404
2405 **/
2406 VOID
2407 MdiWrite (
2408 IN NIC_DATA_INSTANCE *AdapterInfo,
2409 IN UINT8 RegAddress,
2410 IN UINT8 PhyAddress,
2411 IN UINT16 DataValue
2412 )
2413 {
2414 UINT32 WriteCommand;
2415
2416 WriteCommand = ((UINT32) DataValue) |
2417 ((UINT32)(RegAddress << 16)) |
2418 ((UINT32)(PhyAddress << 21)) |
2419 ((UINT32)(MDI_WRITE << 26));
2420
2421 //
2422 // Issue the write command to the MDI control register.
2423 //
2424 OutLong (AdapterInfo, WriteCommand, AdapterInfo->ioaddr + SCBCtrlMDI);
2425
2426 //
2427 // wait 20usec before checking status
2428 //
2429 DelayIt (AdapterInfo, 20);
2430
2431 //
2432 // poll for the mdi write to complete
2433 while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) &
2434 MDI_PHY_READY) == 0){
2435 DelayIt (AdapterInfo, 20);
2436 }
2437 }
2438
2439
2440 /**
2441 This routine will read a value from the specified MII register
2442 of an external MDI compliant device (e.g. PHY 100), and return
2443 it to the calling routine. The command will execute in polled mode.
2444
2445 @param AdapterInfo pointer to the structure that contains
2446 the NIC's context.
2447 @param RegAddress The MII register that we are reading from
2448 @param PhyAddress The MDI address of the Phy component.
2449 @param DataValue pointer to the value that we read from
2450 the MII register.
2451
2452
2453 **/
2454 VOID
2455 MdiRead (
2456 IN NIC_DATA_INSTANCE *AdapterInfo,
2457 IN UINT8 RegAddress,
2458 IN UINT8 PhyAddress,
2459 IN OUT UINT16 *DataValue
2460 )
2461 {
2462 UINT32 ReadCommand;
2463
2464 ReadCommand = ((UINT32) (RegAddress << 16)) |
2465 ((UINT32) (PhyAddress << 21)) |
2466 ((UINT32) (MDI_READ << 26));
2467
2468 //
2469 // Issue the read command to the MDI control register.
2470 //
2471 OutLong (AdapterInfo, ReadCommand, AdapterInfo->ioaddr + SCBCtrlMDI);
2472
2473 //
2474 // wait 20usec before checking status
2475 //
2476 DelayIt (AdapterInfo, 20);
2477
2478 //
2479 // poll for the mdi read to complete
2480 //
2481 while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) &
2482 MDI_PHY_READY) == 0) {
2483 DelayIt (AdapterInfo, 20);
2484
2485 }
2486
2487 *DataValue = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI);
2488 }
2489
2490
2491 /**
2492 This routine will reset the PHY that the adapter is currently
2493 configured to use.
2494
2495 @param AdapterInfo pointer to the structure that contains
2496 the NIC's context.
2497
2498
2499 **/
2500 VOID
2501 PhyReset (
2502 NIC_DATA_INSTANCE *AdapterInfo
2503 )
2504 {
2505 UINT16 MdiControlReg;
2506
2507 MdiControlReg = (MDI_CR_AUTO_SELECT |
2508 MDI_CR_RESTART_AUTO_NEG |
2509 MDI_CR_RESET);
2510
2511 //
2512 // Write the MDI control register with our new Phy configuration
2513 //
2514 MdiWrite (
2515 AdapterInfo,
2516 MDI_CONTROL_REG,
2517 AdapterInfo->PhyAddress,
2518 MdiControlReg
2519 );
2520
2521 return ;
2522 }
2523
2524
2525 /**
2526 This routine will detect what phy we are using, set the line
2527 speed, FDX or HDX, and configure the phy if necessary.
2528 The following combinations are supported:
2529 - TX or T4 PHY alone at PHY address 1
2530 - T4 or TX PHY at address 1 and MII PHY at address 0
2531 - 82503 alone (10Base-T mode, no full duplex support)
2532 - 82503 and MII PHY (TX or T4) at address 0
2533 The sequence / priority of detection is as follows:
2534 - PHY 1 with cable termination
2535 - PHY 0 with cable termination
2536 - PHY 1 (if found) without cable termination
2537 - 503 interface
2538 Additionally auto-negotiation capable (NWAY) and parallel
2539 detection PHYs are supported. The flow-chart is described in
2540 the 82557 software writer's manual.
2541 NOTE: 1. All PHY MDI registers are read in polled mode.
2542 2. The routines assume that the 82557 has been RESET and we have
2543 obtained the virtual memory address of the CSR.
2544 3. PhyDetect will not RESET the PHY.
2545 4. If FORCEFDX is set, SPEED should also be set. The driver will
2546 check the values for inconsistency with the detected PHY
2547 technology.
2548 5. PHY 1 (the PHY on the adapter) may have an address in the range
2549 1 through 31 inclusive. The driver will accept addresses in
2550 this range.
2551 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface
2552 is detected.
2553
2554 @param AdapterInfo pointer to the structure that contains
2555 the NIC's context.
2556
2557 @retval TRUE If a Phy was detected, and configured
2558 correctly.
2559 @retval FALSE If a valid phy could not be detected and
2560 configured.
2561
2562 **/
2563 BOOLEAN
2564 PhyDetect (
2565 NIC_DATA_INSTANCE *AdapterInfo
2566 )
2567 {
2568 UINT16 *eedata;
2569 UINT16 MdiControlReg;
2570 UINT16 MdiStatusReg;
2571 BOOLEAN FoundPhy1;
2572 UINT8 ReNegotiateTime;
2573
2574 eedata = (UINT16 *) (&AdapterInfo->NVData[0]);
2575
2576 FoundPhy1 = FALSE;
2577 ReNegotiateTime = 35;
2578 //
2579 // EEPROM word [6] contains the Primary PHY record in which the least 3 bits
2580 // indicate the PHY address
2581 // and word [7] contains the secondary PHY record
2582 //
2583 AdapterInfo->PhyRecord[0] = eedata[6];
2584 AdapterInfo->PhyRecord[1] = eedata[7];
2585 AdapterInfo->PhyAddress = (UINT8) (AdapterInfo->PhyRecord[0] & 7);
2586
2587 //
2588 // Check for a phy address over-ride of 32 which indicates force use of 82503
2589 // not detecting the link in this case
2590 //
2591 if (AdapterInfo->PhyAddress == 32) {
2592 //
2593 // 503 interface over-ride
2594 // Record the current speed and duplex. We will be in half duplex
2595 // mode unless the user used the force full duplex over-ride.
2596 //
2597 AdapterInfo->LinkSpeed = 10;
2598 return (TRUE);
2599 }
2600
2601 //
2602 // If the Phy Address is between 1-31 then we must first look for phy 1,
2603 // at that address.
2604 //
2605 if ((AdapterInfo->PhyAddress > 0) && (AdapterInfo->PhyAddress < 32)) {
2606
2607 //
2608 // Read the MDI control and status registers at phy 1
2609 // and check if we found a valid phy
2610 //
2611 MdiRead (
2612 AdapterInfo,
2613 MDI_CONTROL_REG,
2614 AdapterInfo->PhyAddress,
2615 &MdiControlReg
2616 );
2617
2618 MdiRead (
2619 AdapterInfo,
2620 MDI_STATUS_REG,
2621 AdapterInfo->PhyAddress,
2622 &MdiStatusReg
2623 );
2624
2625 if (!((MdiControlReg == 0xffff) ||
2626 ((MdiStatusReg == 0) && (MdiControlReg == 0)))) {
2627
2628 //
2629 // we have a valid phy1
2630 // Read the status register again because of sticky bits
2631 //
2632 FoundPhy1 = TRUE;
2633 MdiRead (
2634 AdapterInfo,
2635 MDI_STATUS_REG,
2636 AdapterInfo->PhyAddress,
2637 &MdiStatusReg
2638 );
2639
2640 //
2641 // If there is a valid link then use this Phy.
2642 //
2643 if (MdiStatusReg & MDI_SR_LINK_STATUS) {
2644 return (SetupPhy(AdapterInfo));
2645 }
2646 }
2647 }
2648
2649 //
2650 // Next try to detect a PHY at address 0x00 because there was no Phy 1,
2651 // or Phy 1 didn't have link, or we had a phy 0 over-ride
2652 //
2653
2654 //
2655 // Read the MDI control and status registers at phy 0
2656 //
2657 MdiRead (AdapterInfo, MDI_CONTROL_REG, 0, &MdiControlReg);
2658 MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
2659
2660 //
2661 // check if we found a valid phy 0
2662 //
2663 if (((MdiControlReg == 0xffff) ||
2664 ((MdiStatusReg == 0) && (MdiControlReg == 0)))) {
2665
2666 //
2667 // we don't have a valid phy at address 0
2668 // if phy address was forced to 0, then error out because we
2669 // didn't find a phy at that address
2670 //
2671 if (AdapterInfo->PhyAddress == 0x0000) {
2672 return (FALSE);
2673 } else {
2674 //
2675 // at this point phy1 does not have link and there is no phy 0 at all
2676 // if we are forced to detect the cable, error out here!
2677 //
2678 if (AdapterInfo->CableDetect != 0) {
2679 return FALSE;
2680
2681 }
2682
2683 if (FoundPhy1) {
2684 //
2685 // no phy 0, but there is a phy 1 (no link I guess), so use phy 1
2686 //
2687 return SetupPhy (AdapterInfo);
2688 } else {
2689 //
2690 // didn't find phy 0 or phy 1, so assume a 503 interface
2691 //
2692 AdapterInfo->PhyAddress = 32;
2693
2694 //
2695 // Record the current speed and duplex. We'll be in half duplex
2696 // mode unless the user used the force full duplex over-ride.
2697 //
2698 AdapterInfo->LinkSpeed = 10;
2699 return (TRUE);
2700 }
2701 }
2702 } else {
2703 //
2704 // We have a valid phy at address 0. If phy 0 has a link then we use
2705 // phy 0. If Phy 0 doesn't have a link then we use Phy 1 (no link)
2706 // if phy 1 is present, or phy 0 if phy 1 is not present
2707 // If phy 1 was present, then we must isolate phy 1 before we enable
2708 // phy 0 to see if Phy 0 has a link.
2709 //
2710 if (FoundPhy1) {
2711 //
2712 // isolate phy 1
2713 //
2714 MdiWrite (
2715 AdapterInfo,
2716 MDI_CONTROL_REG,
2717 AdapterInfo->PhyAddress,
2718 MDI_CR_ISOLATE
2719 );
2720
2721 //
2722 // wait 100 microseconds for the phy to isolate.
2723 //
2724 DelayIt (AdapterInfo, 100);
2725 }
2726
2727 //
2728 // Since this Phy is at address 0, we must enable it. So clear
2729 // the isolate bit, and set the auto-speed select bit
2730 //
2731 MdiWrite (
2732 AdapterInfo,
2733 MDI_CONTROL_REG,
2734 0,
2735 MDI_CR_AUTO_SELECT
2736 );
2737
2738 //
2739 // wait 100 microseconds for the phy to be enabled.
2740 //
2741 DelayIt (AdapterInfo, 100);
2742
2743 //
2744 // restart the auto-negotion process
2745 //
2746 MdiWrite (
2747 AdapterInfo,
2748 MDI_CONTROL_REG,
2749 0,
2750 MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT
2751 );
2752
2753 //
2754 // wait no more than 3.5 seconds for auto-negotiation to complete
2755 //
2756 while (ReNegotiateTime) {
2757 //
2758 // Read the status register twice because of sticky bits
2759 //
2760 MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
2761 MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
2762
2763 if (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE) {
2764 break;
2765 }
2766
2767 DelayIt (AdapterInfo, 100);
2768 ReNegotiateTime--;
2769 }
2770
2771 //
2772 // Read the status register again because of sticky bits
2773 //
2774 MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
2775
2776 //
2777 // If the link was not set
2778 //
2779 if ((MdiStatusReg & MDI_SR_LINK_STATUS) == 0) {
2780 //
2781 // PHY1 does not have a link and phy 0 does not have a link
2782 // do not proceed if we need to detect the link!
2783 //
2784 if (AdapterInfo->CableDetect != 0) {
2785 return FALSE;
2786 }
2787
2788 //
2789 // the link wasn't set, so use phy 1 if phy 1 was present
2790 //
2791 if (FoundPhy1) {
2792 //
2793 // isolate phy 0
2794 //
2795 MdiWrite (AdapterInfo, MDI_CONTROL_REG, 0, MDI_CR_ISOLATE);
2796
2797 //
2798 // wait 100 microseconds for the phy to isolate.
2799 //
2800 DelayIt (AdapterInfo, 100);
2801
2802 //
2803 // Now re-enable PHY 1
2804 //
2805 MdiWrite (
2806 AdapterInfo,
2807 MDI_CONTROL_REG,
2808 AdapterInfo->PhyAddress,
2809 MDI_CR_AUTO_SELECT
2810 );
2811
2812 //
2813 // wait 100 microseconds for the phy to be enabled
2814 //
2815 DelayIt (AdapterInfo, 100);
2816
2817 //
2818 // restart the auto-negotion process
2819 //
2820 MdiWrite (
2821 AdapterInfo,
2822 MDI_CONTROL_REG,
2823 AdapterInfo->PhyAddress,
2824 MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT
2825 );
2826
2827 //
2828 // Don't wait for it to complete (we didn't have link earlier)
2829 //
2830 return (SetupPhy (AdapterInfo));
2831 }
2832 }
2833
2834 //
2835 // Definitely using Phy 0
2836 //
2837 AdapterInfo->PhyAddress = 0;
2838 return (SetupPhy(AdapterInfo));
2839 }
2840 }
2841
2842
2843 /**
2844 This routine will setup phy 1 or phy 0 so that it is configured
2845 to match a speed and duplex over-ride option. If speed or
2846 duplex mode is not explicitly specified in the registry, the
2847 driver will skip the speed and duplex over-ride code, and
2848 assume the adapter is automatically setting the line speed, and
2849 the duplex mode. At the end of this routine, any truly Phy
2850 specific code will be executed (each Phy has its own quirks,
2851 and some require that certain special bits are set).
2852 NOTE: The driver assumes that SPEED and FORCEFDX are specified at the
2853 same time. If FORCEDPX is set without speed being set, the driver
2854 will encouter a fatal error and log a message into the event viewer.
2855
2856 @param AdapterInfo pointer to the structure that contains
2857 the NIC's context.
2858
2859 @retval TRUE If the phy could be configured correctly
2860 @retval FALSE If the phy couldn't be configured
2861 correctly, because an unsupported
2862 over-ride option was used
2863
2864 **/
2865 BOOLEAN
2866 SetupPhy (
2867 IN NIC_DATA_INSTANCE *AdapterInfo
2868 )
2869 {
2870 UINT16 MdiControlReg;
2871 UINT16 MdiStatusReg;
2872 UINT16 MdiIdLowReg;
2873 UINT16 MdiIdHighReg;
2874 UINT16 MdiMiscReg;
2875 UINT32 PhyId;
2876 BOOLEAN ForcePhySetting;
2877
2878 ForcePhySetting = FALSE;
2879
2880 //
2881 // If we are NOT forcing a setting for line speed or full duplex, then
2882 // we won't force a link setting, and we'll jump down to the phy
2883 // specific code.
2884 //
2885 if (((AdapterInfo->LinkSpeedReq) || (AdapterInfo->DuplexReq))) {
2886 //
2887 // Find out what kind of technology this Phy is capable of.
2888 //
2889 MdiRead (
2890 AdapterInfo,
2891 MDI_STATUS_REG,
2892 AdapterInfo->PhyAddress,
2893 &MdiStatusReg
2894 );
2895
2896 //
2897 // Read the MDI control register at our phy
2898 //
2899 MdiRead (
2900 AdapterInfo,
2901 MDI_CONTROL_REG,
2902 AdapterInfo->PhyAddress,
2903 &MdiControlReg
2904 );
2905
2906 //
2907 // Now check the validity of our forced option. If the force option is
2908 // valid, then force the setting. If the force option is not valid,
2909 // we'll set a flag indicating that we should error out.
2910 //
2911
2912 //
2913 // If speed is forced to 10mb
2914 //
2915 if (AdapterInfo->LinkSpeedReq == 10) {
2916 //
2917 // If half duplex is forced
2918 //
2919 if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) {
2920 if (MdiStatusReg & MDI_SR_10T_HALF_DPX) {
2921
2922 MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
2923 ForcePhySetting = TRUE;
2924 }
2925 } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) {
2926
2927 //
2928 // If full duplex is forced
2929 //
2930 if (MdiStatusReg & MDI_SR_10T_FULL_DPX) {
2931
2932 MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT);
2933 MdiControlReg |= MDI_CR_FULL_HALF;
2934 ForcePhySetting = TRUE;
2935 }
2936 } else {
2937 //
2938 // If auto duplex (we actually set phy to 1/2)
2939 //
2940 if (MdiStatusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_10T_HALF_DPX)) {
2941
2942 MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
2943 ForcePhySetting = TRUE;
2944 }
2945 }
2946 }
2947
2948 //
2949 // If speed is forced to 100mb
2950 //
2951 else if (AdapterInfo->LinkSpeedReq == 100) {
2952 //
2953 // If half duplex is forced
2954 //
2955 if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) {
2956 if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) {
2957
2958 MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
2959 MdiControlReg |= MDI_CR_10_100;
2960 ForcePhySetting = TRUE;
2961 }
2962 } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) {
2963 //
2964 // If full duplex is forced
2965 //
2966 if (MdiStatusReg & MDI_SR_TX_FULL_DPX) {
2967 MdiControlReg &= ~MDI_CR_AUTO_SELECT;
2968 MdiControlReg |= (MDI_CR_10_100 | MDI_CR_FULL_HALF);
2969 ForcePhySetting = TRUE;
2970 }
2971 } else {
2972 //
2973 // If auto duplex (we set phy to 1/2)
2974 //
2975 if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) {
2976
2977 MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
2978 MdiControlReg |= MDI_CR_10_100;
2979 ForcePhySetting = TRUE;
2980 }
2981 }
2982 }
2983
2984 if (!ForcePhySetting) {
2985 return (FALSE);
2986 }
2987
2988 //
2989 // Write the MDI control register with our new Phy configuration
2990 //
2991 MdiWrite (
2992 AdapterInfo,
2993 MDI_CONTROL_REG,
2994 AdapterInfo->PhyAddress,
2995 MdiControlReg
2996 );
2997
2998 //
2999 // wait 100 milliseconds for auto-negotiation to complete
3000 //
3001 DelayIt (AdapterInfo, 100);
3002 }
3003
3004 //
3005 // Find out specifically what Phy this is. We do this because for certain
3006 // phys there are specific bits that must be set so that the phy and the
3007 // 82557 work together properly.
3008 //
3009
3010 MdiRead (
3011 AdapterInfo,
3012 PHY_ID_REG_1,
3013 AdapterInfo->PhyAddress,
3014 &MdiIdLowReg
3015 );
3016 MdiRead (
3017 AdapterInfo,
3018 PHY_ID_REG_2,
3019 AdapterInfo->PhyAddress,
3020 &MdiIdHighReg
3021 );
3022
3023 PhyId = ((UINT32) MdiIdLowReg | ((UINT32) MdiIdHighReg << 16));
3024
3025 //
3026 // And out the revsion field of the Phy ID so that we'll be able to detect
3027 // future revs of the same Phy.
3028 //
3029 PhyId &= PHY_MODEL_REV_ID_MASK;
3030
3031 //
3032 // Handle the National TX
3033 //
3034 if (PhyId == PHY_NSC_TX) {
3035
3036 MdiRead (
3037 AdapterInfo,
3038 NSC_CONG_CONTROL_REG,
3039 AdapterInfo->PhyAddress,
3040 &MdiMiscReg
3041 );
3042
3043 MdiMiscReg |= (NSC_TX_CONG_TXREADY | NSC_TX_CONG_F_CONNECT);
3044
3045 MdiWrite (
3046 AdapterInfo,
3047 NSC_CONG_CONTROL_REG,
3048 AdapterInfo->PhyAddress,
3049 MdiMiscReg
3050 );
3051 }
3052
3053 FindPhySpeedAndDpx (AdapterInfo, PhyId);
3054
3055 //
3056 // We put a hardware fix on to our adapters to work-around the PHY_100 errata
3057 // described below. The following code is only compiled in, if we wanted
3058 // to attempt a software workaround to the PHY_100 A/B step problem.
3059 //
3060
3061 return (TRUE);
3062 }
3063
3064
3065 /**
3066 This routine will figure out what line speed and duplex mode
3067 the PHY is currently using.
3068
3069 @param AdapterInfo pointer to the structure that contains
3070 the NIC's context.
3071 @param PhyId The ID of the PHY in question.
3072
3073 @return NOTHING
3074
3075 **/
3076 VOID
3077 FindPhySpeedAndDpx (
3078 IN NIC_DATA_INSTANCE *AdapterInfo,
3079 IN UINT32 PhyId
3080 )
3081 {
3082 UINT16 MdiStatusReg;
3083 UINT16 MdiMiscReg;
3084 UINT16 MdiOwnAdReg;
3085 UINT16 MdiLinkPartnerAdReg;
3086
3087 //
3088 // If there was a speed and/or duplex override, then set our current
3089 // value accordingly
3090 //
3091 AdapterInfo->LinkSpeed = AdapterInfo->LinkSpeedReq;
3092 AdapterInfo->Duplex = (UINT8) ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) ?
3093 FULL_DUPLEX : HALF_DUPLEX);
3094
3095 //
3096 // If speed and duplex were forced, then we know our current settings, so
3097 // we'll just return. Otherwise, we'll need to figure out what NWAY set
3098 // us to.
3099 //
3100 if (AdapterInfo->LinkSpeed && AdapterInfo->Duplex) {
3101 return ;
3102
3103 }
3104 //
3105 // If we didn't have a valid link, then we'll assume that our current
3106 // speed is 10mb half-duplex.
3107 //
3108
3109 //
3110 // Read the status register twice because of sticky bits
3111 //
3112 MdiRead (
3113 AdapterInfo,
3114 MDI_STATUS_REG,
3115 AdapterInfo->PhyAddress,
3116 &MdiStatusReg
3117 );
3118 MdiRead (
3119 AdapterInfo,
3120 MDI_STATUS_REG,
3121 AdapterInfo->PhyAddress,
3122 &MdiStatusReg
3123 );
3124
3125 //
3126 // If there wasn't a valid link then use default speed & duplex
3127 //
3128 if (!(MdiStatusReg & MDI_SR_LINK_STATUS)) {
3129
3130 AdapterInfo->LinkSpeed = 10;
3131 AdapterInfo->Duplex = HALF_DUPLEX;
3132 return ;
3133 }
3134
3135 //
3136 // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits
3137 // 1 and 0 of extended register 0, to get the current speed and duplex
3138 // settings.
3139 //
3140 if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || (PhyId == PHY_TX_ID)) {
3141 //
3142 // Read extended register 0
3143 //
3144 MdiRead (
3145 AdapterInfo,
3146 EXTENDED_REG_0,
3147 AdapterInfo->PhyAddress,
3148 &MdiMiscReg
3149 );
3150
3151 //
3152 // Get current speed setting
3153 //
3154 if (MdiMiscReg & PHY_100_ER0_SPEED_INDIC) {
3155 AdapterInfo->LinkSpeed = 100;
3156 } else {
3157 AdapterInfo->LinkSpeed = 10;
3158 }
3159
3160 //
3161 // Get current duplex setting -- if bit is set then FDX is enabled
3162 //
3163 if (MdiMiscReg & PHY_100_ER0_FDX_INDIC) {
3164 AdapterInfo->Duplex = FULL_DUPLEX;
3165 } else {
3166 AdapterInfo->Duplex = HALF_DUPLEX;
3167 }
3168
3169 return ;
3170 }
3171 //
3172 // Read our link partner's advertisement register
3173 //
3174 MdiRead (
3175 AdapterInfo,
3176 AUTO_NEG_LINK_PARTNER_REG,
3177 AdapterInfo->PhyAddress,
3178 &MdiLinkPartnerAdReg
3179 );
3180
3181 //
3182 // See if Auto-Negotiation was complete (bit 5, reg 1)
3183 //
3184 MdiRead (
3185 AdapterInfo,
3186 MDI_STATUS_REG,
3187 AdapterInfo->PhyAddress,
3188 &MdiStatusReg
3189 );
3190
3191 //
3192 // If a True NWAY connection was made, then we can detect speed/duplex by
3193 // ANDing our adapter's advertised abilities with our link partner's
3194 // advertised ablilities, and then assuming that the highest common
3195 // denominator was chosed by NWAY.
3196 //
3197 if ((MdiLinkPartnerAdReg & NWAY_LP_ABILITY) &&
3198 (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE)) {
3199
3200 //
3201 // Read our advertisement register
3202 //
3203 MdiRead (
3204 AdapterInfo,
3205 AUTO_NEG_ADVERTISE_REG,
3206 AdapterInfo->PhyAddress,
3207 &MdiOwnAdReg
3208 );
3209
3210 //
3211 // AND the two advertisement registers together, and get rid of any
3212 // extraneous bits.
3213 //
3214 MdiOwnAdReg = (UINT16) (MdiOwnAdReg & (MdiLinkPartnerAdReg & NWAY_LP_ABILITY));
3215
3216 //
3217 // Get speed setting
3218 //
3219 if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX | NWAY_AD_TX_FULL_DPX | NWAY_AD_T4_CAPABLE)) {
3220 AdapterInfo->LinkSpeed = 100;
3221 } else {
3222 AdapterInfo->LinkSpeed = 10;
3223 }
3224
3225 //
3226 // Get duplex setting -- use priority resolution algorithm
3227 //
3228 if (MdiOwnAdReg & (NWAY_AD_T4_CAPABLE)) {
3229 AdapterInfo->Duplex = HALF_DUPLEX;
3230 return ;
3231 } else if (MdiOwnAdReg & (NWAY_AD_TX_FULL_DPX)) {
3232 AdapterInfo->Duplex = FULL_DUPLEX;
3233 return ;
3234 } else if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX)) {
3235 AdapterInfo->Duplex = HALF_DUPLEX;
3236 return ;
3237 } else if (MdiOwnAdReg & (NWAY_AD_10T_FULL_DPX)) {
3238 AdapterInfo->Duplex = FULL_DUPLEX;
3239 return ;
3240 } else {
3241 AdapterInfo->Duplex = HALF_DUPLEX;
3242 return ;
3243 }
3244 }
3245
3246 //
3247 // If we are connected to a dumb (non-NWAY) repeater or hub, and the line
3248 // speed was determined automatically by parallel detection, then we have
3249 // no way of knowing exactly what speed the PHY is set to unless that PHY
3250 // has a propietary register which indicates speed in this situation. The
3251 // NSC TX PHY does have such a register. Also, since NWAY didn't establish
3252 // the connection, the duplex setting should HALF duplex.
3253 //
3254 AdapterInfo->Duplex = HALF_DUPLEX;
3255
3256 if (PhyId == PHY_NSC_TX) {
3257 //
3258 // Read register 25 to get the SPEED_10 bit
3259 //
3260 MdiRead (
3261 AdapterInfo,
3262 NSC_SPEED_IND_REG,
3263 AdapterInfo->PhyAddress,
3264 &MdiMiscReg
3265 );
3266
3267 //
3268 // If bit 6 was set then we're at 10mb
3269 //
3270 if (MdiMiscReg & NSC_TX_SPD_INDC_SPEED) {
3271 AdapterInfo->LinkSpeed = 10;
3272 } else {
3273 AdapterInfo->LinkSpeed = 100;
3274 }
3275 }
3276
3277 //
3278 // If we don't know what line speed we are set at, then we'll default to
3279 // 10mbs
3280 //
3281 else {
3282 AdapterInfo->LinkSpeed = 10;
3283 }
3284 }
3285
3286
3287 /**
3288 TODO: Add function description
3289
3290 @param AdapterInfo TODO: add argument description
3291
3292 @return TODO: add return values
3293
3294 **/
3295 VOID
3296 XmitWaitForCompletion (
3297 NIC_DATA_INSTANCE *AdapterInfo
3298 )
3299 {
3300 TxCB *TxPtr;
3301
3302 if (AdapterInfo->FreeCBCount == AdapterInfo->TxBufCnt) {
3303 return ;
3304 }
3305
3306 //
3307 // used xmit cb list starts right after the free tail (ends before the
3308 // free head ptr)
3309 //
3310 TxPtr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr;
3311 while (TxPtr != AdapterInfo->FreeTxHeadPtr) {
3312 CommandWaitForCompletion (TxPtr, AdapterInfo);
3313 SetFreeCB (AdapterInfo, TxPtr);
3314 TxPtr = TxPtr->NextTCBVirtualLinkPtr;
3315 }
3316 }
3317
3318
3319 /**
3320 TODO: Add function description
3321
3322 @param cmd_ptr TODO: add argument description
3323 @param AdapterInfo TODO: add argument description
3324
3325 @return TODO: add return values
3326
3327 **/
3328 INT8
3329 CommandWaitForCompletion (
3330 TxCB *cmd_ptr,
3331 NIC_DATA_INSTANCE *AdapterInfo
3332 )
3333 {
3334 INT16 wait;
3335 wait = 5000;
3336 while ((cmd_ptr->cb_header.status == 0) && (--wait > 0)) {
3337 DelayIt (AdapterInfo, 10);
3338 }
3339
3340 if (cmd_ptr->cb_header.status == 0) {
3341 return -1;
3342 }
3343
3344 return 0;
3345 }
3346
3347
3348 /**
3349 TODO: Add function description
3350
3351 @param AdapterInfo TODO: add argument description
3352
3353 @return TODO: add return values
3354
3355 **/
3356 STATIC
3357 INT8
3358 SoftwareReset (
3359 NIC_DATA_INSTANCE *AdapterInfo
3360 )
3361 {
3362 UINT8 tco_stat;
3363 UINT16 wait;
3364
3365 tco_stat = 0;
3366
3367 //
3368 // Reset the chip: stop Tx and Rx processes and clear counters.
3369 // This takes less than 10usec and will easily finish before the next
3370 // action.
3371 //
3372
3373 OutLong (AdapterInfo, PORT_RESET, AdapterInfo->ioaddr + SCBPort);
3374 //
3375 // wait for 5 milli seconds here!
3376 //
3377 DelayIt (AdapterInfo, 5000);
3378 //
3379 // TCO Errata work around for 559s only
3380 // -----------------------------------------------------------------------------------
3381 // TCO Workaround Code
3382 // haifa workaround
3383 // -----------------------------------------------------------------------------------
3384 // 1. Issue SW-RST ^^^ (already done above)
3385 // 2. Issue a redundant Set CU Base CMD immediately
3386 // Do not set the General Pointer before the Set CU Base cycle
3387 // Do not check the SCB CMD before the Set CU Base cycle
3388 // 3. Wait for the SCB-CMD to be cleared
3389 // this indicates the transition to post-driver
3390 // 4. Poll the TCO-Req bit in the PMDR to be cleared
3391 // this indicates the tco activity has stopped for real
3392 // 5. Proceed with the nominal Driver Init:
3393 // Actual Set CU & RU Base ...
3394 //
3395 // Check for ICH2 device ID. If this is an ICH2,
3396 // do the TCO workaround code.
3397 //
3398 if (AdapterInfo->VendorID == D102_DEVICE_ID ||
3399 AdapterInfo->VendorID == ICH3_DEVICE_ID_1 ||
3400 AdapterInfo->VendorID == ICH3_DEVICE_ID_2 ||
3401 AdapterInfo->VendorID == ICH3_DEVICE_ID_3 ||
3402 AdapterInfo->VendorID == ICH3_DEVICE_ID_4 ||
3403 AdapterInfo->VendorID == ICH3_DEVICE_ID_5 ||
3404 AdapterInfo->VendorID == ICH3_DEVICE_ID_6 ||
3405 AdapterInfo->VendorID == ICH3_DEVICE_ID_7 ||
3406 AdapterInfo->VendorID == ICH3_DEVICE_ID_8 ||
3407 AdapterInfo->RevID >= 8) { // do the TCO fix
3408 //
3409 // donot load the scb pointer but just give load_cu cmd.
3410 //
3411 OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd);
3412 //
3413 // wait for command to be accepted.
3414 //
3415 wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
3416 //
3417 // read PMDR register and check bit 1 in it to see if TCO is active
3418 //
3419
3420 //
3421 // wait for 5 milli seconds
3422 //
3423 wait = 5000;
3424 while (wait) {
3425 tco_stat = InByte (AdapterInfo, AdapterInfo->ioaddr + 0x1b);
3426 if ((tco_stat & 2) == 0) {
3427 //
3428 // is the activity bit clear??
3429 //
3430 break;
3431 }
3432
3433 wait--;
3434 DelayIt (AdapterInfo, 1);
3435 }
3436
3437 if ((tco_stat & 2) != 0) {
3438 //
3439 // not zero??
3440 //
3441 return -1;
3442 }
3443 }
3444
3445 return 0;
3446 }
3447
3448
3449 /**
3450 TODO: Add function description
3451
3452 @param AdapterInfo TODO: add argument description
3453
3454 @return TODO: add return values
3455
3456 **/
3457 UINT8
3458 SelectiveReset (
3459 IN NIC_DATA_INSTANCE *AdapterInfo
3460 )
3461 {
3462 UINT16 wait;
3463 UINT32 stat;
3464
3465 wait = 10;
3466 stat = 0;
3467 OutLong (AdapterInfo, POR_SELECTIVE_RESET, AdapterInfo->ioaddr + SCBPort);
3468 //
3469 // wait for this to complete
3470 //
3471
3472 //
3473 // wait for 2 milli seconds here!
3474 //
3475 DelayIt (AdapterInfo, 2000);
3476 while (wait > 0) {
3477 wait--;
3478 stat = InLong (AdapterInfo, AdapterInfo->ioaddr + SCBPort);
3479 if (stat == 0) {
3480 break;
3481 }
3482
3483 //
3484 // wait for 1 milli second
3485 //
3486 DelayIt (AdapterInfo, 1000);
3487 }
3488
3489 if (stat != 0) {
3490 return PXE_STATCODE_DEVICE_FAILURE;
3491 }
3492
3493 return 0;
3494 }
3495
3496
3497 /**
3498 TODO: Add function description
3499
3500 @param AdapterInfo TODO: add argument description
3501
3502 @return TODO: add return values
3503
3504 **/
3505 UINT16
3506 InitializeChip (
3507 IN NIC_DATA_INSTANCE *AdapterInfo
3508 )
3509 {
3510 UINT16 ret_val;
3511 if (SoftwareReset (AdapterInfo) != 0) {
3512 return PXE_STATCODE_DEVICE_FAILURE;
3513 }
3514
3515 //
3516 // disable interrupts
3517 //
3518 OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
3519
3520 //
3521 // Load the base registers with 0s (we will give the complete address as
3522 // offset later when we issue any command
3523 //
3524 if ((ret_val = Load_Base_Regs (AdapterInfo)) != 0) {
3525 return ret_val;
3526 }
3527
3528 if ((ret_val = SetupCBlink (AdapterInfo)) != 0) {
3529 return ret_val;
3530 }
3531
3532 if ((ret_val = SetupReceiveQueues (AdapterInfo)) != 0) {
3533 return ret_val;
3534 }
3535
3536 //
3537 // detect the PHY only if we need to detect the cable as requested by the
3538 // initialize parameters
3539 //
3540 AdapterInfo->PhyAddress = 0xFF;
3541
3542 if (AdapterInfo->CableDetect != 0) {
3543 if (!PhyDetect (AdapterInfo)) {
3544 return PXE_STATCODE_DEVICE_FAILURE;
3545 }
3546 }
3547
3548 if ((ret_val = E100bSetupIAAddr (AdapterInfo)) != 0) {
3549 return ret_val;
3550 }
3551
3552 if ((ret_val = Configure (AdapterInfo)) != 0) {
3553 return ret_val;
3554 }
3555
3556 return 0;
3557 }