source: trunk/minix/drivers/dpeth/netbuff.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 4.1 KB
Line 
1/*
2** File: netbuff.c Jun. 10, 2000
3**
4** Author: Giovanni Falzoni <gfalzoni@inwind.it>
5**
6** This file contains specific implementation of buffering
7** for network packets.
8**
9** $Id: netbuff.c,v 1.3 2005/08/05 19:08:43 beng Exp $
10*/
11
12#include "drivers.h"
13#include <net/gen/ether.h>
14#include <net/gen/eth_io.h>
15#include "dp.h"
16
17#if (HAVE_BUFFERS == 1)
18
19static m_hdr_t *allocptr = NULL;
20static char tx_rx_buff[8192];
21
22/*
23** Name: void *alloc_buff(dpeth_t *dep, int size)
24** Function: Allocates a buffer from the common pool.
25*/
26PUBLIC void *alloc_buff(dpeth_t *dep, int size)
27{
28 m_hdr_t *ptr, *wrk = allocptr;
29 int units = ((size + sizeof(m_hdr_t) - 1) / sizeof(m_hdr_t)) + 1;
30
31 lock();
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;
37 } else {
38 /* Get memory from top address */
39 ptr->size -= units;
40 ptr += ptr->size;
41 ptr->size = units;
42 }
43 allocptr = wrk;
44 unlock();
45 return ptr + 1;
46 }
47 if (ptr == allocptr) break;
48 }
49 unlock();
50 return NULL; /* No memory available */
51}
52
53/*
54** Name: void free_buff(dpeth_t *dep, void *blk)
55** Function: Returns a buffer to the common pool.
56*/
57PUBLIC void free_buff(dpeth_t *dep, void *blk)
58{
59 m_hdr_t *wrk, *ptr = (m_hdr_t *) blk - 1;
60
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;
64
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;
69 } else
70 ptr->next = wrk->next;
71 if (wrk + wrk->size == ptr) {
72 wrk->size += ptr->size;
73 wrk->next = ptr->next;
74 } else
75 wrk->next = ptr;
76 allocptr = wrk; /* Point allocptr to block just released */
77 unlock();
78 return;
79}
80
81/*
82** Name: void init_buff(dpeth_t *dep, buff_t **tx_buff)
83** Function: Initalizes driver data structures.
84*/
85PUBLIC void init_buff(dpeth_t *dep, buff_t **tx_buff)
86{
87
88 /* Initializes buffer pool */
89 if (allocptr == NULL) {
90 m_hdr_t *rx = (m_hdr_t *) tx_rx_buff;
91 rx->next = allocptr = rx;
92 rx->size = 0;
93 rx += 1;
94 rx->next = NULL;
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;
101 }
102 }
103 return; /* Done */
104}
105
106/*
107** Name: void mem2user(dpeth_t *dep, buff_t *rxbuff);
108** Function: Copies a packet from local buffer to user area.
109*/
110PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff)
111{
112 phys_bytes phys_user;
113 int bytes, ix = 0;
114 iovec_dat_t *iovp = &dep->de_read_iovec;
115 int pktsize = rxbuff->size;
116 char *buffer = rxbuff->buffer;
117
118 do { /* Reads chuncks of packet into user buffers */
119
120 bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
121 if (bytes > pktsize) bytes = pktsize;
122
123 /* Reads from Rx buffer to user area */
124 sys_datacopy(SELF, (vir_bytes)buffer, iovp->iod_proc_nr,
125 iovp->iod_iovec[ix].iov_addr, bytes);
126 buffer += bytes;
127
128 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
129 dp_next_iovec(iovp);
130 ix = 0;
131 }
132 /* Till packet done */
133 } while ((pktsize -= bytes) > 0);
134 return;
135}
136
137/*
138** Name: void user2mem(dpeth_t *dep, buff_t *txbuff)
139** Function: Copies a packet from user area to local buffer.
140*/
141PUBLIC void user2mem(dpeth_t *dep, buff_t *txbuff)
142{
143 phys_bytes phys_user;
144 int bytes, ix = 0;
145 iovec_dat_t *iovp = &dep->de_write_iovec;
146 int pktsize = txbuff->size;
147 char *buffer = txbuff->buffer;
148
149 do { /* Reads chuncks of packet from user buffers */
150
151 bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
152 if (bytes > pktsize) bytes = pktsize;
153 sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr,
154 SELF, (vir_bytes)buffer, bytes);
155 buffer += bytes;
156
157 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
158 dp_next_iovec(iovp);
159 ix = 0;
160 }
161 /* Till packet done */
162 } while ((pktsize -= bytes) > 0);
163 return;
164}
165
166#endif /* HAVE_BUFFERS */
167
168/** netbuff.c **/
Note: See TracBrowser for help on using the repository browser.