freebsd compat. layer: a couple more definitions, minimal, mostly adding a new glue method to re-enable device interrupts since if_rl (rtl 8139) will require it.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21092 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-05-09 15:27:13 +00:00
parent d081ee7b5b
commit 2a275df505
12 changed files with 373 additions and 19 deletions
@@ -2,7 +2,8 @@
HAIKU_FBSD_DRIVER_GLUE(e1000, em, pci) HAIKU_FBSD_DRIVER_GLUE(e1000, em, pci)
NO_HAIKU_CHECK_DISABLE_INTERRUPTS() NO_HAIKU_CHECK_DISABLE_INTERRUPTS();
NO_HAIKU_REENABLE_INTERRUPTS();
#ifdef EM_FAST_INTR #ifdef EM_FAST_INTR
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE); HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE);
@@ -451,11 +451,11 @@ am79900_intr(void *arg)
isr = (*sc->sc_rdcsr)(sc, LE_CSR0); isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
#endif #endif
{ {
cpu_status status; HAIKU_INTR_REGISTER_STATE;
HAIKU_INTR_REGISTER_ENTER(status); HAIKU_INTR_REGISTER_ENTER();
isr = sc->sc_lastisr; isr = sc->sc_lastisr;
sc->sc_lastisr = 0; sc->sc_lastisr = 0;
HAIKU_INTR_REGISTER_LEAVE(status); HAIKU_INTR_REGISTER_LEAVE();
} }
#if defined(LEDEBUG) && LEDEBUG > 1 #if defined(LEDEBUG) && LEDEBUG > 1
@@ -32,10 +32,10 @@ struct le_pci_softc {
int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) { int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) {
struct le_pci_softc *lesc = (struct le_pci_softc *)device_get_softc(dev); struct le_pci_softc *lesc = (struct le_pci_softc *)device_get_softc(dev);
cpu_status status; HAIKU_INTR_REGISTER_STATE;
uint16_t value; uint16_t value;
HAIKU_INTR_REGISTER_ENTER(status); HAIKU_INTR_REGISTER_ENTER();
/* get current flags */ /* get current flags */
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, LE_CSR0); bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, LE_CSR0);
@@ -54,7 +54,9 @@ int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) {
lesc->sc_am79900.lsc.sc_lastisr |= value; lesc->sc_am79900.lsc.sc_lastisr |= value;
} }
HAIKU_INTR_REGISTER_LEAVE(status); HAIKU_INTR_REGISTER_LEAVE();
return value & LE_C0_INTR; return value & LE_C0_INTR;
} }
NO_HAIKU_REENABLE_INTERRUPTS();
@@ -195,33 +195,33 @@ static void
le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
{ {
struct le_pci_softc *lesc = (struct le_pci_softc *)sc; struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
cpu_status status = 0; HAIKU_INTR_REGISTER_STATE;
if (port == LE_CSR0) if (port == LE_CSR0)
HAIKU_INTR_REGISTER_ENTER(status); HAIKU_INTR_REGISTER_ENTER();
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port); bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2, bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
BUS_SPACE_BARRIER_WRITE); BUS_SPACE_BARRIER_WRITE);
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val); bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val);
if (port == LE_CSR0) if (port == LE_CSR0)
HAIKU_INTR_REGISTER_LEAVE(status); HAIKU_INTR_REGISTER_LEAVE();
} }
static uint16_t static uint16_t
le_pci_rdcsr(struct lance_softc *sc, uint16_t port) le_pci_rdcsr(struct lance_softc *sc, uint16_t port)
{ {
struct le_pci_softc *lesc = (struct le_pci_softc *)sc; struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
cpu_status status = 0; HAIKU_INTR_REGISTER_STATE;
uint16_t value; uint16_t value;
if (port == LE_CSR0) if (port == LE_CSR0)
HAIKU_INTR_REGISTER_ENTER(status); HAIKU_INTR_REGISTER_ENTER();
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port); bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2, bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
BUS_SPACE_BARRIER_WRITE); BUS_SPACE_BARRIER_WRITE);
value = bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP); value = bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP);
if (port == LE_CSR0) if (port == LE_CSR0)
HAIKU_INTR_REGISTER_LEAVE(status); HAIKU_INTR_REGISTER_LEAVE();
return value; return value;
} }
+1
View File
@@ -212,6 +212,7 @@ intr_handler(void *data)
device_printf(intr->dev, "in soft interrupt handler.\n"); device_printf(intr->dev, "in soft interrupt handler.\n");
intr->handler(intr->arg); intr->handler(intr->arg);
HAIKU_REENABLE_INTERRUPTS(intr->dev);
} }
return 0; return 0;
+3
View File
@@ -314,6 +314,9 @@ _kernel_contigmalloc(const char *file, int line, size_t size, int flags,
if (area < 0) if (area < 0)
return NULL; return NULL;
if (flags & M_ZERO)
memset(addr, 0, size);
driver_printf("(%s) addr = %p, area = %ld, size = %lu\n", driver_printf("(%s) addr = %p, area = %ld, size = %lu\n",
name, addr, area, size); name, addr, area, size);
@@ -0,0 +1,206 @@
/* $NetBSD: mii.h,v 1.9 2001/05/31 03:07:14 thorpej Exp $ */
/*-
* Copyright (c) 1997 Manuel Bouyer. All rights reserved.
*
* Modification to match BSD/OS 3.0 MII interface by Jason R. Thorpe,
* Numerical Aerospace Simulation Facility, NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/dev/mii/mii.h,v 1.5 2005/01/06 01:42:56 imp Exp $
*/
#ifndef _DEV_MII_MII_H_
#define _DEV_MII_MII_H_
/*
* Registers common to all PHYs.
*/
#define MII_NPHY 32 /* max # of PHYs per MII */
/*
* MII commands, used if a device must drive the MII lines
* manually.
*/
#define MII_COMMAND_START 0x01
#define MII_COMMAND_READ 0x02
#define MII_COMMAND_WRITE 0x01
#define MII_COMMAND_ACK 0x02
#define MII_BMCR 0x00 /* Basic mode control register (rw) */
#define BMCR_RESET 0x8000 /* reset */
#define BMCR_LOOP 0x4000 /* loopback */
#define BMCR_SPEED0 0x2000 /* speed selection (LSB) */
#define BMCR_AUTOEN 0x1000 /* autonegotiation enable */
#define BMCR_PDOWN 0x0800 /* power down */
#define BMCR_ISO 0x0400 /* isolate */
#define BMCR_STARTNEG 0x0200 /* restart autonegotiation */
#define BMCR_FDX 0x0100 /* Set duplex mode */
#define BMCR_CTEST 0x0080 /* collision test */
#define BMCR_SPEED1 0x0040 /* speed selection (MSB) */
#define BMCR_S10 0x0000 /* 10 Mb/s */
#define BMCR_S100 BMCR_SPEED0 /* 100 Mb/s */
#define BMCR_S1000 BMCR_SPEED1 /* 1000 Mb/s */
#define BMCR_SPEED(x) ((x) & (BMCR_SPEED0|BMCR_SPEED1))
#define MII_BMSR 0x01 /* Basic mode status register (ro) */
#define BMSR_100T4 0x8000 /* 100 base T4 capable */
#define BMSR_100TXFDX 0x4000 /* 100 base Tx full duplex capable */
#define BMSR_100TXHDX 0x2000 /* 100 base Tx half duplex capable */
#define BMSR_10TFDX 0x1000 /* 10 base T full duplex capable */
#define BMSR_10THDX 0x0800 /* 10 base T half duplex capable */
#define BMSR_100T2FDX 0x0400 /* 100 base T2 full duplex capable */
#define BMSR_100T2HDX 0x0200 /* 100 base T2 half duplex capable */
#define BMSR_EXTSTAT 0x0100 /* Extended status in register 15 */
#define BMSR_MFPS 0x0040 /* MII Frame Preamble Suppression */
#define BMSR_ACOMP 0x0020 /* Autonegotiation complete */
#define BMSR_RFAULT 0x0010 /* Link partner fault */
#define BMSR_ANEG 0x0008 /* Autonegotiation capable */
#define BMSR_LINK 0x0004 /* Link status */
#define BMSR_JABBER 0x0002 /* Jabber detected */
#define BMSR_EXTCAP 0x0001 /* Extended capability */
/*
* Note that the EXTSTAT bit indicates that there is extended status
* info available in register 15, but 802.3 section 22.2.4.3 also
* states that that all 1000 Mb/s capable PHYs will set this bit to 1.
*/
#if 0
#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX|BMSR_10TFDX| \
BMSR_10THDX|BMSR_ANEG)
#else
/* NetBSD uses: */
#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX| \
BMSR_10TFDX|BMSR_10THDX|BMSR_100T2FDX|BMSR_100T2HDX)
#endif
/*
* Convert BMSR media capabilities to ANAR bits for autonegotiation.
* Note the shift chopps off the BMSR_ANEG bit.
*/
#define BMSR_MEDIA_TO_ANAR(x) (((x) & BMSR_MEDIAMASK) >> 6)
#define MII_PHYIDR1 0x02 /* ID register 1 (ro) */
#define MII_PHYIDR2 0x03 /* ID register 2 (ro) */
#define IDR2_OUILSB 0xfc00 /* OUI LSB */
#define IDR2_MODEL 0x03f0 /* vendor model */
#define IDR2_REV 0x000f /* vendor revision */
#define MII_OUI(id1, id2) (((id1) << 6) | ((id2) >> 10))
#define MII_MODEL(id2) (((id2) & IDR2_MODEL) >> 4)
#define MII_REV(id2) ((id2) & IDR2_REV)
#define MII_ANAR 0x04 /* Autonegotiation advertisement (rw) */
/* section 28.2.4.1 and 37.2.6.1 */
#define ANAR_NP 0x8000 /* Next page (ro) */
#define ANAR_ACK 0x4000 /* link partner abilities acknowledged (ro) */
#define ANAR_RF 0x2000 /* remote fault (ro) */
#define ANAR_FC 0x0400 /* local device supports PAUSE */
#define ANAR_T4 0x0200 /* local device supports 100bT4 */
#define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */
#define ANAR_TX 0x0080 /* local device supports 100bTx */
#define ANAR_10_FD 0x0040 /* local device supports 10bT FD */
#define ANAR_10 0x0020 /* local device supports 10bT */
#define ANAR_CSMA 0x0001 /* protocol selector CSMA/CD */
#define ANAR_X_FD 0x0020 /* local device supports 1000BASE-X FD */
#define ANAR_X_HD 0x0040 /* local device supports 1000BASE-X HD */
#define ANAR_X_PAUSE_NONE (0 << 7)
#define ANAR_X_PAUSE_SYM (1 << 7)
#define ANAR_X_PAUSE_ASYM (2 << 7)
#define ANAR_X_PAUSE_TOWARDS (3 << 7)
#define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
/* section 28.2.4.1 and 37.2.6.1 */
#define ANLPAR_NP 0x8000 /* Next page (ro) */
#define ANLPAR_ACK 0x4000 /* link partner accepted ACK (ro) */
#define ANLPAR_RF 0x2000 /* remote fault (ro) */
#define ANLPAR_FC 0x0400 /* link partner supports PAUSE */
#define ANLPAR_T4 0x0200 /* link partner supports 100bT4 */
#define ANLPAR_TX_FD 0x0100 /* link partner supports 100bTx FD */
#define ANLPAR_TX 0x0080 /* link partner supports 100bTx */
#define ANLPAR_10_FD 0x0040 /* link partner supports 10bT FD */
#define ANLPAR_10 0x0020 /* link partner supports 10bT */
#define ANLPAR_CSMA 0x0001 /* protocol selector CSMA/CD */
#define ANLPAR_X_FD 0x0020 /* local device supports 1000BASE-X FD */
#define ANLPAR_X_HD 0x0040 /* local device supports 1000BASE-X HD */
#define ANLPAR_X_PAUSE_MASK (3 << 7)
#define ANLPAR_X_PAUSE_NONE (0 << 7)
#define ANLPAR_X_PAUSE_SYM (1 << 7)
#define ANLPAR_X_PAUSE_ASYM (2 << 7)
#define ANLPAR_X_PAUSE_TOWARDS (3 << 7)
#define MII_ANER 0x06 /* Autonegotiation expansion (ro) */
/* section 28.2.4.1 and 37.2.6.1 */
#define ANER_MLF 0x0010 /* multiple link detection fault */
#define ANER_LPNP 0x0008 /* link parter next page-able */
#define ANER_NP 0x0004 /* next page-able */
#define ANER_PAGE_RX 0x0002 /* Page received */
#define ANER_LPAN 0x0001 /* link parter autoneg-able */
#define MII_ANNP 0x07 /* Autonegotiation next page */
/* section 28.2.4.1 and 37.2.6.1 */
#define MII_ANLPRNP 0x08 /* Autonegotiation link partner rx next page */
/* section 32.5.1 and 37.2.6.1 */
/* This is also the 1000baseT control register */
#define MII_100T2CR 0x09 /* 100base-T2 control register */
#define GTCR_TEST_MASK 0xe000 /* see 802.3ab ss. 40.6.1.1.2 */
#define GTCR_MAN_MS 0x1000 /* enable manual master/slave control */
#define GTCR_ADV_MS 0x0800 /* 1 = adv. master, 0 = adv. slave */
#define GTCR_PORT_TYPE 0x0400 /* 1 = DCE, 0 = DTE (NIC) */
#define GTCR_ADV_1000TFDX 0x0200 /* adv. 1000baseT FDX */
#define GTCR_ADV_1000THDX 0x0100 /* adv. 1000baseT HDX */
/* This is also the 1000baseT status register */
#define MII_100T2SR 0x0a /* 100base-T2 status register */
#define GTSR_MAN_MS_FLT 0x8000 /* master/slave config fault */
#define GTSR_MS_RES 0x4000 /* result: 1 = master, 0 = slave */
#define GTSR_LRS 0x2000 /* local rx status, 1 = ok */
#define GTSR_RRS 0x1000 /* remove rx status, 1 = ok */
#define GTSR_LP_1000TFDX 0x0800 /* link partner 1000baseT FDX capable */
#define GTSR_LP_1000THDX 0x0400 /* link partner 1000baseT HDX capable */
#define GTSR_LP_ASM_DIR 0x0200 /* link partner asym. pause dir. capable */
#define GTSR_IDLE_ERR 0x00ff /* IDLE error count */
#define MII_EXTSR 0x0f /* Extended status register */
#define EXTSR_1000XFDX 0x8000 /* 1000X full-duplex capable */
#define EXTSR_1000XHDX 0x4000 /* 1000X half-duplex capable */
#define EXTSR_1000TFDX 0x2000 /* 1000T full-duplex capable */
#define EXTSR_1000THDX 0x1000 /* 1000T half-duplex capable */
#define EXTSR_MEDIAMASK (EXTSR_1000XFDX|EXTSR_1000XHDX| \
EXTSR_1000TFDX|EXTSR_1000THDX)
#endif /* _DEV_MII_MII_H_ */
@@ -37,6 +37,9 @@ uint32_t bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
void bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t handle, void bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t handle,
bus_size_t offset, uint32_t value); bus_size_t offset, uint32_t value);
#define bus_space_write_stream_4(t, h, o, v) \
bus_space_write_4((t), (h), (o), (v))
#define BUS_SPACE_BARRIER_READ 1 #define BUS_SPACE_BARRIER_READ 1
#define BUS_SPACE_BARRIER_WRITE 2 #define BUS_SPACE_BARRIER_WRITE 2
@@ -81,8 +81,10 @@ extern const char gDriverName[];
extern spinlock __haiku_intr_spinlock; extern spinlock __haiku_intr_spinlock;
extern int __haiku_disable_interrupts(device_t dev); extern int __haiku_disable_interrupts(device_t dev);
extern void __haiku_reenable_interrupts(device_t dev);
#define HAIKU_CHECK_DISABLE_INTERRUPTS __haiku_disable_interrupts #define HAIKU_CHECK_DISABLE_INTERRUPTS __haiku_disable_interrupts
#define HAIKU_REENABLE_INTERRUPTS __haiku_reenable_interrupts
#define NO_HAIKU_CHECK_DISABLE_INTERRUPTS() \ #define NO_HAIKU_CHECK_DISABLE_INTERRUPTS() \
int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) { \ int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) { \
@@ -90,6 +92,9 @@ extern int __haiku_disable_interrupts(device_t dev);
return -1; \ return -1; \
} }
#define NO_HAIKU_REENABLE_INTERRUPTS() \
void HAIKU_REENABLE_INTERRUPTS(device_t dev) {}
extern int __haiku_driver_requirements; extern int __haiku_driver_requirements;
enum { enum {
@@ -103,14 +108,24 @@ enum {
#define HAIKU_DRIVER_REQUIRES(flag) (__haiku_driver_requirements & (flag)) #define HAIKU_DRIVER_REQUIRES(flag) (__haiku_driver_requirements & (flag))
#define HAIKU_INTR_REGISTER_ENTER(status) do { \ #define HAIKU_INTR_REGISTER_STATE \
status = disable_interrupts(); \ cpu_status __haiku_cpu_state = 0
#define HAIKU_INTR_REGISTER_ENTER() do { \
__haiku_cpu_state = disable_interrupts(); \
acquire_spinlock(&__haiku_intr_spinlock); \ acquire_spinlock(&__haiku_intr_spinlock); \
} while (0) } while (0)
#define HAIKU_INTR_REGISTER_LEAVE(status) do { \ #define HAIKU_INTR_REGISTER_LEAVE() do { \
release_spinlock(&__haiku_intr_spinlock); \ release_spinlock(&__haiku_intr_spinlock); \
restore_interrupts(status); \ restore_interrupts(__haiku_cpu_state); \
} while (0)
#define HAIKU_PROTECT_INTR_REGISTER(x) do { \
HAIKU_INTR_REGISTER_STATE; \
HAIKU_INTR_REGISTER_ENTER(); \
x; \
HAIKU_INTR_REGISTER_LEAVE(); \
} while (0) } while (0)
#define DEFINE_CLASS_0(name, driver, methods, size) \ #define DEFINE_CLASS_0(name, driver, methods, size) \
@@ -103,6 +103,11 @@ u_int m_fixhdr(struct mbuf *m);
void m_cat(struct mbuf *m, struct mbuf *n); void m_cat(struct mbuf *m, struct mbuf *n);
void m_copydata(const struct mbuf *m, int off, int len, caddr_t cp); void m_copydata(const struct mbuf *m, int off, int len, caddr_t cp);
struct ifnet;
struct mbuf *m_devget(char *, int, int, struct ifnet *,
void (*)(char *, caddr_t, u_int));
void m_copyback(struct mbuf *, int, int, caddr_t);
struct mbuf *m_get(int how, short type); struct mbuf *m_get(int how, short type);
struct mbuf *m_gethdr(int how, short type); struct mbuf *m_gethdr(int how, short type);
void m_clget(struct mbuf *m, int how); void m_clget(struct mbuf *m, int how);
@@ -120,6 +125,7 @@ void m_clget(struct mbuf *m, int how);
#define MBUF_CHECKSLEEP(how) do { } while (0) #define MBUF_CHECKSLEEP(how) do { } while (0)
#define MBTOM(how) (how) #define MBTOM(how) (how)
extern int max_linkhdr;
extern int max_protohdr; extern int max_protohdr;
#include <sys/mbuf-fbsd.h> #include <sys/mbuf-fbsd.h>
+116
View File
@@ -404,3 +404,119 @@ m_move_pkthdr(struct mbuf *to, struct mbuf *from)
#endif #endif
from->m_flags &= ~M_PKTHDR; from->m_flags &= ~M_PKTHDR;
} }
/*
* Routine to copy from device local memory into mbufs.
* Note that `off' argument is offset into first mbuf of target chain from
* which to begin copying the data to.
*/
struct mbuf *
m_devget(char *buf, int totlen, int off, struct ifnet *ifp,
void (*copy)(char *from, caddr_t to, u_int len))
{
struct mbuf *m;
struct mbuf *top = NULL, **mp = &top;
int len;
if (off < 0 || off > MHLEN)
return (NULL);
while (totlen > 0) {
if (top == NULL) { /* First one, must be PKTHDR */
if (totlen + off >= MINCLSIZE) {
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
len = MCLBYTES;
} else {
m = m_gethdr(M_DONTWAIT, MT_DATA);
len = MHLEN;
/* Place initial small packet/header at end of mbuf */
if (m && totlen + off + max_linkhdr <= MLEN) {
m->m_data += max_linkhdr;
len -= max_linkhdr;
}
}
if (m == NULL)
return NULL;
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = totlen;
} else {
if (totlen + off >= MINCLSIZE) {
m = m_getcl(M_DONTWAIT, MT_DATA, 0);
len = MCLBYTES;
} else {
m = m_get(M_DONTWAIT, MT_DATA);
len = MLEN;
}
if (m == NULL) {
m_freem(top);
return NULL;
}
}
if (off) {
m->m_data += off;
len -= off;
off = 0;
}
m->m_len = len = min(totlen, len);
if (copy)
copy(buf, mtod(m, caddr_t), (u_int)len);
else
bcopy(buf, mtod(m, caddr_t), (u_int)len);
buf += len;
*mp = m;
mp = &m->m_next;
totlen -= len;
}
return (top);
}
/*
* Copy data from a buffer back into the indicated mbuf chain,
* starting "off" bytes from the beginning, extending the mbuf
* chain if necessary.
*/
void
m_copyback(struct mbuf *m0, int off, int len, caddr_t cp)
{
int mlen;
struct mbuf *m = m0, *n;
int totlen = 0;
if (m0 == NULL)
return;
while (off > (mlen = m->m_len)) {
off -= mlen;
totlen += mlen;
if (m->m_next == NULL) {
n = m_get(M_DONTWAIT, m->m_type);
if (n == NULL)
goto out;
bzero(mtod(n, caddr_t), MLEN);
n->m_len = min(MLEN, len + off);
m->m_next = n;
}
m = m->m_next;
}
while (len > 0) {
mlen = min (m->m_len - off, len);
bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen);
cp += mlen;
len -= mlen;
mlen += off;
off = 0;
totlen += mlen;
if (len == 0)
break;
if (m->m_next == NULL) {
n = m_get(M_DONTWAIT, m->m_type);
if (n == NULL)
break;
n->m_len = min(MLEN, len);
m->m_next = n;
}
m = m->m_next;
}
out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
m->m_pkthdr.len = totlen;
}
+1
View File
@@ -22,6 +22,7 @@
static object_cache *sMBufCache; static object_cache *sMBufCache;
static object_cache *sChunkCache; static object_cache *sChunkCache;
int max_linkhdr = 16;
int max_protohdr = 40 + 20; /* ip6 + tcp */ int max_protohdr = 40 + 20; /* ip6 + tcp */