Implemented UNDI ethernet interface, receiving frames already appears to work.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19628 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -70,12 +70,23 @@ public:
|
||||
|
||||
private:
|
||||
mac_addr_t fMACAddress;
|
||||
bool fRxFinished;
|
||||
PXE_STRUCT * fPxeData;
|
||||
};
|
||||
|
||||
|
||||
UNDI::UNDI()
|
||||
: fMACAddress()
|
||||
, fRxFinished(true)
|
||||
, fPxeData(NULL)
|
||||
{
|
||||
TRACE("UNDI::UNDI\n");
|
||||
|
||||
fPxeData = pxe_undi_find_data();
|
||||
if (!fPxeData)
|
||||
panic("can't find !PXE structure");
|
||||
|
||||
TRACE("PXE API entrypoint at %04x:%04x\n", fPxeData->EntryPointSP.seg, fPxeData->EntryPointSP.ofs);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +100,61 @@ status_t
|
||||
UNDI::Init()
|
||||
{
|
||||
TRACE("UNDI::Init\n");
|
||||
return B_OK;
|
||||
|
||||
PXENV_UNDI_GET_INFORMATION get_info;
|
||||
PXENV_UNDI_GET_STATE get_state;
|
||||
PXENV_UNDI_OPEN undi_open;
|
||||
uint16 res;
|
||||
|
||||
undi_open.OpenFlag = 0;
|
||||
undi_open.PktFilter = FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS;
|
||||
undi_open.R_Mcast_Buf.MCastAddrCount = 0;
|
||||
|
||||
res = call_pxe_bios(fPxeData, UNDI_OPEN, &undi_open);
|
||||
if (res != 0 || get_state.Status != 0) {
|
||||
TRACE("PXENV_UNDI_OPEN failed, res %x, status %x\n", res, undi_open.Status);
|
||||
}
|
||||
|
||||
res = call_pxe_bios(fPxeData, UNDI_GET_STATE, &get_state);
|
||||
if (res != 0 || get_state.Status != 0) {
|
||||
TRACE("PXENV_UNDI_GET_STATE failed, res %x, status %x\n", res, get_state.Status);
|
||||
} else {
|
||||
switch (get_state.UNDIstate) {
|
||||
case PXE_UNDI_GET_STATE_STARTED:
|
||||
TRACE("PXE_UNDI_GET_STATE_STARTED\n");
|
||||
break;
|
||||
case PXE_UNDI_GET_STATE_INITIALIZED:
|
||||
TRACE("PXE_UNDI_GET_STATE_INITIALIZED\n");
|
||||
break;
|
||||
case PXE_UNDI_GET_STATE_OPENED:
|
||||
TRACE("PXE_UNDI_GET_STATE_OPENED\n");
|
||||
break;
|
||||
default:
|
||||
TRACE("unknown undi state 0x%02x\n", get_state.UNDIstate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
res = call_pxe_bios(fPxeData, UNDI_GET_INFORMATION, &get_info);
|
||||
if (res != 0 || get_info.Status != 0) {
|
||||
TRACE("PXENV_UNDI_GET_INFORMATION failed, res %x, status %x\n", res, get_info.Status);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE("Status = %x\n", get_info.Status);
|
||||
TRACE("BaseIo = %x\n", get_info.BaseIo);
|
||||
TRACE("IntNumber = %x\n", get_info.IntNumber);
|
||||
TRACE("MaxTranUnit = %x\n", get_info.MaxTranUnit);
|
||||
TRACE("HwType = %x\n", get_info.HwType);
|
||||
TRACE("HwAddrLen = %x\n", get_info.HwAddrLen);
|
||||
TRACE("RxBufCt = %x\n", get_info.RxBufCt);
|
||||
TRACE("TxBufCt = %x\n", get_info.TxBufCt);
|
||||
|
||||
fMACAddress = get_info.CurrentNodeAddress;
|
||||
|
||||
TRACE("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", fMACAddress[0], fMACAddress[1], fMACAddress[2], fMACAddress[3], fMACAddress[4], fMACAddress[5]);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +164,15 @@ UNDI::MACAddress() const
|
||||
return fMACAddress;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
UNDI::AllocateSendReceiveBuffer(size_t size)
|
||||
{
|
||||
TRACE("UNDI::AllocateSendReceiveBuffer, size %ld\n", size);
|
||||
return 0;
|
||||
if (size > 0x3000)
|
||||
return NULL;
|
||||
|
||||
return (void *)0x500;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,16 +186,120 @@ UNDI::FreeSendReceiveBuffer(void *buffer)
|
||||
ssize_t
|
||||
UNDI::Send(const void *buffer, size_t size)
|
||||
{
|
||||
TRACE("UNDI::Send, size %ld\n", size);
|
||||
return 0;
|
||||
TRACE("UNDI::Send, buffer %p, size %ld\n", buffer, size);
|
||||
|
||||
hex_dump(buffer, size);
|
||||
|
||||
PXENV_UNDI_TRANSMIT undi_tx;
|
||||
PXENV_UNDI_TBD undi_tbd;
|
||||
|
||||
undi_tx.Protocol = P_UNKNOWN;
|
||||
undi_tx.XmitFlag = XMT_DESTADDR;
|
||||
undi_tx.DestAddr.seg = SEG((char *)buffer + 16);
|
||||
undi_tx.DestAddr.ofs = OFS((char *)buffer + 16);
|
||||
undi_tx.TBD.seg = SEG(&undi_tbd);
|
||||
undi_tx.TBD.ofs = OFS(&undi_tbd);
|
||||
|
||||
undi_tbd.ImmedLength = size;
|
||||
undi_tbd.Xmit.seg = SEG(buffer);
|
||||
undi_tbd.Xmit.ofs = OFS(buffer);
|
||||
undi_tbd.DataBlkCount = 1;
|
||||
undi_tbd.DataBlock[0].TDPtrType = 1;
|
||||
undi_tbd.DataBlock[0].TDRsvdByte = 0;
|
||||
undi_tbd.DataBlock[0].TDDataLen = size;
|
||||
undi_tbd.DataBlock[0].TDDataPtr.seg = SEG(buffer);
|
||||
undi_tbd.DataBlock[0].TDDataPtr.ofs = OFS(buffer);
|
||||
|
||||
uint16 res = call_pxe_bios(fPxeData, UNDI_TRANSMIT, &undi_tx);
|
||||
if (res != 0 || undi_tx.Status != 0) {
|
||||
TRACE("UNDI_TRANSMIT failed, res %x, status %x\n", res, undi_tx.Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE("UNDI_TRANSMIT success\n");
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
UNDI::Receive(void *buffer, size_t size)
|
||||
{
|
||||
TRACE("UNDI::Receive, size %ld\n", size);
|
||||
return 0;
|
||||
//TRACE("UNDI::Receive, buffer %p, size %ld\n", buffer, size);
|
||||
|
||||
PXENV_UNDI_ISR undi_isr;
|
||||
uint16 res;
|
||||
|
||||
if (!fRxFinished) {
|
||||
TRACE("continue receive...\n");
|
||||
|
||||
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
|
||||
res = call_pxe_bios(fPxeData, UNDI_ISR, &undi_isr);
|
||||
if (res != 0 || undi_isr.Status != 0) {
|
||||
TRACE("PXENV_UNDI_ISR_IN_GET_NEXT failed, res %x, status %x\n", res, undi_isr.Status);
|
||||
fRxFinished = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
|
||||
|
||||
res = call_pxe_bios(fPxeData, UNDI_ISR, &undi_isr);
|
||||
if (res != 0 || undi_isr.Status != 0) {
|
||||
TRACE("PXENV_UNDI_ISR_IN_START failed, res %x, status %x\n", res, undi_isr.Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS) {
|
||||
// TRACE("not ours\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// send EOI to pic ?
|
||||
|
||||
TRACE("PXENV_UNDI_ISR_OUT_OURS\n");
|
||||
|
||||
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
|
||||
res = call_pxe_bios(fPxeData, UNDI_ISR, &undi_isr);
|
||||
if (res != 0 || undi_isr.Status != 0) {
|
||||
TRACE("PXENV_UNDI_ISR_IN_PROCESS failed, res %x, status %x\n", res, undi_isr.Status);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (undi_isr.FuncFlag) {
|
||||
case PXENV_UNDI_ISR_OUT_TRANSMIT:
|
||||
TRACE("PXENV_UNDI_ISR_OUT_TRANSMIT\n");
|
||||
fRxFinished = false;
|
||||
return 0;
|
||||
|
||||
case PXENV_UNDI_ISR_OUT_RECEIVE:
|
||||
TRACE("PXENV_UNDI_ISR_OUT_RECEIVE\n");
|
||||
TRACE("BufferLength %d\n", undi_isr.BufferLength);
|
||||
TRACE("FrameLength %d\n", undi_isr.FrameLength);
|
||||
TRACE("FrameHeaderLength %d\n", undi_isr.FrameHeaderLength);
|
||||
if (size > undi_isr.BufferLength)
|
||||
size = undi_isr.BufferLength;
|
||||
memcpy(buffer, (const void *)(undi_isr.Frame.seg * 16 + undi_isr.Frame.ofs), size);
|
||||
hex_dump(buffer, size);
|
||||
fRxFinished = false;
|
||||
return size;
|
||||
|
||||
case PXENV_UNDI_ISR_OUT_BUSY:
|
||||
TRACE("PXENV_UNDI_ISR_OUT_BUSY\n");
|
||||
fRxFinished = true;
|
||||
return 0;
|
||||
|
||||
case PXENV_UNDI_ISR_OUT_DONE:
|
||||
TRACE("PXENV_UNDI_ISR_OUT_DONE\n");
|
||||
fRxFinished = true;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
TRACE("default!!!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,14 +308,13 @@ platform_net_stack_init()
|
||||
{
|
||||
TRACE("platform_net_stack_init\n");
|
||||
|
||||
pxe_undi_init();
|
||||
|
||||
UNDI *interface = new(nothrow) UNDI;
|
||||
if (!interface)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = interface->Init();
|
||||
if (error != B_OK) {
|
||||
TRACE("platform_net_stack_init: interface init failed\n");
|
||||
delete interface;
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
PXE_STRUCT *gPxeData;
|
||||
|
||||
|
||||
PXE_STRUCT *
|
||||
pxe_undi_find_data()
|
||||
{
|
||||
@@ -35,39 +30,3 @@ pxe_undi_find_data()
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pxe_undi_init()
|
||||
{
|
||||
TRACE("pxe_undi_init\n");
|
||||
|
||||
gPxeData = pxe_undi_find_data();
|
||||
if (!gPxeData)
|
||||
panic("can't find !PXE structure");
|
||||
|
||||
TRACE("entrypoint at %p\n", *(uint32 *)&gPxeData->EntryPointSP);
|
||||
|
||||
|
||||
PXENV_UNDI_GET_INFORMATION get_info;
|
||||
|
||||
memset(&get_info, 0, sizeof(get_info));
|
||||
|
||||
TRACE("PXENV_UNDI_GET_INFORMATION at %p\n", &get_info);
|
||||
|
||||
uint16 res = call_pxe_bios(gPxeData, UNDI_GET_INFORMATION, &get_info);
|
||||
|
||||
TRACE("res = %04x\n", res);
|
||||
|
||||
TRACE("Status = %x\n", get_info.Status);
|
||||
TRACE("BaseIo = %x\n", get_info.BaseIo);
|
||||
TRACE("IntNumber = %x\n", get_info.IntNumber);
|
||||
TRACE("MaxTranUnit = %x\n", get_info.MaxTranUnit);
|
||||
TRACE("HwType = %x\n", get_info.HwType);
|
||||
TRACE("HwAddrLen = %x\n", get_info.HwAddrLen);
|
||||
TRACE("MAC = %02x:%02x:%02x:%02x:%02x:%02x\n", get_info.CurrentNodeAddress[0], get_info.CurrentNodeAddress[1],
|
||||
get_info.CurrentNodeAddress[2], get_info.CurrentNodeAddress[3],
|
||||
get_info.CurrentNodeAddress[4], get_info.CurrentNodeAddress[5] );
|
||||
TRACE("RxBufCt = %x\n", get_info.RxBufCt);
|
||||
TRACE("TxBufCt = %x\n", get_info.TxBufCt);
|
||||
}
|
||||
|
||||
@@ -8,11 +8,17 @@
|
||||
|
||||
extern "C" uint16 call_pxe_bios(void *pxe, uint16 opcode, void *param);
|
||||
|
||||
void pxe_undi_init();
|
||||
|
||||
|
||||
|
||||
#define UNDI_OPEN 0x0006
|
||||
#define UNDI_TRANSMIT 0x0008
|
||||
#define UNDI_GET_INFORMATION 0x000C
|
||||
#define UNDI_ISR 0x0014
|
||||
#define UNDI_GET_STATE 0x0015
|
||||
|
||||
#define SEG(ptr) ((uint16)(((uint32)(ptr)) >> 4))
|
||||
#define OFS(ptr) (((uint16)(ptr)) & 15)
|
||||
|
||||
#define MAC_ADDR_LEN 16
|
||||
typedef uint8 MAC_ADDR[MAC_ADDR_LEN];
|
||||
|
||||
struct SEGSEL
|
||||
{
|
||||
@@ -21,8 +27,8 @@ struct SEGSEL
|
||||
|
||||
struct SEGOFF16
|
||||
{
|
||||
uint16 seg;
|
||||
uint16 ofs;
|
||||
uint16 seg;
|
||||
};
|
||||
|
||||
struct SEGDESC
|
||||
@@ -54,6 +60,34 @@ struct PXE_STRUCT
|
||||
SEGDESC BC_CodeWrite;
|
||||
};
|
||||
|
||||
struct PXENV_UNDI_MCAST_ADDRESS
|
||||
{
|
||||
#define MAXNUM_MCADDR 8
|
||||
uint16 MCastAddrCount;
|
||||
MAC_ADDR McastAddr[MAXNUM_MCADDR];
|
||||
};
|
||||
|
||||
struct PXENV_UNDI_OPEN
|
||||
{
|
||||
uint16 Status;
|
||||
uint16 OpenFlag;
|
||||
uint16 PktFilter;
|
||||
#define FLTR_DIRECTED 0x0001
|
||||
#define FLTR_BRDCST 0x0002
|
||||
#define FLTR_PRMSCS 0x0004
|
||||
#define FLTR_SRC_RTG 0x0008
|
||||
PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
|
||||
};
|
||||
|
||||
struct PXENV_UNDI_GET_STATE
|
||||
{
|
||||
#define PXE_UNDI_GET_STATE_STARTED 1
|
||||
#define PXE_UNDI_GET_STATE_INITIALIZED 2
|
||||
#define PXE_UNDI_GET_STATE_OPENED 3
|
||||
uint16 Status;
|
||||
uint8 UNDIstate;
|
||||
};
|
||||
|
||||
struct PXENV_UNDI_GET_INFORMATION
|
||||
{
|
||||
uint16 Status;
|
||||
@@ -66,12 +100,75 @@ struct PXENV_UNDI_GET_INFORMATION
|
||||
#define IEEE_TYPE 6
|
||||
#define ARCNET_TYPE 7
|
||||
uint16 HwAddrLen;
|
||||
uint8 CurrentNodeAddress[16];
|
||||
uint8 PermNodeAddress[16];
|
||||
MAC_ADDR CurrentNodeAddress;
|
||||
MAC_ADDR PermNodeAddress;
|
||||
SEGSEL ROMAddress;
|
||||
uint16 RxBufCt;
|
||||
uint16 TxBufCt;
|
||||
};
|
||||
|
||||
struct PXENV_UNDI_TRANSMIT
|
||||
{
|
||||
uint16 Status;
|
||||
uint8 Protocol;
|
||||
#define P_UNKNOWN 0
|
||||
#define P_IP 1
|
||||
#define P_ARP 2
|
||||
#define P_RARP 3
|
||||
uint8 XmitFlag;
|
||||
#define XMT_DESTADDR 0x0000
|
||||
#define XMT_BROADCAST 0x0001
|
||||
SEGOFF16 DestAddr;
|
||||
SEGOFF16 TBD;
|
||||
uint32 Reserved[2];
|
||||
};
|
||||
|
||||
#define MAX_DATA_BLKS 8
|
||||
struct PXENV_UNDI_TBD
|
||||
{
|
||||
uint16 ImmedLength;
|
||||
SEGOFF16 Xmit;
|
||||
uint16 DataBlkCount;
|
||||
struct DataBlk
|
||||
{
|
||||
uint8 TDPtrType;
|
||||
uint8 TDRsvdByte;
|
||||
uint16 TDDataLen;
|
||||
SEGOFF16 TDDataPtr;
|
||||
} DataBlock[MAX_DATA_BLKS];
|
||||
};
|
||||
|
||||
struct PXENV_UNDI_ISR
|
||||
{
|
||||
uint16 Status;
|
||||
uint16 FuncFlag;
|
||||
uint16 BufferLength;
|
||||
uint16 FrameLength;
|
||||
uint16 FrameHeaderLength;
|
||||
SEGOFF16 Frame;
|
||||
uint8 ProtType;
|
||||
uint8 PktType;
|
||||
};
|
||||
|
||||
#define PXENV_UNDI_ISR_IN_START 1
|
||||
#define PXENV_UNDI_ISR_IN_PROCESS 2
|
||||
#define PXENV_UNDI_ISR_IN_GET_NEXT 3
|
||||
|
||||
/* One of these will be returned for
|
||||
PXENV_UNDI_ISR_IN_START
|
||||
*/
|
||||
#define PXENV_UNDI_ISR_OUT_OURS 0
|
||||
#define PXENV_UNDI_USR_OUT_NOT_OURS 1
|
||||
|
||||
/* One of these will be returned for
|
||||
PXENV_UNDI_ISR_IN_PROCESS and
|
||||
PXENV_UNDI_ISR_IN_GET_NEXT
|
||||
*/
|
||||
#define PXENV_UNDI_ISR_OUT_DONE 0
|
||||
#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
|
||||
#define PXENV_UNDI_ISR_OUT_RECEIVE 3
|
||||
#define PXENV_UNDI_ISR_OUT_BUSY 4
|
||||
|
||||
PXE_STRUCT * pxe_undi_find_data();
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user