Fix a bug when '-f -H' is used and the target already exists. cpdup was
[dragonfly.git] / sys / netproto / atm / atm_device.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/netatm/atm_device.c,v 1.5 1999/08/28 00:48:35 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/atm_device.c,v 1.8 2006/01/14 13:36:39 swildner Exp $
28  */
29
30 /*
31  * Core ATM Services
32  * -----------------
33  *
34  * ATM device support functions
35  *
36  */
37
38 #include "kern_include.h"
39
40 /*
41  * Private structures for managing allocated kernel memory resources
42  *
43  * For each allocation of kernel memory, one Mem_ent will be used.  
44  * The Mem_ent structures will be allocated in blocks inside of a 
45  * Mem_blk structure.
46  */
47 #define MEM_NMEMENT     10              /* How many Mem_ent's in a Mem_blk */
48
49 struct mem_ent {
50         void            *me_kaddr;      /* Allocated memory address */
51         u_int           me_ksize;       /* Allocated memory length */
52         void            *me_uaddr;      /* Memory address returned to caller */
53         u_int           me_flags;       /* Flags (see below) */
54 };
55 typedef struct mem_ent  Mem_ent;
56
57 /*
58  * Memory entry flags
59  */
60 #define MEF_NONCACHE    1               /* Memory is noncacheable */
61
62
63 struct mem_blk {
64         struct mem_blk  *mb_next;       /* Next block in chain */
65         Mem_ent         mb_mement[MEM_NMEMENT]; /* Allocated memory entries */
66 };
67 typedef struct mem_blk  Mem_blk;
68
69 static Mem_blk          *atm_mem_head = NULL;
70
71 static struct t_atm_cause       atm_dev_cause = {
72         T_ATM_ITU_CODING,
73         T_ATM_LOC_USER,
74         T_ATM_CAUSE_VPCI_VCI_ASSIGNMENT_FAILURE,
75         {0, 0, 0, 0}
76 };
77
78
79 /*
80  * ATM Device Stack Instantiation
81  *
82  * Called from a critical section.
83  *
84  * Arguments
85  *      ssp             pointer to array of stack definition pointers
86  *                      for connection
87  *                      ssp[0] points to upper layer's stack definition
88  *                      ssp[1] points to this layer's stack definition
89  *                      ssp[2] points to lower layer's stack definition
90  *      cvcp            pointer to connection vcc for this stack
91  *
92  * Returns
93  *      0               instantiation successful
94  *      err             instantiation failed - reason indicated
95  *
96  */
97 int
98 atm_dev_inst(struct stack_defn **ssp, Atm_connvc *cvcp)
99 {
100         Cmn_unit        *cup = (Cmn_unit *)cvcp->cvc_attr.nif->nif_pif;
101         Cmn_vcc         *cvp;
102         int             err;
103
104         /*
105          * Check to see if device has been initialized
106          */
107         if ((cup->cu_flags & CUF_INITED) == 0)
108                 return ( EIO );
109
110         /*
111          * Validate lower SAP
112          */
113         /*
114          * Device driver is the lowest layer - no need to validate
115          */
116
117         /*
118          * Validate PVC vpi.vci
119          */
120         if (cvcp->cvc_attr.called.addr.address_format == T_ATM_PVC_ADDR) {
121                 /*
122                  * Look through existing circuits - return error if found
123                  */
124                 Atm_addr_pvc    *pp;
125
126                 pp = (Atm_addr_pvc *)cvcp->cvc_attr.called.addr.address;
127                 if (atm_dev_vcc_find(cup, ATM_PVC_GET_VPI(pp),
128                                 ATM_PVC_GET_VCI(pp), 0))
129                         return ( EADDRINUSE );
130         }
131
132         /*
133          * Validate our SAP type
134          */
135         switch ((*(ssp+1))->sd_sap) {
136         case SAP_CPCS_AAL3_4:
137         case SAP_CPCS_AAL5:
138         case SAP_ATM:
139                 break;
140         default:
141                 return (EINVAL);
142         }
143
144         /*
145          * Allocate a VCC control block
146          */
147         if ( ( cvp = (Cmn_vcc *)atm_allocate(cup->cu_vcc_pool) ) == NULL )
148                 return ( ENOMEM );
149         
150         cvp->cv_state = CVS_INST;
151         cvp->cv_toku = (*ssp)->sd_toku;
152         cvp->cv_upper = (*ssp)->sd_upper;
153         cvp->cv_connvc = cvcp;
154
155         /*
156          * Let device have a look at the connection request
157          */
158         err = (*cup->cu_instvcc)(cup, cvp);
159         if (err) {
160                 atm_free((caddr_t)cvp);
161                 return (err);
162         }
163
164         /*
165          * Looks good so far, so link in device VCC
166          */
167         LINK2TAIL ( cvp, Cmn_vcc, cup->cu_vcc, cv_next );
168
169         /*
170          * Save my token
171          */
172         (*++ssp)->sd_toku = cvp;
173
174         /*
175          * Pass instantiation down the stack
176          */
177         /*
178          * No need - we're the lowest point.
179          */
180         /* err = (*(ssp + 1))->sd_inst(ssp, cvcp); */
181
182         /*
183          * Save the lower layer's interface info
184          */
185         /*
186          * No need - we're the lowest point
187          */
188         /* cvp->cv_lower = (*++ssp)->sd_lower; */
189         /* cvp->cv_tok1 = (*ssp)->sd_toku; */
190
191         return (0);
192 }
193
194
195 /*
196  * ATM Device Stack Command Handler
197  *
198  * Arguments
199  *      cmd             stack command code
200  *      tok             session token (Cmn_vcc)
201  *      arg1            command specific argument
202  *      arg2            command specific argument
203  *
204  * Returns
205  *      none
206  *
207  */
208 /*ARGSUSED*/
209 void
210 atm_dev_lower(int cmd, void *tok, int arg1, int arg2)
211 {
212         Cmn_vcc         *cvp = (Cmn_vcc *)tok;
213         Atm_connvc      *cvcp = cvp->cv_connvc;
214         Cmn_unit        *cup = (Cmn_unit *)cvcp->cvc_attr.nif->nif_pif;
215         struct vccb     *vcp;
216         u_int           state;
217
218         switch ( cmd ) {
219
220         case CPCS_INIT:
221                 /*
222                  * Sanity check
223                  */
224                 if ( cvp->cv_state != CVS_INST ) {
225                         log ( LOG_ERR,
226                                 "atm_dev_lower: INIT: tok=%p, state=%d\n",
227                                 tok, cvp->cv_state );
228                         break;
229                 }
230
231                 vcp = cvp->cv_connvc->cvc_vcc;
232
233                 /*
234                  * Validate SVC vpi.vci
235                  */
236                 if ( vcp->vc_type & VCC_SVC ) {
237
238                         if (atm_dev_vcc_find(cup, vcp->vc_vpi, vcp->vc_vci,
239                                         vcp->vc_type & (VCC_IN | VCC_OUT))
240                                                 != cvp){
241                                 log ( LOG_ERR,
242                                   "atm_dev_lower: dup SVC (%d,%d) tok=%p\n",
243                                         vcp->vc_vpi, vcp->vc_vci, tok );
244                                 atm_cm_abort(cvp->cv_connvc, &atm_dev_cause);
245                                 break;
246                         }
247                 }
248
249                 /*
250                  * Tell the device to open the VCC
251                  */
252                 cvp->cv_state = CVS_INITED;
253                 crit_enter();
254                 if ((*cup->cu_openvcc)(cup, cvp)) {
255                         atm_cm_abort(cvp->cv_connvc, &atm_dev_cause);
256                         crit_exit();
257                         break;
258                 }
259                 crit_exit();
260                 break;
261
262         case CPCS_TERM: {
263                 KBuffer         *m, *prev, *next;
264                 int             *ip;
265
266                 crit_enter();
267
268                 /*
269                  * Disconnect the VCC - ignore return code
270                  */
271                 if ((cvp->cv_state == CVS_INITED) || 
272                     (cvp->cv_state == CVS_ACTIVE)) {
273                         (*cup->cu_closevcc)(cup, cvp);
274                 }
275                 cvp->cv_state = CVS_TERM;
276
277                 /*
278                  * Remove from interface list
279                  */
280                 UNLINK ( cvp, Cmn_vcc, cup->cu_vcc, cv_next );
281
282                 /*
283                  * Free any buffers from this VCC on the ATM interrupt queue
284                  */
285                 prev = NULL;
286                 for (m = atm_intrq.ifq_head; m; m = next) {
287                         next = KB_QNEXT(m);
288
289                         /*
290                          * See if this entry is for the terminating VCC
291                          */
292                         KB_DATASTART(m, ip, int *);
293                         ip++;
294                         if (*ip == (int)cvp) {
295                                 /*
296                                  * Yep, so dequeue the entry
297                                  */
298                                 if (prev == NULL)
299                                         atm_intrq.ifq_head = next;
300                                 else
301                                         KB_QNEXT(prev) = next;
302
303                                 if (next == NULL)
304                                         atm_intrq.ifq_tail = prev;
305
306                                 atm_intrq.ifq_len--;
307
308                                 /*
309                                  * Free the unwanted buffers
310                                  */
311                                 KB_FREEALL(m);
312                         } else {
313                                 prev = m;
314                         }
315                 }
316                 crit_exit();
317
318                 /*
319                  * Free VCC resources
320                  */
321                 atm_free((caddr_t)cvp);
322                 break;
323                 }
324
325         case CPCS_UNITDATA_INV:
326
327                 /*
328                  * Sanity check
329                  *
330                  * Use temp state variable since we dont want to lock out
331                  * interrupts, but initial VC activation interrupt may
332                  * happen here, changing state somewhere in the middle.
333                  */
334                 state = cvp->cv_state;
335                 if ((state != CVS_ACTIVE) && 
336                     (state != CVS_INITED)) {
337                         log ( LOG_ERR,
338                             "atm_dev_lower: UNITDATA: tok=%p, state=%d\n",
339                                 tok, state );
340                         KB_FREEALL((KBuffer *)arg1);
341                         break;
342                 }
343
344                 /*
345                  * Hand the data off to the device
346                  */
347                 (*cup->cu_output)(cup, cvp, (KBuffer *)arg1);
348
349                 break;
350
351         case CPCS_UABORT_INV:
352                 log ( LOG_ERR,
353                     "atm_dev_lower: unimplemented stack cmd 0x%x, tok=%p\n",
354                         cmd, tok );
355                 break;
356
357         default:
358                 log ( LOG_ERR,
359                         "atm_dev_lower: unknown stack cmd 0x%x, tok=%p\n",
360                         cmd, tok );
361
362         }
363
364         return;
365 }
366
367
368
369 /*
370  * Allocate kernel memory block
371  * 
372  * This function will allocate a kernel memory block of the type specified
373  * in the flags parameter.  The returned address will point to a memory
374  * block of the requested size and alignment.  The memory block will also 
375  * be zeroed.  The alloc/free functions will manage/mask both the OS-specific 
376  * kernel memory management requirements and the bookkeeping required to
377  * deal with data alignment issues. 
378  *
379  * This function should not be called from interrupt level.
380  *
381  * Arguments:
382  *      size    size of memory block to allocate
383  *      align   data alignment requirement 
384  *      flags   allocation flags (ATM_DEV_*)
385  *
386  * Returns:
387  *      uaddr   pointer to aligned memory block
388  *      NULL    unable to allocate memory
389  *
390  */
391 void *         
392 atm_dev_alloc(u_int size, u_int align, u_int flags)
393 {
394         Mem_blk         *mbp;
395         Mem_ent         *mep;
396         u_int           kalign, ksize;
397         int             i;
398
399         crit_enter();
400
401         /*
402          * Find a free Mem_ent
403          */
404         mep = NULL;
405         for (mbp = atm_mem_head; mbp && mep == NULL; mbp = mbp->mb_next) {
406                 for (i = 0; i < MEM_NMEMENT; i++) {
407                         if (mbp->mb_mement[i].me_uaddr == NULL) {
408                                 mep = &mbp->mb_mement[i];
409                                 break;
410                         }
411                 }
412         }
413
414         /*
415          * If there are no free Mem_ent's, then allocate a new Mem_blk
416          * and link it into the chain
417          */
418         if (mep == NULL) {
419                 mbp = KM_ALLOC(sizeof(Mem_blk), M_DEVBUF, 
420                                 M_INTWAIT | M_NULLOK);
421                 if (mbp == NULL) {
422                         log(LOG_ERR, "atm_dev_alloc: Mem_blk failure\n");
423                         crit_exit();
424                         return (NULL);
425                 }
426                 KM_ZERO(mbp, sizeof(Mem_blk));
427
428                 mbp->mb_next = atm_mem_head;
429                 atm_mem_head = mbp;
430                 mep = mbp->mb_mement;
431         }
432
433         /*
434          * Now we need to get the kernel's allocation alignment minimum
435          *
436          * This is obviously very OS-specific stuff
437          */
438         kalign = MINALLOCSIZE;
439
440         /*
441          * Figure out how much memory we must allocate to satify the
442          * user's size and alignment needs
443          */
444         if (align <= kalign)
445                 ksize = size;
446         else
447                 ksize = size + align - kalign;
448
449         /*
450          * Finally, go get the memory
451          */
452         if (flags & ATM_DEV_NONCACHE) {
453                 mep->me_kaddr = KM_ALLOC(ksize, M_DEVBUF, M_INTWAIT | M_NULLOK);
454         } else {
455                 mep->me_kaddr = KM_ALLOC(ksize, M_DEVBUF, M_INTWAIT | M_NULLOK);
456         }
457
458         if (mep->me_kaddr == NULL) {
459                 log(LOG_ERR, "atm_dev_alloc: %skernel memory unavailable\n",
460                         (flags & ATM_DEV_NONCACHE) ? "non-cacheable " : "");
461                 crit_exit();
462                 return (NULL);
463         }
464
465         /*
466          * Calculate correct alignment address to pass back to user
467          */
468         mep->me_uaddr = (void *) roundup((u_int)mep->me_kaddr, align);
469         mep->me_ksize = ksize;
470         mep->me_flags = flags;
471
472         /*
473          * Clear memory for user
474          */
475         KM_ZERO(mep->me_uaddr, size);
476
477         ATM_DEBUG4("atm_dev_alloc: size=%d, align=%d, flags=%d, uaddr=%p\n", 
478                 size, align, flags, mep->me_uaddr);
479
480         crit_exit();
481
482         return (mep->me_uaddr);
483 }
484
485
486 /*
487  * Free kernel memory block
488  * 
489  * This function will free a kernel memory block previously allocated by
490  * the atm_dev_alloc function.  
491  *
492  * This function should not be called from interrupt level.
493  *
494  * Arguments:
495  *      uaddr   pointer to allocated aligned memory block
496  *
497  * Returns:
498  *      none
499  *
500  */
501 void
502 atm_dev_free(volatile void *uaddr)
503 {
504         Mem_blk         *mbp;
505         Mem_ent         *mep;
506         int             i;
507
508         ATM_DEBUG1("atm_dev_free: uaddr=%p\n", uaddr);
509
510         crit_enter();
511
512         /*
513          * Protect ourselves...
514          */
515         if (uaddr == NULL)
516                 panic("atm_dev_free: trying to free null address");
517
518         /*
519          * Find our associated entry
520          */
521         mep = NULL;
522         for (mbp = atm_mem_head; mbp && mep == NULL; mbp = mbp->mb_next) {
523                 for (i = 0; i < MEM_NMEMENT; i++) {
524                         if (mbp->mb_mement[i].me_uaddr == uaddr) {
525                                 mep = &mbp->mb_mement[i];
526                                 break;
527                         }
528                 }
529         }
530
531         /*
532          * If we didn't find our entry, then unceremoniously let the caller
533          * know they screwed up (it certainly couldn't be a bug here...)
534          */
535         if (mep == NULL)
536                 panic("atm_dev_free: trying to free unknown address");
537         
538         /*
539          * Give the memory space back to the kernel
540          */
541         if (mep->me_flags & ATM_DEV_NONCACHE) {
542                 KM_FREE(mep->me_kaddr, mep->me_ksize, M_DEVBUF);
543         } else {
544                 KM_FREE(mep->me_kaddr, mep->me_ksize, M_DEVBUF);
545         }
546
547         /*
548          * Free our entry
549          */
550         mep->me_uaddr = NULL;
551
552         crit_exit();
553
554         return;
555 }
556
557 /*
558  * Compress buffer chain
559  * 
560  * This function will compress a supplied buffer chain into a minimum number
561  * of kernel buffers.  Typically, this function will be used because the
562  * number of buffers in an output buffer chain is too large for a device's
563  * DMA capabilities.  This should only be called as a last resort, since
564  * all the data copying will surely kill any hopes of decent performance.
565  *
566  * Arguments:
567  *      m       pointer to source buffer chain
568  *
569  * Returns:
570  *      n       pointer to compressed buffer chain
571  *
572  */
573 KBuffer *         
574 atm_dev_compress(KBuffer *m)
575 {
576         KBuffer         *n, *n0, **np;
577         int             len, space;
578         caddr_t         src, dst;
579
580         n = n0 = NULL;
581         np = &n0;
582         dst = NULL;
583         space = 0;
584
585         /*
586          * Copy each source buffer into compressed chain
587          */
588         while (m) {
589
590                 if (space == 0) {
591
592                         /*
593                          * Allocate another buffer for compressed chain
594                          */
595                         KB_ALLOCEXT(n, ATM_DEV_CMPR_LG, KB_F_NOWAIT, KB_T_DATA);
596                         if (n) {
597                                 space = ATM_DEV_CMPR_LG;
598                         } else {
599                                 KB_ALLOC(n, ATM_DEV_CMPR_SM, KB_F_NOWAIT, 
600                                         KB_T_DATA);
601                                 if (n) {
602                                         space = ATM_DEV_CMPR_SM;
603                                 } else {
604                                         /*
605                                          * Unable to get any new buffers, so
606                                          * just return the partially compressed
607                                          * chain and hope...
608                                          */
609                                         *np = m;
610                                         break;
611                                 }
612                         }
613
614                         KB_HEADSET(n, 0);
615                         KB_LEN(n) = 0;
616                         KB_BFRSTART(n, dst, caddr_t);
617
618                         *np = n;
619                         np = &KB_NEXT(n);
620                 }
621
622                 /*
623                  * Copy what we can from source buffer
624                  */
625                 len = MIN(space, KB_LEN(m));
626                 KB_DATASTART(m, src, caddr_t);
627                 KM_COPY(src, dst, len);
628
629                 /*
630                  * Adjust for copied data
631                  */
632                 dst += len;
633                 space -= len;
634
635                 KB_HEADADJ(m, -len);
636                 KB_TAILADJ(n, len);
637
638                 /*
639                  * If we've exhausted our current source buffer, free it
640                  * and move to the next one
641                  */
642                 if (KB_LEN(m) == 0) {
643                         KB_FREEONE(m, m);
644                 }
645         }
646
647         return (n0);
648 }
649
650
651 /*
652  * Locate VCC entry
653  * 
654  * This function will return the VCC entry for a specified interface and
655  * VPI/VCI value.
656  *
657  * Arguments:
658  *      cup     pointer to interface unit structure
659  *      vpi     VPI value
660  *      vci     VCI value
661  *      type    VCC type
662  *
663  * Returns:
664  *      vcp     pointer to located VCC entry matching
665  *      NULL    no VCC found
666  *
667  */
668 Cmn_vcc *
669 atm_dev_vcc_find(Cmn_unit *cup, u_int vpi, u_int vci, u_int type)
670 {
671         Cmn_vcc         *cvp;
672
673         crit_enter();
674         /*
675          * Go find VCC
676          *
677          * (Probably should stick in a hash table some time)
678          */
679         for (cvp = cup->cu_vcc; cvp; cvp = cvp->cv_next) {
680                 struct vccb     *vcp;
681
682                 vcp = cvp->cv_connvc->cvc_vcc;
683                 if ((vcp->vc_vci == vci) && (vcp->vc_vpi == vpi) && 
684                     ((vcp->vc_type & type) == type))
685                         break;
686         }
687         crit_exit();
688         return (cvp);
689 }
690
691
692 #ifdef notdef
693 /*
694  * Module unloading notification
695  * 
696  * This function must be called just prior to unloading the module from 
697  * memory.  All allocated memory will be freed here and anything else that
698  * needs cleaning up.
699  *
700  * Arguments:
701  *      none
702  *
703  * Returns:
704  *      none
705  *
706  */
707 void
708 atm_unload(void)
709 {
710         Mem_blk         *mbp;
711         Mem_ent         *mep;
712         int             i;
713
714         crit_enter();
715
716         /*
717          * Free up all of our memory management storage
718          */
719         while (mbp = atm_mem_head) {
720
721                 /*
722                  * Make sure users have freed up all of their memory
723                  */
724                 for (i = 0; i < MEM_NMEMENT; i++) {
725                         if (mbp->mb_mement[i].me_uaddr != NULL) {
726                                 panic("atm_unload: unfreed memory");
727                         }
728                 }
729
730                 atm_mem_head = mbp->mb_next;
731
732                 /*
733                  * Hand this block back to the kernel
734                  */
735                 KM_FREE((caddr_t) mbp, sizeof(Mem_blk), M_DEVBUF);
736         }
737
738         crit_exit();
739
740         return;
741 }
742 #endif  /* notdef */
743
744
745 /*
746  * Print a PDU
747  * 
748  * Arguments:
749  *      cup     pointer to device unit
750  *      cvp     pointer to VCC control block
751  *      m       pointer to pdu buffer chain
752  *      msg     pointer to message string
753  *
754  * Returns:
755  *      none
756  *
757  */
758 void
759 atm_dev_pdu_print(Cmn_unit *cup, Cmn_vcc *cvp, KBuffer *m, char *msg)
760 {
761         char            buf[128];
762
763         snprintf(buf, sizeof(buf), "%s vcc=(%d,%d)", msg, 
764                 cvp->cv_connvc->cvc_vcc->vc_vpi, 
765                 cvp->cv_connvc->cvc_vcc->vc_vci);
766
767         atm_pdu_print(m, buf);
768 }
769