#include "crc.h" /* * Algorithm from "Computer Networks" by Andrew S. Tanenbaum pp. 129-132. * * Code lifted from ROMlib's crc.c. by mjhostet (with permission), 3/28/93. * Lookup table added 3/29/93. */ #define GEN 0x88108000 #define GEN1 (GEN >> 1) #define GEN2 (GEN >> 2) #define GEN3 (GEN >> 3) #define GEN4 (GEN >> 4) #define GEN5 (GEN >> 5) #define GEN6 (GEN >> 6) #define GEN7 (GEN >> 7) #if 0 static unsigned long polydivide(unsigned long l) { if (l & 0x80000000) l ^= GEN; if (l & 0x40000000) l ^= GEN1; if (l & 0x20000000) l ^= GEN2; if (l & 0x10000000) l ^= GEN3; if (l & 0x08000000) l ^= GEN4; if (l & 0x04000000) l ^= GEN5; if (l & 0x02000000) l ^= GEN6; if (l & 0x01000000) l ^= GEN7; return l; } #else static unsigned long polydivide (unsigned long l) { static const unsigned long crc_table[] = { 0x00000000, 0x01102100, 0x02204200, 0x03306300, 0x04408400, 0x0550A500, 0x0660C600, 0x0770E700, 0x08810800, 0x09912900, 0x0AA14A00, 0x0BB16B00, 0x0CC18C00, 0x0DD1AD00, 0x0EE1CE00, 0x0FF1EF00, 0x10123100, 0x11021000, 0x12327300, 0x13225200, 0x1452B500, 0x15429400, 0x1672F700, 0x1762D600, 0x18933900, 0x19831800, 0x1AB37B00, 0x1BA35A00, 0x1CD3BD00, 0x1DC39C00, 0x1EF3FF00, 0x1FE3DE00, 0x20246200, 0x21344300, 0x22042000, 0x23140100, 0x2464E600, 0x2574C700, 0x2644A400, 0x27548500, 0x28A56A00, 0x29B54B00, 0x2A852800, 0x2B950900, 0x2CE5EE00, 0x2DF5CF00, 0x2EC5AC00, 0x2FD58D00, 0x30365300, 0x31267200, 0x32161100, 0x33063000, 0x3476D700, 0x3566F600, 0x36569500, 0x3746B400, 0x38B75B00, 0x39A77A00, 0x3A971900, 0x3B873800, 0x3CF7DF00, 0x3DE7FE00, 0x3ED79D00, 0x3FC7BC00, 0x4048C400, 0x4158E500, 0x42688600, 0x4378A700, 0x44084000, 0x45186100, 0x46280200, 0x47382300, 0x48C9CC00, 0x49D9ED00, 0x4AE98E00, 0x4BF9AF00, 0x4C894800, 0x4D996900, 0x4EA90A00, 0x4FB92B00, 0x505AF500, 0x514AD400, 0x527AB700, 0x536A9600, 0x541A7100, 0x550A5000, 0x563A3300, 0x572A1200, 0x58DBFD00, 0x59CBDC00, 0x5AFBBF00, 0x5BEB9E00, 0x5C9B7900, 0x5D8B5800, 0x5EBB3B00, 0x5FAB1A00, 0x606CA600, 0x617C8700, 0x624CE400, 0x635CC500, 0x642C2200, 0x653C0300, 0x660C6000, 0x671C4100, 0x68EDAE00, 0x69FD8F00, 0x6ACDEC00, 0x6BDDCD00, 0x6CAD2A00, 0x6DBD0B00, 0x6E8D6800, 0x6F9D4900, 0x707E9700, 0x716EB600, 0x725ED500, 0x734EF400, 0x743E1300, 0x752E3200, 0x761E5100, 0x770E7000, 0x78FF9F00, 0x79EFBE00, 0x7ADFDD00, 0x7BCFFC00, 0x7CBF1B00, 0x7DAF3A00, 0x7E9F5900, 0x7F8F7800, 0x80918800, 0x8181A900, 0x82B1CA00, 0x83A1EB00, 0x84D10C00, 0x85C12D00, 0x86F14E00, 0x87E16F00, 0x88108000, 0x8900A100, 0x8A30C200, 0x8B20E300, 0x8C500400, 0x8D402500, 0x8E704600, 0x8F606700, 0x9083B900, 0x91939800, 0x92A3FB00, 0x93B3DA00, 0x94C33D00, 0x95D31C00, 0x96E37F00, 0x97F35E00, 0x9802B100, 0x99129000, 0x9A22F300, 0x9B32D200, 0x9C423500, 0x9D521400, 0x9E627700, 0x9F725600, 0xA0B5EA00, 0xA1A5CB00, 0xA295A800, 0xA3858900, 0xA4F56E00, 0xA5E54F00, 0xA6D52C00, 0xA7C50D00, 0xA834E200, 0xA924C300, 0xAA14A000, 0xAB048100, 0xAC746600, 0xAD644700, 0xAE542400, 0xAF440500, 0xB0A7DB00, 0xB1B7FA00, 0xB2879900, 0xB397B800, 0xB4E75F00, 0xB5F77E00, 0xB6C71D00, 0xB7D73C00, 0xB826D300, 0xB936F200, 0xBA069100, 0xBB16B000, 0xBC665700, 0xBD767600, 0xBE461500, 0xBF563400, 0xC0D94C00, 0xC1C96D00, 0xC2F90E00, 0xC3E92F00, 0xC499C800, 0xC589E900, 0xC6B98A00, 0xC7A9AB00, 0xC8584400, 0xC9486500, 0xCA780600, 0xCB682700, 0xCC18C000, 0xCD08E100, 0xCE388200, 0xCF28A300, 0xD0CB7D00, 0xD1DB5C00, 0xD2EB3F00, 0xD3FB1E00, 0xD48BF900, 0xD59BD800, 0xD6ABBB00, 0xD7BB9A00, 0xD84A7500, 0xD95A5400, 0xDA6A3700, 0xDB7A1600, 0xDC0AF100, 0xDD1AD000, 0xDE2AB300, 0xDF3A9200, 0xE0FD2E00, 0xE1ED0F00, 0xE2DD6C00, 0xE3CD4D00, 0xE4BDAA00, 0xE5AD8B00, 0xE69DE800, 0xE78DC900, 0xE87C2600, 0xE96C0700, 0xEA5C6400, 0xEB4C4500, 0xEC3CA200, 0xED2C8300, 0xEE1CE000, 0xEF0CC100, 0xF0EF1F00, 0xF1FF3E00, 0xF2CF5D00, 0xF3DF7C00, 0xF4AF9B00, 0xF5BFBA00, 0xF68FD900, 0xF79FF800, 0xF86E1700, 0xF97E3600, 0xFA4E5500, 0xFB5E7400, 0xFC2E9300, 0xFD3EB200, 0xFE0ED100, 0xFF1EF000, }; return l ^ crc_table[l >> 24]; } #endif unsigned short compute_crc (unsigned char *data, long length, unsigned short seed) { unsigned long l; #if 0 if (length == 0) l = 0; else if (length == 1) l = data[0]; else if (length == 2) l = (data[0] << 8) | data[1]; else l = (data[0] << 16) | (data[1] << 8) | data[2]; data += 3; length -= 2; #else /* This is spew, but it munges in the seed. */ if (length == 0) l = seed; else l = (seed << 8) | data[0]; data++; #endif while (--length > 0) { l = (l << 8) | *data++; l = polydivide(l); } l <<= 8; l = polydivide(l); l <<= 8; l = polydivide(l); return l >> 8; }