réplica de
https://github.com/Arnau478/quark.git
synced 2024-11-23 12:58:07 +01:00
Created DMA driver
This commit is contained in:
pare
92b14a5331
commit
44c78007d8
S'han modificat 4 arxius amb 201 adicions i 1 eliminacions
94
src/kernel/arch/i686/dma.c
Normal file
94
src/kernel/arch/i686/dma.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include <stdint.h>
|
||||
#include "dma.h"
|
||||
#include "io.h"
|
||||
|
||||
void i686_dma_set_address(uint8_t channel, uint16_t addr){
|
||||
if(channel > 8) return;
|
||||
|
||||
uint16_t port = 0;
|
||||
switch(channel){
|
||||
case 0: port = i686_DMA0_CHAN0_ADDR_REG; break;
|
||||
case 1: port = i686_DMA0_CHAN1_ADDR_REG; break;
|
||||
case 2: port = i686_DMA0_CHAN2_ADDR_REG; break;
|
||||
case 3: port = i686_DMA0_CHAN3_ADDR_REG; break;
|
||||
case 4: port = i686_DMA1_CHAN4_ADDR_REG; break;
|
||||
case 5: port = i686_DMA1_CHAN5_ADDR_REG; break;
|
||||
case 6: port = i686_DMA1_CHAN6_ADDR_REG; break;
|
||||
case 7: port = i686_DMA1_CHAN7_ADDR_REG; break;
|
||||
}
|
||||
|
||||
i686_outw(port, addr);
|
||||
}
|
||||
|
||||
void i686_dma_set_count(uint8_t channel, uint16_t count){
|
||||
if(channel > 8) return;
|
||||
|
||||
uint16_t port = 0;
|
||||
switch(channel){
|
||||
case 0: port = i686_DMA0_CHAN0_COUNT_REG; break;
|
||||
case 1: port = i686_DMA0_CHAN1_COUNT_REG; break;
|
||||
case 2: port = i686_DMA0_CHAN2_COUNT_REG; break;
|
||||
case 3: port = i686_DMA0_CHAN3_COUNT_REG; break;
|
||||
case 4: port = i686_DMA1_CHAN4_COUNT_REG; break;
|
||||
case 5: port = i686_DMA1_CHAN5_COUNT_REG; break;
|
||||
case 6: port = i686_DMA1_CHAN6_COUNT_REG; break;
|
||||
case 7: port = i686_DMA1_CHAN7_COUNT_REG; break;
|
||||
}
|
||||
|
||||
i686_outw(port, count);
|
||||
}
|
||||
|
||||
void i686_dma_set_external_page_register(uint8_t reg, uint8_t val){
|
||||
uint16_t port = 0;
|
||||
|
||||
switch(reg){
|
||||
case 1: port = i686_DMA_PAGE_CHAN1_ADDRBYTE2; break;
|
||||
case 2: port = i686_DMA_PAGE_CHAN2_ADDRBYTE2; break;
|
||||
case 3: port = i686_DMA_PAGE_CHAN3_ADDRBYTE2; break;
|
||||
// 4 is not valid
|
||||
case 5: port = i686_DMA_PAGE_CHAN5_ADDRBYTE2; break;
|
||||
case 6: port = i686_DMA_PAGE_CHAN6_ADDRBYTE2; break;
|
||||
case 7: port = i686_DMA_PAGE_CHAN7_ADDRBYTE2; break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void i686_dma_set_mode(uint8_t channel, uint8_t mode){
|
||||
int dma = (channel < 4) ? 0 : 1;
|
||||
int chan = (dma == 0) ? channel : channel-4;
|
||||
|
||||
i686_dma_mask_channel(channel);
|
||||
i686_outb((channel < 4) ? i686_DMA0_MODE_REG : i686_DMA1_MODE_REG, chan | mode);
|
||||
i686_dma_unmask_all(dma);
|
||||
}
|
||||
|
||||
void i686_dma_set_read(uint8_t channel){
|
||||
i686_dma_set_mode(channel, i686_DMA_MODE_READ_TRANSFER | i686_DMA_MODE_TRANSFER_SINGLE | i686_DMA_MODE_MASK_AUTO);
|
||||
}
|
||||
|
||||
void i686_dma_set_write(uint8_t channel){
|
||||
i686_dma_set_mode(channel, i686_DMA_MODE_WRITE_TRANSFER | i686_DMA_MODE_TRANSFER_SINGLE | i686_DMA_MODE_MASK_AUTO);
|
||||
}
|
||||
|
||||
void i686_dma_mask_channel(uint8_t channel){
|
||||
if(channel <= 4) i686_outb(i686_DMA0_CHANMASK_REG, (1 << (channel-1)));
|
||||
else i686_outb(i686_DMA1_CHANMASK_REG, (1 << (channel-5)));
|
||||
}
|
||||
|
||||
void i686_dma_unmask_channel(uint8_t channel){
|
||||
i686_outb(channel <= 4 ? i686_DMA0_CHANMASK_REG : i686_DMA1_CHANMASK_REG, channel);
|
||||
}
|
||||
|
||||
void i686_dma_reset_flipflop(int dma){
|
||||
if(dma > 2) return;
|
||||
|
||||
i686_outb((dma == 0) ? i686_DMA0_CLEARBYTE_FLIPFLOP_REG : i686_DMA1_CLEARBYTE_FLIPFLOP_REG, 0xFF);
|
||||
}
|
||||
|
||||
void i686_dma_reset(int dma){
|
||||
i686_outb(i686_DMA0_TEMP_REG, 0xFF);
|
||||
}
|
||||
|
||||
void i686_dma_unmask_all(int dma){
|
||||
i686_outb(i686_DMA1_UNMASK_ALL_REG, 0xFF);
|
||||
}
|
85
src/kernel/arch/i686/dma.h
Normal file
85
src/kernel/arch/i686/dma.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define i686_DMA0_STATUS_REG 0x08
|
||||
#define i686_DMA0_COMMAND_REG 0x08
|
||||
#define i686_DMA0_REQUEST_REG 0x09
|
||||
#define i686_DMA0_CHANMASK_REG 0x0A
|
||||
#define i686_DMA0_MODE_REG 0x0B
|
||||
#define i686_DMA0_CLEARBYTE_FLIPFLOP_REG 0x0C
|
||||
#define i686_DMA0_TEMP_REG 0x0D
|
||||
#define i686_DMA0_MASTER_CLEAR_REG 0x0D
|
||||
#define i686_DMA0_CLEAR_MASK_REG 0x0E
|
||||
#define i686_DMA0_MASK_REG 0x0F
|
||||
#define i686_DMA0_CHAN0_ADDR_REG 0x00
|
||||
#define i686_DMA0_CHAN0_COUNT_REG 0x01
|
||||
#define i686_DMA0_CHAN1_ADDR_REG 0x02
|
||||
#define i686_DMA0_CHAN1_COUNT_REG 0x03
|
||||
#define i686_DMA0_CHAN2_ADDR_REG 0x04
|
||||
#define i686_DMA0_CHAN2_COUNT_REG 0x05
|
||||
#define i686_DMA0_CHAN3_ADDR_REG 0x06
|
||||
#define i686_DMA0_CHAN3_COUNT_REG 0x07
|
||||
#define i686_DMA1_STATUS_REG 0xD0
|
||||
#define i686_DMA1_COMMAND_REG 0xD0
|
||||
#define i686_DMA1_REQUEST_REG 0xD2
|
||||
#define i686_DMA1_CHANMASK_REG 0xD4
|
||||
#define i686_DMA1_MODE_REG 0xD6
|
||||
#define i686_DMA1_CLEARBYTE_FLIPFLOP_REG 0xD8
|
||||
#define i686_DMA1_INTER_REG 0xDA
|
||||
#define i686_DMA1_UNMASK_ALL_REG 0xDC
|
||||
#define i686_DMA1_MASK_REG 0xDE
|
||||
#define i686_DMA1_CHAN4_ADDR_REG 0xC0
|
||||
#define i686_DMA1_CHAN4_COUNT_REG 0xC2
|
||||
#define i686_DMA1_CHAN5_ADDR_REG 0xC4
|
||||
#define i686_DMA1_CHAN5_COUNT_REG 0xC6
|
||||
#define i686_DMA1_CHAN6_ADDR_REG 0xC8
|
||||
#define i686_DMA1_CHAN6_COUNT_REG 0xCA
|
||||
#define i686_DMA1_CHAN7_ADDR_REG 0xCC
|
||||
#define i686_DMA1_CHAN7_COUNT_REG 0xCE
|
||||
#define i686_DMA_PAGE_EXTRA0 0x80
|
||||
#define i686_DMA_PAGE_CHAN2_ADDRBYTE2 0x81
|
||||
#define i686_DMA_PAGE_CHAN3_ADDRBYTE2 0x82
|
||||
#define i686_DMA_PAGE_CHAN1_ADDRBYTE2 0x83
|
||||
#define i686_DMA_PAGE_EXTRA1 0x84
|
||||
#define i686_DMA_PAGE_EXTRA2 0x85
|
||||
#define i686_DMA_PAGE_EXTRA3 0x86
|
||||
#define i686_DMA_PAGE_CHAN6_ADDRBYTE2 0x87
|
||||
#define i686_DMA_PAGE_CHAN7_ADDRBYTE2 0x88
|
||||
#define i686_DMA_PAGE_CHAN5_ADDRBYTE2 0x89
|
||||
#define i686_DMA_PAGE_EXTRA4 0x8C
|
||||
#define i686_DMA_PAGE_EXTRA5 0x8D
|
||||
#define i686_DMA_PAGE_EXTRA6 0x8E
|
||||
#define i686_DMA_PAGE_DRAM_REFRESH 0x8F
|
||||
#define i686_DMA_CMD_MASK_MEMTOMEM 0x01
|
||||
#define i686_DMA_CMD_MASK_CHAN0ADDRHOLD 0x02
|
||||
#define i686_DMA_CMD_MASK_ENABLE 0x04
|
||||
#define i686_DMA_CMD_MASK_TIMING 0x08
|
||||
#define i686_DMA_CMD_MASK_PRIORITY 0x10
|
||||
#define i686_DMA_CMD_MASK_WRITESEL 0x20
|
||||
#define i686_DMA_CMD_MASK_DREQ 0x40
|
||||
#define i686_DMA_CMD_MASK_DACK 0x80
|
||||
#define i686_DMA_MODE_MASK_SEL 0x03
|
||||
#define i686_DMA_MODE_MASK_TRA 0x0C
|
||||
#define i686_DMA_MODE_MASK_TEST 0x00
|
||||
#define i686_DMA_MODE_READ_TRANSFER 0x04
|
||||
#define i686_DMA_MODE_WRITE_TRANSFER 0x08
|
||||
#define i686_DMA_MODE_MASK_AUTO 0x10
|
||||
#define i686_DMA_MODE_MASK_IDEC 0x20
|
||||
#define i686_DMA_MODE_MASK 0xC0
|
||||
#define i686_DMA_MODE_TRANSFER_ON_DEMAND 0x00
|
||||
#define i686_DMA_MODE_TRANSFER_SINGLE 0x40
|
||||
#define i686_DMA_MODE_TRANSFER_BLOCK 0x80
|
||||
#define i686_DMA_MODE_TRANSFER_CASCADE 0xC0
|
||||
|
||||
void i686_dma_set_address(uint8_t channel, uint16_t addr);
|
||||
void i686_dma_set_count(uint8_t channel, uint16_t count);
|
||||
void i686_dma_set_external_page_register(uint8_t reg, uint8_t val);
|
||||
void i686_dma_set_mode(uint8_t channel, uint8_t mode);
|
||||
void i686_dma_set_read(uint8_t channel);
|
||||
void i686_dma_set_write(uint8_t channel);
|
||||
void i686_dma_mask_channel(uint8_t channel);
|
||||
void i686_dma_unmask_channel(uint8_t channel);
|
||||
void i686_dma_reset_flipflop(int dma);
|
||||
void i686_dma_reset(int dma);
|
||||
void i686_dma_unmask_all(int dma);
|
|
@ -2,6 +2,7 @@
|
|||
#include "fdc.h"
|
||||
#include "isr.h"
|
||||
#include "io.h"
|
||||
#include "dma.h"
|
||||
#include "../../lib/time.h"
|
||||
#include "../../lib/debug.h"
|
||||
|
||||
|
@ -20,7 +21,7 @@ static inline void wait_irq(){
|
|||
void i686_fdc_initialize_dma(){
|
||||
i686_outb(0x0A, 0x06); // Mask DMA channel 2
|
||||
i686_outb(0xD8, 0xFF); // Reset master flip-flop
|
||||
i686_outw(0x04, 0x1000); // Address = 0x1000
|
||||
i686_outw(0x04, i686_FDC_DMA_BUFFER); // Address = 0x1000
|
||||
i686_outb(0xD8, 0xFF); // Reset master flip-flop
|
||||
i686_outb(0x05, 0xFF); // Count to 0x23FF (bytes in 2.5" floppy disk track)
|
||||
i686_outb(0x05, 0x23);
|
||||
|
@ -97,6 +98,9 @@ int i686_fdc_motor(bool b){
|
|||
void i686_fdc_read_sector_imp(uint8_t head, uint8_t track, uint8_t sector){
|
||||
uint32_t st0, cyl;
|
||||
|
||||
// Initialize the DMA
|
||||
i686_dma_initialize_floppy((uint8_t *)i686_FDC_DMA_BUFFER, 512);
|
||||
|
||||
// Set DMA for read
|
||||
i686_fdc_dma_read();
|
||||
|
||||
|
@ -239,3 +243,17 @@ void i686_fdc_initialize(){
|
|||
// Set drive info
|
||||
i686_fdc_drive_data(13, 1, 0x0F, true);
|
||||
}
|
||||
|
||||
void i686_dma_initialize_floppy(uint8_t *buffer, unsigned length){
|
||||
i686_dma_reset(1);
|
||||
i686_dma_mask_channel(i686_FDC_DMA_CHANNEL);
|
||||
i686_dma_reset_flipflop(1);
|
||||
|
||||
i686_dma_set_address(i686_FDC_DMA_CHANNEL, (unsigned)buffer);
|
||||
i686_dma_reset_flipflop(1);
|
||||
|
||||
i686_dma_set_count(i686_FDC_DMA_CHANNEL, length);
|
||||
i686_dma_set_read(i686_FDC_DMA_CHANNEL);
|
||||
|
||||
i686_dma_unmask_all(1);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#define i686_FDC_SECTOR_DTL_512 2
|
||||
#define i686_FDC_SECTOR_DTL_1024 4
|
||||
#define i686_FDC_SECTORS_PER_TRACK 18
|
||||
#define i686_FDC_DMA_BUFFER 0x1000
|
||||
#define i686_FDC_DMA_CHANNEL 2
|
||||
|
||||
void i686_fdc_initialize_dma();
|
||||
void i686_fdc_dma_read();
|
||||
|
@ -68,3 +70,4 @@ void i686_fdc_enable();
|
|||
void i686_fdc_reset();
|
||||
void i686_fdc_set_working_drive(int drive);
|
||||
void i686_fdc_initialize();
|
||||
void i686_dma_initialize_floppy(uint8_t *buffer, unsigned length);
|
||||
|
|
Loading…
Referencia en una nova incidència