]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/SnpDxe/snp.c
Remove gEfiNetworkInterfaceIdentifierProtocolGuid reference from code base. Only...
[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
333 Status = gBS->OpenProtocol (
334 Controller,
335 &gEfiDevicePathProtocolGuid,
336 NULL,
337 This->DriverBindingHandle,
338 Controller,
339 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
340 );
341 if (EFI_ERROR (Status)) {
342 return Status;
343 }
344
345 Status = gBS->OpenProtocol (
346 Controller,
347 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
348 (VOID **) &NiiProtocol,
349 This->DriverBindingHandle,
350 Controller,
351 EFI_OPEN_PROTOCOL_BY_DRIVER
352 );
353
354 if (EFI_ERROR (Status)) {
355 if (Status == EFI_ALREADY_STARTED) {
356 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %x\n", Controller));
357 }
358 return Status;
359 }
360
361 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %x\n", Controller));
362
363 //
364 // check the version, we don't want to connect to the undi16
365 //
366 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {
367 Status = EFI_UNSUPPORTED;
368 goto Done;
369 }
370 //
371 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
372 //
373 if (NiiProtocol->ID & 0x0F) {
374 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));
375 Status = EFI_UNSUPPORTED;
376 goto Done;
377 }
378
379 pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);
380
381 //
382 // Verify !PXE revisions.
383 //
384 if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) {
385 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));
386 Status = EFI_UNSUPPORTED;
387 goto Done;
388 }
389
390 if (pxe->hw.Rev < PXE_ROMID_REV) {
391 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));
392 Status = EFI_UNSUPPORTED;
393 goto Done;
394 }
395
396 if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {
397
398 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));
399 Status = EFI_UNSUPPORTED;
400 goto Done;
401
402 } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) {
403 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));
404 Status = EFI_UNSUPPORTED;
405 goto Done;
406 }
407 //
408 // Do S/W UNDI specific checks.
409 //
410 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {
411 if (pxe->sw.EntryPoint < pxe->sw.Len) {
412 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));
413 Status = EFI_UNSUPPORTED;
414 goto Done;
415 }
416
417 if (pxe->sw.BusCnt == 0) {
418 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));
419 Status = EFI_UNSUPPORTED;
420 goto Done;
421 }
422 }
423
424 Status = EFI_SUCCESS;
425 DEBUG ((EFI_D_INFO, "Support(): supported on %x\n", Controller));
426
427 Done:
428 gBS->CloseProtocol (
429 Controller,
430 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
431 This->DriverBindingHandle,
432 Controller
433 );
434
435 return Status;
436 }
437
438
439 /**
440 called for any handle that we said "supported" in the above call!
441
442 @param This Protocol instance pointer.
443 @param Controller Handle of device to start
444 @param RemainingDevicePath Not used.
445
446 @retval EFI_SUCCESS This driver supports this device.
447 @retval other This driver failed to start this device.
448
449 **/
450 EFI_STATUS
451 EFIAPI
452 SimpleNetworkDriverStart (
453 IN EFI_DRIVER_BINDING_PROTOCOL *This,
454 IN EFI_HANDLE Controller,
455 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
456 )
457 {
458 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
459 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;
460 EFI_STATUS Status;
461 PXE_UNDI *pxe;
462 SNP_DRIVER *snp;
463 VOID *addr;
464 EFI_HANDLE Handle;
465 PXE_PCI_CONFIG_INFO ConfigInfo;
466 PCI_TYPE00 *ConfigHeader;
467 UINT32 *TempBar;
468 UINT8 BarIndex;
469 PXE_STATFLAGS InitStatFlags;
470
471 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));
472
473 Status = gBS->OpenProtocol (
474 Controller,
475 &gEfiDevicePathProtocolGuid,
476 (VOID **) &NiiDevicePath,
477 This->DriverBindingHandle,
478 Controller,
479 EFI_OPEN_PROTOCOL_BY_DRIVER
480 );
481
482 if (EFI_ERROR (Status)) {
483 return Status;
484 }
485
486 Status = gBS->LocateDevicePath (
487 &gEfiPciIoProtocolGuid,
488 &NiiDevicePath,
489 &Handle
490 );
491
492 if (EFI_ERROR (Status)) {
493 return Status;
494 }
495
496 Status = gBS->OpenProtocol (
497 Handle,
498 &gEfiPciIoProtocolGuid,
499 (VOID **) &mPciIoFncs,
500 This->DriverBindingHandle,
501 Controller,
502 EFI_OPEN_PROTOCOL_GET_PROTOCOL
503 );
504 if (EFI_ERROR (Status)) {
505 return Status;
506 }
507 //
508 // Get the NII interface.
509 //
510 Status = gBS->OpenProtocol (
511 Controller,
512 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
513 (VOID **) &Nii,
514 This->DriverBindingHandle,
515 Controller,
516 EFI_OPEN_PROTOCOL_BY_DRIVER
517 );
518 if (EFI_ERROR (Status)) {
519 gBS->CloseProtocol (
520 Controller,
521 &gEfiDevicePathProtocolGuid,
522 This->DriverBindingHandle,
523 Controller
524 );
525 return Status;
526 }
527
528 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));
529
530 pxe = (PXE_UNDI *) (UINTN) (Nii->ID);
531
532 if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) {
533 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));
534 goto NiiError;
535 }
536
537 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
538 //
539 // We can get any packets.
540 //
541 } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
542 //
543 // We need to be able to get broadcast packets for DHCP.
544 // If we do not have promiscuous support, we must at least have
545 // broadcast support or we cannot do DHCP!
546 //
547 } else {
548 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));
549 goto NiiError;
550 }
551 //
552 // OK, we like this UNDI, and we know snp is not already there on this handle
553 // Allocate and initialize a new simple network protocol structure.
554 //
555 Status = mPciIoFncs->AllocateBuffer (
556 mPciIoFncs,
557 AllocateAnyPages,
558 EfiBootServicesData,
559 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
560 &addr,
561 0
562 );
563
564 if (Status != EFI_SUCCESS) {
565 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));
566 goto NiiError;
567 }
568
569 snp = (SNP_DRIVER *) (UINTN) addr;
570
571 ZeroMem (snp, sizeof (SNP_DRIVER));
572
573 snp->IoFncs = mPciIoFncs;
574 snp->Signature = SNP_DRIVER_SIGNATURE;
575
576 EfiInitializeLock (&snp->lock, TPL_NOTIFY);
577
578 snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
579 snp->snp.Start = snp_undi32_start;
580 snp->snp.Stop = snp_undi32_stop;
581 snp->snp.Initialize = snp_undi32_initialize;
582 snp->snp.Reset = snp_undi32_reset;
583 snp->snp.Shutdown = snp_undi32_shutdown;
584 snp->snp.ReceiveFilters = snp_undi32_receive_filters;
585 snp->snp.StationAddress = snp_undi32_station_address;
586 snp->snp.Statistics = snp_undi32_statistics;
587 snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac;
588 snp->snp.NvData = snp_undi32_nvdata;
589 snp->snp.GetStatus = snp_undi32_get_status;
590 snp->snp.Transmit = snp_undi32_transmit;
591 snp->snp.Receive = snp_undi32_receive;
592 snp->snp.WaitForPacket = NULL;
593
594 snp->snp.Mode = &snp->mode;
595
596 snp->tx_rx_bufsize = 0;
597 snp->tx_rx_buffer = NULL;
598
599 snp->if_num = Nii->IfNum;
600
601 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
602 snp->is_swundi = FALSE;
603 snp->issue_undi32_command = &issue_hwundi_command;
604 } else {
605 snp->is_swundi = TRUE;
606
607 if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {
608 snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint;
609 } else {
610 snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint);
611 }
612 }
613 //
614 // Allocate a global CPB and DB buffer for this UNDI interface.
615 // we do this because:
616 //
617 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
618 // within 2GB limit, create them here and map them so that when undi calls
619 // v2p callback to check if the physical address is < 2gb, we will pass.
620 //
621 // -This is not a requirement for 3.1 or later UNDIs but the code looks
622 // simpler if we use the same cpb, db variables for both old and new undi
623 // interfaces from all the SNP interface calls (we don't map the buffers
624 // for the newer undi interfaces though)
625 // .
626 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
627 // interface as EFI does not multi-task and so SNP will not be re-entered!
628 //
629 Status = mPciIoFncs->AllocateBuffer (
630 mPciIoFncs,
631 AllocateAnyPages,
632 EfiBootServicesData,
633 SNP_MEM_PAGES (4096),
634 &addr,
635 0
636 );
637
638 if (Status != EFI_SUCCESS) {
639 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));
640 goto Error_DeleteSNP;
641 }
642
643 snp->cpb = (VOID *) (UINTN) addr;
644 snp->db = (VOID *) ((UINTN) addr + 2048);
645
646 //
647 // pxe_start call is going to give the callback functions to UNDI, these callback
648 // functions use the BarIndex values from the snp structure, so these must be initialized
649 // with default values before doing a pxe_start. The correct values can be obtained after
650 // getting the config information from UNDI
651 //
652 snp->MemoryBarIndex = 0;
653 snp->IoBarIndex = 1;
654
655 //
656 // we need the undi init information many times in this snp code, just get it
657 // once here and store it in the snp driver structure. to get Init Info
658 // from UNDI we have to start undi first.
659 //
660 Status = pxe_start (snp);
661
662 if (Status != EFI_SUCCESS) {
663 goto Error_DeleteSNP;
664 }
665
666 snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;
667 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
668
669 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
670 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
671
672 snp->cdb.DBsize = sizeof snp->init_info;
673 snp->cdb.DBaddr = (UINT64)(UINTN) &snp->init_info;
674
675 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
676 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
677
678 snp->cdb.IFnum = snp->if_num;
679 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
680
681 DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() "));
682
683 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
684
685 //
686 // Save the INIT Stat Code...
687 //
688 InitStatFlags = snp->cdb.StatFlags;
689
690 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
691 DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
692 pxe_stop (snp);
693 goto Error_DeleteSNP;
694 }
695
696 snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;
697 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
698
699 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
700 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
701
702 snp->cdb.DBsize = sizeof ConfigInfo;
703 snp->cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;
704
705 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
706 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
707
708 snp->cdb.IFnum = snp->if_num;
709 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
710
711 DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() "));
712
713 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
714
715 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
716 DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
717 pxe_stop (snp);
718 goto Error_DeleteSNP;
719 }
720 //
721 // Find the correct BAR to do IO.
722 //
723 //
724 // Enumerate through the PCI BARs for the device to determine which one is
725 // the IO BAR. Save the index of the BAR into the adapter info structure.
726 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
727 //
728 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];
729 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];
730 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {
731 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {
732 //
733 // This is a 64-bit memory bar, skip this and the
734 // next bar as well.
735 //
736 TempBar++;
737 }
738
739 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {
740 snp->IoBarIndex = BarIndex;
741 break;
742 }
743
744 TempBar++;
745 }
746
747 //
748 // Initialize simple network protocol mode structure
749 //
750 snp->mode.State = EfiSimpleNetworkStopped;
751 snp->mode.HwAddressSize = snp->init_info.HWaddrLen;
752 snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen;
753 snp->mode.MaxPacketSize = snp->init_info.FrameDataLen;
754 snp->mode.NvRamAccessSize = snp->init_info.NvWidth;
755 snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize;
756 snp->mode.IfType = snp->init_info.IFtype;
757 snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt;
758 snp->mode.MCastFilterCount = 0;
759
760 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {
761 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:
762 snp->mode.MediaPresentSupported = TRUE;
763 break;
764
765 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:
766 default:
767 snp->mode.MediaPresentSupported = FALSE;
768 }
769
770 if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {
771 snp->mode.MacAddressChangeable = TRUE;
772 } else {
773 snp->mode.MacAddressChangeable = FALSE;
774 }
775
776 if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {
777 snp->mode.MultipleTxSupported = TRUE;
778 } else {
779 snp->mode.MultipleTxSupported = FALSE;
780 }
781
782 snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
783
784 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
785 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
786
787 }
788
789 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
790 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
791
792 }
793
794 if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
795 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
796
797 }
798
799 if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {
800 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
801
802 }
803
804 if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {
805 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
806
807 }
808
809 snp->mode.ReceiveFilterSetting = 0;
810
811 //
812 // need to get the station address to save in the mode structure. we need to
813 // initialize the UNDI first for this.
814 //
815 snp->tx_rx_bufsize = snp->init_info.MemoryRequired;
816 Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
817
818 if (Status) {
819 pxe_stop (snp);
820 goto Error_DeleteSNP;
821 }
822
823 Status = pxe_get_stn_addr (snp);
824
825 if (Status != EFI_SUCCESS) {
826 DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n"));
827 pxe_shutdown (snp);
828 pxe_stop (snp);
829 goto Error_DeleteSNP;
830 }
831
832 snp->mode.MediaPresent = FALSE;
833
834 //
835 // We should not leave UNDI started and initialized here. this DriverStart()
836 // routine must only find and attach the SNP interface to UNDI layer that it
837 // finds on the given handle!
838 // The UNDI layer will be started when upper layers call snp->start.
839 // How ever, this DriverStart() must fill up the snp mode structure which
840 // contains the MAC address of the NIC. For this reason we started and
841 // initialized UNDI here, now we are done, do a shutdown and stop of the
842 // UNDI interface!
843 //
844 pxe_shutdown (snp);
845 pxe_stop (snp);
846
847 //
848 // add SNP to the undi handle
849 //
850 Status = gBS->InstallProtocolInterface (
851 &Controller,
852 &gEfiSimpleNetworkProtocolGuid,
853 EFI_NATIVE_INTERFACE,
854 &(snp->snp)
855 );
856
857 if (!EFI_ERROR (Status)) {
858 return Status;
859 }
860
861 Status = mPciIoFncs->FreeBuffer (
862 mPciIoFncs,
863 SNP_MEM_PAGES (4096),
864 snp->cpb
865 );
866
867 Error_DeleteSNP:
868
869 mPciIoFncs->FreeBuffer (
870 mPciIoFncs,
871 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
872 snp
873 );
874 NiiError:
875 gBS->CloseProtocol (
876 Controller,
877 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
878 This->DriverBindingHandle,
879 Controller
880 );
881
882 gBS->CloseProtocol (
883 Controller,
884 &gEfiDevicePathProtocolGuid,
885 This->DriverBindingHandle,
886 Controller
887 );
888
889 return Status;
890 }
891
892
893 /**
894
895
896
897 **/
898 EFI_STATUS
899 EFIAPI
900 SimpleNetworkDriverStop (
901 IN EFI_DRIVER_BINDING_PROTOCOL *This,
902 IN EFI_HANDLE Controller,
903 IN UINTN NumberOfChildren,
904 IN EFI_HANDLE *ChildHandleBuffer
905 )
906 {
907 EFI_STATUS Status;
908 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
909 SNP_DRIVER *Snp;
910
911 //
912 // Get our context back.
913 //
914 Status = gBS->OpenProtocol (
915 Controller,
916 &gEfiSimpleNetworkProtocolGuid,
917 (VOID **) &SnpProtocol,
918 This->DriverBindingHandle,
919 Controller,
920 EFI_OPEN_PROTOCOL_GET_PROTOCOL
921 );
922
923 if (EFI_ERROR (Status)) {
924 return EFI_UNSUPPORTED;
925 }
926
927 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);
928
929 Status = gBS->UninstallProtocolInterface (
930 Controller,
931 &gEfiSimpleNetworkProtocolGuid,
932 &Snp->snp
933 );
934
935 if (EFI_ERROR (Status)) {
936 return Status;
937 }
938
939 Status = gBS->CloseProtocol (
940 Controller,
941 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
942 This->DriverBindingHandle,
943 Controller
944 );
945
946 Status = gBS->CloseProtocol (
947 Controller,
948 &gEfiDevicePathProtocolGuid,
949 This->DriverBindingHandle,
950 Controller
951 );
952
953 pxe_shutdown (Snp);
954 pxe_stop (Snp);
955
956 mPciIoFncs->FreeBuffer (
957 mPciIoFncs,
958 SNP_MEM_PAGES (4096),
959 Snp->cpb
960 );
961
962 mPciIoFncs->FreeBuffer (
963 mPciIoFncs,
964 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
965 Snp
966 );
967
968 return Status;
969 }
970
971
972 /**
973 Install all the driver protocol
974
975 @param entry EFI_IMAGE_ENTRY_POINT)
976
977 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
978 loaded it's ROM, and installed a notify event for
979 the Network Indentifier Interface Protocol
980 successfully.
981 @retval Other Return value from HandleProtocol for
982 DeviceIoProtocol or LoadedImageProtocol
983
984 **/
985 EFI_STATUS
986 EFIAPI
987 InitializeSnpNiiDriver (
988 IN EFI_HANDLE ImageHandle,
989 IN EFI_SYSTEM_TABLE *SystemTable
990 )
991 {
992 return EfiLibInstallDriverBindingComponentName2 (
993 ImageHandle,
994 SystemTable,
995 &mSimpleNetworkDriverBinding,
996 NULL,
997 &gSimpleNetworkComponentName,
998 &gSimpleNetworkComponentName2
999 );
1000 }