diff options
| author | Michal Idziorek <m.i@gmx.at> | 2015-05-14 10:44:00 +0200 |
|---|---|---|
| committer | Michal Idziorek <m.i@gmx.at> | 2015-05-14 10:44:00 +0200 |
| commit | dc7bf2f47d6f97407e3b50ae0b8ab59fd51079e5 (patch) | |
| tree | 1ed444c804d9ff55e23a7a007275c3d5c649a455 /xxx/inactive/floppy.c | |
| parent | 7df4060ae807dd27f3ae0a11f243897f36053ba1 (diff) | |
moving unused files folder
Diffstat (limited to 'xxx/inactive/floppy.c')
| -rw-r--r-- | xxx/inactive/floppy.c | 575 |
1 files changed, 575 insertions, 0 deletions
diff --git a/xxx/inactive/floppy.c b/xxx/inactive/floppy.c new file mode 100644 index 0000000..1dbe137 --- /dev/null +++ b/xxx/inactive/floppy.c @@ -0,0 +1,575 @@ + +/* + * Fool OS Simple Floppy Driver. + * + * coded by M.idziorek <m.i@gmx.at> on 20th of august 2014 A.D + * + * tested in : bochs, qemu and virutalbox so far + * + * resources: + * + * * http://wiki.osdev.org/Floppy_Disk_Controller#DMA_Data_Transfers + * * http://forum.osdev.org/viewtopic.php?f=1&t=13538 + * * http://www.brokenthorn.com/Resources/OSDev20.html + * * http://bochs.sourceforge.net/cgi-bin/lxr/source/iodev/floppy.cc + * * http://viralpatel.net/taj/tutorial/chs_translation.php + * + */ + +#define FOOLOS_MODULE_NAME "floppy" +#include "config.h" + +#ifdef FOOLOS_COMPILE_FLOPPY + +#include "lib/logger/log.h" + +#include "x86.h" + +#define FLPY_SECTORS_PER_TRACK 18 + +void flpydsk_send_command (uint8_t cmd); +void flpydsk_wait_irq (); +void flpydsk_check_int (uint32_t* st0, uint32_t* cyl); + +static volatile int _CurrentDrive=0; +static volatile uint8_t _FloppyDiskIRQ; + +// temporary dma hack +//! initialize DMA to use phys addr 1k-64k +void flpydsk_initialize_dma () { + + x86_outb (0x0a,0x06); //mask dma channel 2 + + x86_outb (0xd8,0xff); //reset master flip-flop + + //changed to 0x000 (Address) + x86_outb (0x04, 0x00); //low + x86_outb (0x04, 0x05); //high + x86_outb (0x81,0x00); //page reg + + x86_outb (0xd8, 0xff); //reset master flip-flop + + // x86_outb (0x05, 0xff); //count to 0x23ff (number of bytes in a 3.5" floppy disk track) +// x86_outb (0x05, 0x23); +// hey, lets do just ONE sector instead (0x200) + x86_outb (0x05, 0xff); //low + x86_outb (0x05, 0x01); //high + + x86_outb (0x80, 0); //external page register = 0 + + x86_outb (0x0a, 0x02); //unmask dma channel 2 + log("dma",FOOLOS_LOG_INFO,"initialized"); +} + +//! prepare the DMA for read transfer +void flpydsk_dma_read () { + x86_outb (0x0a, 0x06); //mask dma channel 2 + + x86_outb (0x0b, 0x56); //single transfer, address increment, autoinit, read, channel 2 + + x86_outb (0x0a, 0x02); //unmask dma channel 2 + log("dma",FOOLOS_LOG_INFO,"configured for reading"); +} + +//! prepare the DMA for write transfer +void flpydsk_dma_write () { + + x86_outb (0x0a, 0x06); //mask dma channel 2 + x86_outb (0x0b, 0x5a); //single transfer, address increment, autoinit, write, channel 2 + x86_outb (0x0a, 0x02); //unmask dma channel 2 + log("dma",FOOLOS_LOG_INFO,"configured for writing"); +} +// +// + +enum FLPYDSK_IO { + + FLPYDSK_DOR = 0x3f2, + FLPYDSK_MSR = 0x3f4, + FLPYDSK_FIFO = 0x3f5, //data register + FLPYDSK_CTRL = 0x3f7 +}; + +enum FLPYDSK_DOR_MASK { + + FLPYDSK_DOR_MASK_DRIVE0 = 0, //00000000 = here for completeness sake + FLPYDSK_DOR_MASK_DRIVE1 = 1, //00000001 + FLPYDSK_DOR_MASK_DRIVE2 = 2, //00000010 + FLPYDSK_DOR_MASK_DRIVE3 = 3, //00000011 + FLPYDSK_DOR_MASK_RESET = 4, //00000100 + FLPYDSK_DOR_MASK_DMA = 8, //00001000 + FLPYDSK_DOR_MASK_DRIVE0_MOTOR = 16, //00010000 + FLPYDSK_DOR_MASK_DRIVE1_MOTOR = 32, //00100000 + FLPYDSK_DOR_MASK_DRIVE2_MOTOR = 64, //01000000 + FLPYDSK_DOR_MASK_DRIVE3_MOTOR = 128 //10000000 +}; + +enum FLPYDSK_MSR_MASK { + + FLPYDSK_MSR_MASK_DRIVE1_POS_MODE = 1, //00000001 + FLPYDSK_MSR_MASK_DRIVE2_POS_MODE = 2, //00000010 + FLPYDSK_MSR_MASK_DRIVE3_POS_MODE = 4, //00000100 + FLPYDSK_MSR_MASK_DRIVE4_POS_MODE = 8, //00001000 + FLPYDSK_MSR_MASK_BUSY = 16, //00010000 + FLPYDSK_MSR_MASK_DMA = 32, //00100000 + FLPYDSK_MSR_MASK_DATAIO = 64, //01000000 + FLPYDSK_MSR_MASK_DATAREG = 128 //10000000 +}; + +enum FLPYDSK_CMD { + + FDC_CMD_READ_TRACK = 2, + FDC_CMD_SPECIFY = 3, + FDC_CMD_CHECK_STAT = 4, + FDC_CMD_WRITE_SECT = 5, + FDC_CMD_READ_SECT = 6, + FDC_CMD_CALIBRATE = 7, + FDC_CMD_CHECK_INT = 8, + FDC_CMD_WRITE_DEL_S = 9, + FDC_CMD_READ_ID_S = 0xa, + FDC_CMD_READ_DEL_S = 0xc, + FDC_CMD_FORMAT_TRACK = 0xd, + FDC_CMD_SEEK = 0xf +}; + +enum FLPYDSK_CMD_EXT { + + FDC_CMD_EXT_SKIP = 0x20, //00100000 + FDC_CMD_EXT_DENSITY = 0x40, //01000000 + FDC_CMD_EXT_MULTITRACK = 0x80 //10000000 +}; + +enum FLPYDSK_GAP3_LENGTH { + + FLPYDSK_GAP3_LENGTH_STD = 42, + FLPYDSK_GAP3_LENGTH_5_14= 32, + FLPYDSK_GAP3_LENGTH_3_5= 27 +}; + +enum FLPYDSK_SECTOR_DTL { + + FLPYDSK_SECTOR_DTL_128 = 0, + FLPYDSK_SECTOR_DTL_256 = 1, + FLPYDSK_SECTOR_DTL_512 = 2, + FLPYDSK_SECTOR_DTL_1024 = 4 +}; + +void flpydsk_write_dor (uint8_t val ) { + + //! write the digital output register + x86_outb (FLPYDSK_DOR, val); + +} + +void flpydsk_write_ccr (uint8_t val) { + + //! write the configuation control + x86_outb (FLPYDSK_CTRL, val); +} + + +void flpydsk_motor_on() +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"starting motor..."); + //x86_outb (FLPYDSK_DOR, FLPYDSK_DOR_MASK_DRIVE0_MOTOR | FLPYDSK_DOR_MASK_RESET); + x86_outb (FLPYDSK_DOR, 0x1c); + sleep(10); // wait ~ 1/3 second +} + +void flpydsk_motor_off() +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"stopping motor..."); + x86_outb (FLPYDSK_DOR, 0x0c); +} + +int flpydsk_calibrate (uint32_t drive) { + + uint32_t st0, cyl; + + if (drive >= 4) + { + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"ERROR!"); + return -2; + } + + //! turn on the motor + flpydsk_motor_on(); + + int i; + for (i = 0; i < 10; i++) { + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"calibrating"); + //! send command + flpydsk_send_command ( FDC_CMD_CALIBRATE ); + flpydsk_send_command ( drive ); + flpydsk_wait_irq (); + flpydsk_check_int ( &st0, &cyl); + + //! did we fine cylinder 0? if so, we are done + if (!cyl) { + if(st0 & 0xC0) { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"calibrating FAILED!"); + } + // flpydsk_control_motor (false); + flpydsk_motor_off(); + return 0; + } + } + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"calibrating FAILED!"); + +// flpydsk_control_motor (false); + flpydsk_motor_off(); + return -1; +} + + + +void flpydsk_disable_controller () { + + flpydsk_write_dor (0); +} + +void flpydsk_enable_controller () { + + flpydsk_write_dor ( FLPYDSK_DOR_MASK_RESET | FLPYDSK_DOR_MASK_DMA); +} + + +uint8_t flpydsk_read_status () { + + //! just return main status register + return x86_inb (FLPYDSK_MSR); +} + +uint8_t flpydsk_read_data () { + + //! same as above function but returns data register for reading + int i; + for (i = 0; i < 500; i++ ) + if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG ) + return x86_inb (FLPYDSK_FIFO); + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"reading data FAILED!"); +} +void flpydsk_send_command (uint8_t cmd) { + + //! wait until data register is ready. We send commands to the data register + int i; + for (i = 0; i < 500; i++ ) + if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG ) + { + x86_outb(FLPYDSK_FIFO, cmd); + return; + } + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"writing data FAILED!"); +} + +void flpydsk_drive_data (uint32_t stepr, uint32_t loadt, uint32_t unloadt, int dma ) { + + uint32_t data = 0; + + flpydsk_send_command (FDC_CMD_SPECIFY); + + data = ( (stepr & 0xf) << 4) | (unloadt & 0xf); + flpydsk_send_command (data); + + data = (loadt) << 1 | dma; + flpydsk_send_command (data); +} + +void flpydsk_reset() +{ + uint32_t st0, cyl; + + //! reset the controller + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"reset controller"); + flpydsk_disable_controller (); + flpydsk_enable_controller (); + flpydsk_wait_irq (); + + //! send CHECK_INT/SENSE INTERRUPT command to all drives + int i; + for (i=0; i<4; i++) + flpydsk_check_int (&st0,&cyl); + + //! transfer speed 500kb/s + flpydsk_write_ccr (0); + + //! pass mechanical drive info. steprate=3ms, unload time=240ms, load time=16ms +// flpydsk_drive_data (3,16,240,0); +// + + flpydsk_send_command (FDC_CMD_SPECIFY); + flpydsk_send_command (0xdf); /* steprate = 3ms, unload time = 240ms */ + flpydsk_send_command (0x02); /* load time = 16ms, no-DMA = 0 */ + + //! calibrate the disk + flpydsk_calibrate ( _CurrentDrive ); +} + +void int_floppy_handler() +{ + X86_IRQ_BEGIN + _FloppyDiskIRQ=1; + X86_IRQ_END +} + +void flpydsk_wait_irq() +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"waiting for irq6"); + + while (1) + { + sleep(2); + x86_int_disable(); + if(_FloppyDiskIRQ==1)break; + x86_int_enable(); + + } + _FloppyDiskIRQ = 0; + x86_int_enable(); + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"irq6 received"); +} + +void flpydsk_check_int (uint32_t* st0, uint32_t* cyl) { + + flpydsk_send_command (FDC_CMD_CHECK_INT); + + *st0 = flpydsk_read_data (); + *cyl = flpydsk_read_data (); +} + +void flpydsk_write_sector_imp (uint8_t head, uint8_t track, uint8_t sector) { + + //sector=1; + //! set the DMA for read transfer + flpydsk_dma_write (); + + //flpydsk_drive_data (13, 1, 0xf, 0); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"writing head/track/sector"); + + uint32_t st0, cyl; + + //! write a sector + flpydsk_send_command ( + FDC_CMD_WRITE_SECT | FDC_CMD_EXT_MULTITRACK | + FDC_CMD_EXT_DENSITY); + flpydsk_send_command ( head << 2 | _CurrentDrive ); + flpydsk_send_command ( track); + flpydsk_send_command ( head); // first head should match with above! + flpydsk_send_command ( sector); + flpydsk_send_command ( FLPYDSK_SECTOR_DTL_512 ); + //flpydsk_send_command ( 1 ); // number of tracks we want + flpydsk_send_command ( FLPY_SECTORS_PER_TRACK ); // number of tracks ! + + /* + flpydsk_send_command ( + ( ( sector + 1 ) >= FLPY_SECTORS_PER_TRACK ) + ? FLPY_SECTORS_PER_TRACK : sector + 1 ); + */ + + flpydsk_send_command ( FLPYDSK_GAP3_LENGTH_3_5 ); + flpydsk_send_command ( 0xff ); + + //! wait for irq + flpydsk_wait_irq (); + + //! read status info + int j; + for (j=0; j<7; j++) + flpydsk_read_data (); + + //! let FDC know we handled interrupt + flpydsk_check_int (&st0,&cyl); +} +void flpydsk_read_sector_imp (uint8_t head, uint8_t track, uint8_t sector) { + + //sector=1; + //! set the DMA for read transfer + flpydsk_dma_read (); + + //flpydsk_drive_data (13, 1, 0xf, 0); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"reading head/track/sector"); + + uint32_t st0, cyl; + + //! read in a sector + flpydsk_send_command ( + FDC_CMD_READ_SECT | FDC_CMD_EXT_MULTITRACK | + FDC_CMD_EXT_SKIP | FDC_CMD_EXT_DENSITY); + flpydsk_send_command ( head << 2 | _CurrentDrive ); + flpydsk_send_command ( track); + flpydsk_send_command ( head); + flpydsk_send_command ( sector); + flpydsk_send_command ( FLPYDSK_SECTOR_DTL_512 ); + //flpydsk_send_command ( 1 ); // number of tracks we want + flpydsk_send_command ( FLPY_SECTORS_PER_TRACK ); // number of tracks ! + + /* + flpydsk_send_command ( + ( ( sector + 1 ) >= FLPY_SECTORS_PER_TRACK ) + ? FLPY_SECTORS_PER_TRACK : sector + 1 ); + */ + + + flpydsk_send_command ( FLPYDSK_GAP3_LENGTH_3_5 ); + flpydsk_send_command ( 0xff ); + + //! wait for irq + flpydsk_wait_irq (); + + //! read status info + int j; + for (j=0; j<7; j++) + flpydsk_read_data (); + + //! let FDC know we handled interrupt + flpydsk_check_int (&st0,&cyl); +} + +int flpydsk_seek ( uint32_t cyl, uint32_t head ) +{ + //cyl=1; + //head=1; + + uint32_t st0, cyl0; + + if (_CurrentDrive >= 4) + return -1; + + int i; + for (i = 0; i < 10; i++ ) { + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"seeking cyl: %d, head: %d",cyl,head); + + //! send the command + flpydsk_send_command (FDC_CMD_SEEK); + flpydsk_send_command ( (head << 2) | _CurrentDrive); + flpydsk_send_command (cyl); + + + //! wait for the results phase IRQ + flpydsk_wait_irq (); + flpydsk_check_int (&st0,&cyl0); + + //! found the cylinder? + if ( cyl0 == cyl) + return 0; + } + + return -1; +} + +void flpydsk_lba_to_chs (int lba,int *head,int *track,int *sector) { + + //cylinder + // +// *track = lba % ( FLPY_SECTORS_PER_TRACK * 2 ); + /// *head = ( lba % FLPY_SECTORS_PER_TRACK ) % 2;//* 2 ) ) / ( FLPY_SECTORS_PER_TRACK ); + //*sector = (lba % FLPY_SECTORS_PER_TRACK) +1; + + *head = ( lba % ( FLPY_SECTORS_PER_TRACK * 2 ) ) / ( FLPY_SECTORS_PER_TRACK ); + *track = lba / ( FLPY_SECTORS_PER_TRACK * 2 ); + *sector = lba % FLPY_SECTORS_PER_TRACK + 1; +} + + +uint8_t* flpydsk_read_sector (int sectorLBA) { + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"reading sector: %d",sectorLBA); + + + if (_CurrentDrive >= 4) + return 0; + + //! convert LBA sector to CHS + int head=0, track=0, sector=1; + flpydsk_lba_to_chs (sectorLBA, &head, &track, §or); + + + //! turn motor on and seek to track + // start motor + flpydsk_motor_on(); + + if (flpydsk_seek (track, head) != 0) + return 0; + + //! read sector and turn motor off + flpydsk_read_sector_imp (head, track, sector); + // flpydsk_control_motor (false); + flpydsk_motor_off(); + + + //! warning: this is a bit hackish + //return (uint8_t*) DMA_BUFFER; + return (uint8_t*) 0x0; +} + +uint8_t* flpydsk_write_sector (int sectorLBA) { + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"writing sector: %d",sectorLBA); + + if (_CurrentDrive >= 4) + return 0; + + //! convert LBA sector to CHS + int head=0, track=0, sector=1; + flpydsk_lba_to_chs (sectorLBA, &head, &track, §or); + + + //! turn motor on and seek to track + // start motor + flpydsk_motor_on(); + + if (flpydsk_seek (track, head) != 0) + return 0; + + //! read sector and turn motor off + flpydsk_write_sector_imp (head, track, sector); + // flpydsk_control_motor (false); + flpydsk_motor_off(); + + + //! warning: this is a bit hackish + //return (uint8_t*) DMA_BUFFER; + return (uint8_t*) 0x0; +} + +void floppy_init() +{ + // init dma + flpydsk_initialize_dma (); + + _CurrentDrive=0; + _FloppyDiskIRQ = 0; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"driver init (wathchdog: 0x%08X)",&_FloppyDiskIRQ); + + + flpydsk_reset (); + + char *dma=0x0500; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test reading"); + + flpydsk_read_sector(65); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"finished reading"); + + flpydsk_reset (); + + flpydsk_read_sector(64); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"finished reading"); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test read: %s",dma); + + flpydsk_reset (); + +// log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test write (sector: 100)"); +// flpydsk_write_sector(100); +// log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"finished writing"); + + +} + +#endif |
