Exemplo n.º 1
0
/* --- Main FDC dispatcher --- */
static void fdc_execute(FDC_765 *self)
{
/* This code to dump out FDC commands as they are received is very useful
 * in debugging
 *
 * */
	int NC;
	fdc_dprintf(5, "FDC: ");
	for (NC = 0; NC < bytes_in_cmd[self->fdc_cmd_buf[0] & 0x1F]; NC++)
		fdc_dprintf(5, "%02x ", self->fdc_cmd_buf[NC]);
	fdc_dprintf(5, "\n");
 /* */
	/* Check if the DOR (ugh!) is being used to force us to a 
	   different drive. */
	fdc_dorcheck(self);

	/* Reset "seek finished" flag */
	self->fdc_st0 &= 0xBF;	 
	switch(self->fdc_cmd_buf[0] & 0x1F)
	{
		case 2: fdc_read_track(self);	break;	/* 2: READ TRACK */
		case 3: fdc_specify(self);	break;	/* 3: SPECIFY */
		case 4:	fdc_sense_drive(self);	break;	/* 4: SENSE DRV STATUS*/
		case 5:	fdc_write(self, 0);	break;	/* 5: WRITE */
		case 6: fdc_read(self, 0);	break;	/* 6: READ */
		case 7:	fdc_recalibrate(self);	break;	/* 7: RECALIBRATE */
		case 8: fdc_sense_int(self);	break;	/* 8: SENSE INT STATUS*/
		case 9: fdc_write(self, 1);	break;	/* 9: WRITE DELETED */
		case 10:fdc_read_id(self);	break;	/*10: READ ID */
		case 12:fdc_read(self, 1);	break;	/*12: READ DELETED */
		case 13:fdc_format(self);	break;	/*13: FORMAT TRACK */
		case 15:fdc_seek(self);		break;	/*15: SEEK */
		case 17:				/*17: SCAN EQUAL */
		case 25:				/*25: SCAN LOW/EQUAL */
		case 30:fdc_scan(self);		break;	/*30: SCAN HIGH/EQUAL*/
		default:
			fdc_dprintf(2, "Unknown FDC command %d\n", 
					self->fdc_cmd_buf[0] & 0x1F);
			fdc_error(self);	break;
	}

}
Exemplo n.º 2
0
void fdc_write(unsigned char a) { // Write byte to data register
	static int cmdlen = 9; // length of FDC command
#ifdef FDC_DEBUG	
	printf("FDC DATA WRITE = 0x%x\n", a);
#endif	
	switch(phase) {
		case P_COMMAND:
			fdccommand[CmdByte] = a; // store part of command
			if (CmdByte == 0) { // first byte of command
				switch(a&0x1F) {
					case CMD_READDATA:
					case CMD_READDELETEDDATA:
					case CMD_WRITEDATA:
					case CMD_WRITEDELETEDDATA:
					case CMD_READDIAGNOSTIC:
					case CMD_SCANEQUAL:
					case CMD_SCANLOWEQUAL:
					case CMD_SCANHIGHEQUAL:
						cmdlen = 9;
						break;
					case CMD_WRITEID:
						cmdlen = 6;
						break;
					case CMD_SPECIFY:
					case CMD_SEEK:
						cmdlen = 3;
						break;
					case CMD_READID:
					case CMD_RECALIBRATE:
					case CMD_SENSEDRV:
						cmdlen = 2;
						break;
					case CMD_SENSEINT:
					case CMD_VERSION:
						cmdlen = 1;
						break;
					default: // Invalid Command
						cmdlen = 1;
						printf("Invalid FDC Command received: 0x%x\n", a);
						break;	
				}
			// Set CB (Busy) flag
			//fdc_status_main|=MAIN_CB;	
			}
			CmdByte++;
			if (CmdByte == cmdlen) { // Command phase finished
				switch(fdccommand[0]&0x1F) {
					case CMD_READDATA:
						fdc_read_data();
						break;
					case CMD_READDELETEDDATA:
						printf("*** Unimplemented FDC Command READ DELETED DATA\n");
						break;
					case CMD_WRITEDATA:
						printf("*** Unimplemented FDC Command WRITE DATA\n");
						break;
					case CMD_WRITEDELETEDDATA:
						printf("*** Unimplemented FDC Command WRITE DELETED DATA\n");
						break;
					case CMD_READDIAGNOSTIC:
						printf("*** Unimplemented FDC Command READ DIAGNOSTIC\n");
						break;
					case CMD_READID:
						// Read sector ID
						fdc_read_id();
						break;
					case CMD_WRITEID:
						printf("*** Unimplemented FDC Command WRITE ID\n");
						break;
					case CMD_SCANEQUAL:
						printf("*** Unimplemented FDC Command SCAN EQUAL\n");
						break;
					case CMD_SCANLOWEQUAL:
						printf("*** Unimplemented FDC Command SCAN LOW OR EQUAL\n");
						break;
					case CMD_SCANHIGHEQUAL:
						printf("*** Unimplemented FDC Command SCAN HIGH OR EQUAL\n");
						break;
					case CMD_RECALIBRATE:
						// Reset to track 0
						fdc_seek(0);
						break;
					case CMD_SENSEINT:
						// Get Interrupt status register
						fdc_senseint();
						break;
					case CMD_SPECIFY:
						// We really don't need to do anything here. This command only sets
						// physical timing parameters. These are not relevant to a virtual FDC.
						fdc_status_main&=~MAIN_CB; // Clear CB (busy) flag
						break;
					case CMD_SENSEDRV:
						printf("*** Unimplemented FDC Command SENSE DRIVE\n");
						break;
					case CMD_VERSION:
						printf("*** Unimplemented FDC Command VERSION\n");
						break;
					case CMD_SEEK:
						// Seek to a specified track
						fdc_seek(fdccommand[2]);
						break;
					default:
						break;
				}
				CmdByte = 0;
			}
			break;
		case P_EXECUTION: // Execution phase
			break;
		case P_RESULT: // There should be no write acces in result phase
			break;
	}
}
Exemplo n.º 3
0
/* If no request is currently being processed and there's new requests in
   the queue, process the first one. This can be called from an interrupt
   or the normal kernel context. */
