[Kos-dev] ATA, probleme
kos-dev@enix.org
kos-dev@enix.org
11 Feb 2002 18:23:20 +0100
--=-=-=
salut a tous,
j'ai une question, plutot pour Hlide, mais si d'autres savent, c'est
tout aussi bien.
lorsque j'utilise le mode d'adressage des secteurs CHS
(cylinder/head/sector) ca marche nickel, je peux lire n'importe quel
secteur du disque, decoder la table des partitions, et les tables des
partitions etendues.
par contre, quand j'utilise le mode d'adressage LBA, quelque soit le
secteur que je veux lire, ca me renvoie toujours le contenu du secteur
0. Ca me permet de lire la table des partitions, mais pas de lire
d'autres secteurs. Ce qui est un peu ennuyeux. Je suis sur que
l'ordinateur sur lequel je teste supporte le LBA car Linux utilise le
LBA (j'ai modifie le noyau pour qu'il me dise si oui ou non il utilise
le LBA).
Je joins le code, la partie interessante pour cette question etant
dans add_ide_op_polled_mode.
Merci bcp
Thomas
--=-=-=
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>
#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 identify_device_info
{
k_ui16_t general_config_info; /* 0 */
k_ui16_t nb_logical_cylinders; /* 1 */
k_ui16_t reserved1; /* 2 */
k_ui16_t nb_logical_heads; /* 3 */
k_ui16_t unformatted_bytes_track; /* 4 */
k_ui16_t unformatted_bytes_sector; /* 5 */
k_ui16_t nb_logical_sectors; /* 6 */
k_ui16_t vendor1[3]; /* 7-9 */
k_ui8_t serial_number[20]; /* 10-19 */
k_ui16_t buffer_type; /* 20 */
k_ui16_t buffer_size; /* 21 */
k_ui16_t ecc_bytes; /* 22 */
k_ui8_t firmware_revision[8]; /* 23-26 */
k_ui8_t model_number[40]; /* 27-46 */
k_ui8_t max_multisect; /* 47 */
k_ui8_t vendor2;
k_ui16_t dword_io; /* 48 */
k_ui8_t vendor3; /* 49 */
k_ui8_t capabilities;
k_ui16_t reserved2; /* 50 */
k_ui8_t vendor4; /* 51 */
k_ui8_t pio_trans_mode;
k_ui8_t vendor5; /* 52 */
k_ui8_t dma_trans_mode;
k_ui16_t fields_valid; /* 53 */
k_ui16_t cur_logical_cylinders; /* 54 */
k_ui16_t cur_logical_heads; /* 55 */
k_ui16_t cur_logical_sectors; /* 56 */
k_ui16_t capacity1; /* 57 */
k_ui16_t capacity0; /* 58 */
k_ui8_t multsect; /* 59 */
k_ui8_t multsect_valid;
k_ui32_t lba_capacity; /* 60-61 */
k_ui16_t dma_1word; /* 62 */
k_ui16_t dma_multiword; /* 63 */
k_ui16_t pio_modes; /* 64 */
k_ui16_t min_mword_dma; /* 65 */
k_ui16_t recommended_mword_dma; /* 66 */
k_ui16_t min_pio_cycle_time; /* 67 */
k_ui16_t min_pio_cycle_time_iordy; /* 68 */
k_ui16_t reserved3[11]; /* 69-79 */
k_ui16_t major_version; /* 80 */
k_ui16_t minor_version; /* 81 */
k_ui16_t command_sets1; /* 82 */
k_ui16_t command_sets2; /* 83 dixit lk : b14 (smart enabled) */
k_ui16_t reserved4[4]; /* 84-87 */
k_ui16_t dma_ultra; /* 88 dixit lk */
k_ui16_t reserved5[37]; /* 89-125 */
k_ui16_t last_lun; /* 126 */
k_ui16_t reserved6; /* 127 */
k_ui16_t security; /* 128 */
k_ui16_t reserved7[127];
} identify_device_info_t __attribute__((packed));
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 { ACTIVE, NOT_ACTIVE } is_active;
k_ui8_t fs_type;
k_ui32_t start;
k_ui32_t size;
int number;
struct partition *next;
struct partition *prev;
} 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 logical_cylinder_nb;
k_ui16_t logical_head_nb;
k_ui16_t logical_sector_per_track;
k_ui32_t lba_capacity;
char serial_number[21];
char firmware_revision[9];
char model_number[41];
controller_t *ctrl;
int flags;
#define HARDDISK_LBA_CAPABLE 0x1
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_ui32_t sector_num,
char *buffer)
{
int timeout, status = 0;
int i, tmp;
k_ui8_t cyl_lo, cyl_hi, sect, head;
controller_t *ctrl;
__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) | 0x40 /* 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);
*/
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");
outb(ATA_A_nIEN | ATA_A_4BIT, 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");
__dbg_printk("Checking for error\n");
if(!(status & ATA_S_DRQ))
{
__dbg_printk("erreur qui pue\n");
printk("Error (0x%x)\n", inb(ctrl->ioaddr + ATA_ERROR));
return -1;
}
__dbg_printk("Avec bochs c'est la fete, on lit des secteurs\n");
for(i = 0; i < 512; i++)
{
tmp = inw(ctrl->ioaddr);
buffer[i] = (tmp & 0xff);
buffer[++i] = (tmp & 0xff00) >> 8;
}
__dbg_printk("[add_ide_op_polled_mode] bonjour\n");
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, buffer) < 0)
{
__dbg_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;
/* GROS TEST POUR DEBUGGAGE LBA
{
char buffer2[512];
if(add_ide_op_polled_mode(harddisk, READ, 1, buffer2) < 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("%x ", buffer2[446+i]);
}
*/
/* 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, 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)
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);
__dbg_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";
}
}
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
--=-=-=--