ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / scsi / scsi_pc98.c
1 /*
2  *  Copyright (C) 2003  Osamu Tomita <tomita@cinet.co.jp>
3  *
4  *  PC9801 BIOS geometry handling.
5  */
6
7 #include <linux/module.h>
8 #include <linux/fs.h>
9 #include <linux/kernel.h>
10 #include <linux/genhd.h>
11 #include <linux/blkdev.h>
12 #include <asm/pc9800.h>
13
14 #include "scsi.h"
15 #include "hosts.h"
16
17
18 static int pc98_first_bios_param(struct scsi_device *sdev, int *ip)
19 {
20         const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS) + sdev->id * 4);
21
22         ip[0] = p[1];   /* # of heads */
23         ip[1] = p[0];   /* # of sectors/track */
24         ip[2] = *(u16 *)&p[2] & 0x0fff; /* # of cylinders */
25         if (p[3] & (1 << 6)) { /* #-of-cylinders is 16-bit */
26                 ip[2] |= (ip[0] & 0xf0) << 8;
27                 ip[0] &= 0x0f;
28         }
29
30         return 0;
31 }
32
33 int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev,
34                         sector_t capacity, int *ip)
35 {
36         struct Scsi_Host *first_real = first_real_host();
37
38         /*
39          * XXX
40          * XXX This needs to become a sysfs attribute that's set
41          * XXX by code that knows which host is the first one.
42          * XXX
43          * XXX Currently we support only one host on with a
44          * XXX PC98ish HBA.
45          * XXX
46          */
47         if (1 || sdev->host == first_real && sdev->id < 7 &&
48             __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id))
49                 return pc98_first_bios_param(sdev, ip);
50
51         /* Assume PC-9801-92 compatible parameters for HAs without BIOS.  */
52         ip[0] = 8;
53         ip[1] = 32;
54         ip[2] = capacity / (8 * 32);
55         if (ip[2] > 65535) {    /* if capacity >= 8GB */
56                 /* Recent on-board adapters seem to use this parameter. */
57                 ip[1] = 128;
58                 ip[2] = capacity / (8 * 128);
59                 if (ip[2] > 65535) { /* if capacity >= 32GB  */
60                         /* Clip the number of cylinders.  Currently
61                            this is the limit that we deal with.  */
62                         ip[2] = 65535;
63                 }
64         }
65
66         return 0;
67 }
68
69 EXPORT_SYMBOL(pc98_bios_param);