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