Remove some duplicate FreeBSD CVS IDs, move some IDs to better places.
[dragonfly.git] / sys / dev / atm / hfa / fore_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/hfa/fore_vcm.c,v 1.4 1999/08/28 00:41:53 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_vcm.c,v 1.3 2003/08/07 21:16:49 dillon Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Virtual Channel Management
35  *
36  */
37
38 #include "fore_include.h"
39
40 /*
41  * VCC Stack Instantiation
42  * 
43  * This function is called via the common driver code during a device VCC
44  * stack instantiation.  The common code has already validated some of
45  * the request so we just need to check a few more Fore-specific details.
46  *
47  * Called at splnet.
48  *
49  * Arguments:
50  *      cup     pointer to device common unit
51  *      cvp     pointer to common VCC entry
52  *
53  * Returns:
54  *      0       instantiation successful
55  *      err     instantiation failed - reason indicated
56  *
57  */
58 int
59 fore_instvcc(cup, cvp)
60         Cmn_unit        *cup;
61         Cmn_vcc         *cvp;
62 {
63         Fore_vcc        *fvp = (Fore_vcc *)cvp;
64         Atm_attributes  *ap = &fvp->fv_connvc->cvc_attr;
65
66         /*
67          * Validate requested AAL
68          */
69         switch (ap->aal.type) {
70
71         case ATM_AAL0:
72                 fvp->fv_aal = FORE_AAL_0;
73                 break;
74
75         case ATM_AAL3_4:
76                 fvp->fv_aal = FORE_AAL_4;
77                 if ((ap->aal.v.aal4.forward_max_SDU_size > FORE_IFF_MTU) ||
78                     (ap->aal.v.aal4.backward_max_SDU_size > FORE_IFF_MTU))
79                         return (EINVAL);
80                 break;
81
82         case ATM_AAL5:
83                 fvp->fv_aal = FORE_AAL_5;
84                 if ((ap->aal.v.aal5.forward_max_SDU_size > FORE_IFF_MTU) ||
85                     (ap->aal.v.aal5.backward_max_SDU_size > FORE_IFF_MTU))
86                         return (EINVAL);
87                 break;
88
89         default:
90                 return (EINVAL);
91         }
92
93         return (0);
94 }
95
96
97 /*
98  * Open a VCC
99  * 
100  * This function is called via the common driver code after receiving a
101  * stack *_INIT command.  The common code has already validated most of
102  * the request so we just need to check a few more Fore-specific details.
103  * Then we just issue the command to the CP.  Note that we can't wait around
104  * for the CP to process the command, so we return success for now and abort
105  * the connection if the command later fails.
106  *
107  * Called at splimp.
108  *
109  * Arguments:
110  *      cup     pointer to device common unit
111  *      cvp     pointer to common VCC entry
112  *
113  * Returns:
114  *      0       open successful
115  *      else    open failed
116  *
117  */
118 int
119 fore_openvcc(cup, cvp)
120         Cmn_unit        *cup;
121         Cmn_vcc         *cvp;
122 {
123         Fore_unit       *fup = (Fore_unit *)cup;
124         Fore_vcc        *fvp = (Fore_vcc *)cvp;
125         H_cmd_queue     *hcp;
126         Cmd_queue       *cqp;
127         struct vccb     *vcp;
128
129         vcp = fvp->fv_connvc->cvc_vcc;
130
131         ATM_DEBUG4("fore_openvcc: fup=%p, fvp=%p, vcc=(%d,%d)\n", 
132                 fup, fvp, vcp->vc_vpi, vcp->vc_vci);
133
134         /*
135          * Validate the VPI and VCI values
136          */
137         if ((vcp->vc_vpi > fup->fu_pif.pif_maxvpi) ||
138             (vcp->vc_vci > fup->fu_pif.pif_maxvci)) {
139                 return (1);
140         }
141
142         /*
143          * Only need to tell the CP about incoming VCCs
144          */
145         if ((vcp->vc_type & VCC_IN) == 0) {
146                 DEVICE_LOCK((Cmn_unit *)fup);
147                 fup->fu_open_vcc++;
148                 fvp->fv_state = CVS_ACTIVE;
149                 DEVICE_UNLOCK((Cmn_unit *)fup);
150                 return (0);
151         }
152
153         /*
154          * Queue command at end of command queue
155          */
156         hcp = fup->fu_cmd_tail;
157         if ((*hcp->hcq_status) & QSTAT_FREE) {
158
159                 /*
160                  * Queue entry available, so set our view of things up
161                  */
162                 hcp->hcq_code = CMD_ACT_VCCIN;
163                 hcp->hcq_arg = fvp;
164                 fup->fu_cmd_tail = hcp->hcq_next;
165                 fvp->fv_flags |= FVF_ACTCMD;
166
167                 /*
168                  * Now set the CP-resident queue entry - the CP will grab
169                  * the command when the op-code is set.
170                  */
171                 cqp = hcp->hcq_cpelem;
172                 (*hcp->hcq_status) = QSTAT_PENDING;
173                 cqp->cmdq_act.act_vccid = CP_WRITE(vcp->vc_vci);
174                 if (fvp->fv_aal == FORE_AAL_0)
175                         cqp->cmdq_act.act_batch = CP_WRITE(1);
176                 cqp->cmdq_act.act_spec = CP_WRITE(
177                         ACT_SET_SPEC(BUF_STRAT_1, fvp->fv_aal,
178                                 CMD_ACT_VCCIN | CMD_INTR_REQ));
179         } else {
180                 /*
181                  * Command queue full
182                  */
183                 fup->fu_stats->st_drv.drv_cm_full++;
184                 return (1);
185         }
186
187         return (0);
188 }
189
190
191 /*
192  * Close a VCC
193  * 
194  * This function is called via the common driver code after receiving a
195  * stack *_TERM command.  The common code has already validated most of
196  * the request so we just need to check a few more Fore-specific details.
197  * Then we just issue the command to the CP.  Note that we can't wait around
198  * for the CP to process the command, so we return success for now and whine
199  * if the command later fails.
200  *
201  * Called at splimp.
202  *
203  * Arguments:
204  *      cup     pointer to device common unit
205  *      cvp     pointer to common VCC entry
206  *
207  * Returns:
208  *      0       close successful
209  *      else    close failed
210  *
211  */
212 int
213 fore_closevcc(cup, cvp)
214         Cmn_unit        *cup;
215         Cmn_vcc         *cvp;
216 {
217         Fore_unit       *fup = (Fore_unit *)cup;
218         Fore_vcc        *fvp = (Fore_vcc *)cvp;
219         H_xmit_queue    *hxp;
220         H_cmd_queue     *hcp;
221         Cmd_queue       *cqp;
222         struct vccb     *vcp;
223         int             i, err = 0;
224
225         vcp = fvp->fv_connvc->cvc_vcc;
226
227         ATM_DEBUG4("fore_closevcc: fup=%p, fvp=%p, vcc=(%d,%d)\n", 
228                 fup, fvp, vcp->vc_vpi, vcp->vc_vci);
229
230         DEVICE_LOCK((Cmn_unit *)fup);
231
232         /*
233          * Clear any references to this VCC in our transmit queue
234          */
235         for (hxp = fup->fu_xmit_head, i = 0;
236              (*hxp->hxq_status != QSTAT_FREE) && (i < XMIT_QUELEN);
237              hxp = hxp->hxq_next, i++) {
238                 if (hxp->hxq_vcc == fvp) {
239                         hxp->hxq_vcc = NULL;
240                 }
241         }
242
243         /*
244          * Clear any references to this VCC in our command queue
245          */
246         for (hcp = fup->fu_cmd_head, i = 0;
247              (*hcp->hcq_status != QSTAT_FREE) && (i < CMD_QUELEN);
248              hcp = hcp->hcq_next, i++) {
249                 switch (hcp->hcq_code) {
250
251                 case CMD_ACT_VCCIN:
252                 case CMD_ACT_VCCOUT:
253                         if (hcp->hcq_arg == fvp) {
254                                 hcp->hcq_arg = NULL;
255                         }
256                         break;
257                 }
258         }
259
260         /*
261          * If this VCC has been previously activated, then we need to tell
262          * the CP to deactivate it.
263          */
264         if (fvp->fv_flags & FVF_ACTCMD) {
265
266                 /*
267                  * Queue command at end of command queue
268                  */
269                 hcp = fup->fu_cmd_tail;
270                 if ((*hcp->hcq_status) & QSTAT_FREE) {
271
272                         /*
273                          * Queue entry available, so set our view of things up
274                          */
275                         hcp->hcq_code = CMD_DACT_VCCIN;
276                         hcp->hcq_arg = fvp;
277                         fup->fu_cmd_tail = hcp->hcq_next;
278
279                         /*
280                          * Now set the CP-resident queue entry - the CP will 
281                          * grab the command when the op-code is set.
282                          */
283                         cqp = hcp->hcq_cpelem;
284                         (*hcp->hcq_status) = QSTAT_PENDING;
285                         cqp->cmdq_dact.dact_vccid = CP_WRITE(vcp->vc_vci);
286                         cqp->cmdq_dact.dact_cmd =
287                                 CP_WRITE(CMD_DACT_VCCIN|CMD_INTR_REQ);
288                 } else {
289                         /*
290                          * Command queue full
291                          *
292                          * If we get here, we'll be getting out-of-sync with
293                          * the CP because we can't (for now at least) do
294                          * anything about close errors in the common code.
295                          * This won't be too bad, since we'll just toss any
296                          * PDUs received from the VCC and the sigmgr's will
297                          * always get open failures when trying to use this
298                          * (vpi,vci)...oh, well...always gotta have that one
299                          * last bug to fix! XXX
300                          */
301                         fup->fu_stats->st_drv.drv_cm_full++;
302                         err = 1;
303                 }
304         }
305
306         /*
307          * Finish up...
308          */
309         if (fvp->fv_state == CVS_ACTIVE)
310                 fup->fu_open_vcc--;
311
312         DEVICE_UNLOCK((Cmn_unit *)fup);
313
314         return (err);
315 }
316