/**************************************************************************** Jade Double D floppy controller test/exercisor program ***************************************************************************** Revisions: 1.0 - 26 Nov 85 grh Release ****************************************************************************/ #include stdio.h #include ctype.h #define TRUE -1 #define FALSE 0 unsigned char in(); char sec_buf[2048], /* Sector buffer */ fmt_buf[] = {0x55,0xaa,0x24,0,0x21,0x10,0x80,0x11, 0x80,0x83,1,0x14,0,0xed,0xb0,0xc9, 'H','e','l','l','o',' ','W','o','r','l','d','!',0,0,0}, *cptr, /* Ptr to command block array elements */ *gets(), /* Tell cc that this is a char ptr */ tbuf[80]; /* Input buffer */ unsigned atob(), atoh(), a, dd_addr, /* Location of selected DD window */ dd_port; /* I/O port number of selected DD card */ int i, d, j, c; struct cb { unsigned char dd_cmd; /* command */ unsigned char dd_drv; /* drive */ unsigned dd_trk; /* track */ unsigned dd_sec; /* sector */ unsigned char dd_ffg; /* flags */ unsigned dd_dma; /* Unused dma address */ unsigned char dd_dmax;/* Unused dma extended address */ unsigned char dd_sts; /* Controller status */ unsigned char dd_st1; /* fdc status if dd_mod == 0x1f */ unsigned char dd_st2; /* returned value #1 */ unsigned char dd_st3; /* returned value #2 */ unsigned char dd_st4; /* returned value #3 */ unsigned char dd_st5; /* returned value #4 */ } cmd_blk; /**************************************************************************** main program ****************************************************************************/ main () { puts("\nJade Double D Controller Exercisor Vers. 1.0\n"); help(); /* Display the command list */ dd_port = 0x40; /* Initialize port & data area */ dd_addr = sec_buf; /* One = the other */ while (TRUE) { crlf(); printf("-"); gets(tbuf); switch (c = toupper(tbuf[0])) { case 'X': /* Exit to DOS */ exit(0); break; case 'H': /* Display help message */ help(); break; case 'Q': /* Dump the DD ram */ printf("\nEnter start address (Hex) - "); gets(tbuf); i = atoh(tbuf); if (i < 0) break; while (i < 2048) { dump_16(i); i += 16; if ((i % 256) == 0) if (*gets(tbuf) != '\0') { printf("\n%c\n", *tbuf); break; } } break; case 'Z': /* Dump the sector buffer */ for (i=0x400; i < 2048;) { dump_16(i); i += 16; if ((i % 256) == 0) if (*gets(tbuf) != '\0') break; } break; case 'P': /* Display ports from 0x40..0x43 */ for (i=0; i < 4; i++) { c = in(0x40 + i); if (c != 0xff) printf("\nA Controller responds to port: %02xH", 0x40+i); } case 'S': /* Set controller port to respond to */ printf("\nEnter controller port to respond to (Hex):"); dd_port = atoh(gets(tbuf)); crlf(); if(dd_port > 0x43 || dd_port < 0x40) printf("Illegal port!"); c = in(dd_port); dd_addr = (((c & 0x0e) << 1) | 0xe0) << 8; printf("DD Window at %04xH",dd_addr); break; case 'T': /* Run diagnostics */ out(dd_port,0x80); /* reset dd processor */ wait_dd(); get_cdb(); dmp_cdb(); dd_dump(); break; case '0': /* Log on drive */ cmd_blk.dd_cmd = 0; if (get_drive()) break; dd_exec(); break; case '1': /* Read sector */ cmd_blk.dd_cmd = 1; if (get_drive()) break; if (get_sec_trk()) break; dd_exec(); break; case '2': /* Write sector */ cmd_blk.dd_cmd = 2; if (get_drive()) break; if (get_sec_trk()) break; dd_exec(); break; case '3': /* Format track */ cmd_blk.dd_cmd = 3; if (get_drive()) break; fmt_buf[2] = sizeof (fmt_buf); for (a=0, i=0; i < ((sizeof (fmt_buf)) - 1); i++) a += fmt_buf[i]; fmt_buf[sizeof (fmt_buf) - 1] = (-a); out(dd_port, 1); movmem(fmt_buf, dd_addr, sizeof (fmt_buf)); out(dd_port,0); for (i=0, a=0; i> 8; } printf("Enter motor start delay: "); gets(tbuf); if (tbuf[0] != '\0') { i = -1; a = atoi(tbuf); cmd_blk.dd_st4 = a & 0xff; cmd_blk.dd_st5 = a >> 8; } cmd_blk.dd_ffg = 0; /* Set parameters */ if (i) dd_exec(); break; case 'D': /* Return drive status */ cmd_blk.dd_cmd = 13; if (get_drive()) break; dd_exec(); printf("\nBoard level status= "); for (i=0, j=cmd_blk.dd_st2; i<8; i++, j = j << 1) { printf("%c", (j & 0x80) ? '1' : '0'); } break; case 'E': /* Set/return baud rate */ cmd_blk.dd_cmd = 14; cmd_blk.dd_st5 = 0xff; dd_exec(); printf("\n\ 0: Level only 1: 600 baud (5\042) 2: 1200 baud 3: 2400 baud\n\ 4: 4800 baud 5: 9600 baud 6: 19,200 baud (8\042)\n\ Current baud rate= %u\n\ Enter new baud rate: ", cmd_blk.dd_st5); gets(tbuf); if (tbuf[0] != '\0') { cmd_blk.dd_st5 = atoi(tbuf); dd_exec(); } break; default: /* Command error */ printf("\nCommand Error!\n"); break; } } } /**************************************************************************** Display help message ****************************************************************************/ help() { printf("\nCommands:\n\ H- Help X- Exit to DOS\n\ Q- Dump the entire RAM Z- Dump the sector buffer\n\ P- Find the ports S- Set the port\n\ T- Run diagnostics\n\ 0- Log on drive 8- Return firmware version\n\ 1- Read sector 9- Set disk flags/sectors per track\n\ 2- Write sector A- Load head & idle\n\ 3- Format track B- Seek track\n\ 4- Read address C- Set/return drive params\n\ 5- EIA output D- Return drive status\n\ 6- EIA input E- Set EIA baud rate\n\ 7- Idle\n"); } /**************************************************************************** new line ****************************************************************************/ crlf() { printf("\n"); } /**************************************************************************** Dump Jade controller ram ****************************************************************************/ dd_dump() { out(dd_port,1); /* Fetch DD window */ movmem(dd_addr,sec_buf,1024); /* Move the window */ out(dd_port,3); /* Fetch 2nd window */ movmem(dd_addr,&sec_buf[1024],1024); out(dd_port,1); /* Restore DD */ out(dd_port,0); } /**************************************************************************** Execute the command ****************************************************************************/ dd_exec() { int i; out(dd_port,1); movmem(&cmd_blk,dd_addr + 0x370, sizeof (cmd_blk)); out(dd_port,2); wait_dd(); get_cdb(); dmp_cdb(); dd_dump(); } /**************************************************************************** Get command block from controller ****************************************************************************/ get_cdb() { out(dd_port,1); movmem(dd_addr + 0x370, &cmd_blk, sizeof (cmd_blk)); out(dd_port,0); if (cmd_blk.dd_sts != 0) printf("\n**** ERROR! **** -> %2x - %2x\n", cmd_blk.dd_sts, cmd_blk.dd_st1); } /**************************************************************************** Dump command block ****************************************************************************/ dmp_cdb() { printf("\n\ Cmd Drv Trk Sec Flg Sts St1 St2 St3 St4 St5\n\ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",\ cmd_blk.dd_cmd, cmd_blk.dd_drv, cmd_blk.dd_trk, cmd_blk.dd_sec, cmd_blk.dd_ffg, cmd_blk.dd_sts, cmd_blk.dd_st1, cmd_blk.dd_st2, cmd_blk.dd_st3, cmd_blk.dd_st4, cmd_blk.dd_st5); } /**************************************************************************** Get drive from user returns TRUE if error, FALSE if ok ****************************************************************************/ int get_drive() { int d; printf("\nEnter drive number {0..3}: "); gets(tbuf); d = atoi(tbuf); if (d > 3) {printf("\nDrive error!"); return TRUE;} cmd_blk.dd_drv = d; return FALSE; } /**************************************************************************** Get sector & track info from user returns TRUE if error, FALSE if ok ****************************************************************************/ int get_sec_trk() { int d; printf("\nEnter sector number {1..48}: "); gets(tbuf); d = atoi(tbuf); if (d > 48) {printf("\nSector error!"); return TRUE;} cmd_blk.dd_sec = d; printf("Enter Side {0,1}: "); gets(tbuf); d = atoi(tbuf); if (d < 0 || d > 1) {printf("\nSide Error!"); return TRUE;} cmd_blk.dd_sec += (d == 0) ? 0 : 0x80; get_trk(); } /**************************************************************************** Get track info from user returns TRUE if error, FALSE if ok ****************************************************************************/ int get_trk() { int d; printf("\nEnter track number {0..76}: "); gets(tbuf); d = atoi(tbuf); if (d > 76) {printf("\nTrack error!"); return TRUE;} cmd_blk.dd_trk = d; return FALSE; } /**************************************************************************** Wait a specific time for controller completion returns TRUE if timeout, FALSE if no timeout (normal) ****************************************************************************/ int wait_dd() { unsigned i; for (i=0; i < 40000; i++) if ((in(dd_port) & 1) == 0) break; if (i == 40000) { printf("\nController timeout!"); return TRUE; } printf("\nExecution time = %4u of 40000", i); return FALSE; } /**************************************************************************** Convert ASCII to binary returns value ****************************************************************************/ unsigned atob(p) char *p;{ unsigned a; for (a=0; (*p == '0' || *p == '1');) a = (a << 1) + (*p++ - '0'); return a; } /**************************************************************************** Convert ASCII to hex number returns value ****************************************************************************/ unsigned atoh(p) char *p; { unsigned a; for (a = 0; (isdigit(*p) || (*p >= 'A' && *p <= 'F'));) { a = a << 4; if (*p > '9') a += (*p++ - '7'); else a += (*p++ - '0'); } return a; } /**************************************************************************** Dump a line of buffer data to console in Hex - ASCII output format is argument = offset address of sector buffer {0..size} ("address" of format) ****************************************************************************/ dump_16(addr) char *addr; { int j; for (j=0; j < 16; j++) { if (j == 0) printf("\n%04x: ",addr); printf("%02x ", sec_buf[addr + j]); } for (j=0; j < 16; j++) { c = sec_buf[addr + j] & 0x7f; if (c >= ' ' && c < 0x7f) printf("%c", c); else printf("."); } }