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