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