/* ** Name: void el3_write_fifo(dpeth_t * dep, int pktsize); ** Function: Writes a packet from user area to board. ** Remark: Writing a word/dword at a time may result faster ** but is a lot more complicated. Let's go simpler way. */ static void el3_write_fifo(dpeth_t * dep, int pktsize) { int bytes, ix = 0; iovec_dat_s_t *iovp = &dep->de_write_iovec; int r, padding = pktsize; do { /* Writes chuncks of packet from user buffers */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ if (bytes > pktsize) bytes = pktsize; /* Writes from user buffer to Tx FIFO */ r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, bytes); if (r != OK) panic("el3_write_fifo: sys_safe_outsb failed: %d", r); if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00); return; }
/* ** Name: void pio_user2nic(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from user area to board (Prog. I/O). */ static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize) { iovec_dat_s_t *iovp = &dep->de_write_iovec; int r, bytes, ix = 0; /* Sets up board for writing */ ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE); do { /* Reads chuncks of packet from user area */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */ if (bytes > pktsize) bytes = pktsize; r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, bytes); if (r != OK) panic("pio_user2nic: sys_safe_outsb failed: %d", r); if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); for (ix = 0; ix < 100; ix += 1) { if (inb_reg0(dep, DP_ISR) & ISR_RDC) break; } if (ix == 100) { panic(RdmaErrMsg); } return; }
/* ** Name: void user2mem(dpeth_t *dep, buff_t *txbuff) ** Function: Copies a packet from user area to local buffer. */ void user2mem(dpeth_t *dep, buff_t *txbuff) { int bytes, ix = 0; iovec_dat_s_t *iovp = &dep->de_write_iovec; int r, pktsize = txbuff->size; char *buffer = txbuff->buffer; do { /* Reads chuncks of packet from user buffers */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ if (bytes > pktsize) bytes = pktsize; r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, (vir_bytes)buffer, bytes); if (r != OK) panic("user2mem: sys_safecopyfrom failed: %d", r); buffer += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); return; }
/* ** Name: void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from user area to board (shared memory). */ static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) { #if 1 panic("mem_user2nic: not converted to safecopies"); #else phys_bytes offset, phys_user; iovec_dat_s_t *iovp = &dep->de_write_iovec; int bytes, ix = 0; /* Computes shared memory address */ offset = pageno * DP_PAGESIZE; do { /* Reads chuncks of packet from user area */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */ if (bytes > pktsize) bytes = pktsize; /* Reads from user area to board (shared memory) */ sys_user2nic_s(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, dep->de_linmem + offset, bytes); offset += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); return; #endif }
/* ** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from user area to board (Prog. I/O, 16bits). */ static void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize) { u8_t two_bytes[2]; phys_bytes phys_user, phys_2bytes = vir2phys(two_bytes); vir_bytes ecount = (pktsize + 1) & NOT(0x0001); int bytes, ix = 0, odd_byte = 0; iovec_dat_t *iovp = &dep->de_write_iovec; outb_reg0(dep, DP_ISR, ISR_RDC); dp_read_setup(dep, ecount, pageno * DP_PAGESIZE); do { bytes = iovp->iod_iovec[ix].iov_size; if (bytes > pktsize) bytes = pktsize; phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, bytes); if (!phys_user) panic(UmapErrMsg); if (odd_byte) { phys_copy(phys_user, phys_2bytes + 1, (phys_bytes) 1); out_word(dep->de_data_port, *(u16_t *)two_bytes); pktsize--; bytes--; phys_user++; odd_byte = 0; if (!bytes) continue; } ecount = bytes & NOT(0x0001); if (ecount != 0) { phys_outsw(dep->de_data_port, phys_user, ecount); pktsize -= ecount; bytes -= ecount; phys_user += ecount; } if (bytes) { phys_copy(phys_user, phys_2bytes, (phys_bytes) 1); pktsize--; bytes--; phys_user++; odd_byte = 1; } if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */ dp_next_iovec(iovp); ix = 0; } } while (bytes > 0); if (odd_byte) out_word(dep->de_data_port, *(u16_t *) two_bytes); for (ix = 0; ix < 100; ix++) { if (inb_reg0(dep, DP_ISR) & ISR_RDC) break; } if (ix == 100) { panic(RdmaErrMsg); } return; }
/* ** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from board to user area (Prog. I/O, 16bits). */ static void dp_pio16_nic2user(dpeth_t * dep, int nic_addr, int count) { phys_bytes phys_user; vir_bytes ecount; int bytes, i; u8_t two_bytes[2]; phys_bytes phys_2bytes; int odd_byte; ecount = (count + 1) & ~1; phys_2bytes = vir2phys(two_bytes); odd_byte = 0; dp_read_setup(dep, ecount, nic_addr); i = 0; while (count > 0) { if (i >= IOVEC_NR) { dp_next_iovec(iovp); i = 0; continue; } bytes = iovp->iod_iovec[i].iov_size; if (bytes > count) bytes = count; phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr, bytes); if (!phys_user) panic(UmapErrMsg); if (odd_byte) { phys_copy(phys_2bytes + 1, phys_user, (phys_bytes) 1); count--; bytes--; phys_user++; odd_byte = 0; if (!bytes) continue; } ecount = bytes & ~1; if (ecount != 0) { phys_insw(dep->de_data_port, phys_user, ecount); count -= ecount; bytes -= ecount; phys_user += ecount; } if (bytes) { *(u16_t *) two_bytes = in_word(dep->de_data_port); phys_copy(phys_2bytes, phys_user, (phys_bytes) 1); count--; bytes--; phys_user++; odd_byte = 1; } } return; }
/* ** Name: void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from board to user area (Prog. I/O). */ static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) { iovec_dat_s_t *iovp = &dep->de_read_iovec; unsigned offset, iov_offset; int r, bytes, ix = 0; /* Computes memory address (skipping receive header) */ offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); /* Sets up board for reading */ ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ? (dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset); iov_offset= 0; do { /* Reads chuncks of packet into user area */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */ if (bytes > pktsize) bytes = pktsize; if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) { /* Circular buffer wrap-around */ bytes = dep->de_stoppage * DP_PAGESIZE - offset; r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, iov_offset, bytes); if (r != OK) { panic("pio_nic2user: sys_safe_insb failed: %d", r); } pktsize -= bytes; iov_offset += bytes; bytes = iovp->iod_iovec[ix].iov_size - bytes; if (bytes > pktsize) bytes = pktsize; offset = dep->de_startpage * DP_PAGESIZE; ns_rw_setup(dep, CR_DM_RR, pktsize, offset); } r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, iov_offset, bytes); if (r != OK) panic("pio_nic2user: sys_safe_insb failed: %d", r); offset += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } iov_offset= 0; /* Till packet done */ } while ((pktsize -= bytes) > 0); return; }
/* ** Name: int calc_iovec_size(iovec_dat_t *iovp) ** Function: Compute the size of a request. */ static int calc_iovec_size(iovec_dat_s_t * iovp) { int size, ix; size = ix = 0; do { size += iovp->iod_iovec[ix].iov_size; if (++ix >= IOVEC_NR) { dp_next_iovec(iovp); ix = 0; } /* Till all vectors added */ } while (ix < iovp->iod_iovec_s); return size; }
/* ** Name: void mem_nic2user(dpeth_t *dep, int pageno, int pktsize); ** Function: Copies a packet from board to user area (shared memory). */ static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize) { panic("mem_nic2user: not converted to safecopies"); #if 0 phys_bytes offset; iovec_dat_s_t *iovp = &dep->de_read_iovec; int bytes, ix = 0; /* Computes shared memory address (skipping receive header) */ offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); do { /* Reads chuncks of packet into user area */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */ if (bytes > pktsize) bytes = pktsize; /* Reads from board to user area */ if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) { /* Circular buffer wrap-around */ bytes = dep->de_stoppage * DP_PAGESIZE - offset; sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, bytes); pktsize -= bytes; phys_user += bytes; bytes = iovp->iod_iovec[ix].iov_size - bytes; if (bytes > pktsize) bytes = pktsize; offset = dep->de_startpage * DP_PAGESIZE; } sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, bytes); offset += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); return; #endif }
/* ** Name: void el3_write_fifo(dpeth_t * dep, int pktsize); ** Function: Writes a packet from user area to board. ** Remark: Writing a word/dword at a time may result faster ** but is a lot more complicated. Let's go simpler way. */ static void el3_write_fifo(dpeth_t * dep, int pktsize) { phys_bytes phys_user; int bytes, ix = 0; iovec_dat_t *iovp = &dep->de_write_iovec; int padding = pktsize; do { /* Writes chuncks of packet from user buffers */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ if (bytes > pktsize) bytes = pktsize; /* Writes from user buffer to Tx FIFO */ outsb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes); if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00); return; }