in hotplug/ibmphp_ebda.c [231:395]
int __init ibmphp_access_ebda(void)
{
u8 format, num_ctlrs, rio_complete, hs_complete, ebda_sz;
u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base;
int rc = 0;
rio_complete = 0;
hs_complete = 0;
io_mem = ioremap((0x40 << 4) + 0x0e, 2);
if (!io_mem)
return -ENOMEM;
ebda_seg = readw(io_mem);
iounmap(io_mem);
debug("returned ebda segment: %x\n", ebda_seg);
io_mem = ioremap(ebda_seg<<4, 1);
if (!io_mem)
return -ENOMEM;
ebda_sz = readb(io_mem);
iounmap(io_mem);
debug("ebda size: %d(KiB)\n", ebda_sz);
if (ebda_sz == 0)
return -ENOMEM;
io_mem = ioremap(ebda_seg<<4, (ebda_sz * 1024));
if (!io_mem)
return -ENOMEM;
next_offset = 0x180;
for (;;) {
offset = next_offset;
/* Make sure what we read is still in the mapped section */
if (WARN(offset > (ebda_sz * 1024 - 4),
"ibmphp_ebda: next read is beyond ebda_sz\n"))
break;
next_offset = readw(io_mem + offset); /* offset of next blk */
offset += 2;
if (next_offset == 0) /* 0 indicate it's last blk */
break;
blk_id = readw(io_mem + offset); /* this blk id */
offset += 2;
/* check if it is hot swap block or rio block */
if (blk_id != 0x4853 && blk_id != 0x4752)
continue;
/* found hs table */
if (blk_id == 0x4853) {
debug("now enter hot swap block---\n");
debug("hot blk id: %x\n", blk_id);
format = readb(io_mem + offset);
offset += 1;
if (format != 4)
goto error_nodev;
debug("hot blk format: %x\n", format);
/* hot swap sub blk */
base = offset;
sub_addr = base;
re = readw(io_mem + sub_addr); /* next sub blk */
sub_addr += 2;
rc_id = readw(io_mem + sub_addr); /* sub blk id */
sub_addr += 2;
if (rc_id != 0x5243)
goto error_nodev;
/* rc sub blk signature */
num_ctlrs = readb(io_mem + sub_addr);
sub_addr += 1;
hpc_list_ptr = alloc_ebda_hpc_list();
if (!hpc_list_ptr) {
rc = -ENOMEM;
goto out;
}
hpc_list_ptr->format = format;
hpc_list_ptr->num_ctlrs = num_ctlrs;
hpc_list_ptr->phys_addr = sub_addr; /* offset of RSRC_CONTROLLER blk */
debug("info about hpc descriptor---\n");
debug("hot blk format: %x\n", format);
debug("num of controller: %x\n", num_ctlrs);
debug("offset of hpc data structure entries: %x\n ", sub_addr);
sub_addr = base + re; /* re sub blk */
/* FIXME: rc is never used/checked */
rc = readw(io_mem + sub_addr); /* next sub blk */
sub_addr += 2;
re_id = readw(io_mem + sub_addr); /* sub blk id */
sub_addr += 2;
if (re_id != 0x5245)
goto error_nodev;
/* signature of re */
num_entries = readw(io_mem + sub_addr);
sub_addr += 2; /* offset of RSRC_ENTRIES blk */
rsrc_list_ptr = alloc_ebda_rsrc_list();
if (!rsrc_list_ptr) {
rc = -ENOMEM;
goto out;
}
rsrc_list_ptr->format = format;
rsrc_list_ptr->num_entries = num_entries;
rsrc_list_ptr->phys_addr = sub_addr;
debug("info about rsrc descriptor---\n");
debug("format: %x\n", format);
debug("num of rsrc: %x\n", num_entries);
debug("offset of rsrc data structure entries: %x\n ", sub_addr);
hs_complete = 1;
} else {
/* found rio table, blk_id == 0x4752 */
debug("now enter io table ---\n");
debug("rio blk id: %x\n", blk_id);
rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL);
if (!rio_table_ptr) {
rc = -ENOMEM;
goto out;
}
rio_table_ptr->ver_num = readb(io_mem + offset);
rio_table_ptr->scal_count = readb(io_mem + offset + 1);
rio_table_ptr->riodev_count = readb(io_mem + offset + 2);
rio_table_ptr->offset = offset + 3 ;
debug("info about rio table hdr ---\n");
debug("ver_num: %x\nscal_count: %x\nriodev_count: %x\noffset of rio table: %x\n ",
rio_table_ptr->ver_num, rio_table_ptr->scal_count,
rio_table_ptr->riodev_count, rio_table_ptr->offset);
rio_complete = 1;
}
}
if (!hs_complete && !rio_complete)
goto error_nodev;
if (rio_table_ptr) {
if (rio_complete && rio_table_ptr->ver_num == 3) {
rc = ebda_rio_table();
if (rc)
goto out;
}
}
rc = ebda_rsrc_controller();
if (rc)
goto out;
rc = ebda_rsrc_rsrc();
goto out;
error_nodev:
rc = -ENODEV;
out:
iounmap(io_mem);
return rc;
}