/*  server.c
 *  by Frank Barrus
 */


#include <stdio.h>
#include "memtype.h"
#include "vdisk.h"
#include "psio.h"
#include "sio.h"


extern char errmsg[];



int do_disk_cmd(int drive, byte cmd, word sec)
{
byte buf[512];
int secsize;
	switch(cmd) {
	case Read:
		if(sec < 1 || sec > disk[drive].nsec)  {
			sprintf(errmsg, "bad sector: %d", sec);
			break;
		}
		disable_interrupts();
		buf[0] = Ack;
		sio_psend(buf, 1);
		enable_interrupts();
		secsize = disk[drive].secsize;
		fseek(disk[drive].file,
			sizeof(struct sio2pc_image_hdr)
			+(sec-1)*secsize, SEEK_SET);
		if(sec < 4)
			secsize = 128;
		fread(&buf[1], secsize, 1, disk[drive].file);
		disable_interrupts();
		buf[0] = Complete;
		buf[secsize+1] = compute_checksum(&buf[1], secsize);
		sio_psend(buf, secsize+2);
		enable_interrupts();
		return True;
	case Status:
		buf[0] = Ack;
		disable_interrupts();
		sio_psend(buf, 1);
		delay_usec(500);
		buf[0] = Complete;
		buf[1] = CSTAT_READY|(CSTAT_DOUBLE*
			(disk[drive].secsize == 256));
		buf[2] = 0xff;
		buf[3] = 0xe0;
		buf[4] = 0;
		buf[5] = compute_checksum(&buf[1], 4);
		sio_psend(buf, 6);
		enable_interrupts();
		dump_sector(buf, 6);
		return True;
	default:
		sprintf(errmsg, "unknown command: %02X", cmd);
	}
	buf[0] = Nak;
	disable_interrupts();
	sio_psend(buf, 1);
	enable_interrupts();
	return False;
}


void do_command(void)
{
byte buf[512];
int i, n;
byte ck;
	disable_interrupts();
	n = sio_precv(buf, sizeof(buf), 10);
	enable_interrupts();
	do {
		disable_interrupts();
		i = in_portb(PAR1);
		enable_interrupts();
	} while(i & COMMAND);
	if(!n) {
		printf("timeout: no command received\n");
		return;
	}
	if(n != 5) {
		printf("bad command frame:\n");
		dump_sector(buf, n);
		return;
	}
	ck = compute_checksum(buf, 4);
	if(ck != buf[4]) {
		printf("bad checksum: %02X != %02X\n",
			ck, buf[4]);
		dump_sector(buf, n);
	}
	switch(buf[0]) {
	case D1: case D2: case D3: case D4:
	case D5: case D6: case D7: case D8:
		dump_sector(buf, n);
		if(!do_disk_cmd(buf[0]-D1, buf[1], WORD(buf[2], buf[3])))
			printf("D%d: error: %s\n", buf[0]-D1+1, errmsg);
		break;
	case P1: case P2:
		printf("Printer not supported\n");
		break;
	case R1: case R2: case R3: case R4:
		printf("RS232 not supported\n");
		break;
	default:
		printf("%02x: unknown device code\n");
		dump_sector(buf, n);
	}
}


void fileserver(void)
{
int b, ob;
	disable_interrupts();
	out_portb(PAR1, 0);
	pbyte = 0;
	b = in_portb(PAR1)^READY;
	enable_interrupts();
	while(1) {
		ob = b;
		disable_interrupts();
		b = in_portb(PAR1);	
		enable_interrupts();
		if((b&READY) && !(ob&READY)) 
			printf("Atari computer is on\n");
		if(!(b&READY) && (ob&READY))
			printf("Atari computer is off\n");
		if((b&READY) && (b&COMMAND) && !(ob&COMMAND)) 
			do_command();
	}
}

