[Kos-dev] ATA & LBA : new experimentations

kos-dev@enix.org kos-dev@enix.org
12 Feb 2002 12:04:06 +0100


--=-=-=

Hi,

I made some experimentations about my problem concerning the use of
LBA.

First experimentation :
-----------------------
Instead of reading sector 0, and then reading sector 64, I did the
following :
 * read sector 0
 * identify drive (to make sure there is something else in the
controller buffer)
 * read sector 64

But read sector 64 still returned the contents of sector 0.

Second experimentation :
------------------------

I tested if the Error bit was set BEFORE sending the command, and it
was set. So I added a software reset BEFORE sending the command. I
don't know why exactly I need to reset the device, but it works much
more better now.

Then, AFTER sending the command (for a LBA read, for any sector,
including sector 0), the Error bit is set, and the Error register is
set to 0x10, which means IDNF : Requested Sector ID Not Found.

That's strange because I have
 sector = 0;
 cyl_lo = 0;
 cyl_hi = 0;
 drive_head = 0xA0     | 0x40 | 0      | 0
              SETBITS    LBA    HEAD 0   MASTER

And it returns an error.

Do you have any idea ?

Note that on an other computer, without doing the reset BEFORE sending
the command, it perfectly works.

Thanks a lot,

Thomas

(code included interesting function is still add_ide_op_polled_mode,
and get_partition_table to see the tests I make)
--=-=-=
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=_ide.c

/* ATA driver for KOS
   by Thomas Petazzoni, <thomas.petazzoni@enix.org>
   with the help of Soren Schmidt, <sos@freebsd.dk>
*/

#include <kos/asm.h>
#include <lib/stdio.h>
#include <scheduler/scheduler.h>
#include <idt/irq.h>
#include <ide/_ide.h>
#include <liblist/liblist.h>
#include <kos/spinlock.h>
#include <lib/string.h>
#include <kmem/kmem.h>

typedef struct ide_op
{
  enum { READ, WRITE } type;
  enum { IDE_OP_WAITING, IDE_OP_IN_PROGRESS } status;
  harddisk_t *harddisk;
  int cyl;
  int sector;
  int head;
  char *buffer;
  struct ide_op *next, *prev;
} ide_op_t;

ide_op_t *ide_op_list;

controller_t controllers[NB_CONTROLLERS] =
{
  { 0x1F0, 14, ATA_NOT_PRESENT, PRIMARY_CONTROLLER, 0, { NULL, NULL }},
  { 0x170, 15, ATA_NOT_PRESENT, SECONDARY_CONTROLLER, 0, { NULL, NULL }}
};

