1 /** @file
2     Implementation of starting a network adapter.
3 
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "Snp.h"
10 
11 
12 /**
13   Call UNDI to start the interface and changes the snp state.
14 
15   @param  Snp                    pointer to snp driver structure.
16 
17   @retval EFI_SUCCESS            UNDI is started successfully.
18   @retval EFI_DEVICE_ERROR       UNDI could not be started.
19 
20 **/
21 EFI_STATUS
PxeStart(IN SNP_DRIVER * Snp)22 PxeStart (
23   IN SNP_DRIVER *Snp
24   )
25 {
26   PXE_CPB_START_31  *Cpb31;
27 
28   Cpb31  = Snp->Cpb;
29   //
30   // Initialize UNDI Start CDB for H/W UNDI
31   //
32   Snp->Cdb.OpCode     = PXE_OPCODE_START;
33   Snp->Cdb.OpFlags    = PXE_OPFLAGS_NOT_USED;
34   Snp->Cdb.CPBsize    = PXE_CPBSIZE_NOT_USED;
35   Snp->Cdb.DBsize     = PXE_DBSIZE_NOT_USED;
36   Snp->Cdb.CPBaddr    = PXE_CPBADDR_NOT_USED;
37   Snp->Cdb.DBaddr     = PXE_DBADDR_NOT_USED;
38   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;
39   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;
40   Snp->Cdb.IFnum      = Snp->IfNum;
41   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;
42 
43   //
44   // Make changes to H/W UNDI Start CDB if this is
45   // a S/W UNDI.
46   //
47   if (Snp->IsSwUndi) {
48     Snp->Cdb.CPBsize  = (UINT16) sizeof (PXE_CPB_START_31);
49     Snp->Cdb.CPBaddr  = (UINT64)(UINTN) Cpb31;
50 
51     Cpb31->Delay     = (UINT64)(UINTN) &SnpUndi32CallbackDelay;
52     Cpb31->Block     = (UINT64)(UINTN) &SnpUndi32CallbackBlock;
53 
54     //
55     // Virtual == Physical.  This can be set to zero.
56     //
57     Cpb31->Virt2Phys = (UINT64)(UINTN) 0;
58     Cpb31->Mem_IO    = (UINT64)(UINTN) &SnpUndi32CallbackMemio;
59 
60     Cpb31->Map_Mem   = (UINT64)(UINTN) &SnpUndi32CallbackMap;
61     Cpb31->UnMap_Mem = (UINT64)(UINTN) &SnpUndi32CallbackUnmap;
62     Cpb31->Sync_Mem  = (UINT64)(UINTN) &SnpUndi32CallbackSync;
63 
64     Cpb31->Unique_ID = (UINT64)(UINTN) Snp;
65   }
66   //
67   // Issue UNDI command and check result.
68   //
69   DEBUG ((EFI_D_NET, "\nsnp->undi.start()  "));
70 
71   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
72 
73   if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
74     //
75     // UNDI could not be started. Return UNDI error.
76     //
77     DEBUG (
78       (EFI_D_ERROR,
79       "\nsnp->undi.start()  %xh:%xh\n",
80       Snp->Cdb.StatCode,
81       Snp->Cdb.StatFlags)
82       );
83 
84     return EFI_DEVICE_ERROR;
85   }
86   //
87   // Set simple network state to Started and return success.
88   //
89   Snp->Mode.State = EfiSimpleNetworkStarted;
90 
91   return EFI_SUCCESS;
92 }
93 
94 
95 /**
96   Change the state of a network interface from "stopped" to "started."
97 
98   This function starts a network interface. If the network interface successfully
99   starts, then EFI_SUCCESS will be returned.
100 
101   @param  This                   A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
102 
103   @retval EFI_SUCCESS            The network interface was started.
104   @retval EFI_ALREADY_STARTED    The network interface is already in the started state.
105   @retval EFI_INVALID_PARAMETER  This parameter was NULL or did not point to a valid
106                                  EFI_SIMPLE_NETWORK_PROTOCOL structure.
107   @retval EFI_DEVICE_ERROR       The command could not be sent to the network interface.
108   @retval EFI_UNSUPPORTED        This function is not supported by the network interface.
109 
110 **/
111 EFI_STATUS
112 EFIAPI
SnpUndi32Start(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)113 SnpUndi32Start (
114   IN EFI_SIMPLE_NETWORK_PROTOCOL *This
115   )
116 {
117   SNP_DRIVER  *Snp;
118   EFI_STATUS  Status;
119   UINTN       Index;
120   EFI_TPL     OldTpl;
121 
122   if (This == NULL) {
123     return EFI_INVALID_PARAMETER;
124   }
125 
126   Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
127 
128   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
129 
130   switch (Snp->Mode.State) {
131   case EfiSimpleNetworkStopped:
132     break;
133 
134   case EfiSimpleNetworkStarted:
135   case EfiSimpleNetworkInitialized:
136     Status = EFI_ALREADY_STARTED;
137     goto ON_EXIT;
138 
139   default:
140     Status = EFI_DEVICE_ERROR;
141     goto ON_EXIT;
142   }
143 
144   Status = PxeStart (Snp);
145   if (EFI_ERROR (Status)) {
146     goto ON_EXIT;
147   }
148   //
149   // clear the map_list in SNP structure
150   //
151   for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
152     Snp->MapList[Index].VirtualAddress = 0;
153     Snp->MapList[Index].MapCookie      = 0;
154   }
155 
156   Snp->Mode.MCastFilterCount = 0;
157 
158 ON_EXIT:
159   gBS->RestoreTPL (OldTpl);
160 
161   return Status;
162 }
163