]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.c
ab3c997448b2b17d0dcd2cb6c860d35179ac8701
[mirror_edk2.git] / EdkModulePkg / Universal / Network / Snp32_64 / Dxe / snp.c
1 /*++
2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 Module name:
12 snp.c
13
14 Abstract:
15
16 --*/
17
18
19 #include "snp.h"
20
21 EFI_STATUS
22 pxe_start (
23 SNP_DRIVER *snp
24 );
25 EFI_STATUS
26 pxe_stop (
27 SNP_DRIVER *snp
28 );
29 EFI_STATUS
30 pxe_init (
31 SNP_DRIVER *snp,
32 UINT16 OpFlags
33 );
34 EFI_STATUS
35 pxe_shutdown (
36 SNP_DRIVER *snp
37 );
38 EFI_STATUS
39 pxe_get_stn_addr (
40 SNP_DRIVER *snp
41 );
42
43 EFI_STATUS
44 EFIAPI
45 InitializeSnpNiiDriver (
46 IN EFI_HANDLE image_handle,
47 IN EFI_SYSTEM_TABLE *system_table
48 );
49
50 EFI_STATUS
51 EFIAPI
52 SimpleNetworkDriverSupported (
53 IN EFI_DRIVER_BINDING_PROTOCOL *This,
54 IN EFI_HANDLE Controller,
55 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
56 );
57
58 EFI_STATUS
59 EFIAPI
60 SimpleNetworkDriverStart (
61 IN EFI_DRIVER_BINDING_PROTOCOL *This,
62 IN EFI_HANDLE Controller,
63 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
64 );
65
66 EFI_STATUS
67 EFIAPI
68 SimpleNetworkDriverStop (
69 IN EFI_DRIVER_BINDING_PROTOCOL *This,
70 IN EFI_HANDLE Controller,
71 IN UINTN NumberOfChildren,
72 IN EFI_HANDLE *ChildHandleBuffer
73 );
74
75 //
76 // Simple Network Protocol Driver Global Variables
77 //
78 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = {
79 SimpleNetworkDriverSupported,
80 SimpleNetworkDriverStart,
81 SimpleNetworkDriverStop,
82 0x10,
83 NULL,
84 NULL
85 };
86
87 //
88 // Module global variables needed to support undi 3.0 interface
89 //
90 EFI_PCI_IO_PROTOCOL *mPciIoFncs;
91 struct s_v2p *_v2p = NULL; // undi3.0 map_list head
92 // End Global variables
93 //
94 EFI_STATUS
95 add_v2p (
96 IN OUT struct s_v2p **v2p,
97 EFI_PCI_IO_PROTOCOL_OPERATION type,
98 VOID *vaddr,
99 UINTN bsize
100 )
101 /*++
102
103 Routine Description:
104 This routine maps the given CPU address to a Device address. It creates a
105 an entry in the map list with the virtual and physical addresses and the
106 un map cookie.
107
108 Arguments:
109 v2p - pointer to return a map list node pointer.
110 type - the direction in which the data flows from the given virtual address
111 device->cpu or cpu->device or both ways.
112 vaddr - virtual address (or CPU address) to be mapped
113 bsize - size of the buffer to be mapped.
114
115 Returns:
116
117 EFI_SUCEESS - routine has completed the mapping
118 other - error as indicated.
119
120 --*/
121 {
122 EFI_STATUS Status;
123
124 if ((v2p == NULL) || (vaddr == NULL) || (bsize == 0)) {
125 return EFI_INVALID_PARAMETER;
126 }
127
128 Status = gBS->AllocatePool (
129 EfiBootServicesData,
130 sizeof (struct s_v2p),
131 (VOID **) v2p
132 );
133
134 if (Status != EFI_SUCCESS) {
135 return Status;
136 }
137
138 Status = mPciIoFncs->Map (
139 mPciIoFncs,
140 type,
141 vaddr,
142 &bsize,
143 &(*v2p)->paddr,
144 &(*v2p)->unmap
145 );
146 if (Status != EFI_SUCCESS) {
147 gBS->FreePool (*v2p);
148 return Status;
149 }
150 (*v2p)->vaddr = vaddr;
151 (*v2p)->bsize = bsize;
152 (*v2p)->next = _v2p;
153 _v2p = *v2p;
154
155 return EFI_SUCCESS;
156 }
157
158 EFI_STATUS
159 find_v2p (
160 struct s_v2p **v2p,
161 VOID *vaddr
162 )
163 /*++
164
165 Routine Description:
166 This routine searches the linked list of mapped address nodes (for undi3.0
167 interface) to find the node that corresponds to the given virtual address and
168 returns a pointer to that node.
169
170 Arguments:
171 v2p - pointer to return a map list node pointer.
172 vaddr - virtual address (or CPU address) to be searched in the map list
173
174 Returns:
175
176 EFI_SUCEESS - if a match found!
177 Other - match not found
178
179 --*/
180 {
181 struct s_v2p *v;
182
183 if (v2p == NULL || vaddr == NULL) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 for (v = _v2p; v != NULL; v = v->next) {
188 if (v->vaddr == vaddr) {
189 *v2p = v;
190 return EFI_SUCCESS;
191 }
192 }
193
194 return EFI_NOT_FOUND;
195 }
196
197 EFI_STATUS
198 del_v2p (
199 VOID *vaddr
200 )
201 /*++
202
203 Routine Description:
204 This routine unmaps the given virtual address and frees the memory allocated
205 for the map list node corresponding to that address.
206
207 Arguments:
208 vaddr - virtual address (or CPU address) to be unmapped
209
210 Returns:
211 EFI_SUCEESS - if successfully unmapped
212 Other - as indicated by the error
213
214
215 --*/
216 {
217 struct s_v2p *v;
218 struct s_v2p *t;
219 EFI_STATUS Status;
220
221 if (vaddr == NULL) {
222 return EFI_INVALID_PARAMETER;
223 }
224
225 if (_v2p == NULL) {
226 return EFI_NOT_FOUND;
227 }
228 //
229 // Is our node at the head of the list??
230 //
231 if ((v = _v2p)->vaddr == vaddr) {
232 _v2p = _v2p->next;
233
234 Status = mPciIoFncs->Unmap (mPciIoFncs, v->unmap);
235
236 gBS->FreePool (v);
237
238 #if SNP_DEBUG
239 if (Status) {
240 Print (L"Unmap failed with status = %x\n", Status);
241 }
242 #endif
243 return Status;
244 }
245
246 for (; v->next != NULL; v = t) {
247 if ((t = v->next)->vaddr == vaddr) {
248 v->next = t->next;
249 Status = mPciIoFncs->Unmap (mPciIoFncs, t->unmap);
250 gBS->FreePool (t);
251 #if SNP_DEBUG
252 if (Status) {
253 Print (L"Unmap failed with status = %x\n", Status);
254 }
255 #endif
256 return Status;
257 }
258 }
259
260 return EFI_NOT_FOUND;
261 }
262
263 #if SNP_DEBUG
264 VOID
265 snp_wait_for_key (
266 VOID
267 )
268 /*++
269
270 Routine Description:
271 Wait for a key stroke, used for debugging purposes
272
273 Arguments:
274 none
275
276 Returns:
277 none
278
279 --*/
280 {
281 EFI_INPUT_KEY key;
282
283 Aprint ("\nPress any key to continue\n");
284
285 while (gST->ConIn->ReadKeyStroke (gST->ConIn, &key) == EFI_NOT_READY) {
286 ;
287 }
288 }
289 #endif
290
291 STATIC
292 EFI_STATUS
293 issue_hwundi_command (
294 UINT64 cdb
295 )
296 /*++
297
298 Routine Description:
299
300 Arguments:
301
302 Returns:
303
304 --*/
305 {
306 #if SNP_DEBUG
307 Aprint ("\nissue_hwundi_command() - This should not be called!");
308 snp_wait_for_key ();
309 #endif
310 if (cdb == 0) {
311 return EFI_INVALID_PARAMETER;
312
313 }
314 //
315 // %%TBD - For now, nothing is done.
316 //
317 return EFI_UNSUPPORTED;
318 }
319
320 STATIC
321 UINT8
322 calc_8bit_cksum (
323 VOID *ptr,
324 UINTN len
325 )
326 /*++
327
328 Routine Description:
329 Compute 8-bit checksum of a buffer.
330
331 Arguments:
332 ptr - Pointer to buffer.
333 len - Length of buffer in bytes.
334
335 Returns:
336 8-bit checksum of all bytes in buffer.
337 If ptr is NULL or len is zero, zero is returned.
338
339 --*/
340 {
341 UINT8 *bptr;
342 UINT8 cksum;
343
344 bptr = ptr;
345 cksum = 0;
346
347 if (ptr == NULL || len == 0) {
348 return 0;
349 }
350
351 while (len--) {
352 cksum = (UINT8) (cksum +*bptr++);
353 }
354
355 return cksum;
356 }
357
358 EFI_STATUS
359 EFIAPI
360 SimpleNetworkDriverSupported (
361 IN EFI_DRIVER_BINDING_PROTOCOL *This,
362 IN EFI_HANDLE Controller,
363 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
364 )
365 /*++
366
367 Routine Description:
368 Test to see if this driver supports Controller. Any Controller
369 that contains a Nii protocol can be supported.
370
371 Arguments:
372 This - Protocol instance pointer.
373 Controller - Handle of device to test.
374 RemainingDevicePath - Not used.
375
376 Returns:
377 EFI_SUCCESS - This driver supports this device.
378 EFI_ALREADY_STARTED - This driver is already running on this device.
379 other - This driver does not support this device.
380
381 --*/
382 {
383 EFI_STATUS Status;
384 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;
385 PXE_UNDI *pxe;
386 BOOLEAN IsUndi31;
387
388 IsUndi31 = FALSE;
389 Status = gBS->OpenProtocol (
390 Controller,
391 &gEfiDevicePathProtocolGuid,
392 NULL,
393 This->DriverBindingHandle,
394 Controller,
395 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
396 );
397 if (EFI_ERROR (Status)) {
398 return Status;
399 }
400
401 Status = gBS->OpenProtocol (
402 Controller,
403 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
404 (VOID **) &NiiProtocol,
405 This->DriverBindingHandle,
406 Controller,
407 EFI_OPEN_PROTOCOL_BY_DRIVER
408 );
409 if (Status == EFI_ALREADY_STARTED)
410 {
411 #if SNP_DEBUG
412 Aprint ("Support(): Already Started. on handle %x\n", Controller);
413 #endif
414 return EFI_ALREADY_STARTED;
415 }
416
417 if (!EFI_ERROR (Status))
418 {
419
420 #if SNP_DEBUG
421 Aprint ("Support(): UNDI3.1 found on handle %x\n", Controller);
422 snp_wait_for_key ();
423 #endif
424 IsUndi31 = TRUE;
425 } else {
426 //
427 // try the older 3.0 driver
428 //
429 Status = gBS->OpenProtocol (
430 Controller,
431 &gEfiNetworkInterfaceIdentifierProtocolGuid,
432 (VOID **) &NiiProtocol,
433 This->DriverBindingHandle,
434 Controller,
435 EFI_OPEN_PROTOCOL_BY_DRIVER
436 );
437 if (EFI_ERROR (Status)) {
438 return Status;
439 }
440
441 #if SNP_DEBUG
442 Aprint ("Support(): UNDI3.0 found on handle %x\n", Controller);
443 snp_wait_for_key ();
444 #endif
445 }
446 //
447 // check the version, we don't want to connect to the undi16
448 //
449 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {
450 Status = EFI_UNSUPPORTED;
451 goto Done;
452 }
453 //
454 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
455 //
456 if (NiiProtocol->ID & 0x0F) {
457 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));
458 Status = EFI_UNSUPPORTED;
459 goto Done;
460 }
461
462 pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);
463
464 //
465 // Verify !PXE revisions.
466 //
467 if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) {
468 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));
469 Status = EFI_UNSUPPORTED;
470 goto Done;
471 }
472
473 if (pxe->hw.Rev < PXE_ROMID_REV) {
474 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));
475 Status = EFI_UNSUPPORTED;
476 goto Done;
477 }
478
479 if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {
480
481 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));
482 Status = EFI_UNSUPPORTED;
483 goto Done;
484
485 } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) {
486 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));
487 Status = EFI_UNSUPPORTED;
488 goto Done;
489 }
490 //
491 // Do S/W UNDI specific checks.
492 //
493 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {
494 if (pxe->sw.EntryPoint < pxe->sw.Len) {
495 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));
496 Status = EFI_UNSUPPORTED;
497 goto Done;
498 }
499
500 if (pxe->sw.BusCnt == 0) {
501 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));
502 Status = EFI_UNSUPPORTED;
503 goto Done;
504 }
505 }
506
507 Status = EFI_SUCCESS;
508 #if SNP_DEBUG
509 Aprint ("Support(): supported on %x\n", Controller);
510 snp_wait_for_key ();
511 #endif
512
513 Done:
514 if (IsUndi31) {
515 gBS->CloseProtocol (
516 Controller,
517 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
518 This->DriverBindingHandle,
519 Controller
520 );
521
522 } else {
523 gBS->CloseProtocol (
524 Controller,
525 &gEfiNetworkInterfaceIdentifierProtocolGuid,
526 This->DriverBindingHandle,
527 Controller
528 );
529 }
530
531 return Status;
532 }
533
534 EFI_STATUS
535 EFIAPI
536 SimpleNetworkDriverStart (
537 IN EFI_DRIVER_BINDING_PROTOCOL *This,
538 IN EFI_HANDLE Controller,
539 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
540 )
541 /*++
542
543 Routine Description:
544 called for any handle that we said "supported" in the above call!
545
546 Arguments:
547 This - Protocol instance pointer.
548 Controller - Handle of device to start
549 RemainingDevicePath - Not used.
550
551 Returns:
552 EFI_SUCCESS - This driver supports this device.
553 other - This driver failed to start this device.
554
555 --*/
556 {
557 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
558 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;
559 EFI_STATUS Status;
560 PXE_UNDI *pxe;
561 SNP_DRIVER *snp;
562 VOID *addr;
563 VOID *addrUnmap;
564 EFI_PHYSICAL_ADDRESS paddr;
565 EFI_HANDLE Handle;
566 UINTN Size;
567 BOOLEAN UndiNew;
568 PXE_PCI_CONFIG_INFO ConfigInfo;
569 PCI_TYPE00 *ConfigHeader;
570 UINT32 *TempBar;
571 UINT8 BarIndex;
572 PXE_STATFLAGS InitStatFlags;
573
574 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));
575
576 Status = gBS->OpenProtocol (
577 Controller,
578 &gEfiDevicePathProtocolGuid,
579 (VOID **) &NiiDevicePath,
580 This->DriverBindingHandle,
581 Controller,
582 EFI_OPEN_PROTOCOL_BY_DRIVER
583 );
584
585 if (EFI_ERROR (Status)) {
586 return Status;
587 }
588
589 Status = gBS->LocateDevicePath (
590 &gEfiPciIoProtocolGuid,
591 &NiiDevicePath,
592 &Handle
593 );
594
595 if (EFI_ERROR (Status)) {
596 return Status;
597 }
598
599 Status = gBS->OpenProtocol (
600 Handle,
601 &gEfiPciIoProtocolGuid,
602 (VOID **) &mPciIoFncs,
603 This->DriverBindingHandle,
604 Controller,
605 EFI_OPEN_PROTOCOL_GET_PROTOCOL
606 );
607 if (EFI_ERROR (Status)) {
608 return Status;
609 }
610 //
611 // Get the NII interface. look for 3.1 undi first, if it is not there
612 // then look for 3.0, validate the interface.
613 //
614 Status = gBS->OpenProtocol (
615 Controller,
616 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
617 (VOID **) &Nii,
618 This->DriverBindingHandle,
619 Controller,
620 EFI_OPEN_PROTOCOL_BY_DRIVER
621 );
622 if (Status == EFI_ALREADY_STARTED) {
623 gBS->CloseProtocol (
624 Controller,
625 &gEfiDevicePathProtocolGuid,
626 This->DriverBindingHandle,
627 Controller
628 );
629 return Status;
630 }
631
632 if (!EFI_ERROR (Status)) {
633 //
634 // probably not a 3.1 UNDI
635 //
636 UndiNew = TRUE;
637 #if SNP_DEBUG
638 Aprint ("Start(): UNDI3.1 found\n");
639 snp_wait_for_key ();
640 #endif
641 } else {
642 UndiNew = FALSE;
643 Status = gBS->OpenProtocol (
644 Controller,
645 &gEfiNetworkInterfaceIdentifierProtocolGuid,
646 (VOID **) &Nii,
647 This->DriverBindingHandle,
648 Controller,
649 EFI_OPEN_PROTOCOL_BY_DRIVER
650 );
651 if (EFI_ERROR (Status)) {
652 gBS->CloseProtocol (
653 Controller,
654 &gEfiDevicePathProtocolGuid,
655 This->DriverBindingHandle,
656 Controller
657 );
658
659 return Status;
660 }
661
662 #if SNP_DEBUG
663 Aprint ("Start(): UNDI3.0 found\n");
664 snp_wait_for_key ();
665 #endif
666 }
667
668 pxe = (PXE_UNDI *) (UINTN) (Nii->ID);
669
670 if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) {
671 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));
672 goto NiiError;
673 }
674
675 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
676 //
677 // We can get any packets.
678 //
679 } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
680 //
681 // We need to be able to get broadcast packets for DHCP.
682 // If we do not have promiscuous support, we must at least have
683 // broadcast support or we cannot do DHCP!
684 //
685 } else {
686 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));
687 goto NiiError;
688 }
689 //
690 // OK, we like this UNDI, and we know snp is not already there on this handle
691 // Allocate and initialize a new simple network protocol structure.
692 //
693 Status = mPciIoFncs->AllocateBuffer (
694 mPciIoFncs,
695 AllocateAnyPages,
696 EfiBootServicesData,
697 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
698 &addr,
699 0
700 );
701
702 if (Status != EFI_SUCCESS) {
703 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));
704 goto NiiError;
705 }
706
707 snp = (SNP_DRIVER *) (UINTN) addr;
708
709 if (!UndiNew) {
710 Size = SNP_MEM_PAGES (sizeof (SNP_DRIVER));
711
712 Status = mPciIoFncs->Map (
713 mPciIoFncs,
714 EfiPciIoOperationBusMasterCommonBuffer,
715 addr,
716 &Size,
717 &paddr,
718 &addrUnmap
719 );
720
721 ASSERT (paddr);
722
723 DEBUG ((EFI_D_NET, "\nSNP_DRIVER @ %Xh, sizeof(SNP_DRIVER) == %d", addr, sizeof (SNP_DRIVER)));
724 snp = (SNP_DRIVER *) (UINTN) paddr;
725 snp->SnpDriverUnmap = addrUnmap;
726 }
727
728 ZeroMem (snp, sizeof (SNP_DRIVER));
729
730 snp->IoFncs = mPciIoFncs;
731 snp->IsOldUndi = (BOOLEAN) (!UndiNew);
732
733 snp->Signature = SNP_DRIVER_SIGNATURE;
734
735 EfiInitializeLock (&snp->lock, EFI_TPL_NOTIFY);
736
737 snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
738 snp->snp.Start = snp_undi32_start;
739 snp->snp.Stop = snp_undi32_stop;
740 snp->snp.Initialize = snp_undi32_initialize;
741 snp->snp.Reset = snp_undi32_reset;
742 snp->snp.Shutdown = snp_undi32_shutdown;
743 snp->snp.ReceiveFilters = snp_undi32_receive_filters;
744 snp->snp.StationAddress = snp_undi32_station_address;
745 snp->snp.Statistics = snp_undi32_statistics;
746 snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac;
747 snp->snp.NvData = snp_undi32_nvdata;
748 snp->snp.GetStatus = snp_undi32_get_status;
749 snp->snp.Transmit = snp_undi32_transmit;
750 snp->snp.Receive = snp_undi32_receive;
751 snp->snp.WaitForPacket = NULL;
752
753 snp->snp.Mode = &snp->mode;
754
755 snp->tx_rx_bufsize = 0;
756 snp->tx_rx_buffer = NULL;
757
758 snp->if_num = Nii->IfNum;
759
760 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
761 snp->is_swundi = FALSE;
762 snp->issue_undi32_command = &issue_hwundi_command;
763 } else {
764 snp->is_swundi = TRUE;
765
766 if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {
767 snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint;
768 } else {
769 snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint);
770 }
771 }
772 //
773 // Allocate a global CPB and DB buffer for this UNDI interface.
774 // we do this because:
775 //
776 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
777 // within 2GB limit, create them here and map them so that when undi calls
778 // v2p callback to check if the physical address is < 2gb, we will pass.
779 //
780 // -This is not a requirement for 3.1 or later UNDIs but the code looks
781 // simpler if we use the same cpb, db variables for both old and new undi
782 // interfaces from all the SNP interface calls (we don't map the buffers
783 // for the newer undi interfaces though)
784 // .
785 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
786 // interface as EFI does not multi-task and so SNP will not be re-entered!
787 //
788 Status = mPciIoFncs->AllocateBuffer (
789 mPciIoFncs,
790 AllocateAnyPages,
791 EfiBootServicesData,
792 SNP_MEM_PAGES (4096),
793 &addr,
794 0
795 );
796
797 if (Status != EFI_SUCCESS) {
798 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));
799 goto Error_DeleteSNP;
800 }
801
802 if (snp->IsOldUndi) {
803 Size = SNP_MEM_PAGES (4096);
804
805 Status = mPciIoFncs->Map (
806 mPciIoFncs,
807 EfiPciIoOperationBusMasterCommonBuffer,
808 addr,
809 &Size,
810 &paddr,
811 &snp->CpbUnmap
812 );
813
814 ASSERT (paddr);
815
816 snp->cpb = (VOID *) (UINTN) paddr;
817 snp->db = (VOID *) ((UINTN) paddr + 2048);
818 } else {
819 snp->cpb = (VOID *) (UINTN) addr;
820 snp->db = (VOID *) ((UINTN) addr + 2048);
821 }
822 //
823 // pxe_start call is going to give the callback functions to UNDI, these callback
824 // functions use the BarIndex values from the snp structure, so these must be initialized
825 // with default values before doing a pxe_start. The correct values can be obtained after
826 // getting the config information from UNDI
827 //
828 snp->MemoryBarIndex = 0;
829 snp->IoBarIndex = 1;
830
831 //
832 // we need the undi init information many times in this snp code, just get it
833 // once here and store it in the snp driver structure. to get Init Info
834 // from UNDI we have to start undi first.
835 //
836 Status = pxe_start (snp);
837
838 if (Status != EFI_SUCCESS) {
839 goto Error_DeleteCPBDB;
840 }
841
842 snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;
843 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
844
845 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
846 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
847
848 snp->cdb.DBsize = sizeof snp->init_info;
849 snp->cdb.DBaddr = (UINT64) (UINTN) &snp->init_info;
850
851 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
852 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
853
854 snp->cdb.IFnum = snp->if_num;
855 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
856
857 DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() "));
858
859 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
860
861 //
862 // Save the INIT Stat Code...
863 //
864 InitStatFlags = snp->cdb.StatFlags;
865
866 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
867 DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
868 pxe_stop (snp);
869 goto Error_DeleteCPBDB;
870 }
871
872 snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;
873 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
874
875 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
876 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
877
878 snp->cdb.DBsize = sizeof ConfigInfo;
879 snp->cdb.DBaddr = (UINT64) (UINTN) &ConfigInfo;
880
881 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
882 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
883
884 snp->cdb.IFnum = snp->if_num;
885 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
886
887 DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() "));
888
889 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
890
891 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
892 DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
893 pxe_stop (snp);
894 goto Error_DeleteCPBDB;
895 }
896 //
897 // Find the correct BAR to do IO.
898 //
899 //
900 // Enumerate through the PCI BARs for the device to determine which one is
901 // the IO BAR. Save the index of the BAR into the adapter info structure.
902 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
903 //
904 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];
905 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];
906 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {
907 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {
908 //
909 // This is a 64-bit memory bar, skip this and the
910 // next bar as well.
911 //
912 TempBar++;
913 }
914
915 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {
916 snp->IoBarIndex = BarIndex;
917 break;
918 }
919
920 TempBar++;
921 }
922
923 //
924 // We allocate 2 more global buffers for undi 3.0 interface. We use these
925 // buffers to pass to undi when the user buffers are beyond 4GB.
926 // UNDI 3.0 wants all the addresses passed to it to be
927 // within 2GB limit, create them here and map them so that when undi calls
928 // v2p callback to check if the physical address is < 2gb, we will pass.
929 //
930 // For 3.1 and later UNDIs, we do not do this because undi is
931 // going to call the map() callback if and only if it wants to use the
932 // device address for any address it receives.
933 //
934 if (snp->IsOldUndi) {
935 //
936 // buffer for receive
937 //
938 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
939 Status = mPciIoFncs->AllocateBuffer (
940 mPciIoFncs,
941 AllocateAnyPages,
942 EfiBootServicesData,
943 Size,
944 &addr,
945 0
946 );
947
948 if (Status != EFI_SUCCESS) {
949 DEBUG ((EFI_D_ERROR, "\nCould not allocate receive buffer.\n"));
950 goto Error_DeleteCPBDB;
951 }
952
953 Status = mPciIoFncs->Map (
954 mPciIoFncs,
955 EfiPciIoOperationBusMasterCommonBuffer,
956 addr,
957 &Size,
958 &paddr,
959 &snp->ReceiveBufUnmap
960 );
961
962 ASSERT (paddr);
963
964 snp->receive_buf = (UINT8 *) (UINTN) paddr;
965
966 //
967 // buffer for fill_header
968 //
969 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen);
970 Status = mPciIoFncs->AllocateBuffer (
971 mPciIoFncs,
972 AllocateAnyPages,
973 EfiBootServicesData,
974 Size,
975 &addr,
976 0
977 );
978
979 if (Status != EFI_SUCCESS) {
980 DEBUG ((EFI_D_ERROR, "\nCould not allocate fill_header buffer.\n"));
981 goto Error_DeleteRCVBuf;
982 }
983
984 Status = mPciIoFncs->Map (
985 mPciIoFncs,
986 EfiPciIoOperationBusMasterCommonBuffer,
987 addr,
988 &Size,
989 &paddr,
990 &snp->FillHdrBufUnmap
991 );
992
993 ASSERT (paddr);
994 snp->fill_hdr_buf = (UINT8 *) (UINTN) paddr;
995 }
996 //
997 // Initialize simple network protocol mode structure
998 //
999 snp->mode.State = EfiSimpleNetworkStopped;
1000 snp->mode.HwAddressSize = snp->init_info.HWaddrLen;
1001 snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen;
1002 snp->mode.MaxPacketSize = snp->init_info.FrameDataLen;
1003 snp->mode.NvRamAccessSize = snp->init_info.NvWidth;
1004 snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize;
1005 snp->mode.IfType = snp->init_info.IFtype;
1006 snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt;
1007 snp->mode.MCastFilterCount = 0;
1008
1009 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {
1010 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:
1011 snp->mode.MediaPresentSupported = TRUE;
1012 break;
1013
1014 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:
1015 default:
1016 snp->mode.MediaPresentSupported = FALSE;
1017 }
1018
1019 if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {
1020 snp->mode.MacAddressChangeable = TRUE;
1021 } else {
1022 snp->mode.MacAddressChangeable = FALSE;
1023 }
1024
1025 if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {
1026 snp->mode.MultipleTxSupported = TRUE;
1027 } else {
1028 snp->mode.MultipleTxSupported = FALSE;
1029 }
1030
1031 snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1032
1033 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
1034 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1035
1036 }
1037
1038 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
1039 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1040
1041 }
1042
1043 if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
1044 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1045
1046 }
1047
1048 if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {
1049 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1050
1051 }
1052
1053 if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {
1054 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1055
1056 }
1057
1058 snp->mode.ReceiveFilterSetting = 0;
1059
1060 //
1061 // need to get the station address to save in the mode structure. we need to
1062 // initialize the UNDI first for this.
1063 //
1064 snp->tx_rx_bufsize = snp->init_info.MemoryRequired;
1065 Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
1066
1067 if (Status) {
1068 pxe_stop (snp);
1069 goto Error_DeleteHdrBuf;
1070 }
1071
1072 Status = pxe_get_stn_addr (snp);
1073
1074 if (Status != EFI_SUCCESS) {
1075 DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n"));
1076 pxe_shutdown (snp);
1077 pxe_stop (snp);
1078 goto Error_DeleteHdrBuf;
1079 }
1080
1081 snp->mode.MediaPresent = FALSE;
1082
1083 //
1084 // We should not leave UNDI started and initialized here. this DriverStart()
1085 // routine must only find and attach the SNP interface to UNDI layer that it
1086 // finds on the given handle!
1087 // The UNDI layer will be started when upper layers call snp->start.
1088 // How ever, this DriverStart() must fill up the snp mode structure which
1089 // contains the MAC address of the NIC. For this reason we started and
1090 // initialized UNDI here, now we are done, do a shutdown and stop of the
1091 // UNDI interface!
1092 //
1093 pxe_shutdown (snp);
1094 pxe_stop (snp);
1095
1096 //
1097 // add SNP to the undi handle
1098 //
1099 Status = gBS->InstallProtocolInterface (
1100 &Controller,
1101 &gEfiSimpleNetworkProtocolGuid,
1102 EFI_NATIVE_INTERFACE,
1103 &(snp->snp)
1104 );
1105
1106 if (!EFI_ERROR (Status)) {
1107 return Status;
1108 }
1109
1110 Error_DeleteHdrBuf:
1111 if (snp->IsOldUndi) {
1112 Status = mPciIoFncs->Unmap (
1113 mPciIoFncs,
1114 snp->FillHdrBufUnmap
1115 );
1116 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen);
1117 mPciIoFncs->FreeBuffer (
1118 mPciIoFncs,
1119 Size,
1120 snp->fill_hdr_buf
1121 );
1122 }
1123
1124 Error_DeleteRCVBuf:
1125 if (snp->IsOldUndi) {
1126 Status = mPciIoFncs->Unmap (
1127 mPciIoFncs,
1128 snp->ReceiveBufUnmap
1129 );
1130 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
1131 mPciIoFncs->FreeBuffer (
1132 mPciIoFncs,
1133 Size,
1134 snp->receive_buf
1135 );
1136
1137 }
1138
1139 Error_DeleteCPBDB:
1140 if (snp->IsOldUndi) {
1141 Status = mPciIoFncs->Unmap (
1142 mPciIoFncs,
1143 snp->CpbUnmap
1144 );
1145 }
1146
1147 Status = mPciIoFncs->FreeBuffer (
1148 mPciIoFncs,
1149 SNP_MEM_PAGES (4096),
1150 snp->cpb
1151 );
1152
1153 Error_DeleteSNP:
1154 if (snp->IsOldUndi) {
1155 Status = mPciIoFncs->Unmap (
1156 mPciIoFncs,
1157 snp->SnpDriverUnmap
1158 );
1159 }
1160
1161 mPciIoFncs->FreeBuffer (
1162 mPciIoFncs,
1163 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
1164 snp
1165 );
1166 NiiError:
1167 if (!UndiNew) {
1168 gBS->CloseProtocol (
1169 Controller,
1170 &gEfiNetworkInterfaceIdentifierProtocolGuid,
1171 This->DriverBindingHandle,
1172 Controller
1173 );
1174 } else {
1175 gBS->CloseProtocol (
1176 Controller,
1177 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
1178 This->DriverBindingHandle,
1179 Controller
1180 );
1181 }
1182
1183 gBS->CloseProtocol (
1184 Controller,
1185 &gEfiDevicePathProtocolGuid,
1186 This->DriverBindingHandle,
1187 Controller
1188 );
1189
1190 return Status;
1191 }
1192
1193 EFI_STATUS
1194 EFIAPI
1195 SimpleNetworkDriverStop (
1196 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1197 IN EFI_HANDLE Controller,
1198 IN UINTN NumberOfChildren,
1199 IN EFI_HANDLE *ChildHandleBuffer
1200 )
1201 /*++
1202
1203 Routine Description:
1204
1205 Arguments:
1206
1207 Returns:
1208
1209 --*/
1210 {
1211 EFI_STATUS Status;
1212 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
1213 SNP_DRIVER *Snp;
1214
1215 //
1216 // Get our context back.
1217 //
1218 Status = gBS->OpenProtocol (
1219 Controller,
1220 &gEfiSimpleNetworkProtocolGuid,
1221 (VOID **) &SnpProtocol,
1222 This->DriverBindingHandle,
1223 Controller,
1224 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1225 );
1226
1227 if (EFI_ERROR (Status)) {
1228 return EFI_UNSUPPORTED;
1229 }
1230
1231 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);
1232
1233 Status = gBS->UninstallProtocolInterface (
1234 Controller,
1235 &gEfiSimpleNetworkProtocolGuid,
1236 &Snp->snp
1237 );
1238
1239 if (EFI_ERROR (Status)) {
1240 return Status;
1241 }
1242
1243 if (!Snp->IsOldUndi) {
1244 Status = gBS->CloseProtocol (
1245 Controller,
1246 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
1247 This->DriverBindingHandle,
1248 Controller
1249 );
1250 } else {
1251 Status = gBS->CloseProtocol (
1252 Controller,
1253 &gEfiNetworkInterfaceIdentifierProtocolGuid,
1254 This->DriverBindingHandle,
1255 Controller
1256 );
1257 }
1258
1259 Status = gBS->CloseProtocol (
1260 Controller,
1261 &gEfiDevicePathProtocolGuid,
1262 This->DriverBindingHandle,
1263 Controller
1264 );
1265
1266 pxe_shutdown (Snp);
1267 pxe_stop (Snp);
1268
1269 if (Snp->IsOldUndi) {
1270 Status = mPciIoFncs->Unmap (
1271 mPciIoFncs,
1272 Snp->FillHdrBufUnmap
1273 );
1274
1275 mPciIoFncs->FreeBuffer (
1276 mPciIoFncs,
1277 SNP_MEM_PAGES (Snp->init_info.MediaHeaderLen),
1278 Snp->fill_hdr_buf
1279 );
1280 Status = mPciIoFncs->Unmap (
1281 mPciIoFncs,
1282 Snp->ReceiveBufUnmap
1283 );
1284
1285 mPciIoFncs->FreeBuffer (
1286 mPciIoFncs,
1287 SNP_MEM_PAGES (Snp->init_info.MediaHeaderLen + Snp->init_info.FrameDataLen),
1288 Snp->receive_buf
1289 );
1290
1291 Status = mPciIoFncs->Unmap (
1292 mPciIoFncs,
1293 Snp->CpbUnmap
1294 );
1295 Status = mPciIoFncs->Unmap (
1296 mPciIoFncs,
1297 Snp->SnpDriverUnmap
1298 );
1299 }
1300
1301 mPciIoFncs->FreeBuffer (
1302 mPciIoFncs,
1303 SNP_MEM_PAGES (4096),
1304 Snp->cpb
1305 );
1306
1307 mPciIoFncs->FreeBuffer (
1308 mPciIoFncs,
1309 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
1310 Snp
1311 );
1312
1313 return Status;
1314 }
1315