static inline int __init indy_sc_probe(void) { volatile unsigned int *cpu_control; unsigned short cmd = 0xc220; unsigned long data = 0; int i, n; #ifdef __MIPSEB__ cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034); #else cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030); #endif #define DEASSERT(bit) (*(cpu_control) &= (~(bit))) #define ASSERT(bit) (*(cpu_control) |= (bit)) #define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("") DEASSERT(SGIMC_EEPROM_PRE); DEASSERT(SGIMC_EEPROM_SDATAO); DEASSERT(SGIMC_EEPROM_SECLOCK); DEASSERT(SGIMC_EEPROM_PRE); DELAY; ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK); for(i = 0; i < 11; i++) { if(cmd & (1<<15)) ASSERT(SGIMC_EEPROM_SDATAO); else DEASSERT(SGIMC_EEPROM_SDATAO); DEASSERT(SGIMC_EEPROM_SECLOCK); ASSERT(SGIMC_EEPROM_SECLOCK); cmd <<= 1; } DEASSERT(SGIMC_EEPROM_SDATAO); for(i = 0; i < (sizeof(unsigned short) * 8); i++) { unsigned int tmp; DEASSERT(SGIMC_EEPROM_SECLOCK); DELAY; ASSERT(SGIMC_EEPROM_SECLOCK); DELAY; data <<= 1; tmp = *cpu_control; if(tmp & SGIMC_EEPROM_SDATAI) data |= 1; } DEASSERT(SGIMC_EEPROM_SECLOCK); DEASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_PRE); ASSERT(SGIMC_EEPROM_SECLOCK); data <<= PAGE_SHIFT; if (data == 0) return 0; scache_size = data; printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n", scache_size >> 10); return 1; }
// Word to the wise: I've been testing this code against the Impinj RFIDemo, // using the InventoryFilter page. It appears to me that it only sends the first // three bytes pattern fields (aka the mask field in the spec) correctly. So // don't expect it to be able to look for (say) entire EPCs correctly. Also, // when testing this code out in RFIDDemo, put your mask data in hex in the // leftmost part of the pattern field. void handle_select(volatile short nextState) { do_nothing(); #if ENABLE_SESSIONS // command-specific bit masks #define SELECT_TARGET_MASK 0x0E #define SELECT_ACTIONB0_MASK 0x01 #define SELECT_ACTIONB1_MASK 0xC0 #define SELECT_MEMBANK_MASK 0x30 #define SELECT_POINTERB0_MASK 0x0F #define SELECT_POINTERB1_MASK 0xF0 #define SELECT_LENGTHB0_MASK 0x0F #define SELECT_LENGTHB1_MASK 0xF0 #define SELECT_MASK_MASK 0x0F // command-specific bit flags #define SELECT_TARGET_SL 0x04 unsigned short target = (cmd[0] & SELECT_TARGET_MASK) >> 1; unsigned short action = (cmd[0] & SELECT_ACTIONB0_MASK) << 2; unsigned short action2 = (cmd[1] & SELECT_ACTIONB1_MASK) >> 6; action |= action2; unsigned short membank = (cmd[1] & SELECT_MEMBANK_MASK) >> 4; unsigned short pointer = (cmd[1] & SELECT_POINTERB0_MASK) << 4; unsigned short pointer2 = (cmd[2] & SELECT_POINTERB1_MASK) >> 4; pointer |= pointer2; unsigned short length = (cmd[2] & SELECT_LENGTHB0_MASK) << 4; unsigned short length2 = (cmd[3] & SELECT_LENGTHB1_MASK) >> 4; length |= length2; // can only handle length fields > 0 and membanks == 0 are invalid if ( length <= 0 || membank == 0x00 ) return; unsigned char *mask = (unsigned char *)&cmd[3]; unsigned short maskbit = 3; // start match attempt at leftmost bit of mask // field unsigned char *sourcebyte = (unsigned char *)0; // OK, this is a little confusing. The pointer parameter is an offset // into a buffer, with a value of 0 meaning "the leftmost bit" and // a value of 7 meaning "the rightmost bit of the first byte." But my // bitCompare function thinks 7 is the leftmost bit of the first byte // and 0 is the rightmost bit of that byte. So I'll need to do a little // mapping here. unsigned short sourcebyteoffset = ( pointer/8 ); unsigned short sourcebit = (7 - (pointer % 8)); // pointer->bitCompare // translation if ( membank == 0x01 ) { // match on epc if ( sourcebyteoffset >= 8 ) return; sourcebyte = (unsigned char *)&ackReply[2] + sourcebyteoffset; } else if ( membank == 0x02 ) { // matching on tid. if ( sourcebyteoffset >= 3 ) return; sourcebyte = (unsigned char *)&tid[0] + sourcebyteoffset; } else { // matching on user field. for now this is just one byte long, so // mess with the params to make sure the values are sane in this context sourcebyte = (unsigned char *)usermem; sourcebit = 7; if ( length > 8 ) length = 8; } unsigned short matching = 0; if ( bitCompare(sourcebyte,sourcebit,mask,maskbit,length) == 1 ) { matching = 1; } #define ASSERT(t) { \ if (t == SELECT_TARGET_SL) SL = SL_ASSERTED; \ else session_table[t] = SESSION_STATE_A; \ } #define DEASSERT(t) { \ if (t == SELECT_TARGET_SL) SL = SL_NOT_ASSERTED; \ else session_table[t] = SESSION_STATE_B; \ } #define NEGATE(t) { \ if (t == SELECT_TARGET_SL) \ if ( SL == SL_ASSERTED ) \ SL = SL_NOT_ASSERTED; \ else \ SL = SL_ASSERTED; \ else \ if ( session_table[t] == SESSION_STATE_A ) \ session_table[t] = SESSION_STATE_B; \ else \ session_table[t] = SESSION_STATE_A; \ } switch ( action ) { case 0x0: if ( matching ) ASSERT(target) else DEASSERT(target); break; case 0x1: if ( matching ) ASSERT(target); break; case 0x2: if ( ! matching ) DEASSERT(target); break; case 0x3: if ( matching ) NEGATE(target); break; case 0x4: if ( matching ) DEASSERT(target) else ASSERT(target); break; case 0x5: if ( matching ) DEASSERT(target); break; case 0x6: if (! matching ) ASSERT(target); break; case 0x7: if (! matching ) NEGATE(target); break; default: break; } #endif state = nextState; }