]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/idt/idt_harp.c
Use __FBSDID().
[FreeBSD/FreeBSD.git] / sys / dev / idt / idt_harp.c
1 /*
2  * Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Matriplex, inc.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  ******************************************************************************
32  *
33  * This driver is derived from the Nicstar driver by Mark Tinguely, and
34  * some of the original driver still exists here.  Those portions are...
35  *   Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
36  *   All rights reserved.
37  *
38  ******************************************************************************
39  */
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/lock.h>
48 #include <sys/malloc.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/syslog.h>
52
53 #include <sys/bus.h>
54 #include <sys/conf.h>
55
56 #include <sys/module.h>
57 #include <machine/bus_memio.h>
58 #include <machine/bus.h>
59 #include <machine/resource.h>
60 #include <sys/rman.h>
61
62 #include <net/if.h>
63 #include <net/if_arp.h>
64 #include <net/netisr.h>
65 #include <net/if_var.h>
66
67 #include <netatm/port.h>
68 #include <netatm/queue.h>
69 #include <netatm/atm.h>
70 #include <netatm/atm_sys.h>
71 #include <netatm/atm_sap.h>
72 #include <netatm/atm_cm.h>
73 #include <netatm/atm_if.h>
74 #include <netatm/atm_stack.h>
75 #include <netatm/atm_pcb.h>
76 #include <netatm/atm_var.h>
77 #include <netatm/atm_vc.h>
78
79 #include <dev/idt/idtreg.h>
80 #include <dev/idt/idtvar.h>
81
82 /******************************************************************************
83  *
84  * HARP-specific definitions
85  *
86  */
87
88 #define IDT_DEV_NAME    "idt"
89
90 #define IDT_IFF_MTU     9188
91 #define IDT_MAX_VCI     1023    /* 0 - 1023 */
92 #define IDT_MAX_VPI     0
93
94 #define iv_next         iv_cmn.cv_next
95 #define iv_toku         iv_cmn.cv_toku
96 #define iv_upper        iv_cmn.cv_upper
97 #define iv_vccb         iv_cmn.cv_connvc        /* HARP 3.0 */
98 #define iv_state        iv_cmn.cv_state
99 #define iu_pif          iu_cmn.cu_pif
100 #define iu_unit         iu_cmn.cu_unit
101 #define iu_flags        iu_cmn.cu_flags
102 #define iu_mtu          iu_cmn.cu_mtu
103 #define iu_open_vcc     iu_cmn.cu_open_vcc
104 #define iu_instvcc      iu_cmn.cu_instvcc       /* HARP 3.0 */
105 #define iu_vcc          iu_cmn.cu_vcc
106 #define iu_vcc_zone     iu_cmn.cu_vcc_zone
107 #define iu_nif_zone     iu_cmn.cu_nif_zone
108 #define iu_ioctl        iu_cmn.cu_ioctl
109 #define iu_openvcc      iu_cmn.cu_openvcc
110 #define iu_closevcc     iu_cmn.cu_closevcc
111 #define iu_output       iu_cmn.cu_output
112 #define iu_config       iu_cmn.cu_config
113 #define iu_softc        iu_cmn.cu_softc
114
115 /*
116  * ATM Interface services
117  */
118 static struct stack_defn idt_svaal5 = {
119         NULL,
120         SAP_CPCS_AAL5,
121         SDF_TERM,
122         atm_dev_inst,
123         atm_dev_lower,
124         NULL,
125         0,
126 };
127 static struct stack_defn idt_svaal4 = {
128         &idt_svaal5,
129         SAP_CPCS_AAL3_4,
130         SDF_TERM,
131         atm_dev_inst,
132         atm_dev_lower,
133         NULL,
134         0,
135 };
136 static struct stack_defn idt_svaal0 = {
137         &idt_svaal4,
138         SAP_ATM,
139         SDF_TERM,
140         atm_dev_inst,
141         atm_dev_lower,
142         NULL,
143         0,
144 };
145 struct stack_defn *idt_services = &idt_svaal0;
146
147 extern uma_zone_t idt_nif_zone;
148 extern uma_zone_t idt_vcc_zone;
149
150 static int idt_atm_bearerclass(struct attr_bearer *);
151 #ifdef T_ATM_BUFQUEUE
152 static CONNECTION *idt_atm_harpconn(Cmn_unit *, Cmn_vcc *);
153 #endif
154 static int idt_atm_ioctl(int, caddr_t, caddr_t);
155
156 static void idt_output(Cmn_unit *, Cmn_vcc *, KBuffer *);
157 static int idt_openvcc(Cmn_unit *, Cmn_vcc *);
158 static int idt_closevcc(Cmn_unit *, Cmn_vcc *);
159 static int idt_instvcc(Cmn_unit *, Cmn_vcc *);
160
161 static void idt_recv_stack(void *, KBuffer *);
162
163 /******************************************************************************
164  *
165  *                       HARP GLUE SECTION
166  *
167  ******************************************************************************
168  *
169  * Handle netatm core service interface ioctl requests
170  *
171  * Called at splnet.
172  *
173  * Arguments:
174  *    code       ioctl function (sub)code
175  *    data       data to/from ioctl
176  *    arg        optional code-specific argument
177  *
178  * Returns:
179  *    0          request processed successfully
180  *    error      request failed - reason code
181  *
182  */
183 static int
184 idt_atm_ioctl(int code, caddr_t addr, caddr_t arg)
185 {
186 #ifdef T_ATM_BUFQUEUE
187         CONNECTION *connection;
188         TX_QUEUE *txq;
189         struct mbuf *m;
190         Cmn_unit *cup;
191         Cmn_vcc *cvp;
192         int retval;
193 #endif
194
195         switch (code) {
196
197 #ifdef T_ATM_BUFQUEUE
198         case T_ATM_BUFQUEUE:
199                 cup = (Cmn_unit *) addr;
200                 cvp = (Cmn_vcc *) arg;
201                 connection = idt_atm_harpconn(cup, cvp);
202                 if (connection == NULL)
203                         return (-1);
204                 retval = 0;
205                 txq = connection->queue;
206                 if (txq == NULL)
207                         return (-1);
208                 for (m = txq->mget; m != NULL; m = m->m_nextpkt)
209                         retval += m->m_pkthdr.len;
210                 return (retval);
211 #endif
212         }
213
214         return (ENOSYS);
215 }
216
217 #ifdef T_ATM_BUFQUEUE
218 /*******************************************************************************
219  *
220  *  Get connection pointer from Cmn_unit and Cmn_vcc
221  *
222  *  in:  Cmn_unit and Cmn_vcc
223  * out:  connection (NULL=error)
224  *
225  *  Date first: 05/31/2001  last: 05/31/2001
226  */
227
228 static CONNECTION *
229 idt_atm_harpconn(Cmn_unit * cup, Cmn_vcc * cvp)
230 {
231         struct vccb *vccinf;    /* from HARP struct */
232         IDT *idt;
233         int vpi;
234         int vci;
235
236         idt = (IDT *) cup;
237         if (idt == NULL || cvp == NULL)
238                 return (NULL);
239
240         if (cvp->cv_connvc == NULL)
241                 return (NULL);
242
243         vccinf = cvp->cv_connvc->cvc_vcc;
244
245         if (vccinf == NULL)
246                 return (NULL);
247
248         vpi = vccinf->vc_vpi;
249         vci = vccinf->vc_vci;
250
251         return (idt_connect_find(idt, vpi, vci));
252 }
253 #endif  /* T_ATM_BUFQUEUE */
254
255 /*******************************************************************************
256  *
257  *  Get CBR/VBR/UBR class from bearer attribute
258  *
259  *  in:
260  * out:  NICCBR/NICVBR/NICABR/NICUBR
261  *
262  *  Date first: 06/12/2001  last: 06/13/2001
263  */
264
265 static int
266 idt_atm_bearerclass(struct attr_bearer * bearer)
267 {
268         switch (bearer->v.bearer_class) {
269                 case T_ATM_CLASS_A:return (NICCBR);
270         case T_ATM_CLASS_C:
271                 if (idt_sysctl_vbriscbr)
272                         return (NICCBR);        /* use CBR slots for VBR VC's */
273                 else
274                         return (NICVBR);
275         case T_ATM_CLASS_X:
276                 if (bearer->v.traffic_type == T_ATM_CBR)
277                         return (NICCBR);
278                 if (bearer->v.traffic_type == T_ATM_VBR)
279                         return (NICVBR);
280                 return (NICUBR);
281         }
282         return (NICUBR);
283 }
284
285 /*  The flag idt_sysctl_vbriscbr allows us to set up a CBR VC as if it were
286  *  VBR.  This is primarily to avoid cell loss at a switch that cannot seem
287  *  to buffer one or two cells of jitter.  This jitter is created when many
288  *  CBR slots have been taken, and a new CBR VC cannot use the optimally
289  *  spaced slots, and has to use nearby slots instead.
290  *
291  *  In this case, we want to use the VC SCR as the CBR value.  The PCR and MBS
292  *  is only of interest to the switch.
293  *
294  *******************************************************************************
295  *
296  *  Initialize HARP service
297  *  called from device attach
298  */
299
300 int
301 idt_harp_init(nicstar_reg_t *idt)
302 {
303         long long tsc_val;
304         u_char idt_mac[6];
305         int i;
306         int error;
307
308         error = 0;
309
310         /*
311          * Start initializing it
312          */
313         idt->iu_unit = device_get_unit(idt->dev);
314         idt->iu_mtu = IDT_IFF_MTU;
315         idt->iu_ioctl = idt_atm_ioctl;
316         idt->iu_openvcc = idt_openvcc;
317         idt->iu_instvcc = idt_instvcc;
318         idt->iu_closevcc = idt_closevcc;
319         idt->iu_output = idt_output;
320         idt->iu_vcc_zone = idt_vcc_zone;
321         idt->iu_nif_zone = idt_nif_zone;
322         idt->iu_softc = (void *)idt;
323
324         /*
325          * Copy serial number into config space
326          */
327         idt->iu_config.ac_serial = 0;
328
329         idt->iu_config.ac_vendor = VENDOR_IDT;
330         idt->iu_config.ac_vendapi = VENDAPI_IDT_1;
331         idt->iu_config.ac_device = DEV_IDT_155;
332         idt->iu_config.ac_media = MEDIA_UNKNOWN;
333         idt->iu_config.ac_bustype = BUS_PCI;
334
335         idt->iu_pif.pif_pcr = idt->cellrate_rmax;       /* ATM_PCR_OC3C; */
336         idt->iu_pif.pif_maxvpi = idt->conn_maxvpi;
337         idt->iu_pif.pif_maxvci = idt->conn_maxvci;
338
339         snprintf(idt->iu_config.ac_hard_vers,
340                  sizeof(idt->iu_config.ac_hard_vers),
341                  idt->hardware);
342         snprintf(idt->iu_config.ac_firm_vers,
343                  sizeof(idt->iu_config.ac_firm_vers),
344                  IDT_VERSION);
345         /*
346          * Save device ram info for user-level programs NOTE: This really
347          * points to start of EEPROM and includes all the device registers
348          * in the lower 2 Megabytes.
349          */
350         idt->iu_config.ac_ram = NULL;
351         idt->iu_config.ac_ramsize = 0;
352
353         for (i = 0; i < 6; i++) {
354                 idt_mac[i] = nicstar_eeprom_rd(idt, (0x6c + i));
355         }
356
357         /* looks like bad MAC */
358         if ((idt_mac[3] | idt_mac[4] | idt_mac[5]) == 0) {
359                 GET_RDTSC(tsc_val);     /* 24 bits on 500mhz CPU is about
360                                          * 30msec */
361                 idt_mac[0] = 0x00;
362                 idt_mac[1] = 0x20;
363                 idt_mac[2] = 0x48;      /* use Fore prefix */
364                 idt_mac[3] = (tsc_val >> 16) & 0xff;
365                 idt_mac[4] = (tsc_val >> 8) & 0xff;
366                 idt_mac[5] = (tsc_val) & 0xff;
367                 device_printf(idt->dev,
368                         "Cannot read MAC address from EEPROM, generating it.\n");
369         }
370         bcopy(&idt_mac, &idt->iu_pif.pif_macaddr.ma_data, sizeof(idt_mac));
371
372         device_printf(idt->dev, "MAC address %6D, HWrev=%d\n",
373                 (u_int8_t *)&idt->iu_pif.pif_macaddr.ma_data, ":",
374                 idt->pci_rev);
375
376         idt->iu_config.ac_macaddr = idt->iu_pif.pif_macaddr;
377
378         /*
379          * Register this interface with ATM core services
380          */
381         error = atm_physif_register(&idt->iu_cmn, IDT_DEV_NAME, idt_services);
382         if (error != 0) {
383                 /*
384                  * Registration failed - back everything out
385                  */
386
387                 log(LOG_ERR, "%s(): atm_physif_register failed\n", __func__);
388                 return (error);
389         }
390         idt->iu_flags |= CUF_INITED;
391
392 #if BSD >= 199506
393         /*
394          * Add hook to out shutdown function at_shutdown (
395          * (bootlist_fn)idt_pci_shutdown, idt, SHUTDOWN_POST_SYNC );
396          */
397 #endif
398
399         return (error);
400 }
401
402 /*******************************************************************************
403  *
404  *  Output data
405  */
406
407 static void
408 idt_output(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc, KBuffer * m)
409 {
410         struct vccb *vccinf;    /* from HARP struct */
411         IDT *idt;
412         int vpi;
413         int vci;
414         int flags;
415
416         idt = (IDT *) cmnunit;
417         flags = 0;
418
419         if (cmnvcc == NULL) {
420                 device_printf(idt->dev, "idt_output arg error #1\n");
421                 goto bad;
422         }
423         if (cmnvcc->cv_connvc == NULL) {
424                 device_printf(idt->dev, "idt_output arg error #2\n");
425                 goto bad;
426         }
427         vccinf = cmnvcc->cv_connvc->cvc_vcc;
428         if (vccinf == NULL) {
429                 device_printf(idt->dev, "idt_output arg error #3\n");
430                 goto bad;
431         }
432         vpi = vccinf->vc_vpi;
433         vci = vccinf->vc_vci;
434
435 #ifdef CVF_MPEG2TS              /* option to split bufs into small TS bufs */
436         if (cmnvcc->cv_flags & CVF_MPEG2TS)
437                 flags = 1;
438 #endif
439
440         idt_transmit(idt, m, vpi, vci, flags);
441
442         return;
443 bad:
444         m_freem(m);
445         return;
446 }
447
448 /*******************************************************************************
449  *
450  *  Open VCC
451  */
452
453 static int
454 idt_openvcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
455 {
456         Atm_attributes *attrib; /* from HARP struct */
457         struct vccb *vccinf;    /* from HARP struct */
458         CONNECTION *connection;
459         IDT *idt;
460         int vpi;
461         int vci;
462         int class;              /* NICCBR, NICVBR, or NICUBR */
463
464         idt = (IDT *) cmnunit;
465
466         if (cmnvcc == NULL || cmnvcc->cv_connvc == NULL) {
467                 printf("idt_openvcc: bad request #1.\n");
468                 return (1);
469         }
470         attrib = &cmnvcc->cv_connvc->cvc_attr;
471         vccinf = cmnvcc->cv_connvc->cvc_vcc;
472
473         if (attrib == NULL || vccinf == NULL) {
474                 printf("idt_openvcc: bad request #2.\n");
475                 return (1);
476         }
477         vpi = vccinf->vc_vpi;
478         vci = vccinf->vc_vci;
479
480         connection = idt_connect_find(idt, vpi, vci);
481         if (connection == NULL) {
482                 printf("idt_openvcc: vpi/vci invalid: %d/%d\n", vpi, vci);
483                 return (1);
484         }
485         if (connection->status) {
486                 printf("idt_openvcc: connection already open %d/%d\n", vpi, vci);
487                 return (1);
488         }
489         connection->status = 1;
490         connection->recv = NULL;
491         connection->rlen = 0;
492         connection->maxpdu = 20000;
493         connection->aal = IDTAAL5;
494         connection->traf_pcr = attrib->traffic.v.forward.PCR_all_traffic;
495         connection->traf_scr = attrib->traffic.v.forward.SCR_all_traffic;
496         connection->vccinf = vccinf;    /* 12/15/2000 */
497
498         if (connection->traf_pcr <= 0)
499                 connection->traf_pcr = connection->traf_scr;
500         if (connection->traf_scr <= 0)
501                 connection->traf_scr = connection->traf_pcr;
502
503         class = idt_atm_bearerclass(&attrib->bearer);
504         if (vpi == 0 && vci == 5)
505                 class = NICABR; /* higher priority than UBR */
506         if (vpi == 0 && vci == 16)
507                 class = NICABR;
508
509         if (connection->traf_pcr < 0) { /* neither PCR nor SCR given */
510                 connection->traf_pcr = 1;
511                 connection->traf_scr = 1;
512                 class = NICUBR; /* so give it lowest priority */
513         }
514         connection->class = class;
515
516         if (idt_connect_txopen(idt, connection)) {
517                 device_printf(idt->dev, "cannot open connection for %d/%d\n",
518                         vpi, vci);
519                 return (1);
520         }
521         if (idt_sysctl_logvcs)
522                 printf("idt_openvcc: %d/%d, PCR=%d, SCR=%d\n", vpi, vci,
523                     connection->traf_pcr, connection->traf_scr);
524         idt_connect_opencls(idt, connection, 1);        /* open entry in rcv
525                                                          * connect table */
526
527         return (0);
528 }
529
530 /*  We really don't handle ABR, but use it as a higher priority UBR.  The
531  *  idea is that a UBR connection that gives a PCR (like 0/16) should
532  *  be given preference over a UBR connection that wants "everything else".
533  *
534  *  Note that CLASS_X is typically UBR, but the traffic type information
535  *  element may still specify CBR or VBR.
536  *
537  *******************************************************************************
538  *
539  *  Close VCC
540  */
541
542 static int
543 idt_closevcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
544 {
545         CONNECTION *connection;
546         nicstar_reg_t *idt = (nicstar_reg_t *) cmnunit;
547         int vpi;
548         int vci;
549
550         if (cmnvcc && cmnvcc->cv_connvc && cmnvcc->cv_connvc->cvc_vcc) {
551                 vpi = cmnvcc->cv_connvc->cvc_vcc->vc_vpi;
552                 vci = cmnvcc->cv_connvc->cvc_vcc->vc_vci;
553         } else {
554                 printf("idt_closevcc: bad vcivpi\n");
555                 return (0);
556         }
557         connection = idt_connect_find(idt, vpi, vci);
558
559         if (connection == NULL) {
560                 printf("idt_closevcc: vpi/vci invalid: %d/%d\n", vpi, vci);
561                 return (0);
562         }
563         idt_connect_opencls(idt, connection, 0);        /* close entry in rcv
564                                                          * connect table */
565
566         if (connection->status == 0)
567                 printf("idt_closevcc: close on empty connection %d/%d\n", vpi, vci);
568         if (connection->recv != NULL)
569                 m_freem(connection->recv);      /* recycle mbuf of partial PDU */
570         idt_connect_txclose(idt, connection);
571         connection->status = 0;
572         connection->recv = NULL;
573         connection->rlen = 0;
574         connection->maxpdu = 0;
575         connection->aal = 0;
576         connection->traf_pcr = 0;
577         connection->traf_scr = 0;
578
579         if (idt_sysctl_logvcs)
580                 printf("idt_closevcc: vpi=%d vci=%d\n", vpi, vci);
581
582         return (0);
583 }
584
585 /*
586  *
587  * VCC Stack Instantiation
588  *
589  * This function is called via the common driver code during a device VCC
590  * stack instantiation.  The common code has already validated some of
591  * the request so we just need to check a few more IDT-specific details.
592  *
593  * Called at splnet.
594  *
595  * Arguments:
596  *    cup    pointer to device common unit
597  *    cvp    pointer to common VCC entry
598  *
599  * Returns:
600  *    0    instantiation successful
601  *    err     instantiation failed - reason indicated
602  *
603  */
604 static int
605 idt_instvcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
606 {
607         Atm_attributes *attrib; /* from HARP struct */
608         IDT *idt;
609         int class, pcr, scr;
610         int slots_vc, slots_cur, slots_max;
611
612         if (cmnvcc == NULL)
613                 return (EINVAL);
614         if (cmnvcc->cv_connvc == NULL)
615                 return (EINVAL);
616
617         idt = (IDT *) cmnunit;
618         if (idt == NULL)
619                 return (EINVAL);
620
621         attrib = &cmnvcc->cv_connvc->cvc_attr;
622
623         if (attrib == NULL)
624                 return (EINVAL);
625
626         pcr = attrib->traffic.v.forward.PCR_all_traffic;
627         scr = attrib->traffic.v.forward.SCR_all_traffic;
628
629         if (pcr <= 0)
630                 pcr = scr;      /* if PCR missing, default to SCR */
631         if (pcr <= 0)
632                 pcr = 1;
633         if (scr <= 0)
634                 scr = pcr;
635
636         class = idt_atm_bearerclass(&attrib->bearer);
637         if (class == NICCBR) {
638                 slots_max = idt->txslots_max;
639                 slots_cur = idt->txslots_cur;
640                 slots_vc = idt_slots_cbr(idt, scr);     /* 06/13/2001: now using
641                                                          * SCR */
642                 if (slots_vc + slots_cur > slots_max) {
643                         if (idt_sysctl_logvcs)
644                                 device_printf(idt->dev,
645                                         "Insufficient bandwidth (vc=%d cur=%d max=%d)\n",
646                                         slots_vc, slots_cur, slots_max);
647                         return (EINVAL);
648                 }
649         }
650         /* This part was take from /sys/dev/hfa/fore_vcm.c */
651
652         switch (attrib->aal.type) {
653         case ATM_AAL0:
654                 break;
655         case ATM_AAL3_4:
656                 if ((attrib->aal.v.aal4.forward_max_SDU_size > IDT_IFF_MTU) ||
657                     (attrib->aal.v.aal4.backward_max_SDU_size > IDT_IFF_MTU))
658                         return (EINVAL);
659                 break;
660         case ATM_AAL5:
661                 if ((attrib->aal.v.aal5.forward_max_SDU_size > IDT_IFF_MTU) ||
662                     (attrib->aal.v.aal5.backward_max_SDU_size > IDT_IFF_MTU))
663                         return (EINVAL);
664                 break;
665         default:
666                 return (EINVAL);
667         }
668         return (0);
669 }
670
671 /*
672  * Pass Incoming PDU up Stack
673  *
674  * This function is called via the core ATM interrupt queue callback
675  * set in fore_recv_drain().  It will pass the supplied incoming
676  * PDU up the incoming VCC's stack.
677  *
678  * Called at splnet.
679  *
680  * Arguments:
681  *    tok        token to identify stack instantiation
682  *    m        pointer to incoming PDU buffer chain
683  *
684  * Returns:
685  *    none
686  */
687 static void
688 idt_recv_stack(void *tok, KBuffer * m)
689 {
690         Idt_vcc *ivp = (Idt_vcc *) tok;
691         int err;
692
693         if ((m->m_flags & M_PKTHDR) == 0) {
694                 printf("idt_recv_stack: Warning - mbuf chain has no header.\n");
695                 KB_FREEALL(m);
696                 return;
697         }
698         /*
699          * Send the data up the stack
700          */
701         STACK_CALL(CPCS_UNITDATA_SIG, ivp->iv_upper,
702             ivp->iv_toku, ivp->iv_vccb, (int)m, 0, err);
703         if (err)
704                 KB_FREEALL(m);
705
706         return;
707 }
708
709 /******************************************************************************
710  *
711  *  Enqueue received PDU for HARP to handle
712  *
713  *  in:  IDT device, mbuf, vpi, vci
714  *
715  * Date last: 12/14/2000
716  */
717
718 void
719 idt_receive(nicstar_reg_t * idt, struct mbuf * m, int vpi, int vci)
720 {
721         caddr_t cp;
722         Cmn_vcc *vcc;
723         int space;
724
725         /*
726          * The STACK_CALL needs to happen at splnet() in order for the stack
727          * sequence processing to work.  Schedule an interrupt queue
728          * callback at splnet() since we are currently at device level.
729          */
730
731         /*
732          * Prepend callback function pointer and token value to buffer. We
733          * have already guaranteed that the space is available in the first
734          * buffer.
735          */
736
737         /*
738          * vcc = atm_dev_vcc_find(&idt->iu_cmn, (vpivci>> 16), vpivci &
739          * 0xffff, VCC_IN);
740          */
741
742         vcc = atm_dev_vcc_find(&idt->iu_cmn, vpi, vci, VCC_IN);
743
744         if (vcc == NULL) {      /* harp stack not ready or no vcc */
745                 printf("idt_receive: no VCC %d/%d\n", vpi, vci);
746                 KB_FREEALL(m);
747                 return;
748         }
749         space = m->m_data - idt_mbuf_base(m);
750         if (space < sizeof(atm_intr_func_t) + sizeof(int)) {
751                 printf("idt_receive: NOT enough buffer space (%d).\n", space);
752                 KB_FREEALL(m);
753                 return;
754         }
755         KB_HEADADJ(m, sizeof(atm_intr_func_t) + sizeof(int));
756         KB_DATASTART(m, cp, caddr_t);
757         *((atm_intr_func_t *) cp) = idt_recv_stack;
758         cp += sizeof(atm_intr_func_t);
759
760         *((void **)cp) = (void *)vcc;
761
762         /*
763          * Schedule callback
764          */
765         if (! netisr_queue(NETISR_ATM, m))
766                 KB_FREEALL(m);
767 }