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 10 #include <minix/drivers.h> 11 #include <net/gen/ether.h> 12 #include <net/gen/eth_io.h> 13 #include "dp.h" 14 15 #if (HAVE_BUFFERS == 1) 16 17 static m_hdr_t *allocptr = NULL; 18 static char tx_rx_buff[8192]; 19 20 /* 21 ** Name: void *alloc_buff(dpeth_t *dep, int size) 22 ** Function: Allocates a buffer from the common pool. 23 */ 24 void *alloc_buff(dpeth_t *dep, int size) 25 { 26 m_hdr_t *ptr, *wrk = allocptr; 27 int units = ((size + sizeof(m_hdr_t) - 1) / sizeof(m_hdr_t)) + 1; 28 29 lock(); 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; 35 } else { 36 /* Get memory from top address */ 37 ptr->size -= units; 38 ptr += ptr->size; 39 ptr->size = units; 40 } 41 allocptr = wrk; 42 unlock(); 43 return ptr + 1; 44 } 45 if (ptr == allocptr) break; 46 } 47 unlock(); 48 return NULL; /* No memory available */ 49 } 50 51 /* 52 ** Name: void free_buff(dpeth_t *dep, void *blk) 53 ** Function: Returns a buffer to the common pool. 54 */ 55 void free_buff(dpeth_t *dep, void *blk) 56 { 57 m_hdr_t *wrk, *ptr = (m_hdr_t *) blk - 1; 58 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; 62 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; 67 } else 68 ptr->next = wrk->next; 69 if (wrk + wrk->size == ptr) { 70 wrk->size += ptr->size; 71 wrk->next = ptr->next; 72 } else 73 wrk->next = ptr; 74 allocptr = wrk; /* Point allocptr to block just released */ 75 unlock(); 76 return; 77 } 78 79 /* 80 ** Name: void init_buff(dpeth_t *dep, buff_t **tx_buff) 81 ** Function: Initalizes driver data structures. 82 */ 83 void init_buff(dpeth_t *dep, buff_t **tx_buff) 84 { 85 86 /* Initializes buffer pool */ 87 if (allocptr == NULL) { 88 m_hdr_t *rx = (m_hdr_t *) tx_rx_buff; 89 rx->next = allocptr = rx; 90 rx->size = 0; 91 rx += 1; 92 rx->next = NULL; 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)); 98 (*tx_buff)->size = 0; 99 } 100 } 101 return; /* Done */ 102 } 103 104 /* 105 ** Name: void mem2user(dpeth_t *dep, buff_t *rxbuff); 106 ** Function: Copies a packet from local buffer to user area. 107 */ 108 void mem2user(dpeth_t *dep, buff_t *rxbuff) 109 { 110 int bytes, ix = 0; 111 iovec_dat_s_t *iovp = &dep->de_read_iovec; 112 int r, pktsize = rxbuff->size; 113 char *buffer = rxbuff->buffer; 114 115 do { /* Reads chuncks of packet into user buffers */ 116 117 bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ 118 if (bytes > pktsize) bytes = pktsize; 119 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); 123 if (r != OK) 124 panic("mem2user: sys_safecopyto failed: %d", r); 125 buffer += bytes; 126 127 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ 128 dp_next_iovec(iovp); 129 ix = 0; 130 } 131 /* Till packet done */ 132 } while ((pktsize -= bytes) > 0); 133 return; 134 } 135 136 /* 137 ** Name: void user2mem(dpeth_t *dep, buff_t *txbuff) 138 ** Function: Copies a packet from user area to local buffer. 139 */ 140 void user2mem(dpeth_t *dep, buff_t *txbuff) 141 { 142 int bytes, ix = 0; 143 iovec_dat_s_t *iovp = &dep->de_write_iovec; 144 int r, pktsize = txbuff->size; 145 char *buffer = txbuff->buffer; 146 147 do { /* Reads chuncks of packet from user buffers */ 148 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); 153 if (r != OK) 154 panic("user2mem: sys_safecopyfrom failed: %d", r); 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 **/ 169