diff options
| author | Michal Idziorek <m.i@gmx.at> | 2014-11-26 12:48:43 +0100 |
|---|---|---|
| committer | Michal Idziorek <m.i@gmx.at> | 2014-11-26 12:48:43 +0100 |
| commit | 786bd02b01d80e335d4445698d721213a1884ff5 (patch) | |
| tree | f10b97cca2e03c279cd5884919c23de03d3e7223 /kernel/floppy.c | |
| parent | aad4bfe0261ea623342adc392728281be5062967 (diff) | |
some cleanup
Diffstat (limited to 'kernel/floppy.c')
| -rw-r--r-- | kernel/floppy.c | 575 |
1 files changed, 0 insertions, 575 deletions
diff --git a/kernel/floppy.c b/kernel/floppy.c deleted file mode 100644 index 1dbe137..0000000 --- a/kernel/floppy.c +++ /dev/null @@ -1,575 +0,0 @@ - -/* - * 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 |
