OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 5:00 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: IRQ 6 (FDC) firing in initializ.. but not after read command
PostPosted: Tue Jun 26, 2018 6:15 am 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
I doubt that the problem is bad EOI because it has already fired two times before it did not.
No command neither in the initalization neither in the read command before did not report failure, e.g. (recalibrate, seek, specify, data rate, etc.)
... and right, Bochs does not emulate unreliability of the FDC.
Commands should fire an IRQ regardless if the configuration is bad or not, errors should be reported in the result bytes.

(I have attached the related code files. These attachments contain old possibly wrong DMA code, several replies down there is newer, updated code.)


Attachments:
File comment: FDC IRQ handler and IRQ "waiter".
fdcR.asm [440 Bytes]
Downloaded 17 times
File comment: DMA routines.
dma.c [2.37 KiB]
Downloaded 20 times
File comment: Main FDC code.
fdc.c [5.64 KiB]
Downloaded 23 times


Last edited by Ycep on Wed Jul 04, 2018 8:53 am, edited 2 times in total.
Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Tue Jun 26, 2018 8:17 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
I haven't waded through your code, but - you're not sending a sense_interrupt command after the read, are you?


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Wed Jun 27, 2018 5:22 am 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
iansjack wrote:
I haven't waded through your code, but - you're not sending a sense_interrupt command after the read, are you?

Shouldn't that be done after the IRQ and result bytes? I do, in that case.


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Wed Jun 27, 2018 5:27 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
https://wiki.osdev.org/Floppy_Disk_Cont ... _Interrupt


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Wed Jun 27, 2018 12:16 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
Several hours ago I found that there was a too early "break;" in a switch case statement which caused it to skip configuring the gap value.

But I still can't be sure is this really a problem in my floppy code as I have stack and global variables corruption in my kernel for some time.


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Tue Jul 03, 2018 1:55 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
And the problem still persists, even after stack does not corrupt anymore.

