int __init ibmphp_access_ebda()

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