/*-------------------------------------------------------------------------- | 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> 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