void do_request(blkreq_t *req)
{
    fd_dev_t *dev;
    u_long track, sect, cyl, head, big_sect, sects;
    u_long flags;
    int i;

    save_flags(flags);

    /* This label is used to eliminate tail-recursion. */
top:

    cli();
    if(current_req != NULL)
    {
	if(req != NULL)
	    append_node(&fd_reqs, &req->node);
	load_flags(flags);
	return;
    }
    for(i = 0; i < 2; i++)
    {
	if(fd_devs[i].recalibrate)
	{
	    fdc_recal(&fd_devs[i]);
	    if(req != NULL)
		append_node(&fd_reqs, &req->node);
	    load_flags(flags);
	    return;
	}
    }
    if(req == NULL)
    {
	if(!list_empty_p(&fd_reqs))
	{
	    req = (blkreq_t *)fd_reqs.head;
	    remove_node(&req->node);
	}
	else
	{
	    load_flags(flags);
	    return;
	}
    }
    current_req = req;
#if 0
    req->retries = 0;
#endif
    load_flags(flags);

    dev = REQ_FD_DEV(req);

    DB(("fd:do_request: req=%p drive=%d block=%d nblocks=%d cmd=%d buf=%p\n",
	req, dev->drvno, req->block, req->nblocks, req->command, req->buf));

    switch(req->command)
    {
    case FD_CMD_SEEK:	/* We wanna MOVE DA HEAD! */
        /* Do da seek. */
	if(fdc_seek(dev, req->block) == FALSE)
	{
		handle_error("FD_CMD_SEEK, seek");
		goto top;
		break;
	}

	/* Then Sense Interrupt Status */
	if(fdc_sense() == FALSE)
	{
		handle_error("FD_CMD_SEEK, fdc_sense");
		goto top;
		break;
	}

	/* and now we have to Read the ID */
	if(fdc_read_id(dev) == FALSE)
	{
		handle_error("FD_CMD_SEEK, read_id");
		goto top;
		break;
	}

        fd_end_request(0);
	req = NULL;
        goto top;

    case FD_CMD_TIMER:
	fd_end_request(0);
	req = NULL;
	goto top;
    }

    if(req->block >= dev->total_blocks)
    {
	kprintf("fd: Device %s (%p) doesn't have a block %d!\n",
		dev->name, dev, req->block);
	fd_end_request(-1);
	req = NULL;
	goto top;
    }

    big_sect = req->block;
    sects = req->nblocks;

    track = big_sect / dev->disk_p->sectors;
    sect = big_sect % dev->disk_p->sectors + 1;
    head = track % dev->disk_p->heads;
    cyl = track / dev->disk_p->heads;

    DB(("fd:do_request: cyl=%d sect=%d head=%d sects=%d\n", cyl, sect, head, sects));

    switch(req->command)
    {
    case FD_CMD_READ:	/* We wanna READ the floppy! */

#if 0
        fd_end_request(0);
	req = NULL;
        goto top;
#endif

	/* We need to seek to the right cylinder. */
	if(fdc_seek(dev, cyl) == FALSE)
	{
		handle_error("FD_CMD_READ, seek");
		goto top;
		break;
	}

	/* Then Sense Interrupt Status */
	if(fdc_sense() == FALSE)
	{
		handle_error("FD_CMD_READ, fdc_sense");
		goto top;
		break;
	}

	/* and now we have to Read the ID */
	if(fdc_read_id(dev) == FALSE)
	{
		handle_error("FD_CMD_READ, read_id");
		goto top;
		break;
	}

#define TPA(XX) ((u_long)TO_PHYSICAL(XX))

	/* Tell the DMA what to do, and hope for the best! */
	/* Should move this inside fdc, in fdc_read() i think */
	DMAbuf.Buffer = track_buf;
	DMAbuf.Page = (u_int8)((TPA(track_buf) >> 16) & 0xff);
	DMAbuf.Offset = (u_int16)(TPA(track_buf) & 0xffff);
	DMAbuf.Len = (u_int16)(dev->disk_p->sectors * dev->disk_p->heads *
		FD_SECTSIZ) - 1;
	DMAbuf.Chan = FLOPPY_DMA;
	kernel->setup_dma(&DMAbuf, DMA_READ);

	/* Now we issue a read command. */
	if(fdc_read(dev, cyl) == FALSE)
	{
		handle_error("FD_CMD_READ, read");
		goto top;
		break;
	}

	break;

    case FD_CMD_WRITE:	/* We wanna WRITE it too! */

        fd_end_request(0);
	req = NULL;
        goto top;

    default:
	kprintf("fd:do_request: Unknown command in fd_req, %d\n",
		req->command);
	fd_end_request(-1);
	req = NULL;
	goto top;
    }
}