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