Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <hal.h>
- #include <mmngr_phys.h>
- #include <DebugDisplay.h>
- #include "flpydsk.h"
- #include <kybrd.h>
- //*************************************************************************
- // Definitions
- //*************************************************************************
- //=========================================================================
- // Enumerations
- //=========================================================================
- /*
- * Controller I/O Ports. Please see chapter for additional ports
- */
- enum FLPYDSK_IO {
- FLPYDSK_DOR = 0x3f2,
- FLPYDSK_MSR = 0x3f4,
- FLPYDSK_FIFO = 0x3f5,
- FLPYDSK_CTRL = 0x3f7
- };
- /*
- * Bits 0-4 of command byte. Please see chapter for additional commands
- */
- 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_FORMAT_TRACK= 0xd,
- FDC_CMD_SEEK = 0xf
- };
- /*
- * Additional command masks. Can be masked with above commands
- */
- enum FLPYDSK_CMD_EXT {
- FDC_CMD_EXT_SKIP = 0x20, //00100000
- FDC_CMD_EXT_DENSITY = 0x40, //01000000
- FDC_CMD_EXT_MULTITRACK = 0x80 //10000000
- };
- /*
- * Digital Output Register
- */
- 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
- };
- /*
- * Main Status Register
- */
- 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
- };
- /*
- * Controller Status Port 0
- */
- enum FLPYDSK_ST0_MASK {
- FLPYDSK_ST0_MASK_DRIVE0 = 0, //00000000 = for completness sake
- FLPYDSK_ST0_MASK_DRIVE1 = 1, //00000001
- FLPYDSK_ST0_MASK_DRIVE2 = 2, //00000010
- FLPYDSK_ST0_MASK_DRIVE3 = 3, //00000011
- FLPYDSK_ST0_MASK_HEADACTIVE = 4, //00000100
- FLPYDSK_ST0_MASK_NOTREADY = 8, //00001000
- FLPYDSK_ST0_MASK_UNITCHECK = 16, //00010000
- FLPYDSK_ST0_MASK_SEEKEND = 32, //00100000
- FLPYDSK_ST0_MASK_INTCODE = 64 //11000000
- };
- /*
- * LPYDSK_ST0_MASK_INTCODE types
- */
- enum FLPYDSK_ST0_INTCODE_TYP {
- FLPYDSK_ST0_TYP_NORMAL = 0,
- FLPYDSK_ST0_TYP_ABNORMAL_ERR= 1,
- FLPYDSK_ST0_TYP_INVALID_ERR = 2,
- FLPYDSK_ST0_TYP_NOTREADY = 3
- };
- /*
- * GAP 3 sizes
- */
- enum FLPYDSK_GAP3_LENGTH {
- FLPYDSK_GAP3_LENGTH_STD = 42,
- FLPYDSK_GAP3_LENGTH_5_14= 32,
- FLPYDSK_GAP3_LENGTH_3_5= 27
- };
- /*
- * Formula: 2^sector_number * 128, where ^ denotes "to the power of"
- */
- enum FLPYDSK_SECTOR_DTL {
- FLPYDSK_SECTOR_DTL_128 = 0,
- FLPYDSK_SECTOR_DTL_256 = 1,
- FLPYDSK_SECTOR_DTL_512 = 2,
- FLPYDSK_SECTOR_DTL_1024 = 4
- };
- KEYCODE getch2 () {
- KEYCODE key = KEY_UNKNOWN;
- //! wait for a keypress
- while (key==KEY_UNKNOWN)
- key = kkybrd_get_last_key ();
- //! discard last keypress (we handled it) and return
- kkybrd_discard_last_key ();
- return key;
- }
- //=========================================================================
- // Constants
- //=========================================================================
- //! floppy irq
- const int FLOPPY_IRQ = 6;
- //! sectors per track
- const int FLPY_SECTORS_PER_TRACK = 18;
- //! DMA tranfer buffer starts here and ends at 0x1000+64k
- //! this must be below 16MB and in idenitity mapped memory
- int DMA_BUFFER = 0x1000; // 0x1000
- //! FDC uses DMA channel 2
- const int FDC_DMA_CHANNEL = 2;
- //=========================================================================
- // Private Data
- //=========================================================================
- //! Working Drive - Default: 0
- static uint8_t _CurrentDrive = 0;
- //! Set when IRQ fires
- static volatile uint8_t _FloppyDiskIRQ = 0;
- //=========================================================================
- // External References
- //=========================================================================
- //! Sleep Function (in milliseconds)
- extern void sleep (int);
- //=========================================================================
- // Private Functions
- //=========================================================================
- /*
- * DMA Routines.
- */
- bool _cdecl dma_initialise_floppy(uint8_t* buffer, unsigned length){
- DebugPrintf("Debug : DMA intlizing\n");
- getch2();
- union{
- uint8_t byte[4];//Lo[0], Mid[1], Hi[2]
- unsigned long l;
- }a, c;
- a.l=(unsigned)buffer;
- c.l=(unsigned)length-1;
- DebugPrintf("Debug : Strt lil\n");
- getch2();
- //Check for buffer issues
- if ((a.l >> 24) || (c.l >> 16) || (((a.l & 0xffff)+c.l) >> 16)){
- #ifdef _DEBUG
- _asm{
- mov eax, 0x1337
- cli
- hlt
- }
- #endif
- DebugPrintf("\n\n\nDMA ERROR\n");
- return false;
- }
- DebugPrintf("Debug : Tsk lil ok\n");
- getch2();
- dma_reset (1);
- DebugPrintf("Debug : Strt Dma Reset\n");
- getch2();
- dma_mask_channel( FDC_DMA_CHANNEL );
- DebugPrintf("Debug : Mask channel 2 \n");
- getch2();
- dma_reset_flipflop ( 1 );//Flipflop reset on DMA 1
- DebugPrintf("Debug : Flip flop 1\n");
- getch2();
- dma_set_address( FDC_DMA_CHANNEL, a.byte[0],a.byte[1]);//Buffer address
- DebugPrintf("Debug : Buffer address\n");
- getch2();
- dma_reset_flipflop( 1 );//Flipflop reset on DMA 1
- DebugPrintf("Debug : Flip Flop 1 ag\n");
- getch2();
- dma_set_count( FDC_DMA_CHANNEL, c.byte[0],c.byte[1]);//Set count
- DebugPrintf("Debug : Set count\n");
- getch2();
- dma_set_read ( FDC_DMA_CHANNEL );
- DebugPrintf("Debug : Set read\n");
- getch2();
- dma_unmask_all( 1 );//Unmask channel 2
- DebugPrintf("Debug : un mask\n");
- getch2();
- return true;
- }
- /*
- * Basic Controller I/O Routines
- */
- //! return fdc status
- uint8_t flpydsk_read_status () {
- //! just return main status register
- return inportb (FLPYDSK_MSR);
- }
- //! write to the fdc dor
- void flpydsk_write_dor (uint8_t val ) {
- //! write the digital output register
- outportb (FLPYDSK_DOR, val);
- }
- //! send command byte to fdc
- void flpydsk_send_command (uint8_t cmd) {
- //! wait until data register is ready. We send commands to the data register
- for (int i = 0; i < 500; i++ )
- if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG )
- return outportb (FLPYDSK_FIFO, cmd);
- }
- //! get data from fdc
- uint8_t flpydsk_read_data () {
- //! same as above function but returns data register for reading
- for (int i = 0; i < 500; i++ )
- if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG )
- return inportb (FLPYDSK_FIFO);
- return 0;
- }
- //! write to the configuation control register
- void flpydsk_write_ccr (uint8_t val) {
- //! write the configuation control
- outportb (FLPYDSK_CTRL, val);
- }
- /*
- * Interrupt Handling Routines
- */
- //! wait for irq to fire
- inline void flpydsk_wait_irq () {
- //! wait for irq to fire
- while (_FloppyDiskIRQ==0)
- ;
- _FloppyDiskIRQ = 0;
- }
- //! floppy disk irq handler
- void _cdecl i86_flpy_irq () {
- _asm add esp, 12
- _asm pushad
- _asm cli
- //! irq fired
- _FloppyDiskIRQ = 1;
- //DebugPrintf("Interrupt");
- //! tell hal we are done
- interruptdone( FLOPPY_IRQ );
- _asm sti
- _asm popad
- _asm iretd
- }
- /*
- * Controller Command Routines
- */
- //! check interrupt status command
- 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 ();
- }
- //! turns the current floppy drives motor on/off
- void flpydsk_control_motor (bool b) {
- //! sanity check: invalid drive
- if (_CurrentDrive > 3)
- return;
- uint8_t motor = 0;
- //! select the correct mask based on current drive
- switch (_CurrentDrive) {
- case 0:
- motor = FLPYDSK_DOR_MASK_DRIVE0_MOTOR;
- break;
- case 1:
- motor = FLPYDSK_DOR_MASK_DRIVE1_MOTOR;
- break;
- case 2:
- motor = FLPYDSK_DOR_MASK_DRIVE2_MOTOR;
- break;
- case 3:
- motor = FLPYDSK_DOR_MASK_DRIVE3_MOTOR;
- break;
- }
- //! turn on or off the motor of that drive
- if (b)
- flpydsk_write_dor (uint8_t(_CurrentDrive | motor | FLPYDSK_DOR_MASK_RESET | FLPYDSK_DOR_MASK_DMA));
- else
- flpydsk_write_dor (FLPYDSK_DOR_MASK_RESET);
- //! in all cases; wait a little bit for the motor to spin up/turn off
- sleep (20);
- }
- //! configure drive
- void flpydsk_drive_data (uint8_t stepr, uint8_t loadt, uint8_t unloadt, bool dma ) {
- uint8_t data = 0;
- //! send command
- flpydsk_send_command (FDC_CMD_SPECIFY);
- data = ( (stepr & 0xf) << 4) | (unloadt & 0xf);
- flpydsk_send_command (data);
- data = (( loadt << 1 ) | ( (dma) ? 0 : 1 ) );
- flpydsk_send_command (data);
- }
- //! calibrates the drive
- int flpydsk_calibrate (uint8_t drive) {
- uint32_t st0, cyl;
- if (drive >= 4)
- return -2;
- //! turn on the motor
- flpydsk_control_motor (true);
- for (int i = 0; i < 10; i++) {
- //! 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) {
- flpydsk_control_motor (false);
- return 0;
- }
- }
- flpydsk_control_motor (false);
- return -1;
- }
- //! disable controller
- void flpydsk_disable_controller () {
- flpydsk_write_dor (0);
- }
- //! enable controller
- void flpydsk_enable_controller () {
- flpydsk_write_dor ( FLPYDSK_DOR_MASK_RESET | FLPYDSK_DOR_MASK_DMA);
- }
- //! reset controller
- void flpydsk_reset () {
- uint32_t st0, cyl;
- //! reset the controller
- flpydsk_disable_controller ();
- flpydsk_enable_controller ();
- flpydsk_wait_irq ();
- //! send CHECK_INT/SENSE INTERRUPT command to all drives
- for (int 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,true);
- //! calibrate the disk
- flpydsk_calibrate ( _CurrentDrive );
- }
- //! read a sector
- void flpydsk_read_sector_imp (uint8_t head, uint8_t track, uint8_t sector) {
- DebugPrintf("Debug : Strt IMP\n");
- getch2();
- uint32_t st0, cyl;
- //! initialise DMA
- DebugPrintf("Debug : intl dma\n");
- getch2();
- if (!dma_initialise_floppy ((uint8_t*) DMA_BUFFER, 512 ))
- {
- DebugPrintf("\n\nDMA BUFFER ERROR");
- return;
- }
- DebugPrintf("Debug : Dma complete \n");
- getch2();
- //! set the DMA for read transfer
- dma_set_read ( FDC_DMA_CHANNEL );
- DebugPrintf("Debug : Read 2\n");
- getch2();
- //_FloppyDiskIRQ = 0; ///////////////////////////
- _asm sti // Make sure we have interrupts.
- DebugPrintf("Debug : STi complete\n");
- getch2();
- //! read in a sector
- flpydsk_send_command ( FDC_CMD_READ_SECT | FDC_CMD_EXT_MULTITRACK | FDC_CMD_EXT_SKIP | FDC_CMD_EXT_DENSITY );
- DebugPrintf("Debug : CMD 1\n");
- getch2();
- flpydsk_send_command ( head << 2 | _CurrentDrive );
- DebugPrintf("Debug : CMD 2\n");
- getch2();
- flpydsk_send_command ( track );
- DebugPrintf("Debug : CMD 3\n");
- getch2();
- flpydsk_send_command ( head );
- DebugPrintf("Debug : CMD 4\n");
- getch2();
- flpydsk_send_command ( sector );
- DebugPrintf("Debug : CMD 5\n");
- getch2();
- flpydsk_send_command ( FLPYDSK_SECTOR_DTL_512 );
- DebugPrintf("Debug : CMD 6\n");
- getch2();
- flpydsk_send_command ( ( ( sector + 1 ) >= FLPY_SECTORS_PER_TRACK ) ? FLPY_SECTORS_PER_TRACK : sector + 1 );
- DebugPrintf("Debug : CMD 7\n");
- getch2();
- flpydsk_send_command ( FLPYDSK_GAP3_LENGTH_3_5 );
- DebugPrintf("Debug : CMD 8\n");
- getch2();
- flpydsk_send_command ( 0xFF );
- DebugPrintf("Debug : CMD 9\n");
- getch2();
- //! wait for irq
- //flpydsk_wait_irq ();
- DebugPrintf("Debug :The stopped IRQ \n");
- getch2();
- //! read status info
- for (int j = 0; j < 7; j++)
- flpydsk_read_data ();
- DebugPrintf("Debug : State\n");
- getch2();
- //! let FDC know we handled interrupt
- flpydsk_check_int (&st0, &cyl);
- DebugPrintf("Debug :INT\n");
- getch2();
- }
- //! seek to given track/cylinder
- int flpydsk_seek ( uint8_t cyl, uint8_t head ) {
- uint32_t st0, cyl0;
- DebugPrintf("Debug : Seeking\n");
- getch2();
- if (_CurrentDrive >= 4)
- return -1;
- for (int i = 0; i < 10; i++ ) {
- //! send the command
- flpydsk_send_command (FDC_CMD_SEEK);
- DebugPrintf("Debug :seek CMD 1\n");
- getch2();
- flpydsk_send_command ( (head) << 2 | _CurrentDrive);
- DebugPrintf("Debug :seek CMD 2\n");
- getch2();
- flpydsk_send_command (cyl);
- DebugPrintf("Debug :seek CMD 3\n");
- getch2();
- //! wait for the results phase IRQ
- flpydsk_wait_irq ();
- DebugPrintf("Debug :seek irq\n");
- getch2();
- flpydsk_check_int (&st0,&cyl0);
- DebugPrintf("Debug :check seek\n");
- getch2();
- //! found the cylinder?
- if ( cyl0 == cyl)
- DebugPrintf("Debug : fnd cyl\n");
- getch2();
- return 0;
- }
- DebugPrintf("Debug : Err cyl\n");
- getch2();
- return -1;
- }
- //! sets DMA base address
- void flpydsk_set_dma (int addr) {
- DMA_BUFFER = addr;
- }
- //=========================================================================
- // INTERFACE FUNCTIONS
- //=========================================================================
- //! convert LBA to CHS
- void flpydsk_lba_to_chs (int lba,int *head,int *track,int *sector) {
- *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;
- }
- extern void *memset (void*, char, size_t); // Get memset from string.h
- //! install floppy driver
- void flpydsk_install (int irq) {
- //! allocate the DMA buffer
- //DMA_BUFFER = (int) flt_pmmngr_alloc_blocks (16);
- //! clear the DMA buffer
- //memset ((void*) DMA_BUFFER, 0xFF, 16*0x1000);
- //! install irq handler
- setvect (irq, i86_flpy_irq);
- //! reset the fdc
- flpydsk_reset ();
- //! set drive information
- flpydsk_drive_data (13, 1, 0xf, true);
- }
- //! set current working drive
- void flpydsk_set_working_drive (uint8_t drive) {
- if (drive < 4)
- _CurrentDrive = drive;
- }
- //! get current working drive
- uint8_t flpydsk_get_working_drive () {
- return _CurrentDrive;
- }
- //! read a sector
- uint8_t* flpydsk_read_sector (int sectorLBA) {
- DebugPrintf("Debug : Start counting\n");
- getch2();
- if (_CurrentDrive >= 4) {
- DebugPrintf("\nFLPY: ERROR1\n");
- return 0;}
- DebugPrintf("Debug : Completed The last task\n");
- getch2();
- //! convert LBA sector to CHS
- DebugPrintf("Debug : Start Converting\n");
- getch2();
- int head=0, track=0, sector=1;
- flpydsk_lba_to_chs (sectorLBA, &head, &track, §or);
- DebugPrintf("Debug : Tsk completed with code - \n");
- DebugPrintf("Debug -----------[%i]--------, head);
- DebugPrintf("Debug -----------[%i]--------, track);
- DebugPrintf("Debug -----------[%i]--------, sector);
- DebugPrintf("\n");
- getch2();
- //! turn motor on and seek to track
- flpydsk_control_motor (true);
- DebugPrintf("Debug : Seeking\n");
- getch2();
- if (flpydsk_seek ((uint8_t)track, (uint8_t)head) != 0) {
- DebugPrintf("\nFLPY: ERROR2\n");
- return 0;}
- DebugPrintf("Debug : Cmd seek ok \n");
- getch2();
- //! read sector and turn motor off
- flpydsk_read_sector_imp ((uint8_t)head, (uint8_t)track, (uint8_t)sector);
- DebugPrintf("Debug : Read sec cpm\n");
- getch2();
- flpydsk_control_motor (false);
- DebugPrintf("Debug : Motor off\n");
- getch2();
- return (uint8_t*) DMA_BUFFER;
- DebugPrintf("Debug : Buffer returned \n");
- getch2();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement