Files

133 lines
3.4 KiB
C++
Raw Permalink Normal View History

2023-03-17 11:40:49 +00:00
// -----------------------------------------------------------------------------
// 3.5"/5.25" DD/HD Disk controller for Arduino
// Copyright (C) 2021 David Hansel
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// -----------------------------------------------------------------------------
#include "diskio.h"
#include "ArduinoFDC.h"
DSTATUS disk_status(BYTE pdrv)
{
// STA_NOINIT: Drive not initialized
// STA_NODISK: No medium in the drive
// STA_PROTECT: Write protected
return ArduinoFDC.isWriteProtected() ? STA_PROTECT : 0;
}
DSTATUS disk_initialize(BYTE pdrv)
{
return ((ArduinoFDC.haveDisk() ? 0 : (STA_NODISK|STA_NOINIT)) |
(ArduinoFDC.isWriteProtected() ? STA_PROTECT : 0));
}
DRESULT disk_read(BYTE pdrv, BYTE *buf, DWORD sec, UINT count)
{
DRESULT res = RES_OK;
byte numsec = ArduinoFDC.numSectors();
if( count!=1 || sec>2*numsec*ArduinoFDC.numTracks() )
res = RES_PARERR;
else
{
byte head = 0;
byte track = sec / (numsec*2);
byte sector = sec % (numsec*2);
if( sector >= numsec ) { head = 1; sector -= numsec; }
byte r = S_NOHEADER, retry = 5;
while( retry>0 && r!=S_OK ) { r = ArduinoFDC.readSector(track, head, sector+1, buf); retry--; }
if( r==S_OK )
{
memmove(buf, buf+1, 512);
res = RES_OK;
}
else if( r==S_NOTREADY )
res = RES_NOTRDY;
else
res = RES_ERROR;
}
return res;
}
DRESULT disk_write(BYTE pdrv, BYTE *buf, DWORD sec, UINT count)
{
DRESULT res = RES_OK;
byte numsec = ArduinoFDC.numSectors();
if( count!=1 || sec>2*numsec*ArduinoFDC.numTracks() )
res = RES_PARERR;
else
{
byte head = 0;
byte track = sec / (numsec*2);
byte sector = sec % (numsec*2);
if( sector >= numsec ) { head = 1; sector -= numsec; }
memmove(buf+1, buf, 512);
byte r = S_NOHEADER, retry = 3;
while( retry>0 && r!=S_OK ) { r = ArduinoFDC.writeSector(track, head, sector+1, buf, true); retry--; }
memmove(buf, buf+1, 512);
if( r==S_OK )
res = RES_OK;
else if( r==S_NOTREADY )
res = RES_NOTRDY;
else if( r==S_READONLY )
res = RES_WRPRT;
else
res = RES_ERROR;
}
return res;
}
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff)
{
DRESULT res = RES_ERROR;
switch( cmd )
{
case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*((DWORD *) buff) = (DWORD) ArduinoFDC.numSectors() * (DWORD) ArduinoFDC.numTracks() * 2;
res = RES_OK;
break;
case GET_SECTOR_SIZE:
*((DWORD *) buff) = 512;
break;
case GET_BLOCK_SIZE:
*((DWORD *) buff) = 1;
break;
}
return res;
}