📄 fl_drver.c
字号:
#if (USE_DMA)
//DM: added
#if defined(PME)
// use buffer we created in memory below 1MB
if (n_todo > DMA_BUF_SECTS)
n_todo = DMA_BUF_SECTS;
#else
/* see how many blocks are left in the dma page containing buffer */
utemp = fl_dma_chk((DMAPTYPE) buffer);
if (!utemp)
{
/* None left in this page. use a local buffer for 1 block */
n_todo = 1;
use_dma_buff = TRUE;
}
else
{
/* Dma right to user space. Don't wrap the segment */
use_dma_buff = FALSE;
if (utemp < n_todo)
n_todo = utemp;
}
#endif /* PME */ //DM: end of added
#endif /* (USE_DMA) */
utemp = cyl;
/* Double step on 360 K disks in 1.2M drives */
if (floppy[unit_number].double_step)
utemp <<= 1;
fl_motor_on(unit_number);
if (!fl_seek(unit_number, utemp, head))
return(fl_report_error(FLERR_SEEK, FALSE));
#if (!USE_DMA)
shadow_dig_out &= ~DORB_DMAEN;
fl_write_dor(shadow_dig_out);
#else
/* Set up the dma controller */
//DM: added conditional for PME
#if defined(PME)
if (!reading) /* copy to a low buf before writing */
WriteRealMem(lo_buf_prot, buffer, (n_todo << 9));
if (!fl_dma_init(lo_buf_real, (word) (n_todo << 9), reading))
return(fl_report_error(FLERR_DMA, FALSE));
#else
if (use_dma_buff)
{
if (!reading) /* copy to a local buf before writing */
WriteRealMem(dma_buffer, buffer, (n_todo << 9));
if (!fl_dma_init((DMAPTYPE)dma_buffer, (word) (n_todo << 9), reading))
return(fl_report_error(FLERR_DMA, FALSE));
}
else
{
/* Never run in protoected mode */
if (!fl_dma_init((DMAPTYPE) buffer,(word) (n_todo << 9), reading))
return(fl_report_error(FLERR_DMA, FALSE));
}
#endif // PME
#endif /* USE_DMA */
/* Send the command to the 765 floppy controller */
b.n_to_send = 9;
b.n_to_get = 7;
#if (USE_DMA)
if (reading)
b.commands[0] = MTBIT|MFMBIT|FL_READ;
else
b.commands[0] = MTBIT|MFMBIT|FL_WRITE;
#else
if (reading)
b.commands[0] = MFMBIT|FL_READ;
else
b.commands[0] = MFMBIT|FL_WRITE;
#endif
b.commands[1] = (byte) ((head << 2)|unit_number);
b.commands[2] = (byte) cyl;
b.commands[3] = (byte) head;
b.commands[4] = (byte) (sec+1);
b.commands[5] = (byte) 2; /* byte length 512 */
#if (USE_DMA)
b.commands[6] = (byte) (floppy[unit_number].sectors_per_track);/* EOT */
#else
b.commands[6] = (byte) (sec+n_todo); /* HACK SET EOT to the sector */
#endif
b.commands[7] = (byte) floppy[unit_number].gpl_read; /* GPL */
b.commands[8] = (byte) 0xff; /* DTL = ff since N == 512 */
fl_motor_on(unit_number);
#if (USE_DMA)
/* Clear any outstanding interrupt complete messages */
OS_FLOPPY_SIGNAL_BIND(0);
OS_FLOPPY_SIGNAL_CLEAR(0);
if (!fl_command_phase(&b))
{
return(fl_report_error(FLERR_CHIP_HUNG, FALSE));
}
/* Wait for the transfer to complete. (In programmed IO situations
do the actual transfer) */
if (!fl_waitdma((int)FLTMO_IO))
return(fl_report_error(FLERR_IO_TMO, FALSE));
/* If we read into a local buffer we need to copy it now to user space */
//DM: added PME conditional
#if defined(PME)
if (reading)
ReadRealMem(buffer, lo_buf_prot, (n_todo << 9));
#else
if (use_dma_buff && reading)
ReadRealMem(buffer, dma_buffer, (n_todo << 9));
#endif // PME
#else
for (i = 0; i < 10; i++)
if ((ready = fl_ready())== FL_TOHOST)
fl_read_data();
else
break;
for (i = 0; i < b.n_to_send; i++)
{
if ((ready = fl_ready()) != FL_FRHOST)
{
do {
fl_read_data();
} while ((ready = fl_ready())== FL_TOHOST);
}
/* Write command bytes. On the last byte call the read routine
so it can set up the last command byte and be ready to
read the data without overruns */
if (i < (b.n_to_send-1))
fl_write_data(b.commands[i]);
else
{
if (reading)
polled_read(buffer, n_todo<<9, b.commands[i]);
else
polled_write(buffer, n_todo<<9, b.commands[i]);
}
}
/* Out of dma mode */
shadow_dig_out |= DORB_DMAEN;
fl_write_dor(shadow_dig_out);
#endif /* USE_DMA */
if (!fl_results_phase(&b))
return(fl_report_error(FLERR_CHIP_HUNG, FALSE));
#if (USE_DMA)
/* Check status registers. We will elaborate on this later */
if (b.results[0] & (BIT7|BIT6))
return(fl_report_error(FLERR_ABN_TERM, FALSE));
/* Check the head/sector/track against what it should be */
final_sec = (word) (sec + n_todo);
final_cyl = cyl;
final_head = head;
if (final_sec > floppy[unit_number].sectors_per_track)
{
final_head = 1;
final_sec = (word) (final_sec - floppy[unit_number].sectors_per_track);
}
if (final_sec < floppy[unit_number].sectors_per_track)
final_sec += (word)1;
else if (final_sec == floppy[unit_number].sectors_per_track)
{
final_sec = 1;
if (final_head == 1)
{
final_cyl += (word)1;
final_head = 0;
}
else
final_head = 1;
}
if ( (b.results[3] != (byte) final_cyl) ||
(b.results[4] != (byte) final_head) ||
(b.results[5] != (byte) final_sec) )
{
return(fl_report_error(FLERR_IO_SECTOR, FALSE));
}
#else
/* Check status registers. We will elaborate on this later */
if (b.results[0] & (BIT7|BIT6))
{
if ((b.results[0]&(BIT7|BIT6)) == BIT6)
{
if (b.results[1] & BIT4)
{
return(FALSE);
}
else if (b.results[1] & BIT7)
{
goto ignore_eot;
}
}
return(fl_report_error(FLERR_ABN_TERM, FALSE));
}
ignore_eot:
/* Check the head/sector/track against what it should be */
final_sec = (word) (sec + n_todo);
final_cyl = cyl;
final_head = head;
/* NOTE: In nondma mode finals are all set */
if ( (b.results[3] != (byte) final_cyl) ||
(b.results[4] != (byte) final_head) ||
(b.results[5] != (byte) final_sec) )
{
return(fl_report_error(FLERR_IO_SECTOR, FALSE));
}
#endif
if (!count)
break;
/* Add n transfered to the sector.
If we wrapped the track reset the sector pointer.
This wrap will occur almost every time. When we have a dma
wrap condition we truncated the sector count and will not
wrap
*/
sec = (word) (sec + n_todo);
if (sec >= floppy[unit_number].sectors_per_track)
{
sec = 0;
if (head)
{
head = 0;
cyl += (word)1;
}
else
head = 1;
}
count = (word) (count - n_todo);
buffer += (n_todo<<9);
/* Read the rest of the blocks or to the end of track. Whichever is less */
/* Note: sec will usually be 0. unless a dma segment wrap occured. */
utemp = (word) (floppy[unit_number].sectors_per_track - sec);
if (count < utemp)
n_todo = count;
else
n_todo = utemp;
}
return (TRUE);
}
/* floppy_format - Format a floppy disk.
*
* Summary:
*
* BOOLEAN floppy_format(driveno, drivesize, interleave)
*
*
* Inputs:
* word driveno - 0 or 1 = a: b:
* int drivesize - 360,1200,1440,720
* int interleave - interleave factor. (1 ==s no interleave gap)
*
* Returns:
* TRUE on success else FALSE.
*
* This routine formats every track on the drive. Before doing so it
* validates the interleave and returns if it is wrong. The interleave
* must be either 1 or it must follow these two rules.
* It may not divide evenly into sectors/track and if sectors/track is an
* even number interleave must be odd. If sectors/track is an odd number
* interleave must be even.
*
* This routine is portable
*
*/
BOOLEAN floppy_format(int driveno, int drivesize, int interleave) /*__fn__*/
{
COMMAND_BLOCK b;
int parmindex;
byte cylinder;
byte sector;
byte head;
int index;
//DM: added PME16 case
#if defined(PME16)
byte far *sec_info;
#else
byte *sec_info;
#endif
word utemp;
BLKBUFF *buf;
byte *parms_buffer;
#if (!USE_DMA)
int i;
int ready;
int residual;
#endif
if (!interleave)
return(FALSE);
buf = pc_scratch_blk();
parms_buffer = buf->data;
for (parmindex = 0; fl_devparms[parmindex].drive_size; parmindex++)
{
if ( (fl_devparms[parmindex].drive_size == drivesize) &&
(floppy[driveno].drive_type == fl_devparms[parmindex].drive_type) )
break;
}
if (!fl_devparms[parmindex].drive_size)
{
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_UNK_DRIVE, FALSE));
}
if ((interleave > 1))
{
/* Interleave can not be an even multiple of sec/per track */
if ( (fl_devparms[parmindex].sectors_per_track%interleave == 0) ||
/* Must be odd/even or even/odd */
((fl_devparms[parmindex].sectors_per_track & 0x01) == (interleave & 0x01) ) )
{
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_INVALID_INTERLEAVE, FALSE));
}
}
/* load the floppy table from the device desc table. */
fl_cp_parms(driveno, parmindex);
fl_write_drr(floppy[driveno].data_rate);
if (!fl_specify(driveno))
{
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_SPECIFY, FALSE));
}
fl_motor_on(driveno);
if (!fl_recalibrate(driveno))
{
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_RECAL, FALSE));
}
for (cylinder = 0; cylinder < fl_devparms[parmindex].cylinders_per_disk; cylinder++)
{
/* print running status */
#if (!defined(ERTFS_SA))
DEBUG_ERROR("Formatting track of total tracks", EBS_INT2, (int)cylinder, (int)(fl_devparms[parmindex].cylinders_per_disk-1));
#else
tm_printf_3("Formatting %d track of %d total tracks\r", (int)cylinder, (int)(fl_devparms[parmindex].cylinders_per_disk-1));
#endif
fl_motor_on(driveno);
for (head = 0; head < 2; head++)
{
utemp = cylinder;
if (floppy[driveno].double_step)
utemp <<= 1;
if (!fl_seek(driveno, utemp, head))
{
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_SEEK, FALSE));
}
index = 0;
/* build of the sector IDs. Include interleave calculation */
for (sector = 1; sector <= fl_devparms[parmindex].sectors_per_track; sector++)
{
//DM: added PME conditional
#if defined(PME)
sec_info = lo_buf_prot+(index*4);
#else
sec_info = &parms_buffer[(index*4)];
#endif
*sec_info++ = cylinder;
*sec_info++ = head;
*sec_info++ = sector;
*sec_info = 0x02; /* N = 2 for 512 byte sectors */
/* These three line do the interleave calulation */
index = (int)(index + interleave);
if (index >= (int) fl_devparms[parmindex].sectors_per_track)
index = (int) (index - fl_devparms[parmindex].sectors_per_track);
}
b.n_to_send = 6;
b.n_to_get = 7;
b.commands[0] = (byte) (MFMBIT|FL_FORMAT);
b.commands[1] = (byte) ((head << 2)|driveno);
b.commands[2] = (byte) 0x02; /* bytes/sector */
b.commands[3] = (byte) fl_devparms[parmindex].sectors_per_track;
b.commands[4] = (byte) fl_devparms[parmindex].gpl_format;
b.commands[5] = (byte) FORMAT_FILLER;
#if (USE_DMA)
/* Set up to write sec_per_track * 4 bytes */
/* Copy the format parameters to a real mode buffer */
//DM: added PME conditional
#if defined(PME)
if (!fl_dma_init((DMAPTYPE) lo_buf_real,(word)((fl_devparms[parmindex].sectors_per_track)<<2), FALSE))
#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -