eaba03c57dbe657cf8c914ab6d7f2d6990843b6d
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Start.c
1 /** @file\r
2 Copyright (c) 2004 - 2007, Intel Corporation\r
3 All rights reserved. This program and the accompanying materials\r
4 are licensed and made available under the terms and conditions of the BSD License\r
5 which accompanies this distribution.  The full text of the license may be found at\r
6 http://opensource.org/licenses/bsd-license.php\r
7 \r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10 \r
11 Module name:\r
12   start.c\r
13 \r
14 Abstract:\r
15 \r
16 Revision history:\r
17   2000-Feb-07 M(f)J   Genesis.\r
18 \r
19 **/\r
20 \r
21 #include "Snp.h"\r
22 \r
23 \r
24 /**\r
25   this routine calls undi to start the interface and changes the snp state!\r
26 \r
27   @param  snp                    pointer to snp driver structure\r
28 \r
29 \r
30 **/\r
31 EFI_STATUS\r
32 pxe_start (\r
33   SNP_DRIVER *snp\r
34   )\r
35 {\r
36   PXE_CPB_START_31  *cpb_31;\r
37 \r
38   cpb_31  = snp->cpb;\r
39   //\r
40   // Initialize UNDI Start CDB for H/W UNDI\r
41   //\r
42   snp->cdb.OpCode     = PXE_OPCODE_START;\r
43   snp->cdb.OpFlags    = PXE_OPFLAGS_NOT_USED;\r
44   snp->cdb.CPBsize    = PXE_CPBSIZE_NOT_USED;\r
45   snp->cdb.DBsize     = PXE_DBSIZE_NOT_USED;\r
46   snp->cdb.CPBaddr    = PXE_CPBADDR_NOT_USED;\r
47   snp->cdb.DBaddr     = PXE_DBADDR_NOT_USED;\r
48   snp->cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
49   snp->cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
50   snp->cdb.IFnum      = snp->if_num;\r
51   snp->cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
52 \r
53   //\r
54   // Make changes to H/W UNDI Start CDB if this is\r
55   // a S/W UNDI.\r
56   //\r
57   if (snp->is_swundi) {\r
58     snp->cdb.CPBsize  = sizeof (PXE_CPB_START_31);\r
59     snp->cdb.CPBaddr  = (UINT64)(UINTN) cpb_31;\r
60 \r
61     cpb_31->Delay     = (UINT64)(UINTN) &snp_undi32_callback_delay;\r
62     cpb_31->Block     = (UINT64)(UINTN) &snp_undi32_callback_block;\r
63 \r
64     //\r
65     // Virtual == Physical.  This can be set to zero.\r
66     //\r
67     cpb_31->Virt2Phys = (UINT64)(UINTN) 0;\r
68     cpb_31->Mem_IO    = (UINT64)(UINTN) &snp_undi32_callback_memio;\r
69 \r
70     cpb_31->Map_Mem   = (UINT64)(UINTN) &snp_undi32_callback_map;\r
71     cpb_31->UnMap_Mem = (UINT64)(UINTN) &snp_undi32_callback_unmap;\r
72     cpb_31->Sync_Mem  = (UINT64)(UINTN) &snp_undi32_callback_sync;\r
73 \r
74     cpb_31->Unique_ID = (UINT64)(UINTN) snp;\r
75   }\r
76   //\r
77   // Issue UNDI command and check result.\r
78   //\r
79   DEBUG ((EFI_D_NET, "\nsnp->undi.start()  "));\r
80 \r
81   (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);\r
82 \r
83   if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
84     //\r
85     // UNDI could not be started. Return UNDI error.\r
86     //\r
87     DEBUG (\r
88       (EFI_D_ERROR,\r
89       "\nsnp->undi.start()  %xh:%xh\n",\r
90       snp->cdb.StatCode,\r
91       snp->cdb.StatFlags)\r
92       );\r
93 \r
94     return EFI_DEVICE_ERROR;\r
95   }\r
96   //\r
97   // Set simple network state to Started and return success.\r
98   //\r
99   snp->mode.State = EfiSimpleNetworkStarted;\r
100 \r
101   return EFI_SUCCESS;\r
102 }\r
103 \r
104 \r
105 /**\r
106   This is the SNP interface routine for starting the interface\r
107   This routine basically retrieves snp structure, checks the SNP state and\r
108   calls the pxe_start routine to actually do start undi interface\r
109 \r
110   @param  This                   context pointer\r
111 \r
112   @retval EFI_INVALID_PARAMETER  "This" is Null\r
113   @retval      No                SNP driver can be extracted from "This"\r
114   @retval EFI_ALREADY_STARTED    The state of SNP is EfiSimpleNetworkStarted or\r
115                                  EfiSimpleNetworkInitialized\r
116   @retval EFI_DEVICE_ERROR       The state of SNP is other than\r
117                                  EfiSimpleNetworkStarted,\r
118                                  EfiSimpleNetworkInitialized, and\r
119                                  EfiSimpleNetworkStopped\r
120   @retval EFI_SUCCESS            UNDI interface is succesfully started\r
121   @retval Other                  Error occurs while calling pxe_start function.\r
122 \r
123 **/\r
124 EFI_STATUS\r
125 EFIAPI\r
126 snp_undi32_start (\r
127   IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
128   )\r
129 {\r
130   SNP_DRIVER  *Snp;\r
131   EFI_STATUS  Status;\r
132   UINTN       Index;\r
133   EFI_TPL     OldTpl;\r
134 \r
135   if (This == NULL) {\r
136     return EFI_INVALID_PARAMETER;\r
137   }\r
138 \r
139   Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
140 \r
141   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
142 \r
143   switch (Snp->mode.State) {\r
144   case EfiSimpleNetworkStopped:\r
145     break;\r
146 \r
147   case EfiSimpleNetworkStarted:\r
148   case EfiSimpleNetworkInitialized:\r
149     Status = EFI_ALREADY_STARTED;\r
150     goto ON_EXIT;\r
151 \r
152   default:\r
153     Status = EFI_DEVICE_ERROR;\r
154     goto ON_EXIT;\r
155   }\r
156 \r
157   Status = pxe_start (Snp);\r
158   if (EFI_ERROR (Status)) {\r
159     goto ON_EXIT;\r
160   }\r
161   //\r
162   // clear the map_list in SNP structure\r
163   //\r
164   for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r
165     Snp->map_list[Index].virt       = 0;\r
166     Snp->map_list[Index].map_cookie = 0;\r
167   }\r
168 \r
169   Snp->mode.MCastFilterCount = 0;\r
170 \r
171 ON_EXIT:\r
172   gBS->RestoreTPL (OldTpl);\r
173 \r
174   return Status;\r
175 }\r