mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
774 lines
17 KiB
774 lines
17 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*[
|
|
Name: gfi_sflop.c
|
|
Derived From: 2.0 gfi_sflop.c
|
|
Author: Jerry Kramskoy
|
|
Created On: Unknown
|
|
Sccs ID: @(#)gfi_sflop.c 1.16 08/14/92
|
|
Purpose:
|
|
Interface between FLA and the IBM PC. The PC acts as a server
|
|
for remote procedure calls from the base product to access
|
|
the 8272A controller.
|
|
Notes: Invalid FDC commands should be trapped by FLA
|
|
|
|
(c)Copyright Insignia Solutions Ltd., 1990. All rights reserved.
|
|
|
|
]*/
|
|
#ifdef SLAVEPC
|
|
|
|
/* bigger than max pkt so as to accom extra header chars*/
|
|
#define MEGAPKTPLUS 1040
|
|
|
|
USHORT megapkt = 512; /* packet size should be in range 120 < mega < 1024 */
|
|
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
#include TimeH
|
|
|
|
#include "xt.h"
|
|
#include "bios.h"
|
|
#include "timeval.h"
|
|
#include "config.h"
|
|
#include "timer.h"
|
|
#include "dma.h"
|
|
#include "gfi.h"
|
|
#include "gfisflop.h"
|
|
#include "host.h"
|
|
#include "error.h"
|
|
#include "trace.h"
|
|
#include "fla.h"
|
|
#include "debug.h"
|
|
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #define specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "SLAVE_FLOPPY.seg"
|
|
#endif
|
|
|
|
/*
|
|
* ============================================================================
|
|
* Local static data and defines
|
|
* ============================================================================
|
|
*/
|
|
#undef NO
|
|
|
|
#define DMA_DISKETTE_CHANNEL 2
|
|
#define NO 2
|
|
#define MRD 1
|
|
#define MWT 0
|
|
|
|
|
|
/*
|
|
* FDC command definitions
|
|
* =======================
|
|
*/
|
|
|
|
typedef struct {
|
|
int comid; /* FDC command numbers */
|
|
int dma; /* see below */
|
|
int intstatus; /* see below */
|
|
int delay; /* delay needed */
|
|
int n_resblk; /* number of result bytes */
|
|
int n_comblk; /* number of command bytes */
|
|
} FDC_CMD_INFO;
|
|
|
|
/*
|
|
* dma flag
|
|
* = NO ... no dma for this command
|
|
* = MRD ... dma read (mem -> FDC)
|
|
* = MWT ... dma write (FDC -> mem)
|
|
*/
|
|
|
|
/* interrupt status
|
|
* = 0 ... command does not generate an interrupt.
|
|
* = 1 ... command does generate interrupt which is cleared by
|
|
* reading the FDC
|
|
* = 2 ... command generates an interrupt ... a sense interrupt command
|
|
* must be issued to get the FDC results and re-enable further
|
|
* command input to the FDC
|
|
*/
|
|
|
|
FDC_CMD_INFO fdc_cmd_info[] = {
|
|
/*
|
|
* com_id dma intstatus n_resblk
|
|
* delay n_comblk
|
|
*/
|
|
{ RDDATA, MWT, 1, 0, 7, 9 },
|
|
{ RDDELDATA, MWT, 1, 0, 7, 9 },
|
|
{ WTDATA, MRD, 1, 0, 7, 9 },
|
|
{ WTDELDATA, MRD, 1, 0, 7, 9 },
|
|
{ RDTRACK, MWT, 1, 0, 7, 9 },
|
|
{ RDID, NO, 1, 0, 7, 2 },
|
|
{ FMTTRACK, MRD, 1, 0, 7, 6 },
|
|
{ SCANEQ, MRD, 1, 0, 7, 9 },
|
|
{ SCANLE, MRD, 1, 0, 7, 9 },
|
|
{ SCANHE, MRD, 1, 0, 7, 9 },
|
|
{ RECAL, NO, 2, 0, 2, 2 },
|
|
{ SENSINT, NO, 0, 0, 2, 1 },
|
|
{ SPECIFY, NO, 0, 1, 0, 3 },
|
|
{ SENSDRIVE, NO, 0, 0, 1, 2 },
|
|
{ SEEK, NO, 2, 0, 2, 3 },
|
|
};
|
|
|
|
#define MAX_FDC_CMD sizeof(fdc_cmd_info)/sizeof(fdc_cmd_info[0])
|
|
|
|
LOCAL UTINY sensint = 8;
|
|
LOCAL half_word channel = DMA_DISKETTE_CHANNEL;
|
|
|
|
LOCAL SHORT gfi_slave_drive_off IPT1( UTINY, drive );
|
|
LOCAL SHORT gfi_slave_drive_on IPT1( UTINY, drive );
|
|
LOCAL SHORT gfi_slave_change_line IPT1( UTINY, drive );
|
|
LOCAL SHORT gfi_slave_drive_type IPT1( UTINY, drive );
|
|
LOCAL SHORT gfi_slave_high IPT2( UTINY, drive, half_word, n);
|
|
LOCAL SHORT gfi_slave_reset IPT2( FDC_RESULT_BLOCK *, res, UTINY, drive );
|
|
LOCAL SHORT gfi_slave_command IPT2( FDC_CMD_BLOCK *, ip, FDC_RESULT_BLOCK *, res);
|
|
LOCAL wt_diskdata IPT2(unsigned int,n,int *,status);
|
|
LOCAL void cominfo IPT2(FDC_CMD_BLOCK *,cmd_block,FDC_CMD_INFO *,cmd_info);
|
|
|
|
LOCAL BOOL slave_opened;
|
|
LOCAL UTINY slave_type[MAX_DISKETTES];
|
|
LOCAL SHORT old_a_type, old_b_type;
|
|
|
|
/*
|
|
* ============================================================================
|
|
* External functions
|
|
* ============================================================================
|
|
*/
|
|
GLOBAL void gfi_slave_change IFN2(UTINY, hostID, BOOL, apply)
|
|
{
|
|
int status;
|
|
|
|
UNUSED(hostID);
|
|
|
|
if (apply && slave_opened)
|
|
{
|
|
logout(&status);
|
|
host_runtime_set(C_FLOPPY_SERVER, GFI_REAL_DISKETTE_SERVER);
|
|
host_rpc_close();
|
|
slave_opened = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
GLOBAL SHORT gfi_slave_active IFN3(UTINY, hostID, BOOL, active, CHAR *, err)
|
|
{
|
|
GFI_FUNCTION_ENTRY *tabP;
|
|
int status;
|
|
SHORT result;
|
|
UTINY i;
|
|
BOOL slaveServer;
|
|
|
|
UNUSED(hostID);
|
|
UNUSED(err);
|
|
|
|
slaveServer = (host_runtime_inquire(C_FLOPPY_SERVER)==GFI_SLAVE_SERVER);
|
|
if (active)
|
|
{
|
|
CHAR *slaveName = host_expand_environment_vars((CHAR *)
|
|
config_inquire(C_SLAVEPC_DEVICE, NULL));
|
|
|
|
if (!*slaveName)
|
|
{
|
|
if (slaveServer)
|
|
{
|
|
gfi_empty_active(hostID,TRUE,err);
|
|
}
|
|
config_set_active(C_SLAVEPC_DEVICE, FALSE);
|
|
return C_CONFIG_OP_OK;
|
|
}
|
|
|
|
/*
|
|
* When SoftPC has already started talking to SlavePC just
|
|
* return that the open operation is ok, no need to attempt
|
|
* to re-open the link. Maintain the flag telling us
|
|
* whether SlavePC is attached.
|
|
*/
|
|
if (!slave_opened)
|
|
{
|
|
if ( result = host_rpc_open(slaveName) )
|
|
return result; /* failed to open */
|
|
else
|
|
{
|
|
if (!host_rpc_reset())
|
|
{
|
|
login(&status);
|
|
if (status != SUCCESS)
|
|
{
|
|
host_rpc_close();
|
|
return EG_SLAVEPC_NO_LOGIN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
host_rpc_close();
|
|
return EG_SLAVEPC_NO_RESET;
|
|
}
|
|
}
|
|
}
|
|
|
|
slave_opened = TRUE;
|
|
|
|
if (!slaveServer)
|
|
return C_CONFIG_OP_OK;
|
|
|
|
for ( i = 0; i < MAX_DISKETTES; i ++)
|
|
{
|
|
if (gfi_slave_drive_type(i) == GFI_DRIVE_TYPE_NULL)
|
|
continue;
|
|
|
|
tabP = &gfi_function_table[i];
|
|
tabP->command_fn = gfi_slave_command;
|
|
tabP->drive_on_fn = gfi_slave_drive_on;
|
|
tabP->drive_off_fn = gfi_slave_drive_off;
|
|
tabP->reset_fn = gfi_slave_reset;
|
|
tabP->high_fn = gfi_slave_high;
|
|
tabP->drive_type_fn = gfi_slave_drive_type;
|
|
tabP->change_fn = gfi_slave_change_line;
|
|
}
|
|
}
|
|
else /* detach the floppy */
|
|
{
|
|
gfi_slave_drive_type(0);
|
|
gfi_slave_drive_type(1);
|
|
|
|
if (slave_opened)
|
|
{
|
|
logout(&status);
|
|
|
|
status = host_rpc_close();
|
|
slave_opened = FALSE;
|
|
}
|
|
|
|
assert0(!status, "gfi_sfloppy: host_rpc_close() failed\n");
|
|
|
|
if (!slaveServer)
|
|
return C_CONFIG_OP_OK;
|
|
|
|
for ( i = 0; i < MAX_DISKETTES; i ++)
|
|
gfi_empty_active(C_FLOPPY_A_DEVICE+i,TRUE,err);
|
|
|
|
gfi_function_table[0].drive_type_fn = gfi_slave_drive_type;
|
|
|
|
if (slave_type[1] != GFI_DRIVE_TYPE_NULL)
|
|
gfi_function_table[1].drive_type_fn =
|
|
gfi_slave_drive_type;
|
|
}
|
|
|
|
return C_CONFIG_OP_OK;
|
|
}
|
|
|
|
/****************************** on *****************************
|
|
* purpose
|
|
* provide interface to slave PC for turning on drive motor
|
|
***************************************************************
|
|
*/
|
|
LOCAL SHORT
|
|
gfi_slave_drive_on IFN1(UTINY, drive)
|
|
{
|
|
int status;
|
|
static unsigned char DRIVE_A_ON = 0x1c;
|
|
static unsigned char DRIVE_B_ON = 0x2d;
|
|
|
|
note_trace1( GFI_VERBOSE, "GFI-slavefloppy: DRIVE %x ON", drive );
|
|
#ifndef PROD
|
|
#endif
|
|
timer_int_enabled = 0;
|
|
if( drive==0 )
|
|
wt_digital_output_register(DRIVE_A_ON, 0, &status);
|
|
else if( drive==1 )
|
|
wt_digital_output_register(DRIVE_B_ON, 0, &status);
|
|
else
|
|
always_trace0( "gfi_slave_drive_on(): ERROR: bad drive parameter" );
|
|
timer_int_enabled = 1;
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************** off *****************************
|
|
* purpose
|
|
* provide interface to slave PC for turning off drive motor
|
|
****************************************************************
|
|
*/
|
|
LOCAL SHORT
|
|
gfi_slave_drive_off IFN1(UTINY, drive)
|
|
{
|
|
int status;
|
|
static unsigned char DRIVE_A_OFF = 0xc;
|
|
static unsigned char DRIVE_B_OFF = 0xd;
|
|
|
|
note_trace1( GFI_VERBOSE, "GFI-slavefloppy: DRIVE %x OFF", drive );
|
|
#ifndef PROD
|
|
#endif
|
|
timer_int_enabled = 0;
|
|
if( drive==0 )
|
|
wt_digital_output_register(DRIVE_A_OFF, 0, &status);
|
|
else if( drive==1 )
|
|
wt_digital_output_register(DRIVE_B_OFF, 0, &status);
|
|
else
|
|
always_trace0( "gfi_slave_drive_off(): ERROR: bad drive parameter" );
|
|
timer_int_enabled = 1;
|
|
return(SUCCESS);
|
|
}
|
|
|
|
/***************************** high ****************************
|
|
* purpose
|
|
* provide interface to slave PC for selecting specified data rate
|
|
***************************************************************
|
|
*/
|
|
LOCAL SHORT
|
|
gfi_slave_high IFN2(UTINY, drive, half_word, rate)
|
|
{
|
|
int status;
|
|
|
|
UNUSED(drive);
|
|
|
|
switch( rate ){
|
|
case 0: datarate( DCR_RATE_500, &status ); break;
|
|
case 1: datarate( DCR_RATE_300, &status ); break;
|
|
case 2: datarate( DCR_RATE_250, &status ); break;
|
|
default:
|
|
always_trace0("ERROR:gfi_slave_high(): bad rate value");
|
|
break;
|
|
}
|
|
if( status != SUCCESS )
|
|
always_trace0( "ERROR: gfi_slave_high()" );
|
|
return(status);
|
|
}
|
|
|
|
|
|
/************************** drive type *************************
|
|
* purpose
|
|
* provide interface to slave PC for returning drive type
|
|
***************************************************************
|
|
*/
|
|
LOCAL SHORT
|
|
gfi_slave_drive_type IFN1(UTINY, drive)
|
|
{
|
|
int status;
|
|
unsigned char dtype;
|
|
|
|
/*
|
|
* Return the last drive type if the slave device is
|
|
* not currently opened.
|
|
*/
|
|
if (!slave_opened)
|
|
return (slave_type[drive]);
|
|
|
|
note_trace1( GFI_VERBOSE, "gfi_slave_drive_type(): drive %x", drive );
|
|
drivetype( drive, &dtype, &status );
|
|
note_trace2( GFI_VERBOSE, "dtype=%x status=%x", dtype, status );
|
|
#ifndef PROD
|
|
switch( dtype )
|
|
{
|
|
case GFI_DRIVE_TYPE_NULL:
|
|
note_trace0( GFI_VERBOSE, "Bad drive" );
|
|
break;
|
|
case GFI_DRIVE_TYPE_360:
|
|
note_trace0( GFI_VERBOSE, "360k" );
|
|
break;
|
|
case GFI_DRIVE_TYPE_12:
|
|
note_trace0( GFI_VERBOSE, "1.2M" );
|
|
break;
|
|
case GFI_DRIVE_TYPE_720:
|
|
note_trace0( GFI_VERBOSE, "720k" );
|
|
break;
|
|
case GFI_DRIVE_TYPE_144:
|
|
note_trace0( GFI_VERBOSE, "1.44M" );
|
|
break;
|
|
default: always_trace0( "Unrecognised drive value" );
|
|
break;
|
|
}
|
|
#endif /* !PROD */
|
|
|
|
if ( status != SUCCESS )
|
|
always_trace0( "ERROR: gfi_slave_drive_type()" );
|
|
|
|
slave_type[drive] = dtype;
|
|
return dtype;
|
|
/* return(GFI_DRIVE_TYPE_360); */
|
|
}
|
|
|
|
/************************* diskette change *********************
|
|
* purpose
|
|
* provide interface to slave PC for diskette change notification
|
|
***************************************************************
|
|
*/
|
|
LOCAL SHORT
|
|
gfi_slave_change_line IFN1(UTINY, drive)
|
|
{
|
|
int status, changed;
|
|
|
|
diskchange( drive, &changed, &status );
|
|
note_trace2( GFI_VERBOSE, "drive %x %s",
|
|
drive, changed ? "CHANGED" : "NOT CHANGED" );
|
|
if( changed!=1 && changed!=0 )
|
|
always_trace1( "ERROR: gfi_slave_change_line(): bad value:%x", changed );
|
|
if( status != SUCCESS )
|
|
always_trace0( "ERROR: gfi_slave_change_line()" );
|
|
return( changed );
|
|
}
|
|
|
|
|
|
|
|
/****************************** reset *****************************
|
|
* purpose
|
|
* provide interface to slave PC for resetting the FDC
|
|
******************************************************************
|
|
*/
|
|
LOCAL SHORT
|
|
gfi_slave_reset IFN2(FDC_RESULT_BLOCK *, r, UTINY, drive)
|
|
{
|
|
int status, i;
|
|
static unsigned char DRIVE_RESET = 0x08;
|
|
static unsigned char DRIVE_A_OFF = 0x0c;
|
|
static unsigned char DRIVE_B_OFF = 0x0d;
|
|
static unsigned char RECALIBRATE[] = {7, 0};
|
|
unsigned char res[10];
|
|
unsigned char drive_off;
|
|
int nres;
|
|
|
|
note_trace1( GFI_VERBOSE, "GFI-slavefloppy: Reset command drive %x", drive );
|
|
#ifndef PROD
|
|
#endif
|
|
if( drive==0 )
|
|
drive_off = DRIVE_A_OFF;
|
|
else if( drive==1 )
|
|
drive_off = DRIVE_B_OFF;
|
|
else
|
|
always_trace0( "gfi_slave_reset(): ERROR: bad drive parameter");
|
|
|
|
clrintflag(&status);
|
|
if (status != FDCSUCCESS)
|
|
return(status);
|
|
wt_digital_output_register(DRIVE_RESET, 0, &status);
|
|
if (status == FDCSUCCESS)
|
|
{
|
|
timer_int_enabled = 0;
|
|
wt_digital_output_register(drive_off, 1, &status);
|
|
timer_int_enabled = 1;
|
|
if (status == FDCSUCCESS)
|
|
{
|
|
wt_floppy_disk_controller(1,&sensint,0, 0, &status);
|
|
if (status == FDCSUCCESS)
|
|
{
|
|
rd_floppy_disk_controller(&nres, res, &status);
|
|
if (status == FDCSUCCESS)
|
|
{
|
|
for (i=0; i<nres; i++)
|
|
r[i] = res[i];
|
|
#ifndef PROD
|
|
#endif
|
|
/*
|
|
gfi_slave_drive_on();
|
|
gfi_slave_command(RECALIBRATE, res);
|
|
gfi_slave_drive_off();
|
|
*/
|
|
}
|
|
else
|
|
always_trace1("RESET error 3, status = %x", status);
|
|
}
|
|
else
|
|
always_trace1("RESET error 2, status = %x", status);
|
|
}
|
|
else
|
|
always_trace1("RESET error 1, status = %x", status);
|
|
}
|
|
else
|
|
always_trace1("RESET error 1, status = %x", status);
|
|
}
|
|
|
|
/*
|
|
** A macro to tell us something when something goes wrong
|
|
*/
|
|
#define failure(i) always_trace0( "failed" ); return( i );
|
|
|
|
/**************************** command *****************************
|
|
* purpose
|
|
* provide interface to slave PC for performing FDC commands
|
|
******************************************************************
|
|
*/
|
|
|
|
LOCAL SHORT
|
|
gfi_slave_command
|
|
IFN2(FDC_CMD_BLOCK *, c, FDC_RESULT_BLOCK *,r)
|
|
{
|
|
FDC_CMD_INFO info;
|
|
sys_addr dummy;
|
|
word ndma;
|
|
int err, status, nres;
|
|
unsigned int nXfer;
|
|
|
|
err = 0;
|
|
|
|
note_trace1( GFI_VERBOSE, "GFI-slavefloppy: Command %x", get_type_cmd(c));
|
|
#ifndef PROD
|
|
#endif
|
|
|
|
cominfo(c,&info);
|
|
if (info.comid == -1)
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
|
|
/*
|
|
* determine how much data is needed for this command
|
|
* in case we are doing DMA or 'pseudo-nonDMA'
|
|
*/
|
|
|
|
if (!fla_ndma)
|
|
{
|
|
dma_enquire(channel, &dummy, &ndma);
|
|
nXfer = ndma+1;
|
|
}
|
|
else
|
|
{
|
|
fla_ndma_enquire(&nXfer);
|
|
ndma = nXfer-1;
|
|
}
|
|
note_trace3( GFI_VERBOSE, "Bytes to transfer nXfer=%x ndma=%x mode=%s",
|
|
nXfer, ndma, fla_ndma ? "NON-DMA" : "DMA" );
|
|
|
|
/*
|
|
* set up the slave PC's disk buffer
|
|
* with any data to be read by the FDC
|
|
*/
|
|
|
|
if (info.dma == MRD)
|
|
if (wt_diskdata(nXfer, &status))
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
else
|
|
{
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* set up the DMA controller for the transfer
|
|
*/
|
|
|
|
if (info.dma != NO)
|
|
if (wt_dma_controller((unsigned int) ndma, info.dma, &status))
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
else
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
|
|
|
|
/*
|
|
* issue the FDC command. Block the slavePC from
|
|
* returning until an interrupt or timeout
|
|
* (provided the command is meant to interrupt!!)
|
|
*/
|
|
|
|
clrintflag(&status);
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
|
|
if (wt_floppy_disk_controller(info.n_comblk, c, info.intstatus,
|
|
info.delay, &status))
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
else
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* issue a sense interrupt command if required
|
|
*/
|
|
|
|
if (info.intstatus == 2)
|
|
if (wt_floppy_disk_controller(1, &sensint, 0, 0, &status))
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
else
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
|
|
|
|
/* delay if needed
|
|
*/
|
|
|
|
if (info.delay)
|
|
{
|
|
timer_int_enabled = 0;
|
|
timer_int_enabled = 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* read the FDC results
|
|
*/
|
|
|
|
if (info.n_resblk)
|
|
if (rd_floppy_disk_controller(&nres, r, &status))
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
else
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
else
|
|
if (nres != info.n_resblk)
|
|
{
|
|
#ifndef PROD
|
|
printf("result block discrepancy !!!\n");
|
|
#endif
|
|
failure(PROTOCOL);
|
|
}
|
|
|
|
|
|
/* dump out results
|
|
*/
|
|
#ifndef PROD
|
|
#endif
|
|
|
|
/*
|
|
* read back any data from
|
|
* the diskette
|
|
*/
|
|
|
|
if (info.dma == MWT && !(r[1] & 4))
|
|
{
|
|
if (rd_diskdata(nXfer, &status))
|
|
{
|
|
failure(LOGICAL);
|
|
}
|
|
else
|
|
if (status != FDCSUCCESS)
|
|
{
|
|
failure(PROTOCOL);
|
|
}
|
|
}
|
|
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* ============================================================================
|
|
* Internal functions
|
|
* ============================================================================
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************* wt_diskdata *********************************
|
|
*/
|
|
LOCAL wt_diskdata IFN2(unsigned int,n,int *,status)
|
|
{
|
|
char diskdata[MEGAPKTPLUS];
|
|
word nbytes, ln;
|
|
int ioff;
|
|
|
|
ln = (word) n;
|
|
ioff = 0;
|
|
while (ln > 0)
|
|
{
|
|
nbytes = (ln > megapkt)? megapkt: ln;
|
|
dma_request(channel, diskdata, nbytes);
|
|
if (wt_disk_buffer(nbytes, diskdata, ioff, status))
|
|
return(1);
|
|
else
|
|
if (*status != FDCSUCCESS)
|
|
break;
|
|
ln -= nbytes;
|
|
ioff += nbytes;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************* rd_diskdata *********************************
|
|
*/
|
|
rd_diskdata(n, status)
|
|
unsigned int n;
|
|
int *status;
|
|
|
|
{
|
|
char diskdata[1024];
|
|
word nbytes, ln;
|
|
int ioff;
|
|
int errors=0;
|
|
|
|
ln = (word) n;
|
|
ioff = 0;
|
|
note_trace1( GFI_VERBOSE, "Reading 0x%x bytes...", n );
|
|
while (ln > 0)
|
|
{
|
|
nbytes = (ln > megapkt)? megapkt: ln;
|
|
if (rd_disk_buffer(nbytes, diskdata, ioff, status)){
|
|
return(1);
|
|
}
|
|
dma_request(channel, diskdata, nbytes);
|
|
if (*status != FDCSUCCESS){
|
|
++errors;
|
|
break;
|
|
}
|
|
ln -= nbytes;
|
|
ioff += nbytes;
|
|
}
|
|
#ifndef PROD
|
|
if( errors>0 ){
|
|
note_trace3( GFI_VERBOSE,
|
|
"Read 0x%x bytes of 0x%x with errors=%d",ioff , n, errors );
|
|
}else
|
|
note_trace1( GFI_VERBOSE, "Read 0x%x bytes OK", ioff );
|
|
#endif
|
|
return(0);
|
|
}
|
|
|
|
|
|
/****************************** cominfo *************************************
|
|
*/
|
|
|
|
LOCAL void cominfo IFN2(FDC_CMD_BLOCK *,cmd_block,FDC_CMD_INFO *,cmd_info)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_FDC_CMD; i++)
|
|
if (fdc_cmd_info[i].comid == get_c0_cmd(cmd_block))
|
|
break;
|
|
|
|
if (i >= MAX_FDC_CMD)
|
|
cmd_info->comid = -1;
|
|
else if (fdc_cmd_info[i].comid == SENSINT)
|
|
cmd_info->comid = -2;
|
|
else
|
|
*cmd_info = fdc_cmd_info[i];
|
|
}
|
|
#endif /* SLAVEPC */
|