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