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
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
|
|
}
|
|
|