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