86F format handler updated to 86F version 2.0 and bit by bit handling;

FDI stream images are now also handled by the 86F handler;
Both floppy drives' motors now spin separately;
Added Plantronics ColorPlus emulation per patch from PCem forum;
Applied all mainline PCem commits;
Fixed several bugs.
This commit is contained in:
OBattler
2016-11-02 22:39:07 +01:00
parent 9a4e044d91
commit e280faa2d6
87 changed files with 16087 additions and 5675 deletions

275
src/crcspeed/crc64speed.c Normal file
View File

@@ -0,0 +1,275 @@
/* Copyright (c) 2014, Matt Stancliff <matt@genges.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. */
#include "crc64speed.h"
/* If CRC64SPEED_DUAL is defined, we allow calls to
* both _little and _big CRC.
* By default, we only allow one endianness to be used
* and the first call to either _init function will set the
* lookup table endianness for the life of this module.
* We don't enable dual lookups by default because
* each 8x256 lookup table is 16k. */
#ifndef CRC64SPEED_DUAL
static uint64_t crc64_table[8][256] = {{0}};
static void *crc64_table_little = NULL, *crc64_table_big = NULL;
static const bool dual = false;
#else
static uint64_t crc64_table_little[8][256] = {{0}};
static uint64_t crc64_table_big[8][256] = {{0}};
static void *crc64_table = NULL;
static const bool dual = true;
#endif
/* value of crc64_table[0][1], architecture dependent. */
#define LITTLE1 UINT64_C(0x7ad870c830358979)
#define BIG1 UINT64_C(0x79893530c870d87a)
/* Define CRC64SPEED_SAFE if you want runtime checks to stop
* CRCs from being calculated by uninitialized tables (and also stop tables
* from being initialized more than once). */
#ifdef CRC64SPEED_SAFE
#define should_init(table, val) \
do { \
if ((table)[0][1] == (val)) \
return false; \
} while (0)
#define check_init(table, val) \
do { \
if ((table)[0][1] != (val)) \
return false; \
} while (0)
#else
#define should_init(a, b)
#define check_init(a, b)
#endif
#define POLY UINT64_C(0xad93d23594c935a9)
/******************** BEGIN GENERATED PYCRC FUNCTIONS ********************/
/**
* Generated on Sun Dec 21 14:14:07 2014,
* by pycrc v0.8.2, https://www.tty1.net/pycrc/
*
* LICENSE ON GENERATED CODE:
* ==========================
* As of version 0.6, pycrc is released under the terms of the MIT licence.
* The code generated by pycrc is not considered a substantial portion of the
* software, therefore the author of pycrc will not claim any copyright on
* the generated code.
* ==========================
*
* CRC configuration:
* Width = 64
* Poly = 0xad93d23594c935a9
* XorIn = 0xffffffffffffffff
* ReflectIn = True
* XorOut = 0x0000000000000000
* ReflectOut = True
* Algorithm = bit-by-bit-fast
*
* Modifications after generation (by matt):
* - included finalize step in-line with update for single-call generation
* - re-worked some inner variable architectures
* - adjusted function parameters to match expected prototypes.
*****************************************************************************/
/**
* Reflect all bits of a \a data word of \a data_len bytes.
*
* \param data The data word to be reflected.
* \param data_len The width of \a data expressed in number of bits.
* \return The reflected data.
*****************************************************************************/
static inline uint_fast64_t crc_reflect(uint_fast64_t data, size_t data_len) {
uint_fast64_t ret = data & 0x01;
for (size_t i = 1; i < data_len; i++) {
data >>= 1;
ret = (ret << 1) | (data & 0x01);
}
return ret;
}
/**
* Update the crc value with new data.
*
* \param crc The current crc value.
* \param data Pointer to a buffer of \a data_len bytes.
* \param data_len Number of bytes in the \a data buffer.
* \return The updated crc value.
******************************************************************************/
uint64_t crc64(uint_fast64_t crc, const void *in_data, const uint64_t len) {
const uint8_t *data = in_data;
bool bit;
for (uint64_t offset = 0; offset < len; offset++) {
uint8_t c = data[offset];
for (uint_fast8_t i = 0x01; i & 0xff; i <<= 1) {
bit = crc & 0x8000000000000000;
if (c & i) {
bit = !bit;
}
crc <<= 1;
if (bit) {
crc ^= POLY;
}
}
crc &= 0xffffffffffffffff;
}
crc = crc & 0xffffffffffffffff;
return crc_reflect(crc, 64) ^ 0x0000000000000000;
}
/******************** END GENERATED PYCRC FUNCTIONS ********************/
/* Only for testing; doesn't support DUAL */
uint64_t crc64_lookup(uint64_t crc, const void *in_data, const uint64_t len) {
const uint8_t *data = in_data;
for (size_t i = 0; i < len; i++) {
crc = crc64_table[0][(uint8_t)crc ^ data[i]] ^ (crc >> 8);
}
return crc;
}
/* Returns false if CRC64SPEED_SAFE and table already initialized. */
bool crc64speed_init(void) {
#ifndef CRC64SPEED_DUAL
should_init(crc64_table, LITTLE1);
#else
should_init(crc64_table_little, LITTLE1);
#endif
crcspeed64little_init(crc64, dual ? crc64_table_little : crc64_table);
return true;
}
/* Returns false if CRC64SPEED_SAFE and table already initialized. */
bool crc64speed_init_big(void) {
#ifndef CRC64SPEED_DUAL
should_init(crc64_table, BIG1);
#else
should_init(crc64_table_big, BIG1);
#endif
crcspeed64big_init(crc64, dual ? crc64_table_big : crc64_table);
return true;
}
uint64_t crc64speed(uint64_t crc, const void *s, const uint64_t l) {
/* Quickly check if CRC table is initialized to little endian correctly. */
#ifndef CRC64SPEED_DUAL
check_init(crc64_table, LITTLE1);
#else
check_init(crc64_table_little, LITTLE1);
#endif
return crcspeed64little(dual ? crc64_table_little : crc64_table, crc,
(void *)s, l);
}
uint64_t crc64speed_big(uint64_t crc, const void *s, const uint64_t l) {
/* Quickly check if CRC table is initialized to big endian correctly. */
#ifndef CRC64SPEED_DUAL
check_init(crc64_table, BIG1);
#else
check_init(crc64_table_big, BIG1);
#endif
return crcspeed64big(dual ? crc64_table_big : crc64_table, crc, (void *)s,
l);
}
bool crc64speed_init_native(void) {
const uint64_t n = 1;
return *(char *)&n ? crc64speed_init() : crc64speed_init_big();
}
/* Iterate over table to fully load it into a cache near the CPU. */
void crc64speed_cache_table(void) {
uint64_t m;
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 256; ++j) {
#ifndef CRC64SPEED_DUAL
m = crc64_table[i][j];
#else
m = crc64_table_little[i][j];
m += crc64_table_big[i][j];
#endif
++m;
}
}
}
/* If you are on a platform where endianness can change at runtime, this
* will break unless you compile with CRC64SPEED_DUAL and manually run
* _init() and _init_big() instead of using _init_native() */
uint64_t crc64speed_native(uint64_t crc, const void *s, const uint64_t l) {
const uint64_t n = 1;
return *(char *)&n ? crc64speed(crc, s, l) : crc64speed_big(crc, s, l);
}
/* Test main */
#if defined(REDIS_TEST) || defined(REDIS_TEST_MAIN)
#include <stdio.h>
#define UNUSED(x) (void)(x)
int crc64Test(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
crc64speed_init();
printf("[calcula]: e9c6d914c4b8d9ca == %016" PRIx64 "\n",
(uint64_t)crc64(0, "123456789", 9));
printf("[lookupt]: e9c6d914c4b8d9ca == %016" PRIx64 "\n",
(uint64_t)crc64_lookup(0, "123456789", 9));
printf("[64speed]: e9c6d914c4b8d9ca == %016" PRIx64 "\n",
(uint64_t)crc64speed(0, "123456789", 9));
char li[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed "
"do eiusmod tempor incididunt ut labore et dolore magna "
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
"ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis "
"aute irure dolor in reprehenderit in voluptate velit esse "
"cillum dolore eu fugiat nulla pariatur. Excepteur sint "
"occaecat cupidatat non proident, sunt in culpa qui officia "
"deserunt mollit anim id est laborum.";
printf("[calcula]: c7794709e69683b3 == %016" PRIx64 "\n",
(uint64_t)crc64(0, li, sizeof(li)));
printf("[lookupt]: c7794709e69683b3 == %016" PRIx64 "\n",
(uint64_t)crc64_lookup(0, li, sizeof(li)));
printf("[64speed]: c7794709e69683b3 == %016" PRIx64 "\n",
(uint64_t)crc64speed(0, li, sizeof(li)));
return 0;
}
#endif
#ifdef REDIS_TEST_MAIN
int main(int argc, char *argv[]) {
return crc64Test(argc, argv);
}
#endif

20
src/crcspeed/crc64speed.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef CRC64SPEED_H
#define CRC64SPEED_H
#include "crcspeed.h"
#include "stdbool.h"
/* Does not require init */
uint64_t crc64(uint64_t crc, const void *data, const uint64_t len);
void crc64speed_cache_table(void);
/* All other crc functions here require _init() before usage. */
bool crc64speed_init(void);
uint64_t crc64_lookup(uint64_t crc, const void *in_data, const uint64_t len);
uint64_t crc64speed(uint64_t crc, const void *s, const uint64_t l);
bool crc64speed_init_big(void);
uint64_t crc64speed_big(uint64_t crc, const void *s, const uint64_t l);
bool crc64speed_init_native(void);
uint64_t crc64speed_native(uint64_t crc, const void *s, const uint64_t l);
#endif

281
src/crcspeed/crcspeed.c Normal file
View File

@@ -0,0 +1,281 @@
/*
* Copyright (C) 2013 Mark Adler
* Originally by: crc64.c Version 1.4 16 Dec 2013 Mark Adler
* Modifications by Matt Stancliff <matt@genges.com>:
* - removed CRC64-specific behavior
* - added generation of lookup tables by parameters
* - removed inversion of CRC input/result
* - removed automatic initialization in favor of explicit initialization
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler
madler@alumni.caltech.edu
*/
#include "crcspeed.h"
/* Fill in a CRC constants table. */
void crcspeed64little_init(crcfn64 crcfn, uint64_t table[8][256]) {
uint64_t crc;
/* generate CRCs for all single byte sequences */
for (int n = 0; n < 256; n++) {
table[0][n] = crcfn(0, &n, 1);
}
/* generate nested CRC table for future slice-by-8 lookup */
for (int n = 0; n < 256; n++) {
crc = table[0][n];
for (int k = 1; k < 8; k++) {
crc = table[0][crc & 0xff] ^ (crc >> 8);
table[k][n] = crc;
}
}
}
void crcspeed16little_init(crcfn16 crcfn, uint16_t table[8][256]) {
uint16_t crc;
/* generate CRCs for all single byte sequences */
for (int n = 0; n < 256; n++) {
table[0][n] = crcfn(0, &n, 1);
}
/* generate nested CRC table for future slice-by-8 lookup */
for (int n = 0; n < 256; n++) {
crc = table[0][n];
for (int k = 1; k < 8; k++) {
crc = table[0][(crc >> 8) & 0xff] ^ (crc << 8);
table[k][n] = crc;
}
}
}
/* Reverse the bytes in a 64-bit word. */
static inline uint64_t rev8(uint64_t a) {
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap64(a);
#else
uint64_t m;
m = UINT64_C(0xff00ff00ff00ff);
a = ((a >> 8) & m) | (a & m) << 8;
m = UINT64_C(0xffff0000ffff);
a = ((a >> 16) & m) | (a & m) << 16;
return a >> 32 | a << 32;
#endif
}
/* This function is called once to initialize the CRC table for use on a
big-endian architecture. */
void crcspeed64big_init(crcfn64 fn, uint64_t big_table[8][256]) {
/* Create the little endian table then reverse all the entires. */
crcspeed64little_init(fn, big_table);
for (int k = 0; k < 8; k++) {
for (int n = 0; n < 256; n++) {
big_table[k][n] = rev8(big_table[k][n]);
}
}
}
void crcspeed16big_init(crcfn16 fn, uint16_t big_table[8][256]) {
/* Create the little endian table then reverse all the entires. */
crcspeed16little_init(fn, big_table);
for (int k = 0; k < 8; k++) {
for (int n = 0; n < 256; n++) {
big_table[k][n] = rev8(big_table[k][n]);
}
}
}
/* Calculate a non-inverted CRC multiple bytes at a time on a little-endian
* architecture. If you need inverted CRC, invert *before* calling and invert
* *after* calling.
* 64 bit crc = process 8 bytes at once;
*/
uint64_t crcspeed64little(uint64_t little_table[8][256], uint64_t crc,
void *buf, size_t len) {
unsigned char *next = buf;
/* process individual bytes until we reach an 8-byte aligned pointer */
while (len && ((uintptr_t)next & 7) != 0) {
crc = little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
/* fast middle processing, 8 bytes (aligned!) per loop */
while (len >= 8) {
crc ^= *(uint64_t *)next;
crc = little_table[7][crc & 0xff] ^
little_table[6][(crc >> 8) & 0xff] ^
little_table[5][(crc >> 16) & 0xff] ^
little_table[4][(crc >> 24) & 0xff] ^
little_table[3][(crc >> 32) & 0xff] ^
little_table[2][(crc >> 40) & 0xff] ^
little_table[1][(crc >> 48) & 0xff] ^
little_table[0][crc >> 56];
next += 8;
len -= 8;
}
/* process remaining bytes (can't be larger than 8) */
while (len) {
crc = little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
return crc;
}
uint16_t crcspeed16little(uint16_t little_table[8][256], uint16_t crc,
void *buf, size_t len) {
unsigned char *next = buf;
/* process individual bytes until we reach an 8-byte aligned pointer */
while (len && ((uintptr_t)next & 7) != 0) {
crc = little_table[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
len--;
}
/* fast middle processing, 8 bytes (aligned!) per loop */
while (len >= 8) {
uint64_t n = *(uint64_t *)next;
crc = little_table[7][(n & 0xff) ^ ((crc >> 8) & 0xff)] ^
little_table[6][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
little_table[5][(n >> 16) & 0xff] ^
little_table[4][(n >> 24) & 0xff] ^
little_table[3][(n >> 32) & 0xff] ^
little_table[2][(n >> 40) & 0xff] ^
little_table[1][(n >> 48) & 0xff] ^
little_table[0][n >> 56];
next += 8;
len -= 8;
}
/* process remaining bytes (can't be larger than 8) */
while (len) {
crc = little_table[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
len--;
}
return crc;
}
/* Calculate a non-inverted CRC eight bytes at a time on a big-endian
* architecture.
*/
uint64_t crcspeed64big(uint64_t big_table[8][256], uint64_t crc, void *buf,
size_t len) {
unsigned char *next = buf;
crc = rev8(crc);
while (len && ((uintptr_t)next & 7) != 0) {
crc = big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
len--;
}
while (len >= 8) {
crc ^= *(uint64_t *)next;
crc = big_table[0][crc & 0xff] ^
big_table[1][(crc >> 8) & 0xff] ^
big_table[2][(crc >> 16) & 0xff] ^
big_table[3][(crc >> 24) & 0xff] ^
big_table[4][(crc >> 32) & 0xff] ^
big_table[5][(crc >> 40) & 0xff] ^
big_table[6][(crc >> 48) & 0xff] ^
big_table[7][crc >> 56];
next += 8;
len -= 8;
}
while (len) {
crc = big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
len--;
}
return rev8(crc);
}
/* WARNING: Completely untested on big endian architecture. Possibly broken. */
uint16_t crcspeed16big(uint16_t big_table[8][256], uint16_t crc_in, void *buf,
size_t len) {
unsigned char *next = buf;
uint64_t crc = crc_in;
crc = rev8(crc);
while (len && ((uintptr_t)next & 7) != 0) {
crc = big_table[0][((crc >> (56 - 8)) ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
while (len >= 8) {
uint64_t n = *(uint64_t *)next;
crc = big_table[0][(n & 0xff) ^ ((crc >> (56 - 8)) & 0xff)] ^
big_table[1][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
big_table[2][(n >> 16) & 0xff] ^
big_table[3][(n >> 24) & 0xff] ^
big_table[4][(n >> 32) & 0xff] ^
big_table[5][(n >> 40) & 0xff] ^
big_table[6][(n >> 48) & 0xff] ^
big_table[7][n >> 56];
next += 8;
len -= 8;
}
while (len) {
crc = big_table[0][((crc >> (56 - 8)) ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
return rev8(crc);
}
/* Return the CRC of buf[0..len-1] with initial crc, processing eight bytes
at a time using passed-in lookup table.
This selects one of two routines depending on the endianess of
the architecture. */
uint64_t crcspeed64native(uint64_t table[8][256], uint64_t crc, void *buf,
size_t len) {
uint64_t n = 1;
return *(char *)&n ? crcspeed64little(table, crc, buf, len)
: crcspeed64big(table, crc, buf, len);
}
uint16_t crcspeed16native(uint16_t table[8][256], uint16_t crc, void *buf,
size_t len) {
uint64_t n = 1;
return *(char *)&n ? crcspeed16little(table, crc, buf, len)
: crcspeed16big(table, crc, buf, len);
}
/* Initialize CRC lookup table in architecture-dependent manner. */
void crcspeed64native_init(crcfn64 fn, uint64_t table[8][256]) {
uint64_t n = 1;
*(char *)&n ? crcspeed64little_init(fn, table)
: crcspeed64big_init(fn, table);
}
void crcspeed16native_init(crcfn16 fn, uint16_t table[8][256]) {
uint64_t n = 1;
*(char *)&n ? crcspeed16little_init(fn, table)
: crcspeed16big_init(fn, table);
}

60
src/crcspeed/crcspeed.h Normal file
View File

@@ -0,0 +1,60 @@
/* Copyright (c) 2014, Matt Stancliff <matt@genges.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. */
#ifndef CRCSPEED_H
#define CRCSPEED_H
#include <inttypes.h>
#include <stdio.h>
typedef uint64_t (*crcfn64)(uint64_t, const void *, const uint64_t);
typedef uint16_t (*crcfn16)(uint16_t, const void *, const uint64_t);
/* CRC-64 */
void crcspeed64little_init(crcfn64 fn, uint64_t table[8][256]);
void crcspeed64big_init(crcfn64 fn, uint64_t table[8][256]);
void crcspeed64native_init(crcfn64 fn, uint64_t table[8][256]);
uint64_t crcspeed64little(uint64_t table[8][256], uint64_t crc, void *buf,
size_t len);
uint64_t crcspeed64big(uint64_t table[8][256], uint64_t crc, void *buf,
size_t len);
uint64_t crcspeed64native(uint64_t table[8][256], uint64_t crc, void *buf,
size_t len);
/* CRC-16 */
void crcspeed16little_init(crcfn16 fn, uint16_t table[8][256]);
void crcspeed16big_init(crcfn16 fn, uint16_t table[8][256]);
void crcspeed16native_init(crcfn16 fn, uint16_t table[8][256]);
uint16_t crcspeed16little(uint16_t table[8][256], uint16_t crc, void *buf,
size_t len);
uint16_t crcspeed16big(uint16_t table[8][256], uint16_t crc, void *buf,
size_t len);
uint16_t crcspeed16native(uint16_t table[8][256], uint16_t crc, void *buf,
size_t len);
#endif