// // "Alpine" file loading // Since the developers were coming after us with torches and pitchforks, we decided to // allow this kind of thing. ;-) But ONLY FOR THE DEVS, DAMMIT! >:-U O_O // bool AlpineLoadFile(char * path) { uint8 * buffer = NULL; jaguarROMSize = JaguarLoadROM(buffer, path); if (jaguarROMSize == 0) { // It's up to the GUI to deal with failure, not us. ;-) WriteLog("FILE: Could not load Alpine from file \"%s\"...\nAborting load!\n", path); return false; } jaguarMainROMCRC32 = crc32_calcCheckSum(buffer, jaguarROMSize); WriteLog("CRC: %08X\n", (unsigned int)jaguarMainROMCRC32); EepromInit(); jaguarRunAddress = 0x802000; WriteLog("FILE: Setting up Alpine ROM with non-standard length... Run address: 00802000, length: %08X\n", jaguarROMSize); memset(jagMemSpace + 0x800000, 0xFF, 0x2000); memcpy(jagMemSpace + 0x802000, buffer, jaguarROMSize); delete[] buffer; // Maybe instead of this, we could try requiring the STUBULATOR ROM? Just a thought... // Try setting the vector to say, $1000 and putting an instruction there that loops forever: // This kludge works! Yeah! SET32(jaguarMainRAM, 0x10, 0x00001000); // Set Exception #4 (Illegal Instruction) SET16(jaguarMainRAM, 0x1000, 0x60FE); // Here: bra Here return true; }
/* * Calculate the Smith-Waterman score. * * This is basically an SSE2 version of Wozniak's vectored implementation, but * without a score table. Further, we assume a fixed database and query size, * so *nogap and *b_gap must be pre-allocated (the malloc overhead for very * small scans is _huge_). * * NOTE THE FOLLOWING: * * 1) seqA must be padded with 7 bytes at the beginning and end. The first * element of seqA should be the first pad byte. * * 2) seqB must be padded with bytes on the end up to mod 8 characters. * The first element of seqB should be (of course) the first character. * * 3) seqA and seqB's padding _must_ be different, otherwise our logic will * consider the padding as matches! * * 4) These is no _mm_max_epu16 prior to SSE 4! We must use the signed max * function. Unfortunately, this limits our maximum score to 2^15 - 1, or * 32767. Since bad things happen if we roll over, our caller must ensure * that this will not happen. */ static int vect_sw_diff_gap(int8_t *seqA, int lena, int8_t *seqB, int lenb, int8_t *ls_seqA, int initbp, bool is_rna) { int i, j, score = 0; __m128i v_score, v_zero, v_match, v_mismatch; __m128i v_a_gap_ext, v_a_gap_open_ext; #ifndef v_b_gap_open_ext __m128i v_b_gap_ext, v_b_gap_open_ext; #endif __m128i v_a_gap, v_b_gap, v_nogap; __m128i v_last_nogap, v_prev_nogap, v_seq_a, v_seq_b; __m128i v_tmp; /* shut up icc */ (void)ls_seqA; (void)initbp; #define SET16(a, e7, e6, e5, e4, e3, e2, e1, e0) \ _mm_set_epi16((int16_t)a[e7], (int16_t)a[e6], \ (int16_t)a[e5], (int16_t)a[e4], \ (int16_t)a[e3], (int16_t)a[e2], \ (int16_t)a[e1], (int16_t)a[e0]) v_score = _mm_setzero_si128(); v_zero = _mm_setzero_si128(); v_match = SET16((&match), 0, 0, 0, 0, 0, 0, 0, 0); v_mismatch = SET16((&mismatch), 0, 0, 0, 0, 0, 0, 0, 0); v_a_gap_ext = SET16((&a_gap_ext), 0, 0, 0, 0, 0, 0, 0, 0); v_a_gap_open_ext = SET16((&a_gap_open), 0, 0, 0, 0, 0, 0, 0, 0); v_a_gap_open_ext = _mm_add_epi16(v_a_gap_open_ext, v_a_gap_ext); v_b_gap_ext = SET16((&b_gap_ext), 0, 0, 0, 0, 0, 0, 0, 0); v_b_gap_open_ext = SET16((&b_gap_open), 0, 0, 0, 0, 0, 0, 0, 0); v_b_gap_open_ext = _mm_add_epi16(v_b_gap_open_ext, v_b_gap_ext); for (i = 0; i < lena + 14; i++) { nogap[i] = 0; b_gap[i] = (int16_t)-b_gap_open; } for (i = 0; i < (lenb + 7)/8; i++) { int k = i * 8; v_b_gap = SET16(b_gap, 6, 6, 5, 4, 3, 2, 1, 0); v_nogap = SET16(nogap, 6, 6, 5, 4, 3, 2, 1, 0); v_seq_a = SET16(seqA, 0, 0, 1, 2, 3, 4, 5, 6); v_seq_b = SET16(seqB, k+7, k+6, k+5, k+4, k+3, k+2, k+1, k+0); v_a_gap = v_a_gap_ext; v_a_gap = _mm_sub_epi16(v_a_gap, v_a_gap_open_ext); v_last_nogap = _mm_setzero_si128(); v_prev_nogap = _mm_setzero_si128(); for (j = 0; j < (lena + 7); j++) { v_b_gap = _mm_slli_si128(v_b_gap, 2); v_b_gap = _mm_insert_epi16(v_b_gap, b_gap[j+7], 0); v_nogap = _mm_slli_si128(v_nogap, 2); v_nogap = _mm_insert_epi16(v_nogap, nogap[j+7], 0); v_seq_a = _mm_slli_si128(v_seq_a, 2); v_seq_a = _mm_insert_epi16(v_seq_a, seqA[j+7], 0); v_tmp = _mm_sub_epi16(v_last_nogap, v_a_gap_open_ext); v_a_gap = _mm_sub_epi16(v_a_gap, v_a_gap_ext); v_a_gap = _mm_max_epi16(v_a_gap, v_tmp); v_tmp = _mm_sub_epi16(v_nogap, v_b_gap_open_ext); v_b_gap = _mm_sub_epi16(v_b_gap, v_b_gap_ext); v_b_gap = _mm_max_epi16(v_b_gap, v_tmp); /* compute the score (v_last_nogap is a tmp variable) */ v_last_nogap = _mm_cmpeq_epi16(v_seq_a, v_seq_b); v_tmp = _mm_and_si128(v_last_nogap, v_match); v_last_nogap = _mm_cmpeq_epi16(v_last_nogap, v_zero); v_last_nogap = _mm_and_si128(v_last_nogap, v_mismatch); v_tmp = _mm_or_si128(v_tmp, v_last_nogap); v_last_nogap = _mm_add_epi16(v_prev_nogap, v_tmp); v_last_nogap = _mm_max_epi16(v_last_nogap, v_zero); v_last_nogap = _mm_max_epi16(v_last_nogap, v_a_gap); v_last_nogap = _mm_max_epi16(v_last_nogap, v_b_gap); v_prev_nogap = v_nogap; v_nogap = v_last_nogap; b_gap[j] = (int16_t)_mm_extract_epi16(v_b_gap, 7); nogap[j] = (int16_t)_mm_extract_epi16(v_nogap, 7); v_score = _mm_max_epi16(v_score, v_last_nogap); } } /* * Ugh. Old gcc can't loop and using _mm_store to an int16_t array * breaks strict-aliasing rules. */ assert(score == 0); score = MAX(score, _mm_extract_epi16(v_score, 0)); score = MAX(score, _mm_extract_epi16(v_score, 1)); score = MAX(score, _mm_extract_epi16(v_score, 2)); score = MAX(score, _mm_extract_epi16(v_score, 3)); score = MAX(score, _mm_extract_epi16(v_score, 4)); score = MAX(score, _mm_extract_epi16(v_score, 5)); score = MAX(score, _mm_extract_epi16(v_score, 6)); score = MAX(score, _mm_extract_epi16(v_score, 7)); return (score); }
/* * Calculate the Smith-Waterman score. * * This is basically an SSE2 version of Wozniak's vectored implementation, but * without a score table. Further, we assume a fixed database and query size, * so *nogap and *b_gap must be pre-allocated (the malloc overhead for very * small scans is _huge_). * * NOTE THE FOLLOWING: * * 1) seqA must be padded with 7 bytes at the beginning and end. The first * element of seqA should be the first pad byte. * * 2) seqB must be padded with bytes on the end up to mod 8 characters. * The first element of seqB should be (of course) the first character. * * 3) seqA and seqB's padding _must_ be different, otherwise our logic will * consider the padding as matches! * * 4) These is no _mm_max_epu16 prior to SSE 4! We must use the signed max * function. Unfortunately, this limits our maximum score to 2^15 - 1, or * 32767. Since bad things happen if we roll over, our caller must ensure * that this will not happen. */ static int vect_sw_diff_gap(int8_t *seqA, int lena, int8_t *seqB, int lenb, int8_t *ls_seqA, int initbp, bool is_rna) { int i, j, score = 0; __m128i v_score, v_zero, v_match, v_mismatch; __m128i v_a_gap_ext, v_a_gap_open_ext; #ifndef v_b_gap_open_ext __m128i v_b_gap_ext, v_b_gap_open_ext; #endif __m128i v_a_gap, v_b_gap, v_nogap; __m128i v_last_nogap, v_prev_nogap, v_seq_a, v_seq_b; __m128i v_tmp; /* shut up icc */ (void)ls_seqA; (void)initbp; #define SET16(a, e7, e6, e5, e4, e3, e2, e1, e0) \ _mm_set_epi16((int16_t)a[e7], (int16_t)a[e6], \ (int16_t)a[e5], (int16_t)a[e4], \ (int16_t)a[e3], (int16_t)a[e2], \ (int16_t)a[e1], (int16_t)a[e0]) v_score = _mm_setzero_si128(); v_zero = _mm_setzero_si128(); v_match = SET16((&match), 0, 0, 0, 0, 0, 0, 0, 0); v_mismatch = SET16((&mismatch), 0, 0, 0, 0, 0, 0, 0, 0); v_a_gap_ext = SET16((&a_gap_ext), 0, 0, 0, 0, 0, 0, 0, 0); v_a_gap_open_ext = SET16((&a_gap_open), 0, 0, 0, 0, 0, 0, 0, 0); v_a_gap_open_ext = _mm_add_epi16(v_a_gap_open_ext, v_a_gap_ext); v_b_gap_ext = SET16((&b_gap_ext), 0, 0, 0, 0, 0, 0, 0, 0); v_b_gap_open_ext = SET16((&b_gap_open), 0, 0, 0, 0, 0, 0, 0, 0); v_b_gap_open_ext = _mm_add_epi16(v_b_gap_open_ext, v_b_gap_ext); for (i = 0; i < lena + 14; i++) { nogap[i] = 0; b_gap[i] = (int16_t)-b_gap_open; } /* * When using colour space reads, we must handle the first row * specially. This is because the read will begin with some marker * base, which will affect matching against the genome. * * For 25mer reads, this actually makes things faster, because our * vectorised portion becomes evenly divisible by 8 again. Yey. */ if (use_colours) { int a_gap, prev_nogap, last_nogap; a_gap = -a_gap_open; last_nogap = prev_nogap = 0; for (i = 7; i < (lena + 7); i++) { int a, ms; a_gap = MAX((last_nogap - a_gap_open - a_gap_ext), (a_gap - a_gap_ext)); b_gap[i] =(uint16_t)MAX((nogap[i] - b_gap_open - b_gap_ext), (b_gap[i] - b_gap_ext)); a = lstocs(ls_seqA[i], initbp, is_rna); ms = (a == seqB[0]) ? match : mismatch; last_nogap = MAX((prev_nogap + ms), 0); last_nogap = MAX(last_nogap, a_gap); last_nogap = MAX(last_nogap, b_gap[i]); prev_nogap = nogap[i]; nogap[i] = (uint16_t)last_nogap; score = MAX(score, last_nogap); } v_score = SET16((&score), 0, 0, 0, 0, 0, 0, 0, 0); score = 0; seqB++; lenb--; assert(lenb != 0); } for (i = 0; i < (lenb + 7)/8; i++) { int k = i * 8; v_b_gap = SET16(b_gap, 6, 6, 5, 4, 3, 2, 1, 0); v_nogap = SET16(nogap, 6, 6, 5, 4, 3, 2, 1, 0); v_seq_a = SET16(seqA, 0, 0, 1, 2, 3, 4, 5, 6); v_seq_b = SET16(seqB, k+7, k+6, k+5, k+4, k+3, k+2, k+1, k+0); v_a_gap = v_a_gap_ext; v_a_gap = _mm_sub_epi16(v_a_gap, v_a_gap_open_ext); v_last_nogap = _mm_setzero_si128(); v_prev_nogap = _mm_setzero_si128(); for (j = 0; j < (lena + 7); j++) { v_b_gap = _mm_slli_si128(v_b_gap, 2); v_b_gap = _mm_insert_epi16(v_b_gap, b_gap[j+7], 0); v_nogap = _mm_slli_si128(v_nogap, 2); v_nogap = _mm_insert_epi16(v_nogap, nogap[j+7], 0); v_seq_a = _mm_slli_si128(v_seq_a, 2); v_seq_a = _mm_insert_epi16(v_seq_a, seqA[j+7], 0); v_tmp = _mm_sub_epi16(v_last_nogap, v_a_gap_open_ext); v_a_gap = _mm_sub_epi16(v_a_gap, v_a_gap_ext); v_a_gap = _mm_max_epi16(v_a_gap, v_tmp); v_tmp = _mm_sub_epi16(v_nogap, v_b_gap_open_ext); v_b_gap = _mm_sub_epi16(v_b_gap, v_b_gap_ext); v_b_gap = _mm_max_epi16(v_b_gap, v_tmp); /* compute the score (v_last_nogap is a tmp variable) */ v_last_nogap = _mm_cmpeq_epi16(v_seq_a, v_seq_b); v_tmp = _mm_and_si128(v_last_nogap, v_match); v_last_nogap = _mm_cmpeq_epi16(v_last_nogap, v_zero); v_last_nogap = _mm_and_si128(v_last_nogap, v_mismatch); v_tmp = _mm_or_si128(v_tmp, v_last_nogap); v_last_nogap = _mm_add_epi16(v_prev_nogap, v_tmp); v_last_nogap = _mm_max_epi16(v_last_nogap, v_zero); v_last_nogap = _mm_max_epi16(v_last_nogap, v_a_gap); v_last_nogap = _mm_max_epi16(v_last_nogap, v_b_gap); v_prev_nogap = v_nogap; v_nogap = v_last_nogap; b_gap[j] = (int16_t)_mm_extract_epi16(v_b_gap, 7); nogap[j] = (int16_t)_mm_extract_epi16(v_nogap, 7); v_score = _mm_max_epi16(v_score, v_last_nogap); } } /* * Ugh. Old gcc can't loop and using _mm_store to an int16_t array * breaks strict-aliasing rules. */ assert(score == 0); score = MAX(score, _mm_extract_epi16(v_score, 0)); score = MAX(score, _mm_extract_epi16(v_score, 1)); score = MAX(score, _mm_extract_epi16(v_score, 2)); score = MAX(score, _mm_extract_epi16(v_score, 3)); score = MAX(score, _mm_extract_epi16(v_score, 4)); score = MAX(score, _mm_extract_epi16(v_score, 5)); score = MAX(score, _mm_extract_epi16(v_score, 6)); score = MAX(score, _mm_extract_epi16(v_score, 7)); return (score); }
static void do_query_reply(unsigned char code) { size_t len; unsigned i; const char *comma = ""; size_t obptr0 = obptr - obuf; unsigned char *obptr_len; unsigned short num, denom; if (qr_in_progress) { trace_ds("> StructuredField\n"); qr_in_progress = false; } space3270out(4); obptr += 2; /* skip length for now */ *obptr++ = SFID_QREPLY; *obptr++ = code; switch (code) { case QR_CHARSETS: trace_ds("> QueryReply(CharacterSets)\n"); space3270out(64); if (dbcs) *obptr++ = 0x8e; /* flags: GE, CGCSGID, DBCS */ else *obptr++ = 0x82; /* flags: GE, CGCSGID present */ *obptr++ = 0x00; /* more flags */ *obptr++ = char_width; /* SDW */ *obptr++ = char_height; /* SDW */ *obptr++ = 0x00; /* no load PS */ *obptr++ = 0x00; *obptr++ = 0x00; *obptr++ = 0x00; if (dbcs) *obptr++ = 0x0b; /* DL (11 bytes) */ else *obptr++ = 0x07; /* DL (7 bytes) */ *obptr++ = 0x00; /* SET 0: */ if (dbcs) *obptr++ = 0x00; /* FLAGS: non-load, single- plane, single-bute */ else *obptr++ = 0x10; /* FLAGS: non-loadable, single-plane, single-byte, no compare */ *obptr++ = 0x00; /* LCID 0 */ if (dbcs) { *obptr++ = 0x00; /* SW 0 */ *obptr++ = 0x00; /* SH 0 */ *obptr++ = 0x00; /* SUBSN */ *obptr++ = 0x00; /* SUBSN */ } SET32(obptr, cgcsgid); /* CGCSGID */ if (!standard_font) { /* special 3270 font, includes APL */ *obptr++ = 0x01;/* SET 1: */ *obptr++ = 0x10;/* FLAGS: non-loadable, single-plane, single-byte, no compare */ *obptr++ = 0xf1;/* LCID */ if (dbcs) { *obptr++ = 0x00;/* SW 0 */ *obptr++ = 0x00;/* SH 0 */ *obptr++ = 0x00;/* SUBSN */ *obptr++ = 0x00;/* SUBSN */ } *obptr++ = 0x03;/* CGCSGID: 3179-style APL2 */ *obptr++ = 0xc3; *obptr++ = 0x01; *obptr++ = 0x36; } if (dbcs) { *obptr++ = 0x80; /* SET 0x80: */ *obptr++ = 0x20; /* FLAGS: DBCS */ *obptr++ = 0xf8; /* LCID: 0xf8 */ *obptr++ = char_width * 2; /* SW */ *obptr++ = char_height; /* SH */ *obptr++ = 0x41; /* SUBSN */ *obptr++ = 0x7f; /* SUBSN */ SET32(obptr, cgcsgid_dbcs); /* CGCSGID */ } break; case QR_IMP_PART: trace_ds("> QueryReply(ImplicitPartition)\n"); space3270out(13); *obptr++ = 0x0; /* reserved */ *obptr++ = 0x0; *obptr++ = 0x0b; /* length of display size */ *obptr++ = 0x01; /* "implicit partition size" */ *obptr++ = 0x00; /* reserved */ SET16(obptr, 72); /* implicit partition width */ SET16(obptr, 66); /* implicit partition height */ SET16(obptr, maxCOLS); /* alternate height */ SET16(obptr, maxROWS); /* alternate width */ break; case QR_NULL: trace_ds("> QueryReply(Null)\n"); break; case QR_SUMMARY: trace_ds("> QueryReply(Summary("); space3270out(NSR); for (i = 0; i < NSR; i++) { if (dbcs || supported_replies[i] != QR_DBCS_ASIA) { trace_ds("%s%s", comma, see_qcode(supported_replies[i])); comma = ","; *obptr++ = supported_replies[i]; } } trace_ds("))\n"); break; case QR_USABLE_AREA: trace_ds("> QueryReply(UsableArea)\n"); space3270out(19); *obptr++ = 0x01; /* 12/14-bit addressing */ *obptr++ = 0x00; /* no special character features */ SET16(obptr, maxCOLS); /* usable width */ SET16(obptr, maxROWS); /* usable height */ *obptr++ = 0x01; /* units (mm) */ num = /*display_widthMM()*/ 8*5/4; denom = /*display_width()*/ 7 * 72; while (!(num %2) && !(denom % 2)) { num /= 2; denom /= 2; } SET16(obptr, (int)num); /* Xr numerator */ SET16(obptr, (int)denom); /* Xr denominator */ num = /*display_heightMM()*/ 11*5/4; denom = /*display_height()*/ 9*66; while (!(num %2) && !(denom % 2)) { num /= 2; denom /= 2; } SET16(obptr, (int)num); /* Yr numerator */ SET16(obptr, (int)denom); /* Yr denominator */ *obptr++ = char_width; /* AW */ *obptr++ = char_height; /* AH */ SET16(obptr, 0); /* buffer */ break; case QR_COLOR: trace_ds("> QueryReply(Color)\n"); space3270out(4 + 2*15); *obptr++ = 0x00; /* no options */ *obptr++ = 16; /* report on 16 colors */ *obptr++ = 0x00; /* default color: */ *obptr++ = 0xf0 + HOST_COLOR_GREEN; /* green */ for (i = 0xf1; i <= 0xff; i++) { *obptr++ = i; *obptr++ = i; } break; case QR_HIGHLIGHTING: trace_ds("> QueryReply(Highlighting)\n"); space3270out(11); *obptr++ = 5; /* report on 5 pairs */ *obptr++ = XAH_DEFAULT; /* default: */ *obptr++ = XAH_NORMAL; /* normal */ *obptr++ = XAH_BLINK; /* blink: */ *obptr++ = XAH_BLINK; /* blink */ *obptr++ = XAH_REVERSE; /* reverse: */ *obptr++ = XAH_REVERSE; /* reverse */ *obptr++ = XAH_UNDERSCORE; /* underscore: */ *obptr++ = XAH_UNDERSCORE; /* underscore */ *obptr++ = XAH_INTENSIFY; /* intensify: */ *obptr++ = XAH_INTENSIFY; /* intensify */ break; case QR_REPLY_MODES: trace_ds("> QueryReply(ReplyModes)\n"); space3270out(3); *obptr++ = SF_SRM_FIELD; *obptr++ = SF_SRM_XFIELD; *obptr++ = SF_SRM_CHAR; break; case QR_DBCS_ASIA: /* XXX: Should we support this, even when not in DBCS mode? */ trace_ds("> QueryReply(DbcsAsia)\n"); space3270out(7); *obptr++ = 0x00; /* flags (none) */ *obptr++ = 0x03; /* field length 3 */ *obptr++ = 0x01; /* SI/SO supported */ *obptr++ = 0x80; /* character set ID 0x80 */ *obptr++ = 0x03; /* field length 3 */ *obptr++ = 0x02; /* input control */ *obptr++ = 0x01; /* creation supported */ break; case QR_ALPHA_PART: trace_ds("> QueryReply(AlphanumericPartitions)\n"); space3270out(4); *obptr++ = 0; /* 1 partition */ SET16(obptr, maxROWS*maxCOLS); /* buffer space */ *obptr++ = 0; /* no special features */ break; case QR_DDM: trace_ds("> QueryReply(DistributedDataManagement)\n"); space3270out(8); SET16(obptr,0); /* set reserved field to 0 */ SET16(obptr,2048); /* set inbound length limit */ SET16(obptr,2048); /* set outbound length limit */ SET16(obptr,0x0101); /* NSS=01, DDMSS=01 */ break; default: return; /* internal error */ } obptr_len = obuf + obptr0; len = (obptr - obuf) - obptr0; SET16(obptr_len, len); }
static int fragment(struct net_buf *buf, void *ptr) { struct queuebuf *q; int max_payload; int framer_hdrlen; uint16_t frag_tag; /* Number of bytes processed. */ uint16_t processed_ip_out_len; struct net_buf *mbuf; bool last_fragment = false; #define USE_FRAMER_HDRLEN 0 #if USE_FRAMER_HDRLEN framer_hdrlen = NETSTACK_FRAMER.length(); if(framer_hdrlen < 0) { /* Framing failed, we assume the maximum header length */ framer_hdrlen = 21; } #else /* USE_FRAMER_HDRLEN */ framer_hdrlen = 21; #endif /* USE_FRAMER_HDRLEN */ max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead(); PRINTF("max_payload: %d, framer_hdrlen: %d \n",max_payload, framer_hdrlen); mbuf = l2_buf_get_reserve(0); if (!mbuf) { goto fail; } uip_last_tx_status(mbuf) = MAC_TX_OK; /* * The destination address will be tagged to each outbound * packet. If the argument localdest is NULL, we are sending a * broadcast packet. */ if((int)uip_len(buf) <= max_payload) { /* The packet does not need to be fragmented, send buf */ packetbuf_copyfrom(mbuf, uip_buf(buf), uip_len(buf)); send_packet(mbuf, &ip_buf_ll_dest(buf), true, ptr); ip_buf_unref(buf); return 1; } uip_uncomp_hdr_len(mbuf) = 0; uip_packetbuf_hdr_len(mbuf) = 0; packetbuf_clear(mbuf); uip_packetbuf_ptr(mbuf) = packetbuf_dataptr(mbuf); packetbuf_set_attr(mbuf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, SICSLOWPAN_MAX_MAC_TRANSMISSIONS); PRINTF("fragmentation: total packet len %d\n", uip_len(buf)); /* * The outbound IPv6 packet is too large to fit into a single 15.4 * packet, so we fragment it into multiple packets and send them. * The first fragment contains frag1 dispatch, then * IPv6/HC1/HC06/HC_UDP dispatchs/headers. * The following fragments contain only the fragn dispatch. */ int estimated_fragments = ((int)uip_len(buf)) / ((int)MAC_MAX_PAYLOAD - SICSLOWPAN_FRAGN_HDR_LEN) + 1; int freebuf = queuebuf_numfree(mbuf) - 1; PRINTF("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len(buf), estimated_fragments, freebuf); if(freebuf < estimated_fragments) { PRINTF("Dropping packet, not enough free bufs\n"); goto fail; } /* Create 1st Fragment */ SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE, ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len(buf))); frag_tag = my_tag++; SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_TAG, frag_tag); PRINTF("fragmentation: fragment %d \n", frag_tag); /* Copy payload and send */ uip_packetbuf_hdr_len(mbuf) += SICSLOWPAN_FRAG1_HDR_LEN; uip_packetbuf_payload_len(mbuf) = (max_payload - uip_packetbuf_hdr_len(mbuf)) & 0xfffffff8; PRINTF("(payload len %d, hdr len %d, tag %d)\n", uip_packetbuf_payload_len(mbuf), uip_packetbuf_hdr_len(mbuf), frag_tag); memcpy(uip_packetbuf_ptr(mbuf) + uip_packetbuf_hdr_len(mbuf), uip_buf(buf), uip_packetbuf_payload_len(mbuf)); packetbuf_set_datalen(mbuf, uip_packetbuf_payload_len(mbuf) + uip_packetbuf_hdr_len(mbuf)); q = queuebuf_new_from_packetbuf(mbuf); if(q == NULL) { PRINTF("could not allocate queuebuf for first fragment, dropping packet\n"); goto fail; } net_buf_ref(mbuf); send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr); queuebuf_to_packetbuf(mbuf, q); queuebuf_free(q); q = NULL; /* Check tx result. */ if((uip_last_tx_status(mbuf) == MAC_TX_COLLISION) || (uip_last_tx_status(mbuf) == MAC_TX_ERR) || (uip_last_tx_status(mbuf) == MAC_TX_ERR_FATAL)) { PRINTF("error in fragment tx, dropping subsequent fragments.\n"); goto fail; } /* set processed_ip_out_len to what we already sent from the IP payload*/ processed_ip_out_len = uip_packetbuf_payload_len(mbuf); /* * Create following fragments * Datagram tag is already in the buffer, we need to set the * FRAGN dispatch and for each fragment, the offset */ uip_packetbuf_hdr_len(mbuf) = SICSLOWPAN_FRAGN_HDR_LEN; SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE, ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len(buf))); uip_packetbuf_payload_len(mbuf) = (max_payload - uip_packetbuf_hdr_len(mbuf)) & 0xfffffff8; while(processed_ip_out_len < uip_len(buf)) { PRINTF("fragmentation: fragment:%d, processed_ip_out_len:%d \n", my_tag, processed_ip_out_len); uip_packetbuf_ptr(mbuf)[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3; /* Copy payload and send */ if(uip_len(buf) - processed_ip_out_len < uip_packetbuf_payload_len(mbuf)) { /* last fragment */ last_fragment = true; uip_packetbuf_payload_len(mbuf) = uip_len(buf) - processed_ip_out_len; } PRINTF("(offset %d, len %d, tag %d)\n", processed_ip_out_len >> 3, uip_packetbuf_payload_len(mbuf), my_tag); memcpy(uip_packetbuf_ptr(mbuf) + uip_packetbuf_hdr_len(mbuf), (uint8_t *)UIP_IP_BUF(buf) + processed_ip_out_len, uip_packetbuf_payload_len(mbuf)); packetbuf_set_datalen(mbuf, uip_packetbuf_payload_len(mbuf) + uip_packetbuf_hdr_len(mbuf)); q = queuebuf_new_from_packetbuf(mbuf); if(q == NULL) { PRINTF("could not allocate queuebuf, dropping fragment\n"); goto fail; } net_buf_ref(mbuf); send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr); queuebuf_to_packetbuf(mbuf, q); queuebuf_free(q); q = NULL; processed_ip_out_len += uip_packetbuf_payload_len(mbuf); /* Check tx result. */ if((uip_last_tx_status(mbuf) == MAC_TX_COLLISION) || (uip_last_tx_status(mbuf) == MAC_TX_ERR) || (uip_last_tx_status(mbuf) == MAC_TX_ERR_FATAL)) { PRINTF("error in fragment tx, dropping subsequent fragments.\n"); goto fail; } } ip_buf_unref(buf); l2_buf_unref(mbuf); return 1; fail: if (mbuf) { l2_buf_unref(mbuf); } return 0; }
// // Jaguar file loading // We do a more intelligent file analysis here instead of relying on (possible false) // file extensions which people don't seem to give two shits about anyway. :-( // bool JaguarLoadFile(char * path) { uint8 * buffer = NULL; jaguarROMSize = JaguarLoadROM(buffer, path); if (jaguarROMSize == 0) { // It's up to the GUI to report errors, not us. :-) WriteLog("FILE: Could not load ROM from file \"%s\"...\nAborting load!\n", path); return false; } jaguarMainROMCRC32 = crc32_calcCheckSum(buffer, jaguarROMSize); WriteLog("CRC: %08X\n", (unsigned int)jaguarMainROMCRC32); // TODO: Check for EEPROM file in ZIP file. If there is no EEPROM in the user's EEPROM // directory, copy the one from the ZIP file, if it exists. EepromInit(); jaguarRunAddress = 0x802000; // For non-BIOS runs, this is true int fileType = ParseFileType(buffer, jaguarROMSize); jaguarCartInserted = false; if (fileType == JST_ROM) { jaguarCartInserted = true; memcpy(jagMemSpace + 0x800000, buffer, jaguarROMSize); // Checking something... jaguarRunAddress = GET32(jagMemSpace, 0x800404); WriteLog("FILE: Cartridge run address is reported as $%X...\n", jaguarRunAddress); delete[] buffer; return true; } else if (fileType == JST_ALPINE) { // File extension ".ROM": Alpine image that loads/runs at $802000 WriteLog("FILE: Setting up Alpine ROM... Run address: 00802000, length: %08X\n", jaguarROMSize); memset(jagMemSpace + 0x800000, 0xFF, 0x2000); memcpy(jagMemSpace + 0x802000, buffer, jaguarROMSize); delete[] buffer; // Maybe instead of this, we could try requiring the STUBULATOR ROM? Just a thought... // Try setting the vector to say, $1000 and putting an instruction there that loops forever: // This kludge works! Yeah! SET32(jaguarMainRAM, 0x10, 0x00001000); SET16(jaguarMainRAM, 0x1000, 0x60FE); // Here: bra Here return true; } else if (fileType == JST_ABS_TYPE1) { // For ABS type 1, run address == load address uint32 loadAddress = GET32(buffer, 0x16), codeSize = GET32(buffer, 0x02) + GET32(buffer, 0x06); WriteLog("FILE: Setting up homebrew (ABS-1)... Run address: %08X, length: %08X\n", loadAddress, codeSize); memcpy(jagMemSpace + loadAddress, buffer + 0x24, codeSize); delete[] buffer; jaguarRunAddress = loadAddress; return true; } else if (fileType == JST_ABS_TYPE2) { uint32 loadAddress = GET32(buffer, 0x28), runAddress = GET32(buffer, 0x24), codeSize = GET32(buffer, 0x18) + GET32(buffer, 0x1C); WriteLog("FILE: Setting up homebrew (ABS-2)... Run address: %08X, length: %08X\n", runAddress, codeSize); memcpy(jagMemSpace + loadAddress, buffer + 0xA8, codeSize); delete[] buffer; jaguarRunAddress = runAddress; return true; } // NB: This is *wrong* /* Basically, if there is no "JAG" at position $1C, then the long there is the load/start address in LITTLE ENDIAN. If "JAG" is present, the the next character ("R" or "L") determines the size of the JagServer command (2 bytes vs. 4). Following that are the commands themselves; typically it will either be 2 (load) or 3 (load & run). Command headers go like so: 2: Load address (long) Length (long) payload 3: Load address (long) Length (long) Run address (long) payload 5: (Reset) [command only] 7: (Run at address) Run address (long) [no payload] 9: (Clear memory) Start address (long) End address (long) [no payload] 10: (Poll for commands) [command only] 12: (Load & run user program) filname, terminated with NULL [no payload] $FFFF: (Halt) [no payload] */ else if (fileType == JST_JAGSERVER) { // This kind of shiaut should be in the detection code below... // (and now it is! :-) // if (buffer[0x1C] == 'J' && buffer[0x1D] == 'A' && buffer[0x1E] == 'G') // { // Still need to do some checking here for type 2 vs. type 3. This assumes 3 // Also, JAGR vs. JAGL (word command size vs. long command size) uint32 loadAddress = GET32(buffer, 0x22), runAddress = GET32(buffer, 0x2A); WriteLog("FILE: Setting up homebrew (Jag Server)... Run address: $%X, length: $%X\n", runAddress, jaguarROMSize - 0x2E); memcpy(jagMemSpace + loadAddress, buffer + 0x2E, jaguarROMSize - 0x2E); delete[] buffer; jaguarRunAddress = runAddress; return true; // } // else // Special WTFOMGBBQ type here... // { // uint32_t loadAddress = (buffer[0x1F] << 24) | (buffer[0x1E] << 16) | (buffer[0x1D] << 8) | buffer[0x1C]; // WriteLog("FILE: Setting up homebrew (GEMDOS WTFOMGBBQ type)... Run address: $%X, length: $%X\n", loadAddress, jaguarROMSize - 0x20); // memcpy(jagMemSpace + loadAddress, buffer + 0x20, jaguarROMSize - 0x20); // delete[] buffer; // jaguarRunAddress = loadAddress; // return true; // } } else if (fileType == JST_WTFOMGBBQ) { uint32_t loadAddress = (buffer[0x1F] << 24) | (buffer[0x1E] << 16) | (buffer[0x1D] << 8) | buffer[0x1C]; WriteLog("FILE: Setting up homebrew (GEMDOS WTFOMGBBQ type)... Run address: $%X, length: $%X\n", loadAddress, jaguarROMSize - 0x20); memcpy(jagMemSpace + loadAddress, buffer + 0x20, jaguarROMSize - 0x20); delete[] buffer; jaguarRunAddress = loadAddress; return true; } // We can assume we have JST_NONE at this point. :-P return false; }
/* * audio1575_dma_stop() * * Description: * This routine is used to put each DMA engine into the quiet state. * * Arguments: * audio1575_state_t *statep The device's state structure */ static void audio1575_dma_stop(audio1575_state_t *statep, boolean_t quiesce) { uint32_t intrsr; int i; if (statep->regsh == NULL) { return; } /* pause bus master (needed for the following reset register) */ for (i = 0; i < M1575_LOOP_CTR; i++) { SET32(M1575_DMACR_REG, M1575_DMACR_PAUSE_ALL); if (GET32(M1575_DMACR_REG) & M1575_DMACR_PAUSE_ALL) { break; } drv_usecwait(10); } if (i >= M1575_LOOP_CTR) { if (!quiesce) audio_dev_warn(statep->adev, "failed to stop DMA"); return; } /* Pause bus master (needed for the following reset register) */ PUT8(M1575_PCMICR_REG, 0); PUT8(M1575_PCMOCR_REG, 0); PUT8(M1575_MICICR_REG, 0); PUT8(M1575_CSPOCR_REG, 0); PUT8(M1575_PCMI2CR_RR, 0); PUT8(M1575_MICI2CR_RR, 0); /* Reset the bus master registers for all DMA engines */ PUT8(M1575_PCMICR_REG, M1575_PCMICR_RR); PUT8(M1575_PCMOCR_REG, M1575_PCMOCR_RR); PUT8(M1575_MICICR_REG, M1575_MICICR_RR); PUT8(M1575_CSPOCR_REG, M1575_CSPOCR_RR); PUT8(M1575_PCMI2CR_REG, M1575_PCMI2CR_RR); PUT8(M1575_MICI2CR_REG, M1575_MICI2CR_RR); /* Reset FIFOS */ PUT32(M1575_FIFOCR1_REG, 0x81818181); PUT32(M1575_FIFOCR2_REG, 0x81818181); PUT32(M1575_FIFOCR3_REG, 0x81818181); /* Clear Interrupts */ SET16(M1575_PCMISR_REG, M1575_SR_CLR); SET16(M1575_PCMOSR_REG, M1575_SR_CLR); SET16(M1575_MICISR_REG, M1575_SR_CLR); SET16(M1575_CSPOSR_REG, M1575_SR_CLR); SET16(M1575_PCMI2SR_REG, M1575_SR_CLR); SET16(M1575_MICI2SR_REG, M1575_SR_CLR); /* * clear the interrupt control and status register * READ/WRITE/READ workaround required to flush PCI caches */ PUT32(M1575_INTRCR_REG, 0); (void) GET32(M1575_INTRCR_REG); intrsr = GET32(M1575_INTRSR_REG); PUT32(M1575_INTRSR_REG, (intrsr & M1575_INTR_MASK)); (void) GET32(M1575_INTRSR_REG); }