This message is from the T13 list server.

On 07 Feb 2004 13:51:35 -0700
Pat LaVarre <[EMAIL PROTECTED]> wrote:
> 
> 
> Good fun, thanks for sharing, sorry I have no immediate full answer.
> 
> Mostly I do not see you deciding port x3F6 DeviceControl, so I wonder
> what's there, especially nIEN.
Is it required ? Can't we manage with 1f7 ?
 
> >    Why isn't the DRQ is not being set to 1 ? 
> 
> Me, I'd start by trying to make op xEC or xA1 Identify work, rather
> than x20 Read, so you could show us those results for context, e.g.
> what to expect from ATAPI differs from what to expect from ATA.
I have added the modified code below. On xEC identify it gives me 0x50
which means work done.
 
> Also I'd like to see you touch the INTRQ ports - I forget if they are
> x20/21 or xA0/A1 or exactly what - so we can see you clear your own
> INTRQ.  That exercise you can go thru with x00 Nop, no DRQ involved.

Can you tell me more about this , if not in this forum atleast in a
mail ?

> 
> >         printf("%x", inb(0x1f7));
> >         /* Prints 0x50 . So the below loops forever.
> >          */
> 
> x50 says complete.
> 
> How have you ensured, for example, that no interrupt-driven BIOS is
> acking the INTRQ you generate?

I am not sure. How do i find out whether other interrupt drive BIOS is
acking the INTRQ ? I am not sure but if that was the case
then 0x50 shouldn't be returned( which means command successfully
completed).
> 
> >         while ((inb(0x1f7) & 0x80) == 0x80
> >                || (inb(0x1f7) & 0x08) != 0x08) ;
> 
> Polling x1F7 Status rather than x3F6 Alternate Status is arguably
> rude, but should work, aye.

Should i change it to x3f6 but how is it going to affect finally ?

Here is modified code.
/* gcc x86 asm */
static inline void insw(unsigned short port, unsigned char *addr,
                        unsigned long count)
{
    __asm__ __volatile__("rep; ins" "w":"=D"(addr),
                         "=c"(count):"d"(port), "0"(addr), "1"(count));
}

void hd_init(void)
{
    unsigned char *p, c[512], *e;
    unsigned int i = 10000;
    e = c;

    /* while loop_1 */
    /* wait until BSY satus register is cleared.
     */
    while ((inb(0x1f7) & 0x80) == 0x80);
    /* Master drive/head */
    outb(0x1f6, 0xa0);

    /* Identify drive */
    outb(0x1f7, 0xec);


    printf("***%x***\n", inb(0x1f7));
    /* The above line returns 0x50.Am i
     * correct ?
     */

    while ((inb(0x1f7) & 0x80) == 0x80);

    printf("HERE 1\n");
    /* HERE 1 is printed .Works fine */
    
    /* register sector count 1 sector */
    outb(0x1f2, 0x01);

    /* register sector number changed to 1st sector */
    outb(0x1f3, 0x01);

    /* register cylinder LSB 8bits */
    outb(0x1f4, 0x00);

    /* register cylinder MSB 2bits */
    outb(0x1f5, 0x00);

    /* register drive/head drive=0 head=0 LBA enabled */
    outb(0x1f6, 0xe0);

    /* Read command without ECC .
     * Only sector data is read and automatic command retry is executed.
     * Changed to 23 but still doesn't work
     */
    outb(0x1f7, 0x20);

    /* Check the value of status register */
    printf("%x#1\n", inb(0x1f7));

    /* while loop_2 */
    /* The below line waits until BSY in status register is cleared */

    while ((inb(0x1f7) & 0x80) == 0x80);

    printf("%x#2\n", inb(0x1f7));
    /* prints 0x50 . BSY not set.Good */

    /* do nothing for a while.Waiting for the status register to
change.*/         for (i = 0; i < 10000; i++)
        __asm__ __volatile__("nop");

    printf("%x#3\n", inb(0x1f7));
    /* Still 0x50. DRQ is not set */

    /* The above is returning 0x50 which means the below while loop_3
doesn't exit . Any techniques for breaking the while loop.
     */

    /* while loop_3 */
    while ((inb(0x1f7) & 0x08) != 0x08);

    /* Doesn't break out of this loop. Something wrong here.
     * But as per the hardware spec this is what is expected.
     * Corrections to be made in this loop.
     */
    printf("HERE 2\n");
    insw(0x1f0, e, 256);

    printf("%x %x #####\n", c[0], e[0]);
}


-- 

Reply via email to