Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

334 lines
9.3 KiB

/*--------------------------------------------------------------------------
| admin.c - Ethernet common admin-packet handling. Includes common
admin. packet handling code.
6-17-97 - start using index field assigned to box to id rx-messages.
Copyright 1996,97 Comtrol Corporation. All rights reserved. Proprietary
information not permitted for development or use with non-Comtrol products.
|--------------------------------------------------------------------------*/
#include "precomp.h"
static int eth_command_reset(BYTE *rx, BYTE *pkt_in, int size);
static int eth_loop_back(BYTE *pkt_in, int size);
static int eth_id_reply(BYTE *rx, BYTE *pkt_in);
static int eth_id_req(BYTE *mac_addr);
#define TraceStr(s) GTrace(D_Nic, sz_modid, s)
#define TraceErr(s) GTrace(D_Error, sz_modid_err, s)
static char *sz_modid = {"Admin"};
static char *sz_modid_err = {"Error,Admin"};
#define MAX_SEND_DATA_SIZE 220
#define DEV_OK 0
#define DEV_PORT_TIMEOUT 1
#define DEV_NO_REPLY 2
#define DEV_SHORT_REPLY 3
#define DEV_BAD_RHEADSHORT 4
#define DEV_BAD_RHEAD 5
#define DEV_BAD_CHKSUM 6
#define DEV_OVERRUN 7
#define DEV_RESPOND_ERROR 100
/*----------------------------------------------------------------------------
| admin_send_query_id -
|----------------------------------------------------------------------------*/
int admin_send_query_id(Nic *nic, BYTE *dest_addr, int set_us_as_master,
BYTE assigned_index)
{
BYTE pkt[60];
int stat;
TraceStr("SndQuery");
memset(pkt, 0, 60);
if (set_us_as_master)
pkt[26] = 2; // take over device(makes it save our mac-addr)
// 2H = Observe Owner LockOut
else pkt[26] = 1; // set 1 bit so device does not save off mac-addr
// 1H = Passive Query
pkt[15] = assigned_index; // assign the box a index value which we
// use to "id" the box messages.
// server query for box-id
if (dest_addr == NULL)
stat = admin_send(nic, pkt, 26, ADMIN_ID_QUERY, broadcast_addr);
else stat = admin_send(nic, pkt, 26, ADMIN_ID_QUERY, dest_addr);
if (stat != 0)
TraceErr("txer5A!");
return stat;
}
/*----------------------------------------------------------------------------
| admin_send_reset -
|----------------------------------------------------------------------------*/
int admin_send_reset(Nic *nic, BYTE *dest_addr)
{
BYTE pkt[60];
int stat;
TraceStr("SndReset");
memset(pkt, 0, 60);
*((WORD *)&pkt[20]) = 0x5555;
if (dest_addr == NULL)
stat = admin_send(nic, pkt, 26, ADMIN_ID_RESET, broadcast_addr);
else stat = admin_send(nic, pkt, 26, ADMIN_ID_RESET, dest_addr);
if (stat != 0)
TraceErr("txer4A!");
return stat;
}
/*----------------------------------------------------------------------------
| admin_send - Used to send common admin packets, takes care of
filling in the header.
|----------------------------------------------------------------------------*/
int admin_send(Nic *nic, BYTE *buf, int len, int admin_type, BYTE *mac_dest)
{
int stat;
TraceStr("SndPkt");
memcpy(&buf[0], mac_dest, 6);
memcpy(&buf[6], nic->address, 6); // our addr
// BYTE 12-13: Comtrol PCI ID (11H, FEH), Ethernet Len field
*((WORD *)&buf[12]) = 0xfe11;
buf[14] = ASYNC_PRODUCT_HEADER_ID; // comtrol packet type = driver management, any product.
buf[15] = 0; // conc. index field
buf[16] = 1; // admin
*((WORD *)&buf[17]) = len;
buf[19] = admin_type; // ADMIN packet type, 1=boot-loader, 3=id-reply
if (admin_type == ADMIN_ID_QUERY)
memcpy(&buf[20], nic->address, 6); // our addr
if (len < 60)
len = 60;
stat = nic_send_pkt(nic, buf, len);
if (stat)
{
TraceErr("txer3!");
}
return stat;
}
/*---------------------------------------------------------------------------
| ioctl_device - send admin, boot loader packets to the box to
upload code, do misc ioctl commands, etc.
|---------------------------------------------------------------------------*/
int ioctl_device(int cmd,
BYTE *buf,
BYTE *pkt,
ULONG offset, // or ioctl-subfunction if cmd=ioctl
int size)
{
int stat;
int pkt_size;
TraceStr("Ioctl");
stat = 1; // err
switch(cmd)
{
case IOCTL_COMMAND:
stat = eth_device_data(cmd, offset, size, buf, pkt, &pkt_size);
break;
case DOWNLOAD_COMMAND:
stat = eth_device_data(cmd, offset, size, buf, pkt, &pkt_size);
break;
case UPLOAD_COMMAND:
stat = eth_device_data(cmd, offset, size, buf, pkt, &pkt_size);
break;
}
return stat;
}
/*---------------------------------------------------------------------------
| eth_device_data - talks with the device, either sets device data or gets
| device data. Returns 0 if communications ok.
|---------------------------------------------------------------------------*/
int eth_device_data(int message_type,
unsigned long offset,
int num_bytes,
unsigned char *data,
unsigned char *pkt,
int *pkt_size)
{
int i;
unsigned char chksum, command, dat_in;
WORD packet_length;
int pkt_i;
unsigned char *bf;
int in_size = num_bytes;
command = message_type;
switch (message_type)
{
case IOCTL_COMMAND :
packet_length = in_size + 6; // num bytes after len, no chksum included
break;
case UPLOAD_COMMAND :
// send: 0=header, 1=addr, 2=len, 3,4=cmd, 5,6,7,8=offset, data, chksum
// reply: 0=header, 1=addr, 2=len, 3,4=cmd, 5=chksum
packet_length = in_size + 6;
break;
case DOWNLOAD_COMMAND :
// 0=header, 1=addr, 2=len, 3,4=cmd, 5,6,7,8=offset, 9=len_ret
// reply: 0=header, 1=addr, 2=len, 3,4=cmd, data, chksum
packet_length = 8;
break;
}
//-------- flush any ethernet packets in rx buffer
//eth_flush();
pkt_i=0; // start data area in eth. packet
pkt[pkt_i++] = '~';
pkt[pkt_i] = (unsigned char) packet_length;
chksum = pkt[pkt_i++];
pkt[pkt_i] = (unsigned char) (packet_length >> 8);
chksum += pkt[pkt_i++];
chksum += command;
pkt[pkt_i++] = command;
pkt[pkt_i++] = 0; /* hi-byte, command */
switch (message_type)
{
case IOCTL_COMMAND :
bf = (BYTE *) &offset;
chksum += bf[0]; pkt[pkt_i++] = bf[0];
chksum += bf[1]; pkt[pkt_i++] = bf[1];
chksum += bf[2]; pkt[pkt_i++] = bf[2];
chksum += bf[3]; pkt[pkt_i++] = bf[3];
//printf("ioctl-id:%d, size\n", bf[3], in_size);
for (i=0; i<in_size; i++)
{
dat_in = data[i];
chksum += dat_in;
pkt[pkt_i++] = dat_in;
}
break;
case UPLOAD_COMMAND :
bf = (BYTE *) &offset;
chksum += bf[0]; pkt[pkt_i++] = bf[0];
chksum += bf[1]; pkt[pkt_i++] = bf[1];
chksum += bf[2]; pkt[pkt_i++] = bf[2];
chksum += bf[3]; pkt[pkt_i++] = bf[3];
for (i=0; i<in_size; i++)
{
dat_in = data[i];
chksum += dat_in;
pkt[pkt_i++] = dat_in;
}
break;
case DOWNLOAD_COMMAND :
bf = (BYTE *) &offset;
chksum += bf[0]; pkt[pkt_i++] = bf[0];
chksum += bf[1]; pkt[pkt_i++] = bf[1];
chksum += bf[2]; pkt[pkt_i++] = bf[2];
chksum += bf[3]; pkt[pkt_i++] = bf[3];
chksum += (unsigned char) in_size;
pkt[pkt_i++] = (unsigned char) in_size;
chksum += (unsigned char) (in_size >> 8);
pkt[pkt_i++] = (unsigned char) (in_size >> 8);
break;
default:
break;
}
pkt[pkt_i++] = ~chksum;
*pkt_size = pkt_i;
return 0;
}
/*---------------------------------------------------------------------------
| eth_device_reply - Validate the ACK reply pkt due to a sent
boot packet. Ack reply may include data if an IOCTL or
DOWNLOAD type. We use UPLOAD command for code uploads.
| Returns 0 if communications ok.
|---------------------------------------------------------------------------*/
int eth_device_reply(int message_type,
unsigned long offset,
int *num_bytes,
unsigned char *data,
unsigned char *pkt)
{
int i;
unsigned char chksum;
unsigned char *bf;
unsigned char uc;
WORD ret_size;
BYTE *bptr;
bptr = pkt;
if (bptr[0] != '|') // good reply header
{
TraceErr("Err3");
return DEV_BAD_RHEAD;
}
chksum = bptr[1];
ret_size = bptr[1]; // get len
chksum += bptr[2];
ret_size += ((WORD)(bptr[2]) << 8); // get len
if (ret_size > 1600) // limit
ret_size = 0;
uc = bptr[3]; // get command return word
chksum += uc;
uc = bptr[4];
chksum += uc;
i = 0;
if ((message_type == IOCTL_COMMAND) || (message_type == DOWNLOAD_COMMAND))
{
// o_printf("ret size:%d\n", ret_size-2);
if (data == NULL)
return 20; // err out
bf = data;
for (i=0; i<ret_size-2; i++)
{
bf[i] = bptr[5+i];
chksum += bf[i];
}
i = ret_size-2;
}
chksum += bptr[5+i];
if (chksum != 0xff)
{
return DEV_BAD_CHKSUM; /* bad chksum */
}
if ((message_type == IOCTL_COMMAND) || (message_type == DOWNLOAD_COMMAND))
*num_bytes = ret_size-2;
else
*num_bytes = 0;
return 0; // ok
}