2 ** File: netbuff.c Jun. 10, 2000
4 ** Author: Giovanni Falzoni <gfalzoni@inwind.it>
6 ** This file contains specific implementation of buffering
7 ** for network packets.
13 #include <net/gen/ether.h>
14 #include <net/gen/eth_io.h>
17 #if (HAVE_BUFFERS == 1)
19 static m_hdr_t
*allocptr
= NULL
;
20 static char tx_rx_buff
[8192];
23 ** Name: void *alloc_buff(dpeth_t *dep, int size)
24 ** Function: Allocates a buffer from the common pool.
26 PUBLIC
void *alloc_buff(dpeth_t
*dep
, int size
)
28 m_hdr_t
*ptr
, *wrk
= allocptr
;
29 int units
= ((size
+ sizeof(m_hdr_t
) - 1) / sizeof(m_hdr_t
)) + 1;
32 for (ptr
= wrk
->next
;; wrk
= ptr
, ptr
= ptr
->next
) {
33 if (ptr
->size
>= units
) {
34 /* Memory is available, carve requested size from pool */
35 if (ptr
->size
== units
) {
36 wrk
->next
= ptr
->next
;
38 /* Get memory from top address */
47 if (ptr
== allocptr
) break;
50 return NULL
; /* No memory available */
54 ** Name: void free_buff(dpeth_t *dep, void *blk)
55 ** Function: Returns a buffer to the common pool.
57 PUBLIC
void free_buff(dpeth_t
*dep
, void *blk
)
59 m_hdr_t
*wrk
, *ptr
= (m_hdr_t
*) blk
- 1;
61 lock(); /* Scan linked list for the correct place */
62 for (wrk
= allocptr
; !(ptr
> wrk
&& ptr
< wrk
->next
); wrk
= wrk
->next
)
63 if (wrk
>= wrk
->next
&& (ptr
> wrk
|| ptr
< wrk
->next
)) break;
65 /* Check if adjacent block is free and join blocks */
66 if (ptr
+ ptr
->size
== wrk
->next
) {
67 ptr
->size
+= wrk
->next
->size
;
68 ptr
->next
= wrk
->next
->next
;
70 ptr
->next
= wrk
->next
;
71 if (wrk
+ wrk
->size
== ptr
) {
72 wrk
->size
+= ptr
->size
;
73 wrk
->next
= ptr
->next
;
76 allocptr
= wrk
; /* Point allocptr to block just released */
82 ** Name: void init_buff(dpeth_t *dep, buff_t **tx_buff)
83 ** Function: Initalizes driver data structures.
85 PUBLIC
void init_buff(dpeth_t
*dep
, buff_t
**tx_buff
)
88 /* Initializes buffer pool */
89 if (allocptr
== NULL
) {
90 m_hdr_t
*rx
= (m_hdr_t
*) tx_rx_buff
;
91 rx
->next
= allocptr
= rx
;
95 rx
->size
= (sizeof(tx_rx_buff
) / sizeof(m_hdr_t
)) - 1;
96 free_buff(dep
, rx
+ 1);
97 dep
->de_recvq_tail
= dep
->de_recvq_head
= NULL
;
98 if (tx_buff
!= NULL
) {
99 *tx_buff
= alloc_buff(dep
, ETH_MAX_PACK_SIZE
+ sizeof(buff_t
));
100 (*tx_buff
)->size
= 0;
107 ** Name: void mem2user(dpeth_t *dep, buff_t *rxbuff);
108 ** Function: Copies a packet from local buffer to user area.
110 PUBLIC
void mem2user(dpeth_t
*dep
, buff_t
*rxbuff
)
113 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
114 int r
, pktsize
= rxbuff
->size
;
115 char *buffer
= rxbuff
->buffer
;
117 do { /* Reads chuncks of packet into user buffers */
119 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
120 if (bytes
> pktsize
) bytes
= pktsize
;
122 /* Reads from Rx buffer to user area */
123 r
= sys_safecopyto(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
, 0,
124 (vir_bytes
)buffer
, bytes
, D
);
126 panic("mem2user: sys_safecopyto failed: %d", r
);
129 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
133 /* Till packet done */
134 } while ((pktsize
-= bytes
) > 0);
139 ** Name: void user2mem(dpeth_t *dep, buff_t *txbuff)
140 ** Function: Copies a packet from user area to local buffer.
142 PUBLIC
void user2mem(dpeth_t
*dep
, buff_t
*txbuff
)
145 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
146 int r
, pktsize
= txbuff
->size
;
147 char *buffer
= txbuff
->buffer
;
149 do { /* Reads chuncks of packet from user buffers */
151 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
152 if (bytes
> pktsize
) bytes
= pktsize
;
153 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
154 0, (vir_bytes
)buffer
, bytes
, D
);
156 panic("user2mem: sys_safecopyfrom failed: %d", r
);
159 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
163 /* Till packet done */
164 } while ((pktsize
-= bytes
) > 0);
168 #endif /* HAVE_BUFFERS */