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]);
}
--