Код:
static struct { // Определить структуру, описывающую дисководы
UINT8 Track, // Номер трека (00..79, при over-позицировании > 79)
Side, // Сторона (0 - нижняя головка, 1 - верхняя головка)
Motor, // Мотор (00 - включен, иначе выключен)
PrevMotor, // Предыдущее состояние мотора (для иконок дискет)
Mode, // Режим (00 - нет чтения/записи, 01 - чтение, 02 - запись)
Sector; // Текущий сектор (0..9)
UINT8 *ImagePTR; // Указатель на образ диска (образ 819200 байт)
} Floppy[2];
static UINT8 FDD_DataBuf[2048]; // Буфер для сектора HDD/FDD
static UINT32 FDD_DataBufAdr; // Указатель адреса в буферном ОЗУ контроллера HDD/FDD
static UINT8 FDD_ComDim[256]; // Буфер для команд ввода-вывода
static UINT8 FDD_ComAdr; // Указатель на текущий адрес в массиве данных ввода-вывода
static UINT8 FDD_ComLen; // Оставшееся число байт до конца пакета
static UINT8 *FDD_DataAdr; // Указатель на массив сектора в памяти
static UINT32 FDD_DataPTR = 0; // Позиция внутри сектора 0..511
static const MaxTrack = 79; // Максимальный разрешенный номер трека
static UINT8 FD_CSR = 0x80; // Регистр статуса FDD
// Бит 7: 0 - контроллер не готов, 1 - контроллер готов
// Бит 6: 0 - обмен по чтению, 1 - обмен по записи
static char FDDImageNames[4][1024]; // Имена файлов для 4-х образов дисков
static UINT16 FASTC CPU_RdW_HD_BUF(void) // hd.buf
{
UINT8 Byte;
//printf("Read word from CPU register HD.BUF from location PC=0x%X\n",
// (UINT16)CPU->l.PC);
Byte = FDD_DataBuf[FDD_DataBufAdr & 0x07FF]; // Чтение байта из буферного ОЗУ контроллера HDD/FDD
FDD_DataBufAdr++;
return(Byte);
}
static UINT16 FASTC CPU_RdW_HD_CSR(void) // hd.csr
{
//printf("Read word from CPU register HD.CSR from location PC=0x%X\n",
// (UINT16)CPU->l.PC);
FDD_DataBufAdr = 0; // [T] Сброс адресного указателя буферного ОЗУ
// (пока что считаем, что он сбрасывается при чтении hd.csr
return(0x41); // Первичная готовность да, вторичная - нет
}
static UINT16 FASTC CPU_RdW_FD_BUF(void) // fd.buf
{
UINT8 Byte = 0;
Byte = FDD_ComDim[FDD_ComAdr++]; // Взять байт из буфера
if (FDD_ComAdr == FDD_ComLen) // Если конец пакета, то
{
switch (FDD_ComDim[0])
{
case 0x08: // Sence Interrupt Status (Опрос состояния)
// FDDNum = FDD_ComDim[1] & 0x3; // FDDNum - номер дисковода
// Floppy[FDDNum].Track = 0; // Установиться на трек 00
FD_CSR = 0x80; // Установить готовность записи данных в контроллер
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
break;
case 0x45: // Write Data MFM
FD_CSR = 0x80; // Установить готовность записи данных в контроллер
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
break;
case 0x46: // Read Data MFM
FD_CSR = 0x80; // Установить готовность записи данных в контроллер
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
break;
default:
printf ("WARNING FDD 002!!!\n");
}
}
//printf("Read word 0x%02X from CPU register FD.BUF from location PC=0x%X\n",
// Byte, (UINT16)CPU->l.PC);
return(Byte);
}
static void FASTC CPU_WrW_HD_CSR(UINT16 Data) // [T] hd.csr
{
//printf("Write word 0x%04X to unrealized CPU register HD.CSR from location PC = 0x%X\n",
// Data, (UINT16)CPU->l.PC);
if (Data == 0x0010) // [T] Если записали 0x0010 в порт, то
PIC_IRQM |= 0x02; // дать запрос на прерывание от FDD/HDD
// (чтобы контроллер отстал и не тормозил)
return;
}
static void FASTC CPU_WrW_FD_BUF(UINT16 Data) // [T] fd.buf
{
UINT8 Byte = (UINT8)Data,
FDDNum,
BCnt;
//printf("Write word 0x%04X to CPU register FD.BUF from location PC = 0x%X\n",
// Data, (UINT16)CPU->l.PC);
if (FDD_ComAdr == 0) // Если адрес в буфере обмена = 0, то код команды
{
switch (Byte)
{
case 0x03: // Specify (Задание параметров)
// printf("FDD Command: Specify\n");
FDD_ComLen = 3; // Длина команды
FDD_ComDim[0] = Byte; // Записать команду в начало буфера
break;
case 0x07: // Recalibrate (Трек-0)
//printf("FDD Command: Track-0\n");
FDD_ComLen = 2; // Длина команды
FDD_ComDim[0] = Byte; // Записать команду в начало буфера
break;
case 0x08: // Sence Interrupt Status (Опрос состояния)
// printf("FDD Command: Sence Status\n");
FDD_ComLen = 3; // Длина команды
FDD_ComDim[0] = Byte; // Записать команду в начало буфера
FDD_ComDim[1] = 0x20; // Записать байт корректного результата в буфер ($20)
FDD_ComDim[2] = 0; // (Остальные байты не опрашиваются)
FD_CSR = 0xC0; // Установить готовность чтения данных из контроллера
break;
case 0x0F: // Seek (Перемещение)
// printf("FDD Command: Seek\n");
FDD_ComLen = 3; // Длина команды
FDD_ComDim[0] = Byte; // Записать команду в начало буфера
break;
case 0x45: // Write Data MFM
// printf("FDD Command: Write Data MFM\n");
FDD_ComLen = 9; // Длина команды
FDD_ComDim[0] = Byte; // Записать команду в начало буфера
break;
case 0x46: // Read Data MFM
// printf("FDD Command: Read Data MFM\n");
FDD_ComLen = 9; // Длина команды
FDD_ComDim[0] = Byte; // Записать команду в начало буфера
break;
default:
printf("WARNING! FDD Command 0x%02X unrealized!\n", Byte);
}
FDD_ComAdr++; // Перейти к следующей позиции в буфере
}
else // Иначе блок данных команды
{
FDD_ComDim[FDD_ComAdr++] = Byte; // Записать байт в буфер
if (FDD_ComAdr == FDD_ComLen) // Если конец пакета, то
{
switch (FDD_ComDim[0])
{
case 0x03: // Specify (Задание параметров)
// Данные игнорируем // [T]
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
break;
case 0x07: // Recalibrate (Трек-0)
FDDNum = FDD_ComDim[1] & 0x3; // FDDNum - номер дисковода
Floppy[FDDNum].Track = 0; // Установиться на трек 00
PIC_IRQM |= 0x02; // Запрос на прерывание от FDD/HDD
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
break;
case 0x0F: // Seek (Перемещение)
FDDNum = FDD_ComDim[1] & 0x3; // FDDNum - номер дисковода
Floppy[FDDNum].Track = FDD_ComDim[2]; // Установиться на трек nn
//printf("FDD - Seek to track %d\n", Floppy[FDDNum].Track);
PIC_IRQM |= 0x02; // Запрос на прерывание от FDD/HDD
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
break;
case 0x45: // Write Data MFM
FDDNum = FDD_ComDim[1] & 0x3; // FDDNum - номер дисковода
Floppy[FDDNum].Track = FDD_ComDim[2]; // Трек
Floppy[FDDNum].Side = (FDD_ComDim[1] >> 2) & 1; // Сторона
Floppy[FDDNum].Sector = FDD_ComDim[4]; // Сектор
if (Floppy[FDDNum].Track > MaxTrack) // Ограничить максимальный номер трека
Floppy[FDDNum].Track = MaxTrack;
if (Floppy[FDDNum].Sector > 10) // Ограничить максимальный номер сектора (1..10)
Floppy[FDDNum].Sector = 10;
FDD_ComDim[9] = 0x20; // Записать байт корректного результата в буфер ($20)
FDD_ComDim[10] = 0; // (Остальные байты не опрашиваются)
FDD_ComDim[11] = 0; //
FDD_ComDim[12] = 0; //
FDD_ComDim[13] = 0; //
FDD_ComDim[14] = 0; //
FDD_ComDim[15] = 0; //
BCnt = 4 - (FD_CNT & 0x3); // BCnt - счетчик секторов для записи за один раз
//printf("FDD - Write MFM: Drive: %d, Track: %d, Head: %d, Sector: %d, Len: %d\n",
// FDDNum, FDD_ComDim[2], FDD_ComDim[3], FDD_ComDim[4], BCnt);
// Самой записи пока нет
FDD_ComLen += 7; // Увеличить длину команды на 7 байт (ответ контроллера)
PIC_IRQM |= 0x02; // Запрос на прерывание от FDD/HDD
FD_CSR = 0xC0; // Установить готовность чтения данных из контроллера
break;
case 0x46: // Read Data MFM
FDDNum = FDD_ComDim[1] & 0x3; // FDDNum - номер дисковода
Floppy[FDDNum].Track = FDD_ComDim[2]; // Трек
Floppy[FDDNum].Side = (FDD_ComDim[1] >> 2) & 1; // Сторона
Floppy[FDDNum].Sector = FDD_ComDim[4]; // Сектор
if (Floppy[FDDNum].Track > MaxTrack) // Ограничить максимальный номер трека
Floppy[FDDNum].Track = MaxTrack;
if (Floppy[FDDNum].Sector > 10) // Ограничить максимальный номер сектора (1..10)
Floppy[FDDNum].Sector = 10;
FDD_ComDim[9] = 0x20; // Записать байт корректного результата в буфер ($20)
FDD_ComDim[10] = 0; // (Остальные байты не опрашиваются)
FDD_ComDim[11] = 0; //
FDD_ComDim[12] = 0; //
FDD_ComDim[13] = 0; //
FDD_ComDim[14] = 0; //
FDD_ComDim[15] = 0; //
BCnt = 4 - (FD_CNT & 0x3); // BCnt - счетчик секторов для чтения за один раз
// Копируем сектор в буферное ОЗУ контроллера
memcpy(FDD_DataBuf,
(Floppy[FDDNum].ImagePTR +
((Floppy[FDDNum].Track << 1) + (Floppy[FDDNum].Side & 0x1)) * 5120 +
((Floppy[FDDNum].Sector - 1) * 512)),
512 * BCnt);
//printf("FDD - Read MFM: Drive: %d, Track: %d, Head: %d, Sector: %d, Len: %d\n",
// FDDNum, FDD_ComDim[2], FDD_ComDim[3], FDD_ComDim[4], BCnt);
FDD_ComLen += 7; // Увеличить длину команды на 7 байт (ответ контроллера)
PIC_IRQM |= 0x02; // Запрос на прерывание от FDD/HDD
FD_CSR = 0xC0; // Установить готовность чтения данных из контроллера
break;
default:
printf ("WARNING FDD 001!!!\n");
}
}
}
return;
}
static void FASTC CPU_WrW_FD_CNT(UINT16 Data) // [T] fd.cnt
{
//printf("Write word 0x%04X to CPU register FD.CNT from location PC = 0x%X\n",
// Data, (UINT16)CPU->l.PC);
FD_CNT = (UINT8)Data;
if (Data == 0x10) // Инициализация регистров контроллера?
{
FD_CSR = 0x80; // Установить готовность записи данных в контроллер
FDD_ComAdr = 0; // Обнулить указатель адреса в буфере обмена
}
if ((Data >= 0) && (Data < 4)) // Если число в диапазоне от 0..3, то это
{ // число секторов (блоков) для чтения в буферное ОЗУ контроллера
;
}
return;
}