I do send a sense interrupt after every recalibrate and seek command (I'm not using PIO mode).
Can I read result bytes from a command even if the interrupt did not arrived?


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Tue Jul 03, 2018 6:31 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
How many times do you expect the interrupt to fire after a reset? Should be four times. Do you Sense Interrupt four times after the reset?

You can read the result bytes any time you want, ignoring the interrupt if you wish. However, if there are no result bytes to read, you can't read them. The FDC will tell you if there is a byte ready or not.

Ben


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Wed Jul 04, 2018 8:51 am 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
@BenLunt: Only one interrupt seems to fire, and of what I have seen in osDev wiki article for FDC it doesn't say that 4 interrupts need to be recieved, only one. (4 sense interrupts should)

Can bad DMA initialization cause the interrupt not to fire on read? I thought so and I have updated and fixed several mistakes in dma.c.
But it still doesn't fire. Maybe it's still wrong?

In case of that, I have posted new DMA code as an attachment.
And slightly updated FDC code for the new implemenation and with some error checking in it.


Attachments:
fdc.c [6.75 KiB]
Downloaded 13 times
File comment: Newer, fixed DMA code.
dma.c [2.64 KiB]
Downloaded 13 times
Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Wed Jul 04, 2018 2:12 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
What can/should I do other than "carefully" reading code and finding possible mistakes?


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Thu Jul 05, 2018 12:50 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
Hmmm... It seems that VirtualBox does fire an interrupt but it writes to 0x14A00 instead of 0x300000. So yes, this is a DMA problem! (But there is good news : it does read! Just writes onto wrong place!)


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Thu Jul 05, 2018 1:06 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
And now I have fixed another mistake:
Code:
inline void dmaMask(byte channel)
{
   if (channel > 3)
      outb(DMA_MASTER_CHMASK, (1 << (channel-4)));
   else
      outb(DMA_SLAVE_CHMASK, (1 << (channel)));
}
inline void dmaUnmask(byte channel)
{
   if (channel > 3)
      outb(DMA_MASTER_CHMASK, (1 << (channel-4)));
   else
      outb(DMA_SLAVE_CHMASK, (1 << (channel)));
}

From this very wrong code:
Code:
inline void dmaMask(byte channel)
{
   if (channel > 3)
      outb(DMA_MASTER_CHMASK, (1 << (channel)));
   else
      outb(DMA_SLAVE_CHMASK, (1 << (channel-4)));
}
inline void dmaUnmask(byte channel)
{
   if (channel > 3)
      outb(DMA_MASTER_CHMASK, channel);
   else
      outb(DMA_SLAVE_CHMASK, channel);
}

But now, VirtualBox doesn't fire interrupts neither.
(Update: _DMA_EXT_ADDR_REG was also wrong; But still no visible good results)


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Fri Jul 06, 2018 4:57 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
Now I tried updating the interrupt code by using increment on IRQ fire and decrement when IRQ is recieved, as Bochs does not emulate "slowness" of the floppy drive so the interrupts may be very quick...
But still no result.
The Wiki article states that 4 sense interrupts should be recieved only with polling mode. Though if I remove them from my code as I use DMA no interrupt fires after they were supposed to be recieved.
This is getting far too long for a fucking controller. Is the wiki article no FDC reliable enough? What could have I possibly do wrong?


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Sat Jul 07, 2018 3:59 pm 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
I looked at Bochs Source Code, and noticed that there were some BX_DEBUG() which seemed like they supposed to writed to console, but in my case they didn't. So I enabled these debug messages only for FDC and DMA (as it spams really much) and noticed that the Bochs set gap value as zero. Which was the correct behavior, I did not configured the gap value indeed in my code. Yet Bochs don't even read (or even set in BIOS calls), so that did not fixed the problem. I have posted the debug output of Bochs (And really nothing seems bad except the end)
Code:
03989229706d[FLOPPY] write access to port 0x03f2, value=0x00
03989229706d[FLOPPY] DMA and interrupt capabilities disabled
03989229706d[FLOPPY] io_write: digital output register
03989229706d[FLOPPY]   motor on, drive0 = 0
03989229706d[FLOPPY]   motor on, drive1 = 0
03989229706d[FLOPPY]   dma_and_interrupt_enable=00
03989229706d[FLOPPY]   normal_operation=00
03989229706d[FLOPPY]   drive_select=00
03989229717d[FLOPPY] write access to port 0x03f2, value=0x1c
03989229717d[FLOPPY] io_write: digital output register
03989229717d[FLOPPY]   motor on, drive0 = 1
03989229717d[FLOPPY]   motor on, drive1 = 0
03989229717d[FLOPPY]   dma_and_interrupt_enable=08
03989229717d[FLOPPY]   normal_operation=04
03989229717d[FLOPPY]   drive_select=00
03989230717i[FLOPPY] controller reset in software
03989230764d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989230803d[FLOPPY] write access to port 0x03f5, value=0x08
03989230803d[FLOPPY] command = 0x08
03989230803d[FLOPPY] COMMAND: [08]
03989230803d[FLOPPY] sense interrupt status
03989230803d[FLOPPY] RESULT: [c0] [00]
03989230823d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989230864d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0xc0
03989230896d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989230923d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x00
03989230968d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989230990d[FLOPPY] write access to port 0x03f5, value=0x08
03989230990d[FLOPPY] command = 0x08
03989230990d[FLOPPY] COMMAND: [08]
03989230990d[FLOPPY] sense interrupt status
03989230990d[FLOPPY] RESULT: [c1] [00]
03989231008d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989231049d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0xc1
03989231067d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989231108d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x00
03989231130d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989231180d[FLOPPY] write access to port 0x03f5, value=0x08
03989231180d[FLOPPY] command = 0x08
03989231180d[FLOPPY] COMMAND: [08]
03989231180d[FLOPPY] sense interrupt status
03989231180d[FLOPPY] RESULT: [c2] [00]
03989231200d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989231244d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0xc2
03989231257d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989231298d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x00
03989231348d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989231370d[FLOPPY] write access to port 0x03f5, value=0x08
03989231370d[FLOPPY] command = 0x08
03989231370d[FLOPPY] COMMAND: [08]
03989231370d[FLOPPY] sense interrupt status
03989231370d[FLOPPY] RESULT: [c3] [00]
03989231407d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989231429d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0xc3
03989231447d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989231488d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x00
03989231548d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989231570d[FLOPPY] write access to port 0x03f5, value=0x12
03989231570d[FLOPPY] command = 0x12
03989231611d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989231633d[FLOPPY] write access to port 0x03f5, value=0x00
03989231633d[FLOPPY] command = 0x00
03989231633d[FLOPPY] COMMAND: [12] [00]
03989231633i[FLOPPY] perpendicular mode: config=0x00
03989231684d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989231706d[FLOPPY] write access to port 0x03f5, value=0x07
03989231706d[FLOPPY] command = 0x07
03989231744d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989231766d[FLOPPY] write access to port 0x03f5, value=0x00
03989231766d[FLOPPY] command = 0x00
03989231766d[FLOPPY] COMMAND: [07] [00]
03989231766d[FLOPPY] floppy_command(): recalibrate drive 0
03989359794d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x81
03989359838d[FLOPPY] write access to port 0x03f5, value=0x08
03989359838d[FLOPPY] command = 0x08
03989359838d[FLOPPY] COMMAND: [08]
03989359838d[FLOPPY] sense interrupt status
03989359838d[FLOPPY] RESULT: [20] [00]
03989359856d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd1
03989359897d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x20
03989359915d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989359956d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x00
03989360013d[FLOPPY] write access to port 0x03f7, value=0x00
03989360013i[FLOPPY] io_write: config control register: 0x00
03989360013d[FLOPPY]   500 Kbps
03989364105d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989364147d[FLOPPY] write access to port 0x03f5, value=0x03
03989364147d[FLOPPY] command = 0x03
03989364169d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989364214d[FLOPPY] write access to port 0x03f5, value=0xa0
03989364214d[FLOPPY] command = 0xa0
03989364232d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989364279d[FLOPPY] write access to port 0x03f5, value=0x0e
03989364279d[FLOPPY] command = 0x0e
03989364279d[FLOPPY] COMMAND: [03] [a0] [0e]
03989364279d[FLOPPY] Specify (SRT     = 0x0a)
03989364279d[FLOPPY]         (HUT     = 0x00)
03989364279d[FLOPPY]         (HLT     = 0x07)
03989364279d[FLOPPY]         (Non-DMA =    0)
03989364297d[FLOPPY] read(): during command 0x00, port 0x03f2 returns 0x1c
03989364309d[FLOPPY] write access to port 0x03f2, value=0x1c
03989364309d[FLOPPY] io_write: digital output register
03989364309d[FLOPPY]   motor on, drive0 = 1
03989364309d[FLOPPY]   motor on, drive1 = 0
03989364309d[FLOPPY]   dma_and_interrupt_enable=08
03989364309d[FLOPPY]   normal_operation=04
03989364309d[FLOPPY]   drive_select=00
03989400632d[FLOPPY] write access to port 0x03f7, value=0x00
03989400632d[FLOPPY]   500 Kbps
03989404713d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989404755d[FLOPPY] write access to port 0x03f5, value=0x03
03989404755d[FLOPPY] command = 0x03
03989404773d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989404822d[FLOPPY] write access to port 0x03f5, value=0xa0
03989404822d[FLOPPY] command = 0xa0
03989404840d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989404887d[FLOPPY] write access to port 0x03f5, value=0x0e
03989404887d[FLOPPY] command = 0x0e
03989404887d[FLOPPY] COMMAND: [03] [a0] [0e]
03989404887d[FLOPPY] Specify (SRT     = 0x0a)
03989404887d[FLOPPY]         (HUT     = 0x00)
03989404887d[FLOPPY]         (HLT     = 0x07)
03989404887d[FLOPPY]         (Non-DMA =    0)
03989404905d[FLOPPY] read(): during command 0x00, port 0x03f2 returns 0x1c
03989404917d[FLOPPY] write access to port 0x03f2, value=0x1c
03989404917d[FLOPPY] io_write: digital output register
03989404917d[FLOPPY]   motor on, drive0 = 1
03989404917d[FLOPPY]   motor on, drive1 = 0
03989404917d[FLOPPY]   dma_and_interrupt_enable=08
03989404917d[FLOPPY]   normal_operation=04
03989404917d[FLOPPY]   drive_select=00
03989440063d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989440115d[FLOPPY] write access to port 0x03f5, value=0x0f
03989440115d[FLOPPY] command = 0x0f
03989440133d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989440179d[FLOPPY] write access to port 0x03f5, value=0x00
03989440179d[FLOPPY] command = 0x00
03989440197d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989440239d[FLOPPY] write access to port 0x03f5, value=0x00
03989440239d[FLOPPY] command = 0x00
03989440239d[FLOPPY] COMMAND: [0f] [00] [00]
03989464287d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x81
03989464309d[FLOPPY] write access to port 0x03f5, value=0x08
03989464309d[FLOPPY] command = 0x08
03989464309d[FLOPPY] COMMAND: [08]
03989464309d[FLOPPY] sense interrupt status
03989464309d[FLOPPY] RESULT: [20] [00]
03989464327d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd1
03989464368d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x20
03989464386d[FLOPPY] read(): during command 0x08, port 0x03f4 returns 0xd0
03989464427d[FLOPPY] read(): during command 0x08, port 0x03f5 returns 0x00
03989464477d[DMA   ] write: address=000d value=ff
03989464477d[DMA   ] DMA-1: master clear
03989464487d[DMA   ] write: address=00da value=ff
03989464487d[DMA   ] DMA-2: master clear
03989464511d[DMA   ] write: address=000a value=04
03989464511d[DMA   ] DMA-1: set_mask_bit=4, channel=0, mask now=01h
03989464539d[DMA   ] write: address=000c value=ff
03989464539d[DMA   ] DMA-1: clear flip/flop
03989464557d[DMA   ] write: address=0081 value=30
03989464557d[DMA   ] DMA-1: page register 2 = 30
03989464585e[DMA   ] io write to address 00000004, len=2
03989464596d[DMA   ] write: address=000c value=ff
03989464596d[DMA   ] DMA-1: clear flip/flop
03989464629e[DMA   ] io write to address 00000005, len=2
03989464664d[DMA   ] write: address=000a value=04
03989464664d[DMA   ] DMA-1: set_mask_bit=4, channel=0, mask now=01h
03989464689d[DMA   ] write: address=000b value=46
03989464689d[DMA   ] DMA-1: mode register[2] = 46
03989464714d[DMA   ] write: address=000a value=04
03989464714d[DMA   ] DMA-1: set_mask_bit=4, channel=0, mask now=01h
03989464739d[DMA   ] write: address=000a value=04
03989464739d[DMA   ] DMA-1: set_mask_bit=4, channel=0, mask now=01h
03989464765d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x80
03989464807d[FLOPPY] write access to port 0x03f5, value=0xe6
03989464807d[FLOPPY] command = 0xe6
03989464829d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989464875d[FLOPPY] write access to port 0x03f5, value=0x00
03989464875d[FLOPPY] command = 0x00
03989464893d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989464937d[FLOPPY] write access to port 0x03f5, value=0x00
03989464937d[FLOPPY] command = 0x00
03989464977d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989465002d[FLOPPY] write access to port 0x03f5, value=0x00
03989465002d[FLOPPY] command = 0x00
03989465039d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989465064d[FLOPPY] write access to port 0x03f5, value=0x01
03989465064d[FLOPPY] command = 0x01
03989465099d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989465127d[FLOPPY] write access to port 0x03f5, value=0x02
03989465127d[FLOPPY] command = 0x02
03989465162d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989465187d[FLOPPY] write access to port 0x03f5, value=0x12
03989465187d[FLOPPY] command = 0x12
03989465225d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989465253d[FLOPPY] write access to port 0x03f5, value=0x1b
03989465253d[FLOPPY] command = 0x1b
03989465285d[FLOPPY] read(): during command 0x00, port 0x03f4 returns 0x90
03989465313d[FLOPPY] write access to port 0x03f5, value=0xff
03989465313d[FLOPPY] command = 0xff
03989465313d[FLOPPY] COMMAND: [e6] [00] [00] [00] [01] [02] [12] [1b] [ff]
03989465313d[FLOPPY] read/write normal data
03989465313d[FLOPPY] BEFORE
03989465313d[FLOPPY]   drive    = 0
03989465313d[FLOPPY]   cylinder = 0
03989465313d[FLOPPY]   head     = 0
03989465313d[FLOPPY]   sector   = 1
03989465313d[FLOPPY]   eot      = 18
03989465313d[FLOPPY] floppy_xfer: drive=0, offset=0, bytes=512, direction=from floppy
04006560269d[FLOPPY] read(): during command 0xe6, port 0x03f4 returns 0x10
04006560309d[FLOPPY] read(): during command 0xe6, port 0x03f4 returns 0x10
04006560326d[FLOPPY] read(): during command 0xe6, port 0x03f4 returns 0x10
04006560350d[FLOPPY] read(): during command 0xe6, port 0x03f4 returns 0x10
... and the same line above repeated in ~2500 times

0x03F4 is the MSR, and 0x10 means BUSY. Which is OK, but it repeats way too many times.
Help?


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Sun Jul 08, 2018 9:05 am 
Offline
Member
Member
User avatar

Joined: Mon Dec 28, 2015 11:11 am
Posts: 401
It seems that MSR busy bit is clear before sending the command and while sending the command bytes it's set together with RQM (of course), but after sending all command bytes it doesn't stop being busy, like the command is still operating. And the RQM and DIO are clear too.

I don't use this thread as a personal log. I'll just ask, is this simply non-fuc.k give-ance or nobody can't see what's wrong? I'm sick of this bullshit. I didn't done really anything to my operating system for a week already, I can't progress.


Top
 Profile  
 
 Post subject: Re: IRQ 6 (FDC) firing in initializ.. but not after read com
PostPosted: Sun Jul 08, 2018 2:19 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
I know your frustration. I have been there, done that.

Okay, so first things first.

First check to see that there is actually a controller at that address.
Code:
   if (inpb(fdc->base+FDC_MSR) == 0xFF)

If that read returns 0xFF, you don't have a controller.

Next, reset the controller:
Code:
    outpb(fdc->base+FDC_DOR, 0x00);   // reset
    outpb(fdc->base+FDC_DOR, 0x00);   // twice

You should send it twice. The reset should be no less than 500ns. As Brendan mentioned in another thread, an I/O from an ISA bus can take as long as 500ns to even more time, so writing it twice will ensure it is long enough.

Next, clear the reset.
Code:
outpb(fdc->base+FDC_DOR, 0x04);   // normal operation

Next, wait for the controller to be ready. Poll the MSR register from within a loop.
Code:
      if (inpb(fdc->base+FDC_MSR) == 0x80)

If bit 7 doesn't ever become set, you don't have a valid controller.

Ignoring that we haven't done a Sense Interrupt for the reset yet, this is were we can assume we have a valid FDC at this Port I/O address and can now detect the type of controller. i.e.: See what type of controller it is to see if it supports the DUMP command, etc. (left up to the reader to implement)

Now, let's do the reset/initialize sequence:
Code:
  // reset the controller
  outpb(fdc->base+FDC_DOR, 0x00);   // reset
  udelay(100);                      // hold for 100 uS (unknown the amount of time we need to be in reset. (500ns on a 82078))
  outpb(fdc->base+FDC_DOR, 0x0C);   // release
  mdelay(20);                       // wait 20 mS for controller to be ready (unknown the time we need to wait)

We know that we have to wait at least 500ns, but some controllers have been known to need more. I have found that 100uS is more than enough. After we release the reset, waiting 20 mS should be enough.

Now wait for the interrupt and then send the Sense Interrupt command receiving two bytes of response per command. If you do not receive two bytes in a fair amount of time, or the first byte does not show the drive number in the lower two bits *and* the second byte is not zero, you should assume that the controller is in error.

If this doesn't work, you can try again a number of times, but after two times, assume you have a faulting controller or drive(s).

Once you have successfully received all four command returns, send the specify command.
Code:
  // Specify command
  buf[0] = FDC_CMD_SPECIFY;
  buf[1] = 0xBB; // until we know what disk is in the drive, just use BBh
  buf[2] = 0x04;
  fdc_command(fdc, buf, 3);

You don't know what kind of disk is inserted, if any, so just send 0xBB.

If that does not fail, you have a valid controller. You can now assume all is well.

At this point, if you found an enhanced controller, done above while determining if the DUMP command is supported, you can configure the controller for implied_seek and disable_polling.
Code:
  // Try the configure command.
  if (write_fdc(fdc, FDC_CMD_CONFIGURE) && fdc_want_more(fdc)) {
    write_fdc(fdc, 0);
    write_fdc(fdc, (flags & ~0x0F) | ((fifo_size - 1) & 0x0F));
    write_fdc(fdc, 0); // pre-compensation from track 0 upwards
    return TRUE;
  }

The fdc_want_more() simply checks to see if the command is expecting parameters, i.e.: waiting for the "ready" bit to be set (MSR 7:6 = 10b).

Now, to read from the disk:
If the controller is not an enhanced controller, you can only read from one track at a time. i.e.: you can only read a count of sectors up to the end of the track. You must specify a new command to move to the next track. If the controller *is* an enhanced controller, you may read up to a cylinder of tracks at a time, ending at the last sector of the last track. i.e.: Some controllers will not increment the track field on the read. Some will, some will not. (I will have to verify that from my notes, but from the top of my head, I think that is correct).

Now for a few notes:
1) You ensure that the disk is turning before you read from it, yes?
2) You ensure that the disk has been turning for at least 2 seconds before you attempt to read from it, yes?
3) Do you send the Specify Command before the transfer? You now should have detected the type of disk in the drive and retrieved the step rate, head settle and unload times.
4) If not an enhanced controller, you must send the Seek command. The 82077AA wants a ReadID command after a seek to verify that you really are at that cylinder.
5) If a double density disk, you need to set the MFM bit on the transfer.
6) If an enhanced controller, you need to set the MT bit on the transfer.
7) If a read command, you need to set the SKIP bit.
8) You should wait no more than 1000mS per sector per read/write for the interrupt to fire. If the interrupt hasn't happened in (sectors * 1000ms), it was not successful.

Hope this helps,
Ben
- http://www.fysnet.net/media_storage_devices.htm


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 80 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group