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.
10 #include <minix/drivers.h>
11 #include <net/gen/ether.h>
12 #include <net/gen/eth_io.h>
15 #if (HAVE_BUFFERS == 1)
17 static m_hdr_t
*allocptr
= NULL
;
18 static char tx_rx_buff
[8192];
21 ** Name: void *alloc_buff(dpeth_t *dep, int size)
22 ** Function: Allocates a buffer from the common pool.
24 void *alloc_buff(dpeth_t
*dep
, int size
)
26 m_hdr_t
*ptr
, *wrk
= allocptr
;
27 int units
= ((size
+ sizeof(m_hdr_t
) - 1) / sizeof(m_hdr_t
)) + 1;
30 for (ptr
= wrk
->next
;; wrk
= ptr
, ptr
= ptr
->next
) {
31 if (ptr
->size
>= units
) {
32 /* Memory is available, carve requested size from pool */
33 if (ptr
->size
== units
) {
34 wrk
->next
= ptr
->next
;
36 /* Get memory from top address */
45 if (ptr
== allocptr
) break;
48 return NULL
; /* No memory available */
52 ** Name: void free_buff(dpeth_t *dep, void *blk)
53 ** Function: Returns a buffer to the common pool.
55 void free_buff(dpeth_t
*dep
, void *blk
)
57 m_hdr_t
*wrk
, *ptr
= (m_hdr_t
*) blk
- 1;
59 lock(); /* Scan linked list for the correct place */
60 for (wrk
= allocptr
; !(ptr
> wrk
&& ptr
< wrk
->next
); wrk
= wrk
->next
)
61 if (wrk
>= wrk
->next
&& (ptr
> wrk
|| ptr
< wrk
->next
)) break;
63 /* Check if adjacent block is free and join blocks */
64 if (ptr
+ ptr
->size
== wrk
->next
) {
65 ptr
->size
+= wrk
->next
->size
;
66 ptr
->next
= wrk
->next
->next
;
68 ptr
->next
= wrk
->next
;
69 if (wrk
+ wrk
->size
== ptr
) {
70 wrk
->size
+= ptr
->size
;
71 wrk
->next
= ptr
->next
;
74 allocptr
= wrk
; /* Point allocptr to block just released */
80 ** Name: void init_buff(dpeth_t *dep, buff_t **tx_buff)
81 ** Function: Initalizes driver data structures.
83 void init_buff(dpeth_t
*dep
, buff_t
**tx_buff
)
86 /* Initializes buffer pool */
87 if (allocptr
== NULL
) {
88 m_hdr_t
*rx
= (m_hdr_t
*) tx_rx_buff
;
89 rx
->next
= allocptr
= rx
;
93 rx
->size
= (sizeof(tx_rx_buff
) / sizeof(m_hdr_t
)) - 1;
94 free_buff(dep
, rx
+ 1);
95 dep
->de_recvq_tail
= dep
->de_recvq_head
= NULL
;
96 if (tx_buff
!= NULL
) {
97 *tx_buff
= alloc_buff(dep
, ETH_MAX_PACK_SIZE
+ sizeof(buff_t
));
105 ** Name: void mem2user(dpeth_t *dep, buff_t *rxbuff);
106 ** Function: Copies a packet from local buffer to user area.
108 void mem2user(dpeth_t
*dep
, buff_t
*rxbuff
)
111 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
112 int r
, pktsize
= rxbuff
->size
;
113 char *buffer
= rxbuff
->buffer
;
115 do { /* Reads chuncks of packet into user buffers */
117 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
118 if (bytes
> pktsize
) bytes
= pktsize
;
120 /* Reads from Rx buffer to user area */
121 r
= sys_safecopyto(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
, 0,
122 (vir_bytes
)buffer
, bytes
);
124 panic("mem2user: sys_safecopyto failed: %d", r
);
127 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
131 /* Till packet done */
132 } while ((pktsize
-= bytes
) > 0);
137 ** Name: void user2mem(dpeth_t *dep, buff_t *txbuff)
138 ** Function: Copies a packet from user area to local buffer.
140 void user2mem(dpeth_t
*dep
, buff_t
*txbuff
)
143 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
144 int r
, pktsize
= txbuff
->size
;
145 char *buffer
= txbuff
->buffer
;
147 do { /* Reads chuncks of packet from user buffers */
149 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
150 if (bytes
> pktsize
) bytes
= pktsize
;
151 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
152 0, (vir_bytes
)buffer
, bytes
);
154 panic("user2mem: sys_safecopyfrom failed: %d", r
);
157 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
161 /* Till packet done */
162 } while ((pktsize
-= bytes
) > 0);
166 #endif /* HAVE_BUFFERS */