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