64 static const char *phases[8] =
65 {
"DATA_OUT",
"DATA_IN",
"COMMAND",
"STATUS",
66 "RESERVED_OUT",
"RESERVED_IN",
"MSG_OUT",
"MSG_IN" };
68 #define DEV_OSIOP_LENGTH OSIOP_NREGS 69 #define OSIOP_CHIP_REVISION 2 71 #define MAX_SCRIPTS_PER_CHUNK 256 73 #define OSIOP_TICK_SHIFT 17 101 static void osiop_free_xfer(
struct osiop_data *d)
103 if (d->
xferp != NULL)
111 static void osiop_new_xfer(
struct osiop_data *d,
int target_scsi_id)
113 if (d->
xferp != NULL) {
114 fatal(
"WARNING! osiop_new_xfer(): freeing previous" 124 static int osiop_get_scsi_phase(
struct osiop_data *d)
130 static void osiop_set_scsi_phase(
struct osiop_data *d,
int phase)
148 static int osiop_update_sip_and_dip(
struct osiop_data *d)
180 static void osiop_reassert_interrupts(
struct osiop_data *d)
184 if (osiop_update_sip_and_dip(d))
220 static uint8_t read_byte(
struct osiop_data *d,
struct cpu *cpu, uint32_t
addr)
231 static void write_byte(
struct osiop_data *d,
struct cpu *cpu, uint32_t
addr, uint8_t byte)
258 uint32_t dsp = *dspp;
262 fatal(
"osiop_get_next_scripts_word: unaligned DSP 0x%08x\n",
267 instr = read_word(d, cpu, dsp);
269 dsp +=
sizeof(
instr);
294 uint32_t dspOrig = *dspp;
297 uint32_t dbc, target_addr = 0;
300 int opcode, phase, relative_addressing, table_indirect_addressing;
301 int select_with_atn, scsi_ids_to_select = -1, scsi_id_to_select;
302 int test_carry, compare_data, compare_phase;
303 int jump_if_true, wait_for_valid_phase;
304 int comparison = 0, interrupt_instead_of_branch = 0;
314 dbc = *dbcp = instr1 & 0x00ffffff;
317 reladdr = (instr2 << 8);
320 opcode = (dcmd >> 3) & 7;
324 debug(
"{ SCRIPTS @ 0x%08x: 0x%08x 0x%08x",
325 (
int) dspOrig, (
int) instr1, (
int) instr2);
327 switch (dcmd & 0xc0) {
331 int ofs1 = instr1 & 0x00ffffff;
332 int ofs2 = instr2 & 0x00ffffff;
333 int indirect_addressing = dcmd & 0x20;
334 uint32_t dsa = *dsap;
335 uint32_t
addr, xfer_byte_count, xfer_addr;
336 int32_t tmp = ofs2 << 8;
341 table_indirect_addressing = dcmd & 0x10;
343 opcode = (dcmd >> 3) & 1;
354 if (indirect_addressing) {
355 fatal(
"osiop: TODO: indirect_addressing move\n");
359 if (!table_indirect_addressing) {
360 fatal(
"osiop: TODO: !table_indirect_addressing move\n");
365 debug(
" FROM %i", tmp);
368 fatal(
"osiop: TODO: move ofs1!=ofs2\n");
372 if (phase != osiop_get_scsi_phase(d)) {
373 fatal(
"osiop: TODO: move: wait for phase. " 374 "phase = %i, osiop_get_scsi_phase = %i\n",
375 phase, osiop_get_scsi_phase(d));
380 debug(
" WHEN %s", phases[phase]);
383 xfer_byte_count = read_word(d, cpu, addr) & 0x00ffffff;
384 xfer_addr = read_word(d, cpu, addr+4);
393 while (xfer_byte_count > 0) {
394 uint8_t byte = read_byte(d, cpu, xfer_addr);
407 &d->
xferp->
cmd, xfer_byte_count, 0);
410 while (xfer_byte_count > 0) {
411 uint8_t byte = read_byte(d, cpu, xfer_addr);
422 fatal(
"osiop TODO: error\n");
441 while (xfer_byte_count > 0) {
442 uint8_t byte = read_byte(d, cpu, xfer_addr);
454 fatal(
"osiop TODO: error on rerun\n");
456 }
else if (res == 2) {
470 write_byte(d, cpu, xfer_addr, byte);
486 write_byte(d, cpu, xfer_addr, byte);
500 write_byte(d, cpu, xfer_addr, byte);
509 default:
fatal(
"osiop: TODO: unimplemented move, " 510 "phase=%i\n", phase);
516 *dbcp = xfer_byte_count;
524 relative_addressing = dcmd & 4;
525 table_indirect_addressing = dcmd & 2;
526 select_with_atn = dcmd & 1;
527 scsi_ids_to_select = (dbc >> 16) & 0xff;
532 if (select_with_atn) {
538 if (table_indirect_addressing) {
539 uint32_t dsa = *dsap;
541 int32_t tmp = dbc << 8;
546 debug(
" FROM %i", dbc);
548 word = read_word(d, cpu, addr);
549 scsi_ids_to_select = (word >> 16) & 0xff;
552 if (scsi_ids_to_select == 0) {
553 fatal(
"osiop: TODO: scsi_ids_to_select = 0!\n");
557 scsi_id_to_select = 0;
558 while (!(scsi_ids_to_select & 1)) {
559 scsi_ids_to_select >>= 1;
560 scsi_id_to_select ++;
563 scsi_ids_to_select &= ~1;
564 if (scsi_ids_to_select != 0) {
565 fatal(
"osiop: TODO: multiselect?\n");
570 debug(
" [SCSI ID %i]", scsi_id_to_select);
572 if (relative_addressing) {
576 target_addr = reladdr + *dspp;
578 debug(
" REL(%i)", reladdr);
580 target_addr = instr2;
582 debug(
" 0x%08x", instr2);
587 osiop_new_xfer(d, scsi_id_to_select);
607 debug(
": WAIT DISCONNECT");
611 debug(
": WAIT RESELECT");
612 fatal(
"osiop: TODO: wait reselect\n");
623 default:
fatal(
": UNIMPLEMENTED dcmd=0x%02x opcode=%i\n",
629 if (opcode == 3 || opcode == 4) {
630 int bit_atn = (dbc >> 3) & 1;
631 int bit_ack = (dbc >> 6) & 1;
632 int bit_target = (dbc >> 9) & 1;
633 int bit_carry = (dbc >> 10) & 1;
667 relative_addressing = (dbc >> 23) & 1;
668 test_carry = (dbc >> 21) & 1;
669 jump_if_true = (dbc >> 19) & 1;
670 compare_data = (dbc >> 18) & 1;
671 compare_phase = (dbc >> 17) & 1;
672 wait_for_valid_phase = (dbc >> 16) & 1;
685 debug(
": INTERRUPT");
687 default:
fatal(
": UNIMPLEMENTED dcmd=0x%02x opcode=%i\n",
692 if (opcode == 0 || opcode == 1) {
693 if (relative_addressing) {
697 target_addr = reladdr + *dspp;
699 debug(
" REL(%i)", reladdr);
701 target_addr = instr2;
703 debug(
" 0x%08x", instr2);
708 target_addr = *tempp;
711 interrupt_instead_of_branch = 1;
716 if (compare_data || compare_phase) {
717 fatal(
"osiop: TODO: test_carry cannot be" 718 " combined with other tests!\n");
722 fatal(
"osiop: TODO: test_carry\n");
727 fatal(
"osiop: TODO: compare_data\n");
736 wait_for_valid_phase ?
"WHEN" :
"IF",
737 jump_if_true?
"" :
"NOT ",
742 cur_phase = osiop_get_scsi_phase(d);
744 comparison = (phase == cur_phase);
747 if (!test_carry && !compare_data && !compare_phase)
748 jump_if_true = comparison = 1;
750 if ((jump_if_true && comparison) ||
751 (!jump_if_true && !comparison)) {
753 if (interrupt_instead_of_branch) {
765 debug(
": MEMORY MOVE");
771 default:
fatal(
": UNIMPLEMENTED dcmd 0x%02x\n", dcmd);
793 debug(
"{ SCRIPTS start }\n");
800 debug(
"{ SCRIPTS end }\n");
811 osiop_reassert_interrupts(d);
817 uint64_t idata = 0, odata = 0;
820 int origofs = relative_addr;
828 (relative_addr & ~3) |
829 (3 - (relative_addr & 3));
832 if (len ==
sizeof(uint32_t)) {
845 relative_addr = origofs;
848 uint32_t *p = (uint32_t*) &d->
reg[origofs];
859 oldreg = d->
reg[relative_addr];
862 d->
reg[relative_addr] = idata;
867 switch (relative_addr) {
878 osiop_reassert_interrupts(d);
882 if (idata != oldreg) {
883 fatal(
"osiop TODO: attempt to change SCID?\n");
890 fatal(
"[ osiop: SBDL set to 0x%x, but should be " 891 "read-only! ]\n", (
int) idata);
897 debug(
"[ osiop: SBCL set to 0x%x ]\n", (
int) idata);
905 osiop_reassert_interrupts(d);
912 osiop_reassert_interrupts(d);
922 debug(
"[ osiop: DSA set to 0x%x ]\n", (
int) idata);
939 debug(
"[ osiop: TEMP set to 0x%x ]\n", (
int) idata);
948 if ((idata & 0x3f) != 0x00) {
949 fatal(
"osiop TODO: istat 0x%x\n", (
int) idata);
953 d->
reg[relative_addr] = idata &
955 osiop_reassert_interrupts(d);
969 debug(
"[ osiop: DSP set to 0x%x ]\n", (
int) idata);
973 osiop_reassert_interrupts(d);
986 osiop_reassert_interrupts(d);
995 fatal(
"osiop TODO: SSM\n");
999 fatal(
"osiop TODO: LLM\n");
1003 fatal(
"osiop TODO: STD\n");
1011 fatal(
"[ osiop: read from 0x%02lx ]\n",
1012 (
long)relative_addr);
1014 fatal(
"[ osiop: write to 0x%02lx: 0x%02x ]\n",
1015 (
long)relative_addr, (
int)idata);
1021 if (len != 1 && !non1lenOk) {
1022 fatal(
"[ osiop: TODO: len != 1, addr 0x%0x ]\n",
1023 (
int)relative_addr);
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
void fatal(const char *fmt,...)
int diskimage_exist(struct machine *machine, int id, int type)
#define OSIOP_SCID_VALUE(i)
uint32_t osiop_get_next_scripts_word(struct cpu *cpu, struct osiop_data *d)
#define EMUL_LITTLE_ENDIAN
#define CHECK_ALLOCATION(ptr)
int osiop_execute_scripts_instr(struct cpu *cpu, struct osiop_data *d)
struct scsi_transfer * scsi_transfer_alloc(void)
#define OSIOP_CHIP_REVISION
void scsi_transfer_free(struct scsi_transfer *p)
#define INTERRUPT_ASSERT(istruct)
void osiop_execute_scripts(struct cpu *cpu, struct osiop_data *d)
void scsi_transfer_allocbuf(size_t *lenp, unsigned char **pp, size_t want_len, int clearflag)
#define INTERRUPT_CONNECT(name, istruct)
struct scsi_transfer * xferp
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
addr & if(addr >=0x24 &&page !=NULL)
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
int diskimage_scsicommand(struct cpu *cpu, int id, int type, struct scsi_transfer *xferp)
#define MAX_SCRIPTS_PER_CHUNK
#define INTERRUPT_DEASSERT(istruct)
unsigned char * memory_paddr_to_hostaddr(struct memory *mem, uint64_t paddr, int writeflag)