/*=====================================================================
 */
void HvCall_writeLogBuffer(const void *buffer, u64 bufLen)
{
	struct HvLpBufferList bufList;
	u64 bytesLeft = bufLen;
	u64 leftThisPage;
	u64 curPtr = virt_to_absolute((unsigned long) buffer);

	while (bytesLeft) {
		bufList.addr = curPtr;

		leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;

		if (leftThisPage > bytesLeft) {
			bufList.len = bytesLeft;
			bytesLeft = 0;
		} else {
			bufList.len = leftThisPage;
			bytesLeft -= leftThisPage;
		}


		HvCall2(HvCallBaseWriteLogBuffer,
			virt_to_absolute((unsigned long) &bufList),
			bufList.len);

		curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
	}
}
/*=====================================================================
 * Note that this call takes at MOST one page worth of data
 */
int HvCall_readLogBuffer(HvLpIndex lpIndex, void *buffer, u64 bufLen)
{
	struct HvLpBufferList *bufList;
	u64 bytesLeft = bufLen;
	u64 leftThisPage;
	u64 curPtr = virt_to_absolute( (unsigned long) buffer );
	u64 retVal;
	int npages;
	int i;

	npages = 0;
	while (bytesLeft) {
		npages++;
		leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;

		if (leftThisPage > bytesLeft)
			bytesLeft = 0;
		else
			bytesLeft -= leftThisPage;

		curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
	}

	if (npages == 0)
		return 0;

	bufList = (struct HvLpBufferList *)
		kmalloc(npages * sizeof(struct HvLpBufferList), GFP_ATOMIC);
	bytesLeft = bufLen;
	curPtr = virt_to_absolute( (unsigned long) buffer );
	for(i=0; i<npages; i++) {
		bufList[i].addr = curPtr;

		leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;

		if (leftThisPage > bytesLeft) {
			bufList[i].len = bytesLeft;
			bytesLeft = 0;
		} else {
			bufList[i].len = leftThisPage;
			bytesLeft -= leftThisPage;
		}

		curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
	}


	retVal = HvCall3(HvCallBaseReadLogBuffer, lpIndex,
			 virt_to_absolute((unsigned long)bufList), bufLen);

	kfree(bufList);

	return (int)retVal;
}
static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, 
				unsigned long uaddr, int direction )
{
	u64 set_tce_rc;
	union Tce tce;
	
	PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr);
	PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", 
	       tcenum, tbl, tbl->index);

	tce.wholeTce = 0;
	tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT;

	tce.tceBits.readWrite = 1;
	if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1;

	set_tce_rc = plpar_tce_put((u64)tbl->index, 
				 (u64)tcenum << 12, 
				 tce.wholeTce );

	if(set_tce_rc) {
		printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", set_tce_rc);
		printk("\tindex   = 0x%lx\n", (u64)tbl->index);
		printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
		printk("\ttce val = 0x%lx\n", tce.wholeTce );
	}
}
Beispiel #4
0
static void
rtas_flash_firmware(void)
{
	unsigned long image_size;
	struct flash_block_list *f, *next, *flist;
	unsigned long rtas_block_list;
	int i, status, update_token;

	update_token = rtas_token("ibm,update-flash-64-and-reboot");
	if (update_token == RTAS_UNKNOWN_SERVICE) {
		printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
		printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
		return;
	}

	/* NOTE: the "first" block list is a global var with no data
	 * blocks in the kernel data segment.  We do this because
	 * we want to ensure this block_list addr is under 4GB.
	 */
	rtas_firmware_flash_list.num_blocks = 0;
	flist = (struct flash_block_list *)&rtas_firmware_flash_list;
	rtas_block_list = virt_to_absolute((unsigned long)flist);
	if (rtas_block_list >= (4UL << 20)) {
		printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
		return;
	}

	printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
	/* Update the block_list in place. */
	image_size = 0;
	for (f = flist; f; f = next) {
		/* Translate data addrs to absolute */
		for (i = 0; i < f->num_blocks; i++) {
			f->blocks[i].data = (char *)virt_to_absolute((unsigned long)f->blocks[i].data);
			image_size += f->blocks[i].length;
		}
		next = f->next;
		/* Don't translate final NULL pointer */
		if (next)
			f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)next);

		/* make num_blocks into the version/length field */
		f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
	}

	printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
	printk(KERN_ALERT "FLASH: performing flash and reboot\n");
	ppc_md.progress("Flashing        \n", 0x0);
	ppc_md.progress("Please Wait...  ", 0x0);
	printk(KERN_ALERT "FLASH: this will take several minutes.  Do not power off!\n");
	status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
	switch (status) {	/* should only get "bad" status */
	    case 0:
		printk(KERN_ALERT "FLASH: success\n");
		break;
	    case -1:
		printk(KERN_ALERT "FLASH: hardware error.  Firmware may not be not flashed\n");
		break;
	    case -3:
		printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform.  Firmware not flashed\n");
		break;
	    case -4:
		printk(KERN_ALERT "FLASH: flash failed when partially complete.  System may not reboot\n");
		break;
	    default:
		printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
		break;
	}
}