?? bclient.c
字號(hào):
/* @(#) pSOSystem PowerPC/V2.2.2: drivers/bclient.c (&U&) 2.7 97/11/04 17:08:09 */
/***********************************************************************/
/* */
/* MODULE: drivers/bootp/bclient.c */
/* DATE: 97/11/04 */
/* PURPOSE: Contains routines that implement the BOOTP protocol. */
/* */
/*---------------------------------------------------------------------*/
/* */
/* Copyright 1991 - 1996, Integrated Systems, Inc. */
/* ALL RIGHTS RESERVED */
/* */
/* Permission is hereby granted to licensees of Integrated Systems, */
/* Inc. products to use or abstract this computer program for the */
/* sole purpose of implementing a product based on Integrated */
/* Systems, Inc. products. No other rights to reproduce, use, */
/* or disseminate this computer program, whether in part or in */
/* whole, are granted. */
/* */
/* Integrated Systems, Inc. makes no representation or warranties */
/* with respect to the performance of this computer program, and */
/* specifically disclaims any responsibility for any damages, */
/* special or consequential, connected with the use of this program. */
/* */
/*---------------------------------------------------------------------*/
/* */
/* */
/* */
/***********************************************************************/
#include <psos.h>
#include "bsp.h"
#include <pna.h>
#include <pna_mib.h>
#include <bspfuncs.h>
#include <ip_udp.h>
#include <bootp.h>
#include <configs.h>
#include <types.h>
/*---------------------------------------------------------------------*/
/* The node anchor address is a pointer to the node configuration */
/* table, which in turn points to the pSOS+ configuration table. This */
/* driver will look in the pSOS+ configuration table to see how many */
/* ticks per second are specified, and thus how many interrupts per */
/* second to generate. */
/*---------------------------------------------------------------------*/
extern NODE_CT *anchor;
/*---------------------------------------------------------------------*/
/* This code can be compiled for use with either a zero-copy LAN */
/* driver or a non-zero-copy LAN driver. */
/*---------------------------------------------------------------------*/
#define NI_RAWMEM (BSP_LAN1_FLAGS & IFF_RAWMEM)
/***********************************************************************/
/* NI interface for Bootp */
/***********************************************************************/
#define BOOTP_IFNUM 188
/***********************************************************************/
/* IP header for BOOTP packet */
/***********************************************************************/
static USHORT ip_id = 1000000 & 0xFFFF; /* IP header id */
/***********************************************************************/
/* Initial transaction ID for BOOTP packet */
/***********************************************************************/
static ULONG InitialXid = -1000000;
/***********************************************************************/
/* PsosUp indicates if pSOS is up when get_bootp_params is called */
/***********************************************************************/
static ULONG PsosUp;
/***********************************************************************/
/* Seconds elapsed since first BOOTP packet was sent out */
/***********************************************************************/
static USHORT SecsSinceStart;
static char Bootp_Replied;
static UCHAR *EthAddrPtr;
static bootppkt_t BootpReplyPkt;
static char BootpServerName[64];
static char BootpFileName[128];
static char BootpBuf[IP_SZ + UDP_SZ + BOOTP_SZ];
static ULONG BootpXid;
static long (*MyNiLan)(ULONG, union nientry *);
/***********************************************************************/
/* Functions used */
/***********************************************************************/
static ULONG process_bootp(int type, char *buff_addr);
static ULONG broadcast_bootp(long (*NiLanPtr)());
static ULONG extract_bootpkt(bootppkt_t *bootp, bootpparms_t *retp);
static USHORT in_cksum(UCHAR *addr, int count);
static void bootp_ip_packet(char *bootpbuf);
static void strcpy(UCHAR *src, UCHAR *dst);
static void bmemset(UCHAR *ptr, register UCHAR fill, register ULONG count);
static void bmemcpy(UCHAR *src, UCHAR *dest, ULONG nbytes);
static void sleep(int count);
extern char *strncpy(char *, const char *, unsigned char);
#if NI_RAWMEM
#define NR_MBLKS 20
/*---------------------------------------------------------------------*/
/* We will maintain a list of mblks which will be allocated and freed */
/* by besballoc() and bfreemsg(). */
/*---------------------------------------------------------------------*/
static mblk_t *bm_freelist; /* head of free list of message blocks */
static mblk_t bm[NR_MBLKS]; /* message blocks */
static dblk_t db[NR_MBLKS]; /* associated data blocks */
/***********************************************************************/
/* ballocb: Allocate a message block */
/* bfreeb: Free a message block */
/* */
/* NOTE: These are unimplemented */
/* */
/***********************************************************************/
static mblk_t *ballocb(long size, long pri) {return NULL;}
static void bfreeb(mblk_t *bp) {}
/***********************************************************************/
/* init_bmbuf: Initialize the mblk free list */
/* */
/* NOTE: Each mblk gets a data block attached to it. The mblks */
/* are linked together in the "free" list, using the */
/* b_next field. */
/***********************************************************************/
static void init_bmbuf(void)
{
int i;
for (i = 0; i < NR_MBLKS; i++)
{
bmemset((unsigned char *)&bm[i], 0, sizeof(mblk_t));
bmemset((unsigned char *)&db[i], 0, sizeof(dblk_t));
bm[i].b_datap = &db[i]; /* attach data block */
bm[i].b_next = &bm[i+1];
}
bm[NR_MBLKS - 1].b_next = 0;
bm_freelist = &bm[0];
}
/***********************************************************************/
/* besballoc: Attach a message block to a buffer */
/* */
/* INPUTS: base: ptr to buffer */
/* size: length of buffer in bytes */
/* pri: ignored */
/* frtn: ptr to struct describing routine to be called */
/* when buffer is to be freed */
/* */
/* RETURNS: ptr to msg block */
/* */
/***********************************************************************/
static mblk_t *besballoc(UCHAR *base, int size, int pri, frtn_t *frtn)
{
register mblk_t *pmblk;
register unsigned long om;
if (base == NULL || frtn == NULL)
return(NULL);
/*---------------------------------------------------------------------*/
/* Get a msg block from the free list (if one is available) */
/*---------------------------------------------------------------------*/
om = splx(MAX_ILEV);
if (pmblk = bm_freelist)
{
bm_freelist = bm_freelist->b_next;
pmblk->b_next = 0;
}
else
{
splx(om);
return(NULL);
}
splx(om);
/*---------------------------------------------------------------------*/
/* Fill in the msg block and its associated data block */
/*---------------------------------------------------------------------*/
pmblk->b_rptr = base;
pmblk->b_wptr = base;
pmblk->b_datap->db_base = base;
pmblk->b_datap->db_lim = (UCHAR *)(base + size + 1);
pmblk->b_datap->db_ref = 1;
pmblk->b_datap->db_frtn = *frtn;
return(pmblk);
}
/***********************************************************************/
/* bfreemsg: Free a message block and its associated buffer, if */
/* there is one. */
/* */
/* INPUTS: mp: ptr to message block triplet */
/* */
/* RETURNS: */
/* OUTPUTS: */
/* NOTE(S): */
/* */
/***********************************************************************/
static void bfreemsg(mblk_t *mp)
{
unsigned long om;
om = splx(MAX_ILEV);
if (mp->b_datap->db_frtn.free_func)
(mp->b_datap->db_frtn.free_func)(mp->b_datap->db_frtn.free_arg);
mp->b_next = bm_freelist;
bm_freelist = mp;
splx(om);
}
#endif /* NI_RAWMEM */
/***********************************************************************/
/* */
/* get_bootp_params: Obtain BOOTP reply packet for a specified */
/* NI interface. */
/* */
/***********************************************************************/
ULONG get_bootp_params(long (*ni_entry)(ULONG, union nientry *),
char *bootp_file_name,
char *bootp_server_name,
int num_retries,
int flags,
char *ret_params)
{
union nientry init_ni, poll_ni;
int wait_count;
int next_retry = 1;
struct ni_funcs NiFuncs;
unsigned long retval;
/*---------------------------------------------------------------------*/
/* Initialize the "mbuf manager" */
/*---------------------------------------------------------------------*/
#if NI_RAWMEM
init_bmbuf();
#endif
/*---------------------------------------------------------------------*/
/* Get Pointer to NI interface used to RARP and initialize that NI. */
/*---------------------------------------------------------------------*/
MyNiLan = (long (*)())ni_entry;
/*---------------------------------------------------------------------*/
/* Set niinit.ap_addr to "process_rarp" the function that the network */
/* interface (driver) will call to process incoming packets. */
/*---------------------------------------------------------------------*/
init_ni.niinit.ap_addr = (long(*)()) process_bootp;
init_ni.niinit.if_num = BOOTP_IFNUM; /* My interface number */
init_ni.niinit.ip_addr = 0; /* Redundant but needed */
#if NI_RAWMEM
init_ni.niinit.funcs = &NiFuncs;
NiFuncs.allocb = ballocb;
NiFuncs.freeb = bfreeb;
NiFuncs.freemsg = bfreemsg;
NiFuncs.esballoc = besballoc;
#endif
/*---------------------------------------------------------------------*/
/* Call network interface initialization function. It will return the */
/* hardware address of this interface. */
/*---------------------------------------------------------------------*/
EthAddrPtr = (UCHAR *)(*ni_entry)(NI_INIT, &init_ni);
/*---------------------------------------------------------------------*/
/* Check to see if the NI init failed, don't continue if it has. */
/*---------------------------------------------------------------------*/
if (EthAddrPtr == (UCHAR *)-1)
return 0xffffffff;
poll_ni.nipoll.if_num = BOOTP_IFNUM;
if (num_retries == 0)
num_retries = BOOTP_RETRIES;
Bootp_Replied = FALSE;
bmemset((UCHAR *)BootpServerName, 0, sizeof(BootpServerName));
bmemset((UCHAR *)BootpFileName, 0, sizeof(BootpFileName));
if (bootp_server_name)
strcpy((UCHAR *)bootp_server_name, (UCHAR *)BootpServerName);
if (bootp_file_name)
strcpy((UCHAR *)bootp_file_name, (UCHAR *)BootpFileName);
SecsSinceStart = 0;
if ((flags & PSOSUP) == PSOSUP)
PsosUp = 1;
else
PsosUp = 0;
#if NI_RAWMEM
bootp_ip_packet(BootpBuf);
#endif
/*---------------------------------------------------------------------*/
/* Send a BOOTP request, poll the NI, and check if the poll caused a */
/* RARP response to occur. This sequence is repeated "retry" times. */
/* During each retry, two NI polls are done, 1 second apart to give */
/* the RARP server a chance to reply. */
/*---------------------------------------------------------------------*/
while (num_retries && !Bootp_Replied)
{
if (broadcast_bootp((long (*)())ni_entry) != 0)
return (0xffffffff);
wait_count = next_retry;
while (!Bootp_Replied && wait_count) {
(*ni_entry)(NI_POLL, &poll_ni);
--wait_count;
sleep(1);
};
SecsSinceStart += next_retry;
if (next_retry < 60)
next_retry *= 2;
--num_retries;
};
/*---------------------------------------------------------------------*/
/* We've fallen through the loop, if there was BOOTP reply then return */
/* the IP address for this board, else return a 0. The LanStop() */
/* routine is always called to prevent further BOOTP responses from */
/* being delivered (and DMAed into memory). */
/*---------------------------------------------------------------------*/
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -