Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 *  Copyright (C) 2003  Osamu Tomita <tomita@cinet.co.jp>
 *
 *  PC9801 BIOS geometry handling.
 */

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <asm/pc9800.h>

#include "scsi.h"
#include "hosts.h"


static int pc98_first_bios_param(struct scsi_device *sdev, int *ip)
{
	const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS) + sdev->id * 4);

	ip[0] = p[1];   /* # of heads */
	ip[1] = p[0];   /* # of sectors/track */
	ip[2] = *(u16 *)&p[2] & 0x0fff; /* # of cylinders */
	if (p[3] & (1 << 6)) { /* #-of-cylinders is 16-bit */
		ip[2] |= (ip[0] & 0xf0) << 8;
		ip[0] &= 0x0f;
	}

	return 0;
}

int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev,
			sector_t capacity, int *ip)
{
	struct Scsi_Host *first_real = first_real_host();

	/*
	 * XXX
	 * XXX This needs to become a sysfs attribute that's set
	 * XXX by code that knows which host is the first one.
	 * XXX
	 * XXX Currently we support only one host on with a
	 * XXX PC98ish HBA.
	 * XXX
	 */
	if (1 || sdev->host == first_real && sdev->id < 7 &&
	    __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id))
	    	return pc98_first_bios_param(sdev, ip);

	/* Assume PC-9801-92 compatible parameters for HAs without BIOS.  */
	ip[0] = 8;
	ip[1] = 32;
	ip[2] = capacity / (8 * 32);
	if (ip[2] > 65535) {    /* if capacity >= 8GB */
		/* Recent on-board adapters seem to use this parameter. */
		ip[1] = 128;
		ip[2] = capacity / (8 * 128);
		if (ip[2] > 65535) { /* if capacity >= 32GB  */
			/* Clip the number of cylinders.  Currently
			   this is the limit that we deal with.  */
			ip[2] = 65535;
		}
	}

	return 0;
}

EXPORT_SYMBOL(pc98_bios_param);