kernel: Sync ACPICA with Intel's version 20140424.
[dragonfly.git] / sys / dev / atm / hea / eni_vcm.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hea/eni_vcm.c,v 1.3 1999/08/28 00:41:47 peter Exp $
27  */
28
29 /*
30  * Efficient ENI Adapter Support
31  * -----------------------------
32  *
33  * Virtual Channel Managment
34  *
35  */
36
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "eni_stats.h"
41 #include "eni.h"
42 #include "eni_var.h"
43
44 /*
45  * VCC Stack Instantiation
46  * 
47  * This function is called via the common driver code during a device VCC
48  * stack instantiation.  The common code has already validated some of
49  * the request so we just need to check a few more ENI-specific details.
50  *
51  * Called at splnet.
52  *
53  * Arguments:
54  *      cup     pointer to device common unit
55  *      cvp     pointer to common VCC entry
56  *
57  * Returns:
58  *      0       instantiation successful
59  *      err     instantiation failed - reason indicated
60  *
61  */
62 int
63 eni_instvcc(Cmn_unit *cup, Cmn_vcc *cvp)
64 {
65         Eni_unit        *eup = (Eni_unit *)cup;
66         Eni_vcc         *evp = (Eni_vcc *)cvp;
67         Atm_attributes  *ap = &evp->ev_connvc->cvc_attr;
68
69         /*
70          * Validate requested AAL
71          */
72         switch (ap->aal.type) {
73
74         case ATM_AAL0:
75                 break;
76
77         case ATM_AAL5:
78                 if ((ap->aal.v.aal5.forward_max_SDU_size > ENI_IFF_MTU) ||
79                     (ap->aal.v.aal5.backward_max_SDU_size > ENI_IFF_MTU)) {
80                         eup->eu_stats.eni_st_drv.drv_vc_maxpdu++;
81                         return (EINVAL);
82                 }
83                 break;
84
85         default:
86                 return (EINVAL);
87         }
88
89         return (0);
90 }
91
92
93 /*
94  * Open a VCC
95  *
96  * This function is called via the common driver code after receiving a
97  * stack *_INIT* command. The common code has already validated most of
98  * the request so we just need to check a few more ENI-specific details.
99  *
100  * Called at splimp.
101  *
102  * Arguments:
103  *      cup     pointer to device common unit
104  *      cvp     pointer to common VCC entry
105  *
106  * Returns:
107  *      0       open successful
108  *      err     open failed
109  *
110  */
111 int
112 eni_openvcc(Cmn_unit *cup, Cmn_vcc *cvp)
113 {
114         Eni_unit        *eup = (Eni_unit *)cup;
115         Eni_vcc         *evp = (Eni_vcc *)cvp;
116         struct vccb     *vcp = evp->ev_connvc->cvc_vcc;
117         int             err = 0;
118
119         VCI_Table       *vct;
120         int             size;
121         int             mode;
122         int             nsize;
123
124         /*
125          * Validate the VPI and VCI values
126          */
127         if ( (vcp->vc_vpi > eup->eu_pif.pif_maxvpi) ||
128              (vcp->vc_vci > eup->eu_pif.pif_maxvci) ) {
129                 eup->eu_stats.eni_st_drv.drv_vc_badrng++;
130                 return ( EFAULT );
131         }
132
133         /*
134          * Check if this VCI is already active
135          */
136         vct = &eup->eu_vcitbl[ vcp->vc_vci ];
137         if ( vct->vci_control >> VCI_MODE_SHIFT != VCI_MODE_TRASH ) {
138                 return ( EEXIST );
139         }
140
141         /*
142          * Allocate some permanent adapter memory for the reassembly
143          * buffer. Special case the signalling channel(s) buffer size.
144          * Otherwise, the buffer size will be based on whether this is
145          * a server or client card.
146          */
147         if ( vcp->vc_vci == UNI_SIG_VCI )       /* HACK */
148                 size = RX_SIG_BSIZE;
149         else
150                 size = (eup->eu_ramsize > MAX_CLIENT_RAM * ENI_BUF_PGSZ) ?
151                         RX_SERVER_BSIZE * ENI_BUF_PGSZ :
152                         RX_CLIENT_BSIZE * ENI_BUF_PGSZ;
153
154         if ( ( evp->ev_rxbuf = eni_allocate_buffer ( eup, (u_long *)&size ) )
155             == NULL ) {
156                 return ( ENOMEM );
157         }
158         evp->ev_rxpos = 0;
159
160         /*
161          * We only need to open incoming VCI's so outbound VCI's
162          * just get set to CVS_ACTIVE state.
163          */
164         if ( ( vcp->vc_type & VCC_IN ) == 0 ) {
165                 /*
166                  * Set the state and return - nothing else needs to be done.
167                  */
168                 evp->ev_state = CVS_ACTIVE;
169                 return ( 0 );
170         }
171
172         /*
173          * Set the VCI Table entry to start receiving
174          */
175         mode = ( evp->ev_connvc->cvc_attr.aal.type == ATM_AAL5
176                 ? VCI_MODE_AAL5 : VCI_MODE_AAL0 );
177         size >>= ENI_LOC_PREDIV;        /* Predivide by 256 WORDS */
178         for ( nsize = -1; size; nsize++ )
179                 size >>= 1;
180
181         vct->vci_control = mode << VCI_MODE_SHIFT |
182             PTI_MODE_TRASH << VCI_PTI_SHIFT |
183                 ( (u_int)(evp->ev_rxbuf) >> ENI_LOC_PREDIV ) << VCI_LOC_SHIFT |
184                 nsize << VCI_SIZE_SHIFT;
185         vct->vci_descr = 0;             /* Descr = Rdptr = 0 */
186         vct->vci_write = 0;             /* WritePtr = CellCount = 0 */
187
188         /*
189          * Indicate VC active
190          */
191         evp->ev_state = CVS_ACTIVE;
192
193         return ( err );
194 }
195
196 /*
197  * Close a VCC
198  *
199  * This function is called via the common driver code after receiving a
200  * stack *_TERM* command. The common code has already validated most of
201  * the request so we just need to check a few more ENI-specific details.
202  *
203  * Called at splimp.
204  *
205  * Arguments:
206  *      cup     pointer to device common unit
207  *      cvp     pointer to common VCC entry
208  *
209  * Returns:
210  *      0       close successful
211  *      err     close failed
212  *
213  */
214 int
215 eni_closevcc(Cmn_unit *cup, Cmn_vcc *cvp)
216 {
217         Eni_unit        *eup = (Eni_unit *)cup;
218         Eni_vcc         *evp = (Eni_vcc *)cvp;
219         struct vccb     *vcp = evp->ev_connvc->cvc_vcc;
220         int             err = 0;
221
222         VCI_Table       *vct;
223
224         /*
225          * Clear any references to this VCC in our transmit queue
226          */
227         /*
228          * We'll simply allow any existing TX requests to be
229          * sent as that's easier then pulling them out of
230          * everywhere. Besides, they should be ignored at the
231          * receiver whenever the other end shuts down.
232          */
233
234         /*
235          * Free the adapter receive buffer
236          */
237         (void) eni_free_buffer ( eup, (caddr_t)evp->ev_rxbuf );
238
239         /*
240          * If this is an outbound only VCI, then we can close
241          * immediately.
242          */
243         if ( ( vcp->vc_type & VCC_IN ) == 0 ) {
244                 /*
245                  * The state will be set to TERM when we return
246                  * to the *_TERM caller.
247                  */
248                 return ( 0 );
249         }
250
251         /*
252          * Find VCI entry in VCI Table
253          */
254         vct = &eup->eu_vcitbl[ vcp->vc_vci ];
255
256         /*
257          * Reset the VCI state
258          */
259         vct->vci_control = ( vct->vci_control & VCI_MODE_MASK )
260                 /* | VCI_MODE_TRASH */;
261         DELAY ( MIDWAY_DELAY );                 /* Give the adapter time to */
262                                         /* make the transition */
263
264         /*
265          * Reset everything
266          */
267         KM_ZERO ( vct, sizeof(VCI_Table) );
268
269         return ( err );
270 }
271