[Kos-dev] Few questions about CHS and LBA
kos-dev@enix.org
kos-dev@enix.org
05 Feb 2002 08:45:28 +0100
--=-=-=
Hi,
Again me with a few questions concerning CHS and LBA.
1) There's seems to be two CHS configuration for a hard drive. A
Physical CHS configuration (used by the ATA device, where head<15,
cylinder up to 65536, and up to 63 sectors/track). And a logical
CHS configuration, which can be found in the values returned by a
IDENTIFY DRIVE command.
For instance on my harddirve (a Quantum 810Mb), I have the
following configurations :
- Logicial : 822 cylinders, 32 heads, 63 sectors/track
- Physical : 1644 cylinders, 16 heads, 63 sectors/track
At the beginning of my test, I tried to directly address the disk
using the Logical CHS configuration, but that's not possible :
there's 32 heads, and the space for Head is 4 bit (in the
register). So I looked at my drive and saw the Physical CHS
configuration. ANd it worked. But now THE QUESTION : how can I
detect this Physical CHS configuration ?
On this drive, the conversion is pretty easy (too much head =>
multiply the number of cylinders), but on other harddrives ? For
instance I can see a harddrive which is 1010/16/51 (51
sectors/track). How can I know that without looking directly inside
the computer.
In some documentations I saw it is not possible to get this
information without calling INT 13 (which actually uses Physical
CHS translation for adressing the disk, and can returns this
configuration).
I'm sure you're doing in an other way. But I looked at the code,
and couldn't find anything about it.
2) My second question is about LBA. On my Quantum 810 Mb, LBA seems to
be present : it's configured in the BIOS, and the information
returned by the IDENTIFY DRIVE Command says that LBA is activated.
But when I try the following piece of code :
for(i = 1; i < 1002; i++)
{
memset(buffer2, 0xBB, 512);
if(add_ide_op_polled_mode(harddisk, /* the harddrive */
READ, /* type of operation */
(i>>8)&0xffff, /* cylinder */
((i>>24)&0xf)|0x40, /* head | 0x40 (LBA) */
i&0xff, /* sector number */
buffer2) < 0)
break;
}
It fails for sector 64. So just the sector after the sectors/track
limit, just as if I had to increment head by one. But this
harddrive should be LBA compliant (and says it is !). I activate
LBA, and use this mode, but nothing works !
For a long time, I thought my code was very wrong. So I tried on a
more recent PC : a laptop (Fujitsu). And this code worked. It
didn't failed at reading the 1001 first sectors using LBA
addressing.
So what's the deal ? It is possible to have a harddrive which
claims to be LBA Compliant, and which is not LBA compliant ? That
would sucks a lot !
3) Last question, for the detection of hard drives and CD-ROMs I used
your code taken from FreeBSD. It works fine on every machine I
tried it, except onmy laptop. On my laptop there's a CD-ROM on hdc
(secondary master), and your code detects it on Secondary Master
AND on Secondary Slave.
So it seems that there's something to do in this code :
/* 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;
}
/* MAYBE WE SHOULD DO SOMETHING HERE TO RESET THE REGISTER TO
ANOTHER VALUE ? (0 for instance). So I suggest :
outb(0, ctrl->ioaddr + ATA_CYL_LSB);
outb(0, ctrl->ioaddr + ATA_CYL_MSB); */
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;
}
What do you think about it ?
Well if you want to look at my code more precisely, I included it in
this mail. It's pretty ugly in some places because it's in heavy
development.
The loop test used to test LBA is in get_partition_table. And the
function used to read is add_ide_op_polled_mode. I don't use
add_ide_op_with_irq for the moment (I don't want to care about locking
and so on).
Thank for all your help
Thomas
--=-=-=
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=_ide.c
#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>
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x10
/* Registers */
#define ATA_DATA 0x00 /* Data register */
#define ATA_ERROR 0x01 /* (R) error register */
#define ATA_PRECOMP 0x01 /* (W) precompensation */
#define ATA_SECTOR_COUNT 0x02 /* sector count register */
#define ATA_SECTOR_NUMBER 0x03 /* sector number register */
#define ATA_CYL_LSB 0x04 /* cylinder# LSB */
#define ATA_CYL_MSB 0x05 /* cylinder# MSB */
#define ATA_DRIVE 0x06
#define ATA_D_IBM 0xa0
#define ATA_STATUS 0x07 /* status register */
#define ATA_S_ERROR 0x01 /* error */
#define ATA_S_INDEX 0x02 /* index */
#define ATA_S_CORR 0x04 /* data corrected */
#define ATA_S_DRQ 0x08 /* data request */
#define ATA_S_DSC 0x10 /* drive Seek Completed */
#define ATA_S_DWF 0x20 /* drive write fault */
#define ATA_S_DRDY 0x40 /* drive ready */
#define ATA_S_BSY 0x80 /* busy */
#define ATA_CMD 0x07 /* command register */
#define ATA_C_ATA_IDENTIFY 0xec /* get ATA params */
#define ATA_C_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
#define ATA_C_READ 0x20 /* read command */
#define ATA_C_WRITE 0x30 /* write command */
#define ATA_C_READ_MULTI 0xc4 /* read multi command */
#define ATA_C_WRITE_MULTI 0xc5 /* write multi command */
#define ATA_C_SET_MULTI 0xc6 /* set multi size command */
#define ATA_C_PACKET_CMD 0xa0 /* set multi size command */
#define ATA_ALTPORT 0x206 /* alternate Status register */
#define ATA_DEVICE_CONTROL 0x206
#define ATA_A_nIEN 0x02 /* disable interrupts */
#define ATA_A_RESET 0x04 /* RESET controller */
#define ATA_A_4BIT 0x08 /* 4 head bits */
/* Devices types */
#define ATA_ATA_MASTER 0x01
#define ATA_ATA_SLAVE 0x02
#define ATA_ATAPI_MASTER 0x04
#define ATA_ATAPI_SLAVE 0x08
#define ATAPI_MAGIC_LSB 0x14
#define ATAPI_MAGIC_MSB 0xeb
typedef struct partition_entry
{
k_ui8_t active;
k_ui8_t start_dl;
k_ui16_t start_cylinder;
k_ui8_t type;
k_ui8_t end_dl;
k_ui16_t end_cylinder;
k_ui32_t lba;
k_ui32_t size;
} partition_entry_t;
#define PRIMARY_CONTROLLER 0
#define SECONDARY_CONTROLLER 1
#define MASTER 0
#define SLAVE 1
#define NB_CONTROLLERS 2
typedef struct partition
{
enum { PRIMARY, EXTENDED } type;
enum { ACTIVE, NOT_ACTIVE } is_active;
k_ui8_t fs_type;
k_ui8_t start_dl;
k_ui16_t start_cylinder;
k_ui8_t end_dl;
k_ui16_t end_cylinder;
k_ui32_t lba;
k_ui32_t size;
int number;
struct partition *next;
} partition_t;
typedef struct controller
{
k_ui16_t ioaddr;
k_ui16_t irq;
enum { ATA_NOT_PRESENT, ATA_IDLE, ATA_WAIT_INTR } state;
int ctrl;
int devices;
void *device[2];
} controller_t;
typedef struct harddisk
{
k_ui16_t general_configuration_info;
k_ui16_t logical_cylinder_nb;
k_ui16_t logical_head_nb;
k_ui16_t unformatted_bytes_per_track;
k_ui16_t unformatted_bytes_per_sector;
k_ui16_t logical_sector_per_track;
k_ui16_t vendor;
k_ui16_t controller_type;
k_ui16_t buffer_size;
k_ui32_t lba_capacity;
char serial_number[21];
char firmware_revision[9];
char model_number[41];
controller_t *ctrl;
int size;
int device;
partition_t *partition_list;
} harddisk_t;
typedef struct cdrom
{
controller_t *ctrl;
} cdrom_t;
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;
}
static int add_ide_op_polled_mode(harddisk_t *harddisk, int type,
k_ui16_t cyl, k_ui8_t head, k_ui8_t sector, char *buffer)
{
int timeout, status = 0;
int i, tmp;
controller_t *ctrl = harddisk->ctrl;
if(type != READ && type != WRITE)
{
printk("Unknown type of operation\n");
return -1;
}
ctrl->state = ATA_IDLE;
for(timeout = 0; timeout < 30000; timeout++)
{
status = inb(ctrl->ioaddr + ATA_STATUS);
if(!(status & ATA_S_BSY))
break;
usleep(1);
}
outb(ATA_A_nIEN | ATA_A_4BIT, ctrl->ioaddr + ATA_ALTPORT);
printk("Cyl low 0x%x, cyl high 0x%x, head 0x%x sector 0x%x\n",
cyl & 0xff, (cyl >> 8) & 0xff, head, sector);
outb(0, ctrl->ioaddr + ATA_PRECOMP);
outb(1, ctrl->ioaddr + ATA_SECTOR_COUNT);
outb(sector, ctrl->ioaddr + ATA_SECTOR_NUMBER);
outb(cyl & 0xff, ctrl->ioaddr + ATA_CYL_LSB);
outb((cyl & 0xff00) >> 8, ctrl->ioaddr + ATA_CYL_MSB);
/* select drive */
outb(ATA_D_IBM
| (harddisk->device == MASTER) ? ATA_MASTER : ATA_SLAVE
| head,
ctrl->ioaddr + ATA_DRIVE);
/* 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(!(status & ATA_S_DRQ))
{
printk("Error (0x%x)\n", inb(ctrl->ioaddr + ATA_ERROR));
return -1;
}
for(i = 0; i < 512; i++)
{
tmp = inw(ctrl->ioaddr);
buffer[i] = (tmp & 0xff);
buffer[++i] = (tmp & 0xff00) >> 8;
}
return 0;
}
static int get_partition_table (harddisk_t *harddisk)
{
int i,j,k;
partition_entry_t *p;
char c;
int sectnum;
k_ui8_t buffer[512];
k_ui8_t buffer2[512];
add_ide_op_polled_mode(harddisk, READ, 0, 0, 1, buffer);
switch(harddisk->ctrl->ctrl)
{
case PRIMARY_CONTROLLER:
c = 'a';
break;
case SECONDARY_CONTROLLER:
c = 'c';
break;
default:
printk("Unknown controller\n");
return -1;
}
for (p = (partition_entry_t *) (buffer+446), i=0;
i < 4;
p++, i++)
{
if (p->size == 0)
continue;
printk("hd%c%d : ", (harddisk->device == MASTER) ? c : c+1, i+1);
printk("type=");
switch(p->type)
{
case 0xc:
printk("FAT32 ");
break;
case 0xe:
printk("FAT16 ");
break;
case 0x82:
printk("Linux Swap ");
break;
case 0x83:
printk("Linux Native ");
break;
case 0x5:
printk("Extended ");
printk("start_sector = %d, start_cylinder = %d (0x%x) (%d)\n",
(p->start_cylinder & 0x3f),
((p->start_cylinder & 0xff00) >> 8) | ((p->start_cylinder & 0xc0) << 2),
p->start_cylinder,
p->start_dl);
/*
for (i = (((p->start_cylinder & 0xff00) >> 8) | ((p->start_cylinder & 0xc0) << 2))-5;
i < (((p->start_cylinder & 0xff00) >> 8) | ((p->start_cylinder & 0xc0) << 2))+5;
i++)
*/
memset(buffer2, 0xBB, 512);
add_ide_op_polled_mode(harddisk, READ,
970,
/* (p->start_dl & 0xf) */ 0,
1,
buffer2);
for(i = 446; i < 446+32; i++)
printk("%x ", buffer2[i]);
printk("end : %x %x\n", buffer2[510], buffer2[511]);
for(i = 1; i < 1002; i++)
{
memset(buffer2, 0xBB, 512);
if(add_ide_op_polled_mode(harddisk, READ, (i>>8)&0xffff,((i>>24)&0xf)|0x40,i&0xff,buffer2) < 0)
break;
}
printk("failure noticed at sector %d\n", i);
// for(i = 446; i < 446+32; i++)
//printk("%x ", buffer2[i]);
// printk("end : %x %x\n", buffer2[510], buffer2[511]);
// printk("(%d) END : %x %x || ", i, buffer2[510], buffer2[511]);
break;
default:
printk("N/A ");
}
printk("size=%dM", (p->size)>>11);
printk("\n");
}
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;
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);
harddisk = (harddisk_t *) ctrl->device[device];
harddisk->ctrl = ctrl;
harddisk->device = device;
harddisk->general_configuration_info = buffer[0];
harddisk->logical_cylinder_nb = buffer[1];
harddisk->logical_head_nb = buffer[3];
harddisk->unformatted_bytes_per_track = buffer[4];
harddisk->unformatted_bytes_per_sector = buffer[5];
harddisk->logical_sector_per_track = buffer[6];
harddisk->lba_capacity =
(buffer[60] & 0xffff) | ((buffer[61] & 0xffff) << 16);
printk("IS LBA CAPABLE ??? : %s\n", ( ((buffer[49] >> 8) & 1) == 1) ? "YES" : "NO");
if(harddisk->logical_head_nb == 16 &&
harddisk->logical_sector_per_track == 63 &&
harddisk->logical_cylinder_nb == 16383)
harddisk->size = harddisk->lba_capacity;
else
harddisk->size =
harddisk->logical_cylinder_nb *
harddisk->logical_sector_per_track *
harddisk->logical_head_nb;
convert_to_ascii((unsigned char *) (buffer + 0x1b), harddisk->model_number,40);
convert_to_ascii((unsigned char *) (buffer + 0xa), harddisk->serial_number,20);
convert_to_ascii((unsigned char *) (buffer + 0x17), harddisk->firmware_revision,8);
get_partition_table(harddisk);
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 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;
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];
get_drv_infos(ctrl, MASTER);
printk("hd%c: (%s = %d Mb) ", c, harddisk->model_number, harddisk->size>>11);
}
if(ctrl->devices & ATA_ATA_SLAVE)
{
harddisk_t *harddisk;
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];
get_drv_infos(ctrl, SLAVE);
printk("hd%c: (%s = %d Mb) ", c+1, harddisk->model_number, harddisk->size>>11);
}
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)
{
printk("Primary : ");
init_ide(&controllers[PRIMARY_CONTROLLER]);
initialize_devices(PRIMARY_CONTROLLER);
printk("Secondary : ");
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
--=-=-=--