loader: create bio_alloc and bio_free for bios bounce buffer
We do have 16KB buffer space defined in pxe.c, move it to bio.c and implement bio_alloc()/bio_free() interface to make it possible to use this space for other BIOS calls (notably, from biosdisk.c). MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D17131
This commit is contained in:
parent
84fe762ce5
commit
75772fa26e
@ -4,7 +4,7 @@
|
||||
|
||||
LIB= i386
|
||||
|
||||
SRCS= biosacpi.c biosdisk.c biosmem.c biospnp.c \
|
||||
SRCS= bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \
|
||||
biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
|
||||
comconsole.c devicename.c elf32_freebsd.c \
|
||||
elf64_freebsd.c multiboot.c multiboot_tramp.S relocater_tramp.S \
|
||||
|
65
stand/i386/libi386/bio.c
Normal file
65
stand/i386/libi386/bio.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stand.h>
|
||||
#include "libi386.h"
|
||||
|
||||
/*
|
||||
* The idea is borrowed from pxe.c and zfsimpl.c. The original buffer
|
||||
* space in pxe.c was 2x 0x2000. Allocating it from BSS will give us needed
|
||||
* memory below 1MB and usable for real mode calls.
|
||||
*
|
||||
* Note the allocations and frees are to be done in reverse order (LIFO).
|
||||
*/
|
||||
|
||||
static char bio_buffer[BIO_BUFFER_SIZE];
|
||||
static char *bio_buffer_end = bio_buffer + BIO_BUFFER_SIZE;
|
||||
static char *bio_buffer_ptr = bio_buffer;
|
||||
|
||||
void *
|
||||
bio_alloc(size_t size)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = bio_buffer_ptr;
|
||||
if (ptr + size > bio_buffer_end)
|
||||
return (NULL);
|
||||
bio_buffer_ptr += size;
|
||||
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
void
|
||||
bio_free(void *ptr, size_t size)
|
||||
{
|
||||
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
|
||||
bio_buffer_ptr -= size;
|
||||
if (bio_buffer_ptr != ptr)
|
||||
panic("bio_alloc()/bio_free() mismatch\n");
|
||||
}
|
@ -469,10 +469,10 @@ bd_get_diskinfo_ext(struct bdinfo *bd)
|
||||
* Sector size must be a multiple of 512 bytes.
|
||||
* An alternate test would be to check power of 2,
|
||||
* powerof2(params.sector_size).
|
||||
* 4K is largest read buffer we can use at this time.
|
||||
* 16K is largest read buffer we can use at this time.
|
||||
*/
|
||||
if (params.sector_size >= 512 &&
|
||||
params.sector_size <= 4096 &&
|
||||
params.sector_size <= 16384 &&
|
||||
(params.sector_size % BIOSDISK_SECSIZE) == 0)
|
||||
bd->bd_sectorsize = params.sector_size;
|
||||
|
||||
@ -861,8 +861,8 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
||||
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
|
||||
bdinfo_t *bd;
|
||||
uint64_t disk_blocks, offset, d_offset;
|
||||
size_t blks, blkoff, bsize, rest;
|
||||
caddr_t bbuf;
|
||||
size_t blks, blkoff, bsize, bio_size, rest;
|
||||
caddr_t bbuf = NULL;
|
||||
int rc;
|
||||
|
||||
bd = bd_get_bdinfo(&dev->dd);
|
||||
@ -937,14 +937,25 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
||||
DEBUG("short I/O %d", blks);
|
||||
}
|
||||
|
||||
if (V86_IO_BUFFER_SIZE / bd->bd_sectorsize == 0)
|
||||
panic("BUG: Real mode buffer is too small");
|
||||
bio_size = min(BIO_BUFFER_SIZE, size);
|
||||
while (bio_size > bd->bd_sectorsize) {
|
||||
bbuf = bio_alloc(bio_size);
|
||||
if (bbuf != NULL)
|
||||
break;
|
||||
bio_size -= bd->bd_sectorsize;
|
||||
}
|
||||
if (bbuf == NULL) {
|
||||
bio_size = V86_IO_BUFFER_SIZE;
|
||||
if (bio_size / bd->bd_sectorsize == 0)
|
||||
panic("BUG: Real mode buffer is too small");
|
||||
|
||||
bbuf = PTOV(V86_IO_BUFFER);
|
||||
/* Use alternate 4k buffer */
|
||||
bbuf = PTOV(V86_IO_BUFFER);
|
||||
}
|
||||
rest = size;
|
||||
|
||||
rc = 0;
|
||||
while (blks > 0) {
|
||||
int x = min(blks, V86_IO_BUFFER_SIZE / bd->bd_sectorsize);
|
||||
int x = min(blks, bio_size / bd->bd_sectorsize);
|
||||
|
||||
switch (rw & F_MASK) {
|
||||
case F_READ:
|
||||
@ -953,8 +964,10 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
||||
if (rest < bsize)
|
||||
bsize = rest;
|
||||
|
||||
if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0)
|
||||
return (EIO);
|
||||
if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0) {
|
||||
rc = EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bcopy(bbuf + blkoff, buf, bsize);
|
||||
break;
|
||||
@ -986,13 +999,16 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
||||
* Put your Data In, and shake it all about
|
||||
*/
|
||||
bcopy(buf, bbuf + blkoff, bsize);
|
||||
if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_WR)) != 0)
|
||||
return (EIO);
|
||||
if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_WR)) != 0) {
|
||||
rc = EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
/* DO NOTHING */
|
||||
return (EROFS);
|
||||
rc = EROFS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
blkoff = 0;
|
||||
@ -1004,7 +1020,10 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
||||
|
||||
if (rsize != NULL)
|
||||
*rsize = size;
|
||||
return (0);
|
||||
error:
|
||||
if (bbuf != PTOV(V86_IO_BUFFER))
|
||||
bio_free(bbuf, bio_size);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -121,6 +121,11 @@ extern vm_offset_t memtop_copyin; /* memtop less heap size for the cases */
|
||||
extern uint32_t high_heap_size; /* extended memory region available */
|
||||
extern vm_offset_t high_heap_base; /* for use as the heap */
|
||||
|
||||
/* 16KB buffer space for real mode data transfers. */
|
||||
#define BIO_BUFFER_SIZE 0x4000
|
||||
void *bio_alloc(size_t size);
|
||||
void bio_free(void *ptr, size_t size);
|
||||
|
||||
/*
|
||||
* Values for width parameter to biospci_{read,write}_config
|
||||
*/
|
||||
|
@ -48,18 +48,10 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <bootp.h>
|
||||
#include <bootstrap.h>
|
||||
#include "libi386.h"
|
||||
#include "btxv86.h"
|
||||
#include "pxe.h"
|
||||
|
||||
/*
|
||||
* Allocate the PXE buffers statically instead of sticking grimy fingers into
|
||||
* BTX's private data area. The scratch buffer is used to send information to
|
||||
* the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS.
|
||||
*/
|
||||
#define PXE_BUFFER_SIZE 0x2000
|
||||
static char scratch_buffer[PXE_BUFFER_SIZE];
|
||||
static char data_buffer[PXE_BUFFER_SIZE];
|
||||
|
||||
static pxenv_t *pxenv_p = NULL; /* PXENV+ */
|
||||
static pxe_t *pxe_p = NULL; /* !PXE */
|
||||
|
||||
@ -68,9 +60,9 @@ static int pxe_debug = 0;
|
||||
#endif
|
||||
|
||||
void pxe_enable(void *pxeinfo);
|
||||
static void (*pxe_call)(int func);
|
||||
static void pxenv_call(int func);
|
||||
static void bangpxe_call(int func);
|
||||
static void (*pxe_call)(int func, void *ptr);
|
||||
static void pxenv_call(int func, void *ptr);
|
||||
static void bangpxe_call(int func, void *ptr);
|
||||
|
||||
static int pxe_init(void);
|
||||
static int pxe_print(int verbose);
|
||||
@ -225,12 +217,17 @@ pxe_init(void)
|
||||
printf("@%04x:%04x\n",
|
||||
pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset);
|
||||
|
||||
gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer;
|
||||
gci_p = bio_alloc(sizeof(*gci_p));
|
||||
if (gci_p == NULL) {
|
||||
pxe_p = NULL;
|
||||
return (0);
|
||||
}
|
||||
bzero(gci_p, sizeof(*gci_p));
|
||||
gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY;
|
||||
pxe_call(PXENV_GET_CACHED_INFO);
|
||||
pxe_call(PXENV_GET_CACHED_INFO, gci_p);
|
||||
if (gci_p->Status != 0) {
|
||||
pxe_perror(gci_p->Status);
|
||||
bio_free(gci_p, sizeof(*gci_p));
|
||||
pxe_p = NULL;
|
||||
return (0);
|
||||
}
|
||||
@ -240,6 +237,7 @@ pxe_init(void)
|
||||
bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset),
|
||||
bootp_response, bootp_response_size);
|
||||
}
|
||||
bio_free(gci_p, sizeof(*gci_p));
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -262,31 +260,37 @@ pxe_print(int verbose)
|
||||
static void
|
||||
pxe_cleanup(void)
|
||||
{
|
||||
#ifdef PXE_DEBUG
|
||||
t_PXENV_UNLOAD_STACK *unload_stack_p =
|
||||
(t_PXENV_UNLOAD_STACK *)scratch_buffer;
|
||||
t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p =
|
||||
(t_PXENV_UNDI_SHUTDOWN *)scratch_buffer;
|
||||
#endif
|
||||
t_PXENV_UNLOAD_STACK *unload_stack_p;
|
||||
t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p;
|
||||
|
||||
if (pxe_call == NULL)
|
||||
return;
|
||||
|
||||
pxe_call(PXENV_UNDI_SHUTDOWN);
|
||||
undi_shutdown_p = bio_alloc(sizeof(*undi_shutdown_p));
|
||||
if (undi_shutdown_p != NULL) {
|
||||
bzero(undi_shutdown_p, sizeof(*undi_shutdown_p));
|
||||
pxe_call(PXENV_UNDI_SHUTDOWN, undi_shutdown_p);
|
||||
|
||||
#ifdef PXE_DEBUG
|
||||
if (pxe_debug && undi_shutdown_p->Status != 0)
|
||||
printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n",
|
||||
undi_shutdown_p->Status);
|
||||
if (pxe_debug && undi_shutdown_p->Status != 0)
|
||||
printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n",
|
||||
undi_shutdown_p->Status);
|
||||
#endif
|
||||
bio_free(undi_shutdown_p, sizeof(*undi_shutdown_p));
|
||||
}
|
||||
|
||||
pxe_call(PXENV_UNLOAD_STACK);
|
||||
unload_stack_p = bio_alloc(sizeof(*unload_stack_p));
|
||||
if (unload_stack_p != NULL) {
|
||||
bzero(unload_stack_p, sizeof(*unload_stack_p));
|
||||
pxe_call(PXENV_UNLOAD_STACK, unload_stack_p);
|
||||
|
||||
#ifdef PXE_DEBUG
|
||||
if (pxe_debug && unload_stack_p->Status != 0)
|
||||
printf("pxe_cleanup: UNLOAD_STACK failed %x\n",
|
||||
unload_stack_p->Status);
|
||||
if (pxe_debug && unload_stack_p->Status != 0)
|
||||
printf("pxe_cleanup: UNLOAD_STACK failed %x\n",
|
||||
unload_stack_p->Status);
|
||||
#endif
|
||||
bio_free(unload_stack_p, sizeof(*unload_stack_p));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -296,7 +300,7 @@ pxe_perror(int err)
|
||||
}
|
||||
|
||||
void
|
||||
pxenv_call(int func)
|
||||
pxenv_call(int func, void *ptr)
|
||||
{
|
||||
#ifdef PXE_DEBUG
|
||||
if (pxe_debug)
|
||||
@ -304,14 +308,13 @@ pxenv_call(int func)
|
||||
#endif
|
||||
|
||||
bzero(&v86, sizeof(v86));
|
||||
bzero(data_buffer, sizeof(data_buffer));
|
||||
|
||||
__pxenvseg = pxenv_p->RMEntry.segment;
|
||||
__pxenvoff = pxenv_p->RMEntry.offset;
|
||||
|
||||
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
|
||||
v86.es = VTOPSEG(scratch_buffer);
|
||||
v86.edi = VTOPOFF(scratch_buffer);
|
||||
v86.es = VTOPSEG(ptr);
|
||||
v86.edi = VTOPOFF(ptr);
|
||||
v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry);
|
||||
v86.ebx = func;
|
||||
v86int();
|
||||
@ -319,7 +322,7 @@ pxenv_call(int func)
|
||||
}
|
||||
|
||||
void
|
||||
bangpxe_call(int func)
|
||||
bangpxe_call(int func, void *ptr)
|
||||
{
|
||||
#ifdef PXE_DEBUG
|
||||
if (pxe_debug)
|
||||
@ -327,14 +330,13 @@ bangpxe_call(int func)
|
||||
#endif
|
||||
|
||||
bzero(&v86, sizeof(v86));
|
||||
bzero(data_buffer, sizeof(data_buffer));
|
||||
|
||||
__bangpxeseg = pxe_p->EntryPointSP.segment;
|
||||
__bangpxeoff = pxe_p->EntryPointSP.offset;
|
||||
|
||||
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
|
||||
v86.edx = VTOPSEG(scratch_buffer);
|
||||
v86.eax = VTOPOFF(scratch_buffer);
|
||||
v86.edx = VTOPSEG(ptr);
|
||||
v86.eax = VTOPOFF(ptr);
|
||||
v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry);
|
||||
v86.ebx = func;
|
||||
v86int();
|
||||
@ -362,11 +364,14 @@ pxe_netif_end(struct netif *nif)
|
||||
{
|
||||
t_PXENV_UNDI_CLOSE *undi_close_p;
|
||||
|
||||
undi_close_p = (t_PXENV_UNDI_CLOSE *)scratch_buffer;
|
||||
bzero(undi_close_p, sizeof(*undi_close_p));
|
||||
pxe_call(PXENV_UNDI_CLOSE);
|
||||
if (undi_close_p->Status != 0)
|
||||
printf("undi close failed: %x\n", undi_close_p->Status);
|
||||
undi_close_p = bio_alloc(sizeof(*undi_close_p));
|
||||
if (undi_close_p != NULL) {
|
||||
bzero(undi_close_p, sizeof(*undi_close_p));
|
||||
pxe_call(PXENV_UNDI_CLOSE, undi_close_p);
|
||||
if (undi_close_p->Status != 0)
|
||||
printf("undi close failed: %x\n", undi_close_p->Status);
|
||||
bio_free(undi_close_p, sizeof(*undi_close_p));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -377,11 +382,15 @@ pxe_netif_init(struct iodesc *desc, void *machdep_hint)
|
||||
uint8_t *mac;
|
||||
int i, len;
|
||||
|
||||
undi_info_p = (t_PXENV_UNDI_GET_INFORMATION *)scratch_buffer;
|
||||
undi_info_p = bio_alloc(sizeof(*undi_info_p));
|
||||
if (undi_info_p == NULL)
|
||||
return;
|
||||
|
||||
bzero(undi_info_p, sizeof(*undi_info_p));
|
||||
pxe_call(PXENV_UNDI_GET_INFORMATION);
|
||||
pxe_call(PXENV_UNDI_GET_INFORMATION, undi_info_p);
|
||||
if (undi_info_p->Status != 0) {
|
||||
printf("undi get info failed: %x\n", undi_info_p->Status);
|
||||
bio_free(undi_info_p, sizeof(*undi_info_p));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -410,32 +419,44 @@ pxe_netif_init(struct iodesc *desc, void *machdep_hint)
|
||||
else
|
||||
desc->xid = 0;
|
||||
|
||||
undi_open_p = (t_PXENV_UNDI_OPEN *)scratch_buffer;
|
||||
bio_free(undi_info_p, sizeof(*undi_info_p));
|
||||
undi_open_p = bio_alloc(sizeof(*undi_open_p));
|
||||
if (undi_open_p == NULL)
|
||||
return;
|
||||
bzero(undi_open_p, sizeof(*undi_open_p));
|
||||
undi_open_p->PktFilter = FLTR_DIRECTED | FLTR_BRDCST;
|
||||
pxe_call(PXENV_UNDI_OPEN);
|
||||
pxe_call(PXENV_UNDI_OPEN, undi_open_p);
|
||||
if (undi_open_p->Status != 0)
|
||||
printf("undi open failed: %x\n", undi_open_p->Status);
|
||||
bio_free(undi_open_p, sizeof(*undi_open_p));
|
||||
}
|
||||
|
||||
static int
|
||||
pxe_netif_receive(void **pkt)
|
||||
{
|
||||
t_PXENV_UNDI_ISR *isr = (t_PXENV_UNDI_ISR *)scratch_buffer;
|
||||
t_PXENV_UNDI_ISR *isr;
|
||||
char *buf, *ptr, *frame;
|
||||
size_t size, rsize;
|
||||
|
||||
bzero(isr, sizeof(*isr));
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_START;
|
||||
pxe_call(PXENV_UNDI_ISR);
|
||||
if (isr->Status != 0)
|
||||
isr = bio_alloc(sizeof(*isr));
|
||||
if (isr == NULL)
|
||||
return (-1);
|
||||
|
||||
bzero(isr, sizeof(*isr));
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
|
||||
pxe_call(PXENV_UNDI_ISR);
|
||||
if (isr->Status != 0)
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_START;
|
||||
pxe_call(PXENV_UNDI_ISR, isr);
|
||||
if (isr->Status != 0) {
|
||||
bio_free(isr, sizeof(*isr));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bzero(isr, sizeof(*isr));
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
|
||||
pxe_call(PXENV_UNDI_ISR, isr);
|
||||
if (isr->Status != 0) {
|
||||
bio_free(isr, sizeof(*isr));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while (isr->FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
|
||||
/*
|
||||
@ -443,26 +464,31 @@ pxe_netif_receive(void **pkt)
|
||||
*/
|
||||
bzero(isr, sizeof(*isr));
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
|
||||
pxe_call(PXENV_UNDI_ISR);
|
||||
pxe_call(PXENV_UNDI_ISR, isr);
|
||||
if (isr->Status != 0 ||
|
||||
isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE)
|
||||
isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) {
|
||||
bio_free(isr, sizeof(*isr));
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
while (isr->FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE) {
|
||||
if (isr->Status != 0 ||
|
||||
isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) {
|
||||
bio_free(isr, sizeof(*isr));
|
||||
return (-1);
|
||||
}
|
||||
bzero(isr, sizeof(*isr));
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
|
||||
pxe_call(PXENV_UNDI_ISR);
|
||||
pxe_call(PXENV_UNDI_ISR, isr);
|
||||
}
|
||||
|
||||
size = isr->FrameLength;
|
||||
buf = malloc(size + ETHER_ALIGN);
|
||||
if (buf == NULL)
|
||||
if (buf == NULL) {
|
||||
bio_free(isr, sizeof(*isr));
|
||||
return (-1);
|
||||
}
|
||||
ptr = buf + ETHER_ALIGN;
|
||||
rsize = 0;
|
||||
|
||||
@ -475,8 +501,9 @@ pxe_netif_receive(void **pkt)
|
||||
|
||||
bzero(isr, sizeof(*isr));
|
||||
isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
|
||||
pxe_call(PXENV_UNDI_ISR);
|
||||
pxe_call(PXENV_UNDI_ISR, isr);
|
||||
if (isr->Status != 0) {
|
||||
bio_free(isr, sizeof(*isr));
|
||||
free(buf);
|
||||
return (-1);
|
||||
}
|
||||
@ -488,6 +515,7 @@ pxe_netif_receive(void **pkt)
|
||||
}
|
||||
|
||||
*pkt = buf;
|
||||
bio_free(isr, sizeof(*isr));
|
||||
return (rsize);
|
||||
}
|
||||
|
||||
@ -515,26 +543,31 @@ pxe_netif_put(struct iodesc *desc, void *pkt, size_t len)
|
||||
t_PXENV_UNDI_TRANSMIT *trans_p;
|
||||
t_PXENV_UNDI_TBD *tbd_p;
|
||||
char *data;
|
||||
ssize_t rv = -1;
|
||||
|
||||
trans_p = (t_PXENV_UNDI_TRANSMIT *)scratch_buffer;
|
||||
bzero(trans_p, sizeof(*trans_p));
|
||||
tbd_p = (t_PXENV_UNDI_TBD *)(scratch_buffer + sizeof(*trans_p));
|
||||
bzero(tbd_p, sizeof(*tbd_p));
|
||||
trans_p = bio_alloc(sizeof(*trans_p));
|
||||
tbd_p = bio_alloc(sizeof(*tbd_p));
|
||||
data = bio_alloc(len);
|
||||
|
||||
data = scratch_buffer + sizeof(*trans_p) + sizeof(*tbd_p);
|
||||
if (trans_p != NULL && tbd_p != NULL && data != NULL) {
|
||||
bzero(trans_p, sizeof(*trans_p));
|
||||
bzero(tbd_p, sizeof(*tbd_p));
|
||||
|
||||
trans_p->TBD.segment = VTOPSEG(tbd_p);
|
||||
trans_p->TBD.offset = VTOPOFF(tbd_p);
|
||||
trans_p->TBD.segment = VTOPSEG(tbd_p);
|
||||
trans_p->TBD.offset = VTOPOFF(tbd_p);
|
||||
|
||||
tbd_p->ImmedLength = len;
|
||||
tbd_p->Xmit.segment = VTOPSEG(data);
|
||||
tbd_p->Xmit.offset = VTOPOFF(data);
|
||||
bcopy(pkt, data, len);
|
||||
tbd_p->ImmedLength = len;
|
||||
tbd_p->Xmit.segment = VTOPSEG(data);
|
||||
tbd_p->Xmit.offset = VTOPOFF(data);
|
||||
bcopy(pkt, data, len);
|
||||
|
||||
pxe_call(PXENV_UNDI_TRANSMIT);
|
||||
if (trans_p->Status != 0) {
|
||||
return (-1);
|
||||
pxe_call(PXENV_UNDI_TRANSMIT, trans_p);
|
||||
if (trans_p->Status == 0)
|
||||
rv = len;
|
||||
}
|
||||
|
||||
return (len);
|
||||
bio_free(data, len);
|
||||
bio_free(tbd_p, sizeof(*tbd_p));
|
||||
bio_free(trans_p, sizeof(*trans_p));
|
||||
return (rv);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user