// memory commands static void cmd_memory(void) { u08 cmd,res; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { case 'i': res = memory_init(); set_result(res); break; case 'c': res = memory_check(parse_hex_byte(0)); set_result(res); break; case 'd': memory_dump(parse_hex_byte(0),parse_hex_byte(0)); set_result(STATUS_OK); break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
static u16 parse_hex_word(u16 def) { if(in_size < 4) return def; u08 a = parse_hex_byte(0); u08 b = parse_hex_byte(0); return (u16)a << 8 | (u16)b; }
// diagnose commands static void cmd_diagnose(void) { u08 cmd, res; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { case 'b': // buttons -> returns 0=no button 1=button2 2=button2 3=both buttons res = button1_pressed() | (button2_pressed() << 1); set_result(res); break; case 'l': // led: param: 1=green 2=yellow 3=both { cmd = parse_hex_byte(3); led_green(cmd & 1); led_yellow(cmd & 2); set_result(cmd); delay_ms(1000); } break; case 'i': // io sd diagnose: show sd detect and sd protect { res = sdpin_no_card() ? 1 :0; res |= sdpin_write_protect() ? 2:0; set_result(res); } break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
static int __init check_mac_addr(const char *addr_str) { u_int8_t addr[6]; int i; for (i = 0; i < 6; i++) { int byte; /* * Enforce "xx:xx:xx:xx:xx:xx\n" format. */ if (addr_str[(i * 3) + 2] != ((i < 5) ? ':' : '\n')) return -1; byte = parse_hex_byte(addr_str + (i * 3)); if (byte < 0) return -1; addr[i] = byte; } printk(KERN_INFO "ts209: found ethernet mac address "); for (i = 0; i < 6; i++) printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n"); memcpy(qnap_ts209_eth_data.mac_addr, addr, 6); return 0; }
static void cmd_read(void) { u08 cmd, res; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { case 'm': // read disk to memory only { u08 start_trk = parse_hex_byte(0); u08 end_trk = parse_hex_byte(160); u08 verbose = parse_hex_byte(0); res = disk_read_all(start_trk,end_trk,0,verbose); set_result(res); } break; case 'f': // read disk to file { u08 start_trk = parse_hex_byte(0); u08 end_trk = parse_hex_byte(160); u08 verbose = parse_hex_byte(0); res = disk_read_all(start_trk,end_trk,1,verbose); set_result(res); } break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
// clock commands static void cmd_clock(void) { u08 cmd, value; u08 exit = 0; rtc_time t; while((cmd = get_char()) != 0) { switch(cmd) { case '?': // get time (raw) { rtc_get(t); for(int i=0;i<7;i++) { uart_send_hex_byte_space(t[i]); } uart_send_crlf(); set_result(0); } break; case 't': // get time { u08 *str = (u08 *)rtc_get_time_str(); uart_send_string(str); uart_send_crlf(); } break; case 'y': // set year value = parse_hex_byte(0); rtc_set_entry(RTC_INDEX_YEAR, value); break; case 'o': // set year value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_MONTH, value); break; case 'd': // set day value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_DAY, value); break; case 'h': // set hour value = parse_hex_byte(0); rtc_set_entry(RTC_INDEX_HOUR, value); break; case 'i': // set minute value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_MINUTE, value); break; case 's': // set seconds value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_SECOND, value); break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
// io commands static void cmd_io(void) { u08 cmd, res; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { case 'd': file_dir(); break; case 's': { if(buffer_get_size()>0) { res = file_save_buffer(1); set_result(res); } else { set_result(0); } } break; case 'f': // find next disk name dir { u32 num = 0; res = file_find_disk_dir(&num); uart_send_hex_dword_crlf(num); set_result(res); } break; case 'm': // make disk dir { res = file_make_disk_dir(parse_hex_byte(0)); set_result(res); } break; case 't': // test file file_test(); break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
/* Parse pairs of hex digits into a byte array. If successful, returns * the number of bytes generated. On error, returns a negative number. */ static int parse_hex_string(const char *in, u8 *out, int max_len) { int len = 0; int cur_byte; while (*in != '\0') { /* Ignore whitespace between bytes */ if (isspace(*in)) { in++; continue; } /* Try to parse a 2-digit hex byte */ cur_byte = parse_hex_byte(&in); if (cur_byte < 0) return -EINVAL; if (len >= max_len) return -EFBIG; out[len++] = (u8)cur_byte; } return len; }
static int parse_line(struct parser_context *ctx, const char *line) { unsigned int length, type; uint32_t address; uint8_t checksum; int r; ctx->ptr = line; ctx->sum = 0; ctx->error = false; // Empty lines are probably OK if (*ctx->ptr++ != ':') return 0; if (strlen(ctx->ptr) < 11) return parse_error(ctx); length = parse_hex_byte(ctx, true); address = parse_hex_short(ctx); type = parse_hex_byte(ctx, true); if (ctx->error) return parse_error(ctx); switch (type) { case 0: // data record address += ctx->base_offset; r = _ty_firmware_expand_image(ctx->fw, address + length); if (r < 0) return r; for (unsigned int i = 0; i < length; i++) ctx->fw->image[address + i] = parse_hex_byte(ctx, true); break; case 1: // EOF record if (length > 0) return parse_error(ctx); break; case 2: // extended segment address record if (length != 2) return parse_error(ctx); ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 4; break; case 3: // start segment address record break; case 4: // extended linear address record if (length != 2) return parse_error(ctx); ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 16; break; case 5: // start linear address record break; default: return parse_error(ctx); } // Don't checksum the checksum :) checksum = parse_hex_byte(ctx, false); if (ctx->error) return parse_error(ctx); if (*ctx->ptr != '\r' && *ctx->ptr != '\n' && *ctx->ptr) return parse_error(ctx); if (((ctx->sum & 0xFF) + (checksum & 0xFF)) & 0xFF) return parse_error(ctx); // Return 1 for EOF records, to end the parsing return type == 1; }
static uint16_t parse_hex_short(struct parser_context *ctx) { return (uint16_t)((parse_hex_byte(ctx, true) << 8) | parse_hex_byte(ctx, true)); }
// wiznet commands static void cmd_wiznet(void) { u08 cmd, res, val; u16 addr, wval; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { // ---------- low level/debug ---------- case 'r': // low level: read byte <addr/16> addr = parse_hex_byte(0) << 8 | parse_hex_byte(0); wiz_low_begin(); res = wiz_low_read(addr); wiz_low_end(); set_result(res); uart_send_hex_word_space(addr); uart_send_hex_byte_crlf(res); break; case 'w': // low level: write byte <addr/16><val/8> addr = parse_hex_byte(0) << 8 | parse_hex_byte(0); val = parse_hex_byte(0); wiz_low_begin(); wiz_low_write(addr,val); wiz_low_end(); set_result(val); uart_send_hex_word_space(addr); uart_send_hex_byte_crlf(val); break; case 'R': // low level: read word <addr/16> addr = parse_hex_byte(0) << 8 | parse_hex_byte(0); wiz_low_begin(); res = wiz_low_read_word(addr); wiz_low_end(); set_result(res); uart_send_hex_word_space(addr); uart_send_hex_word_crlf(res); break; case 'W': // low level: write byte <addr/16><val/8> addr = parse_hex_byte(0) << 8 | parse_hex_byte(0); wval = parse_hex_byte(0) << 8 | parse_hex_byte(0); wiz_low_begin(); wiz_low_write_word(addr,wval); wiz_low_end(); set_result(wval); uart_send_hex_word_space(addr); uart_send_hex_word_crlf(wval); break; // ---------- config ---------- case '?': net_info(); break; case 'm': // set mac addr 6*<8> { wiz_cfg_t *wc = wiz_get_cfg(); for(int i=0;i<6;i++) { wc->mac_addr[i] = parse_hex_byte(0); } wiz_realize_cfg(); } break; case 's': // set src ip 4*<8> { wiz_cfg_t *wc = wiz_get_cfg(); for(int i=0;i<4;i++) { wc->src_ip[i] = parse_hex_byte(0); } wiz_realize_cfg(); } break; case 't': // set tgt ip 4*<8> { wiz_cfg_t *wc = wiz_get_cfg(); for(int i=0;i<4;i++) { wc->tgt_ip[i] = parse_hex_byte(0); } wiz_realize_cfg(); } break; case 'n': // set netmask 4*<8> { wiz_cfg_t *wc = wiz_get_cfg(); for(int i=0;i<4;i++) { wc->net_msk[i] = parse_hex_byte(0); } wiz_realize_cfg(); } break; case 'g': // set gateway 4*<8> { wiz_cfg_t *wc = wiz_get_cfg(); for(int i=0;i<4;i++) { wc->gw_ip[i] = parse_hex_byte(0); } wiz_realize_cfg(); } break; case 'o': // src port { wiz_cfg_t *wc = wiz_get_cfg(); wc->src_port = parse_hex_word(1234); } break; case 'p': // tgt port { wiz_cfg_t *wc = wiz_get_cfg(); wc->tgt_port = parse_hex_word(6800); } break; // ----- load/save config ----- case 'S': // save to sram wiz_save_cfg(); break; case 'L': // load from sram wiz_load_cfg(); wiz_realize_cfg(); break; case 'c': // connect test { int result = wiz_begin_tcp_client(); if(result == 0) { uart_send_string((u08 *)"connected"); const char *hw = "hello world!\r\n"; wiz_write_tcp((u08 *)hw, 14); uart_send_string((u08 *)"disconnect"); wiz_end_tcp_client(); } set_result(result); } break; case 'i': net_init(); break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
// sampler commands static void cmd_sampler(void) { u08 cmd, res; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { case 'm': // read track to spi ram { u08 sel = floppy_select_on(); u08 mot = floppy_motor_on(); track_init(); res = trk_read_to_spiram(parse_hex_byte(1)); if(mot) floppy_motor_off(); if(sel) floppy_select_off(); set_result(res); } break; case 'f': // fake read track (only to spi ram) res = trk_read_sim(parse_hex_byte(1)); set_result(res); break; case 'v': // verify track with spi ram res = trk_check_spiram(parse_hex_byte(1)); set_result(res); break; // ----- checks ----- case 'i': // index check { u08 sel = floppy_select_on(); u08 mot = floppy_motor_on(); track_init(); res = trk_read_count_index(); if(mot) floppy_motor_off(); if(sel) floppy_select_off(); set_result(res); } break; case 'd': // read data check { u08 sel = floppy_select_on(); u08 mot = floppy_motor_on(); track_init(); res = trk_read_count_data(); if(mot) floppy_motor_off(); if(sel) floppy_select_off(); set_result(res); } break; case 's': // read data spectrum { u08 sel = floppy_select_on(); u08 mot = floppy_motor_on(); track_init(); res = trk_read_data_spectrum(parse_hex_byte(0)); if(mot) floppy_motor_off(); if(sel) floppy_select_off(); set_result(res); } break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
// track commands static void cmd_track(void) { // ensure floppy is selected u08 did_sel = floppy_select_on(); u08 cmd,res; u08 exit = 0; while((cmd = get_char()) != 0) { switch(cmd) { case 'i': track_init(); set_result(STATUS_OK); break; case 'c': res = track_check_max(); set_result(res); break; case 'z': track_zero(); set_result(STATUS_OK); break; case '?': set_result(track_num()); break; case '+': track_step_next(parse_hex_byte(1)); set_result(track_num()); break; case '-': track_step_prev(parse_hex_byte(1)); set_result(track_num()); break; case 'n': track_next(parse_hex_byte(1)); set_result(track_num()); break; case 'p': track_prev(parse_hex_byte(1)); set_result(track_num()); break; case 's': track_side_toggle(); set_result(track_num()); break; case 't': track_side_top(); set_result(track_num()); break; case 'b': track_side_bot(); set_result(track_num()); break; case 'm': track_set_max(parse_hex_byte(79)); set_result(track_get_max()); break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } if(did_sel) { floppy_select_off(); } }
static int parse_line(struct parser_context *ctx, const char *line) { unsigned int length, type; uint32_t address; uint8_t checksum; ctx->ptr = line; ctx->sum = 0; ctx->error = false; // Empty lines are probably OK if (*ctx->ptr++ != ':') return 1; if (strlen(ctx->ptr) < 11) return TY_ERROR_PARSE; length = parse_hex_byte(ctx, true); address = parse_hex_short(ctx); type = parse_hex_byte(ctx, true); if (ctx->error) return TY_ERROR_PARSE; switch (type) { case 0: // data record address += ctx->base_offset; if (address + length > ctx->f->size) { ctx->f->size = address + length; if (ctx->f->size > tyb_firmware_max_size) return ty_error(TY_ERROR_RANGE, "Firmware too big (max %zu bytes)", tyb_firmware_max_size); } for (unsigned int i = 0; i < length; i++) ctx->f->image[address + i] = parse_hex_byte(ctx, true); break; case 1: // EOF record if (length > 0) return TY_ERROR_PARSE; return 0; case 2: // extended segment address record if (length != 2) return TY_ERROR_PARSE; ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 4; break; case 3: // start segment address record break; case 4: // extended linear address record if (length != 2) return TY_ERROR_PARSE; ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 16; break; case 5: // start linear address record break; default: return TY_ERROR_PARSE; } // Don't checksum the checksum :) checksum = parse_hex_byte(ctx, false); if (ctx->error) return TY_ERROR_PARSE; if (((ctx->sum & 0xFF) + (checksum & 0xFF)) & 0xFF) return TY_ERROR_PARSE; // 1 to continue, 0 to stop (EOF record) and negative for errors return 1; }