/* @(#)edc.h 1.3 12/12/02 Copyright 1998-2001 Heiko Eissfeldt */ /* * This file contains protected intellectual property. * * Compact disc reed-solomon routines. * Copyright (c) 1998-2001 by Heiko Eissfeldt, heiko@hexco.de * Copyright (c) 2006-2012 by Joerg Schilling */ /* * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * See the file CDDL.Schily.txt in this distribution for details. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file CDDL.Schily.txt from this distribution. */ #ifdef EDC_DECODER_HACK #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) #endif #define DO2(a) a\ a #define DO4(a) DO2(a)\ DO2(a) #define DO8(a) DO4(a)\ DO4(a) #if defined EDC_LAYER1 || defined EDC_LAYER2 #define RS_L12_BITS 8 #endif /* * known sector types */ #define EDC_MODE_0 0 #define EDC_MODE_1 1 #define EDC_MODE_2 2 #define EDC_MODE_2_FORM_1 3 #define EDC_MODE_2_FORM_2 4 #define EDC_AUDIO 5 #define EDC_UNKNOWN 6 typedef struct bcdmsf { unsigned char bcdmsf_min; /* the minute in bcd format */ unsigned char bcdmsf_sec; /* the second in bcd format */ unsigned char bcdmsf_frame; /* the frame in bcd format */ } bcdmsf_t; #ifdef EDC_LAYER2 /* * data sector definitions for RSPC * user data bytes per frame */ #define L2_RAW (1024*2) #define L12_MODUL 255 #define L12_P_ERRORS 1 #define L12_Q_ERRORS 1 #define L12_P_LENGTH 43 #define L12_Q_LENGTH 26 #define L12_P_SKIPPED (L12_MODUL-L12_Q_LENGTH) #define L12_Q_SKIPPED (L12_MODUL-L12_P_LENGTH-2*L12_Q_ERRORS) /* * parity bytes for 16 bit units */ #define L2_Q (L12_Q_LENGTH*2*L12_Q_ERRORS*2) #define L2_P (L12_P_LENGTH*2*L12_P_ERRORS*2) /* * sector access macros * * col = column address of P layer * dia = diagonal address of Q layer * p = position in column or diagonal * * SECxyz calculate the position in the sector from offset 12, where * x is B for byte access and W for word access * y is P for the P parity layer and Q for the Q parity layer * z is L for the least significant and M for the most significant byte */ /* word macros */ #define SECWP(col, p) (L12_P_LENGTH*(p)+(col)) /* byte macros */ #define SECBPL(col, p) (SECWP(col, p) << 1) #define SECBPM(col, p) (SECBPL(col, p)+1) #if defined USE_ARRAY /* word macros */ #define SECWQ(dia, p) (qacc[dia][p] >> 1) #define SECWQLO(dia, p) (qacc[dia][p] >> 1) #define SECWQHI(dia, p) (qacc[dia][p] >> 1) /* byte macros */ #define SECBQLLO(dia, p) (qacc[dia][p]) #define SECBQLHI(dia, p) (qacc[dia][p]) #define SECBQL(dia, p) (qacc[dia][p]) #define SECBQMLO(dia, p) (SECBQLLO(dia, p)+1) #define SECBQMHI(dia, p) (SECBQLHI(dia, p)+1) #define SECBQM(dia, p) (SECBQL(dia, p)+1) #else #define SECWQ(dia, p) (SECWQC(dia, p)) #define SECWQLO(dia, p) (SECWQLOC(dia, p)) #define SECWQHI(dia, p) (SECWQHIC(dia, p)) #define SECBQLLO(dia, p) (SECBQLLOC(dia, p)) #define SECBQLHI(dia, p) (SECBQLHIC(dia, p)) #define SECBQL(dia, p) (SECBQLC(dia, p)) #define SECBQMLO(dia, p) (SECBQMLOC(dia, p)) #define SECBQMHI(dia, p) (SECBQMHIC(dia, p)) #define SECBQM(dia, p) (SECBQMC(dia, p)) #endif /* word macros */ #define SECWQLOC(dia, p) ((unsigned short)(L12_P_LENGTH*((p)+(dia))+(p)) % (unsigned short) (L12_P_LENGTH*L12_Q_LENGTH)) #define SECWQHIC(dia, p) (L12_Q_LENGTH*(p)+(dia)) #define SECWQC(dia, p) ((p) < L12_P_LENGTH ? SECWQLOC(dia, p) : SECWQHIC(dia, p)) /* byte macros */ #define SECBQLLOC(dia, p) (SECWQLOC(dia, p) << 1) #define SECBQLHIC(dia, p) (SECWQHIC(dia, p) << 1) #define SECBQLC(dia, p) ((p) < L12_P_LENGTH ? SECBQLLOC(dia, p) : SECBQLHIC(dia, p)) #define SECBQMLOC(dia, p) (SECBQLLOC(dia, p)+1) #define SECBQMHIC(dia, p) (SECBQLHIC(dia, p)+1) #define SECBQMC(dia, p) (SECBQLC(dia, p)+1) /* * conversion macros * * Calculate layer coordinates from a (12-byte based) sector offset in words * * POSP calculates the position in the column in the P parity layer * COL calculates the column from the offset * * POSQ calculates the position in the diagonal in the Q parity layer * DIA calculates the diagonal */ /* p parity macros */ #define POSP(off) (unsigned)((unsigned short)(off) / (unsigned short)L12_P_LENGTH) #define COL(off) (unsigned)((unsigned short)(off) % (unsigned short)L12_P_LENGTH) /* q parity macros */ #define POSQLO(off) COL(off) #define POSQHI(off) (unsigned)((unsigned short)(off) / (unsigned short)L12_Q_LENGTH) #define POSQ(off) ((unsigned short)(off) < (unsigned short)(L12_P_LENGTH*L12_Q_LENGTH) ? POSQLO(off) : POSQHI(off)) #define DIALO(off) (unsigned)((unsigned short)(POSP(off)-COL(off)+2*L12_Q_LENGTH)%(unsigned short)L12_Q_LENGTH) #define DIAHI(off) (unsigned)((unsigned short)(off) % (unsigned short)L12_Q_LENGTH) #define DIA(off) ((unsigned short)(off) < (unsigned short)(L12_P_LENGTH*L12_Q_LENGTH) ? DIALO(off) : DIAHI(off)) #ifdef EDC_ENCODER /* * data sector layer 2 Reed-Solomon Product Code encoder * * encode the given data portion depending on sector type (see * get/set_sector_type() functions). Use the given address for the header. * The returned data is __unscrambled__ and not in F2-frame format (for that * see function scramble_L2()). * * Input parameter: * sectortype * EDC_MODE_0: a 12-byte sync field, a header and 2336 zeros are returned. * EDC_MODE_1: the user data portion (2048 bytes) has to be given * at offset 16 in the inout array. * Sync-, header-, edc-, spare-, p- and q- fields will be added. * EDC_MODE_2: the user data portion (2336 bytes) has to be given * at offset 16 in the inout array. * Sync- and header- fields will be added. * EDC_MODE_2_FORM_1: the user data portion (8 bytes subheader followed * by 2048 bytes data) has to be given at offset 16 * in the inout array. * Sync-, header-, edc-, p- and q- fields will be added. * EDC_MODE_2_FORM_2: the user data portion (8 bytes subheader followed * by 2324 bytes data) has to be given at offset 16 * in the inout array. * Sync-, header- and edc- fields will be added. * * inout is an array of 2352 or more bytes. * address is a pointer to a bcdmsf_t struct * holding bcd values for minute/second/frame address parts. * */ int do_encode_L2 __PR((unsigned char *inout, int sectortype, bcdmsf_t *address)); #endif #ifdef EDC_DECODER #define NO_ERRORS 1 #define FULLY_CORRECTED 0 #define UNCORRECTABLE -1 #define WRONG_TYPE -2 /* * data sector decoder for MODE 1 and MODE 2 FORM 1 sector types. * Input parameters: * inout: * have_erasures: indicates error positions when > 0 * erasures: a value > 0 indicates an error at the corresponding * position in the inout array. * * On output: inout has error corrected data, if correctable. * return values: * -1 uncorrectable * 0 corrected * 1 uncorrected (no correction needed) */ int do_decode_L2 __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)], int sectortype, int have_erasures, unsigned char erasures[(L2_RAW + L2_Q + L2_P)])); /* * calculate the crc checksum depending on the sector type. * * parameters: * input: * inout is the data sector as a byte array at offset 0 * type is the sector type (MODE_1, MODE_2_FORM_1 or MODE_2_FORM_2) * * return value: 1, if cyclic redundancy checksum is 0 (no errors) * 0, if errors are present. * */ int crc_check __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)], int type)); int encode_L2_P __PR((unsigned char *inout)); int encode_L2_Q __PR((unsigned char *inout)); #endif extern const unsigned short qacc[26][64]; /* * calculates checksum for data sectors */ unsigned int build_edc __PR((unsigned char inout[], unsigned from, unsigned upto)); /* * generates f2 frames from otherwise fully formatted sectors (generated by * do_encode_L2()). */ int scramble_L2 __PR((unsigned char *inout)); #endif #ifdef EDC_SUBCHANNEL /* * r-w sub channel definitions */ #define RS_SUB_RW_BITS 6 #define PACKETS_PER_SUBCHANNELFRAME 4 #define LSUB_RAW 18 #define LSUB_QRAW 2 /* * 6 bit entities */ #define LSUB_Q 2 #define LSUB_P 4 typedef struct del *edc_sub_delp; /* * Create an initialized instance of the subchannel delay line. * * Return a pointer to the initialized delay line object. */ edc_sub_delp create_edc_sub_del __PR((void)); #ifdef EDC_ENCODER /* * R-W subchannel encoder * input: inout has 96 bytes data, four frames with 24 bytes each. * output: four frames with 2 bytes user data, 2 bytes added Q parity, * 16 bytes user data, 4 bytes added P parity. * * This routine fills the q and p parity fields. * No interleaving is done here. */ int do_encode_sub __PR(( unsigned char inout[(LSUB_RAW + LSUB_Q + LSUB_P) * PACKETS_PER_SUBCHANNELFRAME])); /* * R-W subchannel interleaver * * Apply after parity code generation. * * input: inout has 96 bytes user data, four frames with 24 bytes each. * output: as above but swapped and interleaved. * * Parameter: * swap : if true, perform low level permutations (swaps) * delay: if true, use low level delay line * delp: pointer to a edc_sub_del struct * (holding the state of the delay line) * this pointer is dereferenced only, if parameter delay is true. */ int packed_to_raw __PR((unsigned char inout[(LSUB_RAW + LSUB_Q + LSUB_P) * PACKETS_PER_SUBCHANNELFRAME], int swap, int delay, edc_sub_delp delp)); #endif #ifdef EDC_DECODER /* * R-W subchannel deinterleaver * * Apply before correction. * * input: inout has 96 bytes user data, four frames with 24 bytes each. * output: as above but swapped and interleaved (delayed). * * Parameter: * swap : if true, perform permutations (swaps) * delay: if true, use delay line * delp: pointer to a edc_sub_delp struct * (holding the state of the delay line) * this pointer is dereferenced only, if parameter delay is true. */ int raw_to_packed __PR((unsigned char inout[(LSUB_RAW + LSUB_Q + LSUB_P) * PACKETS_PER_SUBCHANNELFRAME], int swap, int delay, edc_sub_delp delp)); /* * R-W subchannel decoder * On input: inout: 96 bytes packed user data, four frames with each 24 bytes. * have_erasures: indicates error positions when > 0 * erasures: a value > 0 indicates an error at the corresponding * position in the inout array. * * On output: inout has error corrected data, if correctable. * return values: * -1 uncorrectable * 0 corrected * 1 uncorrected (not needed) */ int do_decode_sub __PR(( unsigned char inout[(LSUB_RAW + LSUB_Q + LSUB_P) * PACKETS_PER_SUBCHANNELFRAME], int have_erasures, unsigned char erasures[(LSUB_RAW + LSUB_Q+LSUB_P) *PACKETS_PER_SUBCHANNELFRAME], int results[PACKETS_PER_SUBCHANNELFRAME])); int check_sub __PR((unsigned char input[])); #endif #endif #endif /* EDC_DECODER_HACK */ /* * XXX Remove this if EDC_DECODER_HACK is removed */ int do_decode_L2 __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)], int sectortype, int have_erasures, unsigned char erasures[(L2_RAW + L2_Q + L2_P)])); int crc_check __PR((unsigned char inout[(L2_RAW + L2_Q + L2_P)], int type));