|
@@ -2,7 +2,7 @@
|
|
|
* Floppy Driver
|
|
|
* main.c
|
|
|
*
|
|
|
- * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
|
|
|
+ * Copyright (C) 2019 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
|
|
|
*
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
@@ -344,8 +344,19 @@ static dword_t floppy_read(device_t *device, void *buffer, qword_t offset, size_
|
|
|
else if (strcmp(device->name, FLOPPY_SECOND_NAME) == 0) drive = 1;
|
|
|
else return ERR_INVALID;
|
|
|
|
|
|
- dma_buffer = (byte_t*)isa_dma_alloc();
|
|
|
- if (dma_buffer == NULL) return ERR_NOMEMORY;
|
|
|
+ size_t max_transfer = ((dword_t)(offset + length - 1) / FLOPPY_SECTOR_SIZE) - ((dword_t)offset / FLOPPY_SECTOR_SIZE) + 1;
|
|
|
+ if (max_transfer > FLOPPY_SPT) max_transfer = FLOPPY_SPT;
|
|
|
+
|
|
|
+ area_t dma_area;
|
|
|
+ ret = isa_dma_alloc(max_transfer * FLOPPY_SECTOR_SIZE, &dma_area);
|
|
|
+ if (ret != ERR_SUCCESS) return ret;
|
|
|
+
|
|
|
+ ret = memory_view_area(memory_upper_space, (void**)&dma_buffer, &dma_area, MEMORY_FLAG_ACCESSIBLE);
|
|
|
+ if (ret != ERR_SUCCESS)
|
|
|
+ {
|
|
|
+ isa_dma_free(&dma_area);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
lock_acquire(&floppy_lock);
|
|
|
floppy_select(drive);
|
|
@@ -386,7 +397,7 @@ static dword_t floppy_read(device_t *device, void *buffer, qword_t offset, size_
|
|
|
};
|
|
|
byte_t command_output[FLOPPY_RW_OUTPUTS];
|
|
|
|
|
|
- isa_dma_write(FLOPPY_DMA_CHANNEL, dma_buffer, amount);
|
|
|
+ isa_dma_write(FLOPPY_DMA_CHANNEL, &dma_area, amount);
|
|
|
|
|
|
for (i = 0; i < FLOPPY_RW_INPUTS; i++) if (!floppy_fifo_write(command_input[i])) goto timeout;
|
|
|
if (floppy_wait_irq(FLOPPY_READ_TIMEOUT) == ERR_TIMEOUT) goto timeout;
|
|
@@ -408,9 +419,7 @@ static dword_t floppy_read(device_t *device, void *buffer, qword_t offset, size_
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
- ret = read_physical(&dma_buffer[sector_offset], (void*)((uintptr_t)buffer + count), MIN(length - count, amount - sector_offset));
|
|
|
- if (ret != ERR_SUCCESS) goto done;
|
|
|
-
|
|
|
+ memcpy(&((byte_t*)buffer)[count], &dma_buffer[sector_offset], MIN(length - count, amount - sector_offset));
|
|
|
count += MIN(length - count, amount - sector_offset);
|
|
|
sector_offset = 0;
|
|
|
}
|
|
@@ -419,7 +428,8 @@ static dword_t floppy_read(device_t *device, void *buffer, qword_t offset, size_
|
|
|
done:
|
|
|
floppy_motor_off(drive);
|
|
|
lock_release(&floppy_lock);
|
|
|
- isa_dma_free(dma_buffer);
|
|
|
+ memory_free(memory_upper_space, dma_buffer);
|
|
|
+ isa_dma_free(&dma_area);
|
|
|
|
|
|
if (bytes_read) *bytes_read = count;
|
|
|
return ret;
|
|
@@ -456,8 +466,19 @@ static dword_t floppy_write(device_t *device, const void *buffer, qword_t offset
|
|
|
if (ret != ERR_SUCCESS) return ret;
|
|
|
}
|
|
|
|
|
|
- dma_buffer = (byte_t*)isa_dma_alloc();
|
|
|
- if (dma_buffer == NULL) return ERR_NOMEMORY;
|
|
|
+ size_t max_transfer = ((dword_t)(offset + length - 1) / FLOPPY_SECTOR_SIZE) - ((dword_t)offset / FLOPPY_SECTOR_SIZE) + 1;
|
|
|
+ if (max_transfer > FLOPPY_SPT) max_transfer = FLOPPY_SPT;
|
|
|
+
|
|
|
+ area_t dma_area;
|
|
|
+ ret = isa_dma_alloc(max_transfer * FLOPPY_SECTOR_SIZE, &dma_area);
|
|
|
+ if (ret != ERR_SUCCESS) return ret;
|
|
|
+
|
|
|
+ ret = memory_view_area(memory_upper_space, (void**)&dma_buffer, &dma_area, MEMORY_FLAG_ACCESSIBLE | MEMORY_FLAG_WRITABLE);
|
|
|
+ if (ret != ERR_SUCCESS)
|
|
|
+ {
|
|
|
+ isa_dma_free(&dma_area);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
lock_acquire(&floppy_lock);
|
|
|
floppy_select(drive);
|
|
@@ -483,18 +504,15 @@ static dword_t floppy_write(device_t *device, const void *buffer, qword_t offset
|
|
|
|
|
|
if (sector_offset)
|
|
|
{
|
|
|
- ret = write_physical(dma_buffer, first_sector_data, FLOPPY_SECTOR_SIZE);
|
|
|
- if (ret != ERR_SUCCESS) goto done;
|
|
|
+ memcpy(dma_buffer, first_sector_data, FLOPPY_SECTOR_SIZE);
|
|
|
}
|
|
|
|
|
|
if ((length - count) < amount)
|
|
|
{
|
|
|
- ret = write_physical(&dma_buffer[amount - FLOPPY_SECTOR_SIZE], last_sector_data, FLOPPY_SECTOR_SIZE);
|
|
|
- if (ret != ERR_SUCCESS) goto done;
|
|
|
+ memcpy(&dma_buffer[amount - FLOPPY_SECTOR_SIZE], last_sector_data, FLOPPY_SECTOR_SIZE);
|
|
|
}
|
|
|
|
|
|
- ret = write_physical(&dma_buffer[sector_offset], (void*)((uintptr_t)buffer + count), MIN(length - count, amount - sector_offset));
|
|
|
- if (ret != ERR_SUCCESS) goto done;
|
|
|
+ memcpy(&dma_buffer[sector_offset], &((const byte_t*)buffer)[count], MIN(length - count, amount - sector_offset));
|
|
|
|
|
|
while (retries--)
|
|
|
{
|
|
@@ -513,7 +531,7 @@ static dword_t floppy_write(device_t *device, const void *buffer, qword_t offset
|
|
|
};
|
|
|
byte_t command_output[FLOPPY_RW_OUTPUTS];
|
|
|
|
|
|
- isa_dma_read(FLOPPY_DMA_CHANNEL, dma_buffer, amount);
|
|
|
+ isa_dma_read(FLOPPY_DMA_CHANNEL, &dma_area, amount);
|
|
|
|
|
|
for (i = 0; i < FLOPPY_RW_INPUTS; i++) if (!floppy_fifo_write(command_input[i])) goto write_timeout;
|
|
|
if (floppy_wait_irq(FLOPPY_READ_TIMEOUT) == ERR_TIMEOUT) goto write_timeout;
|
|
@@ -543,7 +561,8 @@ static dword_t floppy_write(device_t *device, const void *buffer, qword_t offset
|
|
|
done:
|
|
|
floppy_motor_off(drive);
|
|
|
lock_release(&floppy_lock);
|
|
|
- isa_dma_free(dma_buffer);
|
|
|
+ memory_free(memory_upper_space, dma_buffer);
|
|
|
+ isa_dma_free(&dma_area);
|
|
|
|
|
|
if (bytes_written) *bytes_written = count;
|
|
|
return ret;
|