static int init_ide(controller_t *ctrl)
{
  int status0, status1;
  int mask = 0;
  int timeout;

  outb(ATA_D_IBM | ATA_MASTER, ctrl->ioaddr + ATA_DRIVE);
  usleep(1);
  status0 = inb(ctrl->ioaddr + ATA_STATUS);

  outb(ATA_D_IBM | ATA_SLAVE, ctrl->ioaddr + ATA_DRIVE);
  usleep(1);
  status1 = inb(ctrl->ioaddr + ATA_STATUS);
  
  if((status0 & 0xf8) != 0xf8)
    mask |= 0x01;
  if((status1 & 0xf8) != 0xf8)
    mask |= 0x02;

  /* If both BSY bit are set => leave */
  if((status0 & ATA_S_BSY) && (status1 & ATA_S_BSY))
    return 0;

  /* no device present */
  if(!mask)
    return 0;
  
  /* select the master */
  outb(ATA_D_IBM | ATA_MASTER, ctrl->ioaddr + ATA_DRIVE);
  usleep(1);
  /* send reset */
  outb(ATA_A_nIEN | ATA_A_RESET, ctrl->ioaddr + ATA_ALTPORT);
  usleep(1000);
  outb(ATA_A_nIEN, ctrl->ioaddr + ATA_ALTPORT);
  usleep(1000);
  inb(ctrl->ioaddr + ATA_ERROR);
  outb(ATA_A_4BIT, ctrl->ioaddr + ATA_ALTPORT);
  usleep(1);

  /* wait busy */
  for(timeout = 0; timeout < 300000; timeout++)
    {
      /* select master and get status register */
      outb(ATA_D_IBM | ATA_MASTER, ctrl->ioaddr + ATA_DRIVE);
      usleep(1);
      status0 = inb(ctrl->ioaddr + ATA_STATUS);
      
      /* select slave and get status register */
      outb(ATA_D_IBM | ATA_SLAVE, ctrl->ioaddr + ATA_DRIVE);
      usleep(1);
      status1 = inb(ctrl->ioaddr + ATA_STATUS);

      if(mask == 0x01)
	if(!(status0 & ATA_S_BSY))
	  break;
      if(mask == 0x02)
	if(!(status1 & ATA_S_BSY))
	  break;
      if(mask == 0x03)
	if(!(status0 & ATA_S_BSY) && !(status1 & ATA_S_BSY))
	  break;
      usleep(100);
    }

  if(status0 & ATA_S_BSY)
    mask &= ~0x01;
  if(status1 & ATA_S_BSY)
    mask &= ~0x02;
  
  /* no device */
  if(!mask)
    return 0;

  /* there's at least one device, initialize state */
  ctrl->state = ATA_IDLE;

  /* check what is the type of the device */
  outb(ATA_D_IBM | ATA_MASTER, ctrl->ioaddr + ATA_DRIVE);
  usleep(10);
  
  if(inb(ctrl->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
     inb(ctrl->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB)
    {
      ctrl->devices |= ATA_ATAPI_MASTER;
    }
  
  outb(ATA_D_IBM | ATA_SLAVE, ctrl->ioaddr + ATA_DRIVE);
  usleep(10);
  
  if(inb(ctrl->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
     inb(ctrl->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB)
    {
      ctrl->devices |= ATA_ATAPI_SLAVE;
    }

  if(status0 != 0x00 && !(ctrl->devices & ATA_ATAPI_MASTER))
    {
      outb(ATA_D_IBM | ATA_MASTER, ctrl->ioaddr + ATA_DRIVE);
      usleep(1);
      outb(0x58, ctrl->ioaddr + ATA_ERROR);
      outb(0xa5, ctrl->ioaddr + ATA_CYL_LSB);
      if(inb(ctrl->ioaddr + ATA_ERROR) != 0x58 &&
	 inb(ctrl->ioaddr + ATA_CYL_LSB) == 0xa5)
	{
	  ctrl->devices |= ATA_ATA_MASTER;
	}
    }
  
  if(status1 != 0x00 && !(ctrl->devices & ATA_ATAPI_SLAVE))
    {
      outb(ATA_D_IBM | ATA_SLAVE, ctrl->ioaddr + ATA_DRIVE);
      usleep(1);
      outb(0x58, ctrl->ioaddr + ATA_ERROR);
      outb(0xa5, ctrl->ioaddr + ATA_CYL_LSB);
      if(inb(ctrl->ioaddr + ATA_ERROR) != 0x58 &&
	 inb(ctrl->ioaddr + ATA_CYL_LSB) == 0xa5)
	{
	  ctrl->devices |= ATA_ATA_SLAVE;
	}
    }

  return 0;
}

static int convert_to_ascii(char *src, char *dst, int len)
{
  int i;
  
  for(i = 0; i < len; i=i+2)
    {
      dst[i] = (src[i+1] & 0xff);
      dst[i+1] = (src[i] & 0xff);
    }

  dst[len] = '\0';
  for(i = len; i > 0; i--)
    {
      if(dst[i] == 0)
	continue;
      else if(dst[i] == ' ')
	dst[i] = '\0';
      else
	break;
    }
  
  return 0;
}




/* Will be used for IRQ mode */
static int do_op_first_step(ide_op_t *op)
{
  controller_t *ctrl;

  ctrl = op->harddisk->ctrl;
  ctrl->state = ATA_WAIT_INTR;

  outb(ATA_A_4BIT, ctrl->ioaddr + ATA_ALTPORT);

  /* select drive */
  outb(ATA_D_IBM 
       | (op->harddisk->device == MASTER) ? ATA_MASTER : ATA_SLAVE
       | op->head, 
       ctrl->ioaddr + ATA_DRIVE);
  usleep(1);
  
  outb(1, ctrl->ioaddr + ATA_SECTOR_COUNT);
  outb(op->sector, ctrl->ioaddr + ATA_SECTOR_NUMBER);
  outb((op->cyl & 0xff), ctrl->ioaddr + ATA_CYL_LSB);
  outb(((op->cyl & 0xff00) >> 8), ctrl->ioaddr + ATA_CYL_MSB);

  /* FOR THE MOMENT WE DON'T CARE ABOUT THE OPERATION TYPE ... ALWAYS
     READ ... */
  op->status = IDE_OP_IN_PROGRESS;
  outb(ATA_C_READ, ctrl->ioaddr + ATA_CMD);

  return 0;
}

static int add_ide_op_with_irq(harddisk_t *harddisk, int type, int cyl, int head, int sector, char *buffer)
{
  ide_op_t *new;

  new = kmalloc(sizeof(ide_op_t));
  if(new == NULL)
    {
      printk("Memory allocation error\n");
      return -1;
    }

  if(type != READ && type != WRITE)
    return -1;

  new->status = IDE_OP_WAITING;
  new->harddisk = harddisk;
  new->cyl = cyl;
  new->sector = sector;
  new->head = head;
  new->buffer = buffer;
  new->type = type;
  
  list_add_tail(ide_op_list, new);
  
  if(harddisk->ctrl->state == ATA_IDLE)
    do_op_first_step(new);

  return 0;
}

int add_ide_op_polled_mode(harddisk_t *harddisk, 
			   int type, 
			   k_ui32_t sector_num,
			   k_ui16_t *buffer)
{
  int timeout, status = 0;
  int i;
  k_ui8_t cyl_lo, cyl_hi, sect, head;
  controller_t *ctrl;
  k_ui16_t tmp;

  __dbg_printk("[add_ide_op_polled_mode] bonjour\n");

  ctrl = harddisk->ctrl;

  if(type != READ && type != WRITE)
    {
      printk("Unknown type of operation\n");
      return -1;
    }

  ctrl->state = ATA_IDLE;

  __dbg_printk("Converting to correct sector addressing\n");

  if(harddisk->flags & HARDDISK_LBA_CAPABLE)
    {
      sect   = (sector_num & 0xff);
      cyl_lo = (sector_num >> 8) & 0xff;
      cyl_hi = (sector_num >> 16) & 0xff;
      head   = ((sector_num >> 24) & 0xf) | 0xE0 /* LBA */;
      printk("Using LBA mode %d : sect=%d,cyl_lo=%d,cyl_hi=%d,head=%d\n",
	     sector_num,sect,cyl_lo,cyl_hi,head);
    }
  else
    {
      int cylinder = sector_num / 
	(harddisk->logical_head_nb * harddisk->logical_sector_per_track);
      int temp = sector_num %
	(harddisk->logical_head_nb * harddisk->logical_sector_per_track);
      cyl_lo = cylinder & 0xff;
      cyl_hi = (cylinder >> 8) & 0xff;
      head   = temp / harddisk->logical_sector_per_track;
      sect   = (temp % harddisk->logical_sector_per_track) + 1;
    }

  __dbg_printk("conversion done\n");

  /*
  printk("Going to read cyl_hi=0x%x, cyl_lo=0x%x, head=0x%x, sect=0x%x\n",
	 cyl_hi, cyl_lo, head, sect);
  */

  /* send reset */
  outb(ATA_D_IBM | ATA_MASTER, ctrl->ioaddr + ATA_DRIVE);
  usleep(1);
  outb(ATA_A_nIEN | ATA_A_RESET, ctrl->ioaddr + ATA_ALTPORT);
  usleep(1000);
  outb(ATA_A_nIEN, ctrl->ioaddr + ATA_ALTPORT);
  usleep(1000);
  inb(ctrl->ioaddr + ATA_ERROR);

  for(timeout = 0; timeout < 30000; timeout++)
    {
      status = inb(ctrl->ioaddr + ATA_STATUS);
      if(!(status & ATA_S_BSY))
	break;
      
      usleep(1);
    }
  if(timeout == 30000)
    printk("TIMEOUT");

  if(inb(ctrl->ioaddr + ATA_STATUS) & ATA_S_ERROR)
    {
      printk("Error of type 0x%x\n", inb(ctrl->ioaddr + ATA_ERROR));
    }
  
  //  outb(ATA_A_nIEN | ATA_A_4BIT, ctrl->ioaddr + ATA_ALTPORT);
  //  outb(0, ctrl->ioaddr + ATA_ALTPORT);
  /* select drive */
  outb(ATA_D_IBM 
       | (harddisk->device == MASTER) ? ATA_MASTER : ATA_SLAVE
       | head, 
       ctrl->ioaddr + ATA_DRIVE);

  outb(0, ctrl->ioaddr + ATA_PRECOMP);
  outb(1, ctrl->ioaddr + ATA_SECTOR_COUNT);
  outb(sect, ctrl->ioaddr + ATA_SECTOR_NUMBER);
  outb(cyl_lo, ctrl->ioaddr + ATA_CYL_LSB);
  outb(cyl_hi, ctrl->ioaddr + ATA_CYL_MSB);

  /* FOR THE MOMENT WE DON'T CARE ABOUT THE OPERATION TYPE ... ALWAYS
     READ ... */
  outb(ATA_C_READ, ctrl->ioaddr + ATA_CMD);

  for(timeout = 0; timeout < 30000; timeout++)
    {
      status = inb(ctrl->ioaddr + ATA_STATUS);
      if(!(status & ATA_S_BSY))
	break;
      
      usleep(1);
    }
  if(timeout >= 30000)
    printk("TIMEOUT");

  if(inb(ctrl->ioaddr + ATA_STATUS) & ATA_S_ERROR)
    {
      printk("[after] Error of type 0x%x\n", inb(ctrl->ioaddr + ATA_ERROR));
      return -1;
    }

  if(!(inb(ctrl->ioaddr + ATA_STATUS) & ATA_S_DRQ))
    {
      printk("Error (0x%x)\n", inb(ctrl->ioaddr + ATA_ERROR));
      return -1;
    }

  for(i = 0; i < 256; i++)
    buffer[i] = inw(ctrl->ioaddr);

  return 0;
}

/* TEST FUNCTION ONLY */
static int do_identify_drive(harddisk_t *harddisk, k_ui16_t *buffer)
{
  controller_t *ctrl;
  int timeout;
  int status = 0;
  int i;
  
  ctrl = harddisk->ctrl;
  
  /* On met nIEN a 1 dans device control */
  outb(ATA_A_nIEN | ATA_A_4BIT, ctrl->ioaddr + ATA_DEVICE_CONTROL);
  usleep(1);

  /* on selectionne le device */
  outb(ATA_D_IBM | (harddisk->device == 0) ? ATA_MASTER : ATA_SLAVE, 
       ctrl->ioaddr + ATA_DRIVE);

  /* sencind command */
  outb(ATA_C_ATA_IDENTIFY, ctrl->ioaddr + ATA_CMD);

  for(timeout = 0; timeout < 30000; timeout++)
    {
      status = inb(ctrl->ioaddr + ATA_STATUS);
      if(!(status & ATA_S_BSY))
	break;
      
      usleep(1);
    }

  if(!(status & ATA_S_DRQ))
    {
      printk("Error\n");
      return -1;
    }

  for(i = 0; i < 256; i++)
    buffer[i] = inw(ctrl->ioaddr);
  
  return 0;
}


static int get_partition_table (harddisk_t *harddisk)
{
  int i;
  partition_entry_t *p;
  partition_t *new;
  int extstart = 0;  
  int extsup = 0;
  int partnum = 1;
  k_ui8_t buffer[512];
  
  if(add_ide_op_polled_mode(harddisk, READ, 0, (k_ui16_t *) buffer) < 0)
    {
      printk("Bonjour coucou\n");
      return -1;
    }

  __dbg_printk("Going to dereference harddisk 0x%x.. might explose\n", (unsigned) harddisk);
  p = (partition_entry_t *) (buffer+446);
  harddisk->partition_list = NULL;

  {
    k_ui8_t buffer2[512];
    k_ui8_t buffer3[512];
    
    do_identify_drive(harddisk, (k_ui16_t *) buffer2);
    
    if(add_ide_op_polled_mode(harddisk, READ, 64, (k_ui16_t *) buffer3) < 0)
      printk("*********** EROOOR \n");
    printk("buffer1 : ");
    for(i = 0; i < 16; i++)
      printk("%x ", buffer[446+i]);
    printk("\n");
    printk("buffer2 : ");
    for(i = 0; i < 16; i++)
      printk("%c ", buffer2[27*2+i]);
    printk("\n");
    printk("buffer3 : ");
    for(i = 0; i < 16; i++)
      printk("%x ", buffer3[446+i]);
  }

  return 0;

  /* Manage primary partitions */
  for (i = 0; i < 4; i++)
    {
      if (p[i].size == 0)
	continue;

      new = kmalloc(sizeof(partition_t));
      if(new == NULL)
	{
	  printk("Couldn't allocate memory\n");
	  return -1;
	}

      if(p[i].type != 0x5)
	{
	  new->is_active = (p[i].active == 0) ? 0 : 1;
	  new->fs_type   = p[i].type;
	  new->start     = p[i].lba;
	  new->size      = p[i].size;
	  new->number    = partnum++;
	  list_add_tail(harddisk->partition_list, new);
	}
      else
	extstart = p[i].lba;
    }

  /* Manage extended partitions */
  while(extstart != 0)
    {
      if(partnum > 6)
	break;
      /*
      printk("Reading MBR for extended partition : %d\n",
	     extstart+extsup);
      */

      memset(buffer, 0, 512);
      if(add_ide_op_polled_mode(harddisk, READ, extstart+extsup, 
				(k_ui16_t *) buffer) < 0)
	{
	  printk("Error while reading sector %d\n", extstart+extsup);
	  return -1;
	}
      
      p = (partition_entry_t *) (buffer + 446);

      new = kmalloc(sizeof(partition_t));
      if(new == NULL)
	{
	  printk("Couldn't allocate memory\n");
	  return -1;
	}

      new->is_active = (p[0].active == 0) ? 0 : 1;
      new->fs_type   = p[0].type;
      new->start     = extstart + extsup + p[0].lba;
      new->size      = p[0].size;
      new->number    = partnum++;
      /*
      printk("First entry : ");
      for (i = 0; i < 16; i++)
	printk("%x ", (unsigned) buffer[446+i]);
      printk("Second entry : ");
      for (i = 0; i < 16; i++)
	printk("%x ", (unsigned) buffer[446+16+i]);
      printk("Extended adding %d (%d %d 0x%x) %x%x\n", 
	     partnum-1, new->start, new->size, new->fs_type,
	     (unsigned)buffer[510], (unsigned)buffer[511]);
      */
      list_add_tail(harddisk->partition_list, new);

      extsup = p[1].lba;
      if(extsup == 0)
	break;
    }

  return 0;
}


/* this function set the command "Identify Drive". For this command,
   we don't wait for an IRQ, we just wait for BSY bit to be
   cleared. (polled mode) */

static int get_drv_infos(controller_t *ctrl, int device)
{ 
  int timeout, status=0;
  harddisk_t *harddisk;
  identify_device_info_t *dinfo;
  k_ui16_t buffer[256];
  int i;

  /* On met nIEN a 1 dans device control */
  outb(ATA_A_nIEN | ATA_A_4BIT, ctrl->ioaddr + ATA_DEVICE_CONTROL);
  usleep(1);

  /* on selectionne le device */
  outb(ATA_D_IBM | (device == 0) ? ATA_MASTER : ATA_SLAVE, 
       ctrl->ioaddr + ATA_DRIVE);

  /* sencind command */
  outb(ATA_C_ATA_IDENTIFY, ctrl->ioaddr + ATA_CMD);

  for(timeout = 0; timeout < 30000; timeout++)
    {
      status = inb(ctrl->ioaddr + ATA_STATUS);
      if(!(status & ATA_S_BSY))
	break;
      
      usleep(1);
    }

  if(!(status & ATA_S_DRQ))
    {
      printk("Error\n");
      return -1;
    }

  for(i = 0; i < 256; i++)
    buffer[i] = inw(ctrl->ioaddr);

  dinfo = (identify_device_info_t *) buffer;

  harddisk = (harddisk_t *) ctrl->device[device];
  harddisk->ctrl = ctrl;
  harddisk->device = device;

  harddisk->logical_cylinder_nb      = dinfo->nb_logical_cylinders;
  harddisk->logical_head_nb          = dinfo->nb_logical_heads;
  harddisk->logical_sector_per_track = dinfo->nb_logical_sectors;

  if(harddisk->logical_sector_per_track == 0 ||
     harddisk->logical_head_nb == 0 ||
     harddisk->logical_cylinder_nb == 0)
    {
      printk("Y'a un bleme\n");
      return -1;
    }
  
  
  harddisk->lba_capacity             = dinfo->lba_capacity;
  
  harddisk->flags = 0;

  if(dinfo->capabilities & (1<<1)     /* LBA bit must be set */
     && dinfo->major_version          /* major version must be non 0 */
     && (dinfo->fields_valid & 1)     /* lba fields must be valid */
     && (dinfo->lba_capacity))        /* lba capacity must be non 0 */
    harddisk->flags |= HARDDISK_LBA_CAPABLE;

  if(harddisk->logical_head_nb == 16 &&
     harddisk->logical_sector_per_track == 63 &&
     harddisk->logical_cylinder_nb == 16383)
    {
      if(harddisk->flags & HARDDISK_LBA_CAPABLE)
	harddisk->size = harddisk->lba_capacity;
      else
	FAILED_VERBOSE("Large harddisk without LBA ...\n");
    }
  else
    harddisk->size = 
      harddisk->logical_cylinder_nb * 
      harddisk->logical_sector_per_track *
      harddisk->logical_head_nb;

  convert_to_ascii(dinfo->model_number, harddisk->model_number,40);
  convert_to_ascii(dinfo->serial_number, harddisk->serial_number,20);  
  convert_to_ascii(dinfo->firmware_revision, harddisk->firmware_revision,8);

  printk("Calling get_partition_table for %d-%d\n",
	 ctrl->ctrl, device);
  if(get_partition_table(harddisk) < 0)
    {
      printk("Error while getting partition table\n");
      return -1;
    }

  return 0;
}

static void ide_handler(int nb, cpu_state_t *state)
{
  UNUSED(state);
  if(controllers[PRIMARY_CONTROLLER].state == ATA_WAIT_INTR)
    {
      printk("Got an IRQ %d !\n", nb);
      printk("The job was of type : %d\n", ide_op_list->type);
      controllers[PRIMARY_CONTROLLER].state = ATA_IDLE;
    }
}

static char *partition_type(int type)
{
  switch(type)
    {
    case 0xe:
    case 0x6:
      return "FAT16";
    case 0xb:
    case 0xc:
      return "FAT32";
    case 0x82:
      return "Linux Swap";
    case 0x83:
      return "Linux";
    default:
      return "Unknow";
    }
}

/****** needs to be updated *********/
partition_t *get_partition_list(void)
{
  harddisk_t *hd = (harddisk_t *) controllers[PRIMARY_CONTROLLER].device[MASTER];
  
  if(hd == NULL)
    return NULL;
  
  return hd->partition_list;
}

/******** needs to be updated *******/
int ide_read_on_primary_master(k_ui32_t sector_num, k_ui16_t *buffer)
{
  harddisk_t *hd = (harddisk_t *) controllers[PRIMARY_CONTROLLER].device[MASTER];

  if(hd == NULL)
    return -1;
  
  return add_ide_op_polled_mode(hd,READ,sector_num,buffer);
}



static int initialize_devices(int controller)
{
  char c;
  controller_t *ctrl;

  if(controller == PRIMARY_CONTROLLER)
    {
      c = 'a';
      ctrl = &controllers[PRIMARY_CONTROLLER];
    }
  else if(controller == SECONDARY_CONTROLLER)
    {
      c = 'c';
      ctrl = &controllers[SECONDARY_CONTROLLER];
    }
  else
    {
      printk("Unknow controller !\n");
      return -1;
    }

  if(ctrl->state != ATA_NOT_PRESENT)
    {
      if(ctrl->devices & ATA_ATA_MASTER)
	{
	  harddisk_t *harddisk;
	  partition_t *p;
	  int nb_elts;
	  
	  ctrl->device[MASTER] = kmalloc(sizeof(harddisk_t));
	  if(ctrl->device[MASTER] == NULL)
	    {
	      printk("[test_ide] memory allocation error\n");
	      return -1;
	    }
	  harddisk = (harddisk_t *) ctrl->device[MASTER];
	  if(get_drv_infos(ctrl, MASTER) < 0)
	    {
	      printk("Failure while getting info for master\n");
	      kfree(ctrl->device[MASTER]);
	      ctrl->device[MASTER] = NULL;
	      return -1;
	    }
	  
	  printk("hd%c: (%s = %d Mb : C/H/S : %d/%d/%d\n", 
		 c, harddisk->model_number, harddisk->size>>11,
		 harddisk->logical_cylinder_nb,
		 harddisk->logical_head_nb,
		 harddisk->logical_sector_per_track);
	  list_foreach(harddisk->partition_list, p, nb_elts)
	    {
	      printk(" - hd%c%d start=%d size=%d Mb type=%s\n", 
		     c, nb_elts+1, p->start, p->size>>11, partition_type(p->fs_type));
	    }
	}
      if(ctrl->devices & ATA_ATA_SLAVE)
	{
	  harddisk_t *harddisk;
	  partition_t *p;
	  int nb_elts;
	  
	  ctrl->device[SLAVE] = kmalloc(sizeof(harddisk_t));
	  if(ctrl->device[SLAVE] == NULL)
	    {
	      printk("[test_ide] memory allocation error\n");
	      return -1;
	    }
	  harddisk = (harddisk_t *) ctrl->device[SLAVE];
	  if(get_drv_infos(ctrl, SLAVE) < 0)
	    {
	      printk("Failure while getting info for slave\n");
	      kfree(ctrl->device[SLAVE]);
	      ctrl->device[SLAVE] = NULL;
	      return -1;
	    }

	  printk("hd%c: (%s = %d Mb : C/H/S : %d/%d/%d\n", 
		 c+1, harddisk->model_number, harddisk->size>>11,
		 harddisk->logical_cylinder_nb,
		 harddisk->logical_head_nb,
		 harddisk->logical_sector_per_track);
	  
	  list_foreach(harddisk->partition_list, p, nb_elts)
	    {
	      printk(" - hd%c%d start=%d size=%d Mb type=%s\n", 
		     c+1, nb_elts+1, p->start, p->size>>11, partition_type(p->fs_type));
	    }
	}
      if(ctrl->devices & ATA_ATAPI_MASTER)
	{
	  cdrom_t *cdrom;
	  ctrl->device[MASTER] = kmalloc(sizeof(cdrom_t));
	  if(ctrl->device[MASTER] == NULL)
	    {
	      printk("[test_ide] memory allocation error\n");
	      return -1;
	    }
	  cdrom = (cdrom_t *) ctrl->device[MASTER];
	  printk("hd%c (CD-ROM) ", c);
	}
      if(ctrl->devices & ATA_ATAPI_SLAVE)
	{
	  cdrom_t *cdrom;
	  ctrl->device[SLAVE] = kmalloc(sizeof(cdrom_t));
	  if(ctrl->device[SLAVE] == NULL)
	    {
	      printk("[test_ide] memory allocation error\n");
	      return -1;
	    }
	  cdrom = (cdrom_t *) ctrl->device[SLAVE];
	  printk("hd%c (CD-ROM) ", c+1);
	}
    }
  else
    printk("no controller found");

  printk("\n");

  return 0;
}


int test_ide(void)
{
  /*
  if(ide_init_babel_stuff() < 0)
    {
      __dbg_printk("[ide] error while initializing Babel\n");
      return -1;
    }
  */
  
  printk("Primary : \n");
  init_ide(&controllers[PRIMARY_CONTROLLER]);
  initialize_devices(PRIMARY_CONTROLLER);

  /*
  printk("Secondary : \n");
  init_ide(&controllers[SECONDARY_CONTROLLER]);
  initialize_devices(SECONDARY_CONTROLLER);

  register_irq_handler(14, ide_handler);
  */

  
  return 0;
}

--=-=-=


-- 
PETAZZONI Thomas - thomas.petazzoni@enix.org - UIN : 34937744
(Perso)      http://www.enix.org/~thomas/
(KOS)        http://kos.enix.org/ 
(Club LinUT) http://club-linut.enix.org

--=-=-=--