* [PATCHSET 17/23] add support for PC-9800 architecture (SCSI)
@ 2002-10-28 17:30 Osamu Tomita
2002-10-28 22:33 ` Alan Cox
0 siblings, 1 reply; 7+ messages in thread
From: Osamu Tomita @ 2002-10-28 17:30 UTC (permalink / raw)
To: LKML; +Cc: Linus Torvalds
This is a part 17/23 of patchset for add support NEC PC-9800 architecture,
against 2.5.44.
Summary:
SCSI driver related modules.
- replace bios_param function.
- add new driver. (pc980155)
- export sd_get_sdisk to get disk goemetry.
we need disk geometry to read partition table.
diffstat:
drivers/scsi/Config.in | 3
drivers/scsi/Makefile | 1
drivers/scsi/advansys.c | 9 +
drivers/scsi/aic7xxx/aic7xxx_linux_host.h | 3
drivers/scsi/aic7xxx_old/aic7xxx.h | 9 -
drivers/scsi/pc980155.c | 262 ++++++++++++++++++++++++++++++
drivers/scsi/pc980155.h | 47 +++++
drivers/scsi/pc980155regs.h | 89 ++++++++++
drivers/scsi/scsi_scan.c | 1
drivers/scsi/scsi_syms.c | 6
drivers/scsi/scsicam.c | 91 ++++++++++
drivers/scsi/sd.c | 8
drivers/scsi/wd33c93.c | 51 +++--
drivers/scsi/wd33c93.h | 5
include/scsi/scsicam.h | 5
15 files changed, 567 insertions(+), 23 deletions(-)
patch:
diff -urN linux/drivers/scsi/Config.in linux98/drivers/scsi/Config.in
--- linux/drivers/scsi/Config.in Sat Oct 12 13:22:05 2002
+++ linux98/drivers/scsi/Config.in Sun Oct 13 18:26:42 2002
@@ -258,6 +258,9 @@
# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI
fi
fi
+if [ "$CONFIG_PC9800" = "y" ]; then
+ dep_tristate 'NEC PC-9801-55 SCSI support' CONFIG_SCSI_PC980155 $CONFIG_SCSI
+fi
endmenu
diff -urN linux/drivers/scsi/Makefile linux98/drivers/scsi/Makefile
--- linux/drivers/scsi/Makefile Sat Oct 12 13:21:35 2002
+++ linux98/drivers/scsi/Makefile Sun Oct 13 18:28:50 2002
@@ -31,6 +31,7 @@
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
+obj-$(CONFIG_SCSI_PC980155) += pc980155.o wd33c93.o
obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
diff -urN linux/drivers/scsi/advansys.c linux98/drivers/scsi/advansys.c
--- linux/drivers/scsi/advansys.c Wed Oct 16 13:20:38 2002
+++ linux98/drivers/scsi/advansys.c Wed Oct 16 15:26:55 2002
@@ -815,6 +815,9 @@
#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif /* CONFIG_PCI */
+#ifdef CONFIG_PC9800
+#include <scsi/scsicam.h>
+#endif
/*
@@ -6117,10 +6120,13 @@
int
advansys_biosparam(Disk *dp, struct block_device *dep, int ip[])
{
+#ifndef CONFIG_PC9800
asc_board_t *boardp;
+#endif
ASC_DBG(1, "advansys_biosparam: begin\n");
ASC_STATS(dp->device->host, biosparam);
+#ifndef CONFIG_PC9800
boardp = ASC_BOARDP(dp->device->host);
if (ASC_NARROW_BOARD(boardp)) {
if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
@@ -6142,6 +6148,9 @@
}
}
ip[2] = (unsigned long)dp->capacity / (ip[0] * ip[1]);
+#else /* CONFIG_PC9800 */
+ pc9800_scsi_bios_param(dp, dep, ip);
+#endif /* !CONFIG_PC9800 */
ASC_DBG(1, "advansys_biosparam: end\n");
return 0;
}
diff -urN linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h linux98/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
--- linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Fri Apr 12 13:57:53 2002
+++ linux98/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Fri Apr 12 15:45:26 2002
@@ -52,7 +52,8 @@
int ahc_linux_dev_reset(Scsi_Cmnd *);
int ahc_linux_abort(Scsi_Cmnd *);
-#if defined(__i386__)
+#include <linux/config.h>
+#if defined(__i386__) && !defined(CONFIG_PC9800)
# define AIC7XXX_BIOSPARAM ahc_linux_biosparam
#else
# define AIC7XXX_BIOSPARAM NULL
diff -urN linux/drivers/scsi/aic7xxx_old/aic7xxx.h linux98/drivers/scsi/aic7xxx_old/aic7xxx.h
--- linux/drivers/scsi/aic7xxx_old/aic7xxx.h Sat Oct 19 13:01:08 2002
+++ linux98/drivers/scsi/aic7xxx_old/aic7xxx.h Sat Oct 19 15:39:43 2002
@@ -23,6 +23,13 @@
#ifndef _aic7xxx_h
#define _aic7xxx_h
+#include <linux/config.h>
+
+#ifndef CONFIG_PC9800
+# define AIC7XXX_BIOSPARAM aic7xxx_biosparam
+#else
+# define AIC7XXX_BIOSPARAM NULL
+#endif
#define AIC7XXX_H_VERSION "5.2.0"
/*
@@ -44,7 +51,7 @@
reset: aic7xxx_reset, \
slave_attach: aic7xxx_slave_attach, \
slave_detach: aic7xxx_slave_detach, \
- bios_param: aic7xxx_biosparam, \
+ bios_param: AIC7XXX_BIOSPARAM, \
can_queue: 255, /* max simultaneous cmds */\
this_id: -1, /* scsi id of host adapter */\
sg_tablesize: 0, /* max scatter-gather cmds */\
diff -urN linux/drivers/scsi/pc980155.c linux98/drivers/scsi/pc980155.c
--- linux/drivers/scsi/pc980155.c Thu Jan 1 09:00:00 1970
+++ linux98/drivers/scsi/pc980155.c Sun Feb 3 12:08:14 2002
@@ -0,0 +1,262 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/module.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "pc980155.h"
+#include "pc980155regs.h"
+
+#define DEBUG
+
+#include<linux/stat.h>
+
+static inline void __print_debug_info(unsigned int);
+static inline void __print_debug_info(unsigned int a){}
+#define print_debug_info() __print_debug_info(base_io);
+
+#define NR_BASE_IOS 4
+static int nr_base_ios = NR_BASE_IOS;
+static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0, 0xcf0};
+static unsigned int SASR;
+static unsigned int SCMD;
+static wd33c93_regs regs = {&SASR, &SCMD};
+
+static struct Scsi_Host *pc980155_host = NULL;
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp);
+
+inline void pc980155_dma_enable(unsigned int base_io){
+ outb(0x01, REG_CWRITE);
+ WAIT();
+}
+inline void pc980155_dma_disable(unsigned int base_io){
+ outb(0x02, REG_CWRITE);
+ WAIT();
+}
+
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp)
+{
+ wd33c93_intr(pc980155_host);
+}
+
+static int dma_setup(Scsi_Cmnd *sc, int dir_in){
+ /*
+ * sc->SCp.this_residual : transfer count
+ * sc->SCp.ptr : distination address (virtual address)
+ * dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1)
+ *
+ * if success return 0
+ */
+
+ /*
+ * DMA WRITE MODE
+ * bit 7,6 01b single mode (this mode only)
+ * bit 5 inc/dec (default:0 = inc)
+ * bit 4 auto initialize (normaly:0 = off)
+ * bit 3,2 01b memory -> io
+ * 10b io -> memory
+ * 00b verify
+ * bit 1,0 channel
+ */
+ disable_dma(sc->host->dma_channel);
+ set_dma_mode(sc->host->dma_channel, 0x40 | (dir_in ? 0x04 : 0x08));
+ clear_dma_ff(sc->host->dma_channel);
+ set_dma_addr(sc->host->dma_channel, virt_to_phys(sc->SCp.ptr));
+ set_dma_count(sc->host->dma_channel, sc->SCp.this_residual);
+#if 0
+#ifdef DEBUG
+ printk("D%d(%x)D", sc->SCp.this_residual);
+#endif
+#endif
+ enable_dma(sc->host->dma_channel);
+
+ pc980155_dma_enable(sc->host->io_port);
+
+ return 0;
+}
+
+static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int status){
+ /*
+ * instance: Hostadapter's instance
+ * sc: scsi command
+ * status: True if success
+ */
+
+ pc980155_dma_disable(sc->host->io_port);
+
+ disable_dma(sc->host->dma_channel);
+}
+
+/* return non-zero on detection */
+static inline int pc980155_test_port(wd33c93_regs regs)
+{
+ /* Quick and dirty test for presence of the card. */
+ if (READ_AUX_STAT() == 0xff)
+ return 0;
+ return 1;
+}
+
+static inline int
+pc980155_getconfig(unsigned int base_io, wd33c93_regs regs,
+ unsigned char* irq, unsigned char* dma,
+ unsigned char* scsi_id)
+{
+ static unsigned char irqs[] = { 3, 5, 6, 9, 12, 13 };
+ unsigned char result;
+
+ printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n",
+ base_io, *regs.SASR, *regs.SCMD);
+ result = read_wd33c93(regs, WD_RESETINT);
+ printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result);
+ *scsi_id = result & 0x07;
+ *irq = (result >> 3) & 0x07;
+ if (*irq > 5) {
+ printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ (%d)"
+ " - other device here?\n", base_io, *irq);
+ return 0;
+ }
+
+ *irq = irqs[*irq];
+ result = inb(REG_STATRD);
+ WAIT();
+ *dma = result & 0x03;
+ if (*dma == 1) {
+ printk(KERN_ERR
+ "PC-9801-55 (base %#x): impossible DMA channl (%d)"
+ " - other device here?\n", base_io, *dma);
+ return 0;
+ }
+#ifdef DEBUG
+ printk("PC-9801-55: end of getconfig\n");
+#endif
+ return 1;
+}
+
+/* return non-zero on detection */
+int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
+{
+ unsigned int base_io;
+ unsigned char irq, dma, scsi_id;
+ int i;
+#ifdef DEBUG
+ unsigned char debug;
+#endif
+
+ for (i = 0; i < nr_base_ios; i++) {
+ base_io = base_ios[i];
+ SASR = REG_ADDRST;
+ SCMD = REG_CONTRL;
+
+ /* printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST); */
+ if (check_region(base_io, 6))
+ continue;
+ if (! pc980155_test_port(regs))
+ continue;
+
+ if (!pc980155_getconfig(base_io, regs, &irq, &dma, &scsi_id))
+ continue;
+#ifdef DEBUG
+ printk("PC-9801-55: config: base io = %x, irq = %d, dma channel = %d, scsi id = %d\n",
+ base_io, irq, dma, scsi_id);
+#endif
+ if (request_irq(irq, pc980155_intr_handle, 0, "PC-9801-55",
+ NULL)) {
+ printk(KERN_ERR
+ "PC-9801-55: unable to allocate IRQ %d\n",
+ irq);
+ continue;
+ }
+ if (request_dma(dma, "PC-9801-55")) {
+ printk(KERN_ERR "PC-9801-55: "
+ "unable to allocate DMA channel %d\n", dma);
+ free_irq(irq, NULL);
+ continue;
+ }
+
+ request_region(base_io, 6, "PC-9801-55");
+ pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+ pc980155_host->this_id = scsi_id;
+ pc980155_host->io_port = base_io;
+ pc980155_host->n_io_port = 6;
+ pc980155_host->irq = irq;
+ pc980155_host->dma_channel = dma;
+
+#ifdef DEBUG
+ printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma);
+ debug = read_aux_stat(regs);
+ printk("PC-9801-55: aux: %x ", debug);
+ debug = read_wd33c93(regs, 0x17);
+ printk("status: %x\n", debug);
+#endif
+
+ pc980155_int_enable(regs);
+
+ wd33c93_init(pc980155_host, regs, dma_setup, dma_stop,
+ WD33C93_FS_12_15);
+
+ return 1;
+ }
+
+ printk("PC-9801-55: not found\n");
+ return 0;
+}
+
+int pc980155_proc_info(char *buf, char **start, off_t off, int len,
+ int hostno, int in)
+{
+ /* NOT SUPPORTED YET! */
+
+ if (in) {
+ return -EPERM;
+ }
+ *start = buf;
+ return sprintf(buf, "Sorry, not supported yet.\n");
+}
+
+int pc980155_setup(char *str)
+{
+next:
+ if (!strncmp(str, "io:", 3)){
+ base_ios[0] = simple_strtoul(str+3,NULL,0);
+ nr_base_ios = 1;
+ while (*str > ' ' && *str != ',')
+ str++;
+ if (*str == ','){
+ str++;
+ goto next;
+ }
+ }
+ return 0;
+}
+
+int scsi_pc980155_release(struct Scsi_Host *pc980155_host)
+{
+#ifdef MODULE
+ pc980155_int_disable(regs);
+ release_region(pc980155_host->io_port, pc980155_host->n_io_port);
+ free_irq(pc980155_host->irq, NULL);
+ free_dma(pc980155_host->dma_channel);
+ wd33c93_release();
+#endif
+ return 1;
+}
+
+__setup("pc980155=", pc980155_setup);
+
+Scsi_Host_Template driver_template = SCSI_PC980155;
+
+#include "scsi_module.c"
diff -urN linux/drivers/scsi/pc980155.h linux98/drivers/scsi/pc980155.h
--- linux/drivers/scsi/pc980155.h Thu Jan 1 09:00:00 1970
+++ linux98/drivers/scsi/pc980155.h Sun Feb 3 12:08:14 2002
@@ -0,0 +1,47 @@
+/*
+ * PC-9801-55 SCSI host adapter driver
+ *
+ * Copyright (C) 1997-2000 Kyoto University Microcomputer Club
+ * (Linux/98 project)
+ */
+
+#ifndef _SCSI_PC9801_55_H
+#define _SCSI_PC9801_55_H
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <scsi/scsicam.h>
+
+int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd33c93_abort(Scsi_Cmnd *);
+int wd33c93_reset(Scsi_Cmnd *, unsigned int);
+int scsi_pc980155_detect(Scsi_Host_Template *);
+int scsi_pc980155_release(struct Scsi_Host *);
+int pc980155_proc_info(char *, char **, off_t, int, int, int);
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+#define SCSI_PC980155 { proc_name: "PC-9801-55", \
+ name: "SCSI PC-9801-55", \
+ proc_info: pc980155_proc_info, \
+ detect: scsi_pc980155_detect, \
+ release: scsi_pc980155_release, \
+ /* command: use queue command */ \
+ queuecommand: wd33c93_queuecommand, \
+ abort: wd33c93_abort, \
+ reset: wd33c93_reset, \
+ bios_param: pc9800_scsi_bios_param, \
+ can_queue: CAN_QUEUE, \
+ this_id: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: CMD_PER_LUN, /* dont use link command */ \
+ unchecked_isa_dma: 1, /* use dma **XXXX***/ \
+ use_clustering: ENABLE_CLUSTERING }
+
+#endif /* _SCSI_PC9801_55_H */
diff -urN linux/drivers/scsi/pc980155regs.h linux98/drivers/scsi/pc980155regs.h
--- linux/drivers/scsi/pc980155regs.h Thu Jan 1 09:00:00 1970
+++ linux98/drivers/scsi/pc980155regs.h Mon Dec 3 18:44:10 2001
@@ -0,0 +1,89 @@
+#ifndef __PC980155REGS_H
+#define __PC980155REGS_H
+
+#include "wd33c93.h"
+
+#define REG_ADDRST (base_io+0)
+#define REG_CONTRL (base_io+2)
+#define REG_CWRITE (base_io+4)
+#define REG_STATRD (base_io+4)
+
+#define WD_MEMORYBANK 0x30
+#define WD_RESETINT 0x33
+
+#if 0
+#define WAIT() outb(0x00,0x5f)
+#else
+#define WAIT() do{}while(0)
+#endif
+
+static inline uchar read_wd33c93(const wd33c93_regs regs, uchar reg_num)
+{
+ uchar data;
+ outb(reg_num, *regs.SASR);
+ WAIT();
+ data = inb(*regs.SCMD);
+ WAIT();
+ return data;
+}
+
+static inline uchar read_aux_stat(const wd33c93_regs regs)
+{
+ uchar result;
+ result = inb(*regs.SASR);
+ WAIT();
+ /* printk("PC-9801-55: regp->SASR(%x) = %x\n", regp->SASR, result); */
+ return result;
+}
+#define READ_AUX_STAT() read_aux_stat(regs)
+
+static inline void write_wd33c93(const wd33c93_regs regs, uchar reg_num,
+ uchar value)
+{
+ outb(reg_num, *regs.SASR);
+ WAIT();
+ outb(value, *regs.SCMD);
+ WAIT();
+}
+
+
+#define write_wd33c93_cmd(regs,cmd) write_wd33c93(regs,WD_COMMAND,cmd)
+
+static inline void write_wd33c93_count(const wd33c93_regs regs,
+ unsigned long value)
+{
+ outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
+ WAIT();
+ outb((value >> 16) & 0xff, *regs.SCMD);
+ WAIT();
+ outb((value >> 8) & 0xff, *regs.SCMD);
+ WAIT();
+ outb( value & 0xff, *regs.SCMD);
+ WAIT();
+}
+
+
+static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
+{
+unsigned long value;
+
+ outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
+ value = inb(*regs.SCMD) << 16;
+ value |= inb(*regs.SCMD) << 8;
+ value |= inb(*regs.SCMD);
+ return value;
+}
+
+static inline void write_wd33c93_cdb(const wd33c93_regs regs, unsigned int len,
+ unsigned char cmnd[])
+{
+ int i;
+ outb(WD_CDB_1, *regs.SASR);
+ for (i=0; i<len; i++)
+ outb(cmnd[i], *regs.SCMD);
+}
+
+#define pc980155_int_enable(regs) write_wd33c93(regs, WD_MEMORYBANK, read_wd33c93(regs, WD_MEMORYBANK) | 0x04)
+#define pc980155_int_disable(regs) write_wd33c93(regs, WD_MEMORYBANK, read_wd33c93(regs, WD_MEMORYBANK) & ~0x04)
+
+#endif
diff -urN linux/drivers/scsi/scsi_scan.c linux98/drivers/scsi/scsi_scan.c
--- linux/drivers/scsi/scsi_scan.c Wed Aug 28 09:52:26 2002
+++ linux98/drivers/scsi/scsi_scan.c Wed Aug 28 13:09:39 2002
@@ -131,6 +131,7 @@
{"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */
{"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */
{"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all lun */
+ {"NEC", "D3856", "0009", BLIST_NOLUN},
/*
* Other types of devices that have special flags.
diff -urN linux/drivers/scsi/scsi_syms.c linux98/drivers/scsi/scsi_syms.c
--- linux/drivers/scsi/scsi_syms.c Sat Oct 19 13:01:53 2002
+++ linux98/drivers/scsi/scsi_syms.c Sat Oct 19 15:39:43 2002
@@ -97,6 +97,12 @@
EXPORT_SYMBOL(scsi_devicelist);
EXPORT_SYMBOL(scsi_device_types);
+#ifdef CONFIG_PC9800
+EXPORT_SYMBOL(pc9800_scsi_bios_param);
+extern Scsi_Disk * sd_get_sdisk(int);
+EXPORT_SYMBOL(sd_get_sdisk);
+#endif
+
/*
* Externalize timers so that HBAs can safely start/restart commands.
*/
diff -urN linux/drivers/scsi/scsicam.c linux98/drivers/scsi/scsicam.c
--- linux/drivers/scsi/scsicam.c Sat Oct 19 13:01:59 2002
+++ linux98/drivers/scsi/scsicam.c Sun Oct 20 10:23:06 2002
@@ -12,6 +12,8 @@
#include <linux/module.h>
+#include <linux/config.h>
+
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
@@ -61,7 +63,14 @@
int ret_code;
int size = disk->capacity;
unsigned long temp_cyl;
- unsigned char *p = scsi_bios_ptable(bdev);
+ unsigned char *p;
+
+#ifdef CONFIG_PC9800
+ if (!pc9800_scsi_bios_param(disk, bdev, ip))
+ return 0;
+#endif
+
+ p = scsi_bios_ptable(bdev);
if (!p)
return -1;
@@ -238,3 +247,83 @@
*hds = (unsigned int) heads;
return (rv);
}
+
+#ifdef CONFIG_PC9800
+
+#include <asm/pc9800.h>
+
+/* XXX - For now, we assume the first (i.e. having the least host_no)
+ real (i.e. non-emulated) host adapter shall be BIOS-controlled one.
+ We *SHOULD* invent another way. */
+
+static inline struct Scsi_Host *first_real_host(void)
+{
+ struct Scsi_Host *h = NULL;
+
+ while ((h = scsi_host_get_next(h)))
+ if (!h->hostt->emulated)
+ break;
+
+ return h;
+}
+
+/* There is no standard device-to-name translation function. Sigh. */
+static inline void sd_devname(char *buf, kdev_t dev)
+{
+ int diskno = (major(dev) & SD_MAJOR_MASK) * 16 + (minor(dev) >> 4);
+
+ buf[0] = 'a' + diskno;
+ buf[1] = '\0';
+ if (diskno >= 26) {
+ buf[0] = 'a' + (diskno / 26 - 1);
+ buf[1] = 'a' + (diskno % 26);
+ buf[2] = '\0';
+ }
+}
+
+int pc9800_scsi_bios_param(Disk *disk, struct block_device *bdev, int *ip)
+{
+ char namebuf[4];
+
+ sd_devname(namebuf, to_kdev_t(bdev->bd_dev));
+
+ if (first_real_host () == disk->device->host
+ && disk->device->id < 7
+ && __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, disk->device->id))
+ {
+ const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS)
+ + disk->device->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;
+ }
+ printk(KERN_INFO "sd%s: "
+ "BIOS parameters CHS:%d/%d/%d, %u bytes %s sector\n",
+ namebuf, ip[2], ip[0], ip[1], 256 << ((p[3] >> 4) & 3),
+ p[3] & 0x80 ? "hard" : "soft");
+ return 0;
+ }
+
+ /* Assume PC-9801-92 compatible parameters for HAs without BIOS. */
+ ip[0] = 8;
+ ip[1] = 32;
+ ip[2] = disk->capacity / (8 * 32);
+ if (ip[2] > 65535) { /* if capacity >= 8GB */
+ /* Recent on-board adapters seem to use this parameter. */
+ ip[1] = 128;
+ ip[2] = disk->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;
+ }
+ }
+ printk(KERN_INFO "sd%s: BIOS parameters CHS:%d/%d/%d (assumed)\n",
+ namebuf, ip[2], ip[0], ip[1]);
+ return 0;
+}
+#endif /* CONFIG_PC9800 */
diff -urN linux/drivers/scsi/sd.c linux98/drivers/scsi/sd.c
--- linux/drivers/scsi/sd.c Sat Oct 19 13:02:27 2002
+++ linux98/drivers/scsi/sd.c Sat Oct 19 15:39:43 2002
@@ -124,7 +124,11 @@
static void sd_rw_intr(Scsi_Cmnd * SCpnt);
+#ifndef CONFIG_PC9800
static Scsi_Disk * sd_get_sdisk(int index);
+#else
+Scsi_Disk * sd_get_sdisk(int index);
+#endif
#if defined(CONFIG_PPC32)
/**
@@ -1613,7 +1617,11 @@
return (the_result == 0);
}
+#ifndef CONFIG_PC9800
static Scsi_Disk * sd_get_sdisk(int index)
+#else
+Scsi_Disk * sd_get_sdisk(int index)
+#endif
{
Scsi_Disk * sdkp = NULL;
unsigned long iflags;
diff -urN linux/drivers/scsi/wd33c93.c linux98/drivers/scsi/wd33c93.c
--- linux/drivers/scsi/wd33c93.c Sat Oct 19 13:02:24 2002
+++ linux98/drivers/scsi/wd33c93.c Sat Oct 19 16:16:46 2002
@@ -84,6 +84,7 @@
#include <linux/init.h>
#include <asm/irq.h>
#include <linux/blk.h>
+#include <linux/spinlock.h>
#include "scsi.h"
#include "hosts.h"
@@ -173,7 +174,11 @@
MODULE_PARM(setup_strings, "s");
#endif
+static spinlock_t wd_lock = SPIN_LOCK_UNLOCKED;
+#if defined(CONFIG_SCSI_PC980155) || defined(CONFIG_SCSI_PC980155_MODULE)
+#include "pc980155regs.h"
+#else /* !CONFIG_SCSI_PC980155 */
static inline uchar read_wd33c93(const wd33c93_regs regs, uchar reg_num)
{
@@ -203,6 +208,7 @@
*regs.SCMD = cmd;
mb();
}
+#endif /* CONFIG_SCSI_PC980155 */
static inline uchar read_1_byte(const wd33c93_regs regs)
@@ -220,6 +226,7 @@
return x;
}
+#if !defined(CONFIG_SCSI_PC980155) && !defined(CONFIG_SCSI_PC980155_MODULE)
static void write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
{
@@ -244,6 +251,7 @@
mb();
return value;
}
+#endif /* !CONFIG_SCSI_PC980155 */
/* The 33c93 needs to be told which direction a command transfers its
@@ -385,8 +393,7 @@
* sense data is not lost before REQUEST_SENSE executes.
*/
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&wd_lock, flags);
if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
cmd->host_scribble = (uchar *)hostdata->input_Q;
@@ -407,7 +414,7 @@
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
- restore_flags(flags);
+ spin_unlock_irqrestore(&wd_lock, flags);
return 0;
}
@@ -428,7 +435,6 @@
struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata *)instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *cmd, *prev;
-int i;
DB(DB_EXECUTE,printk("EX("))
@@ -591,9 +597,16 @@
* (take advantage of auto-incrementing)
*/
- *regs.SASR = WD_CDB_1;
- for (i=0; i<cmd->cmd_len; i++)
- *regs.SCMD = cmd->cmnd[i];
+#if defined(CONFIG_SCSI_PC980155) || defined(CONFIG_SCSI_PC980155_MODULE)
+ write_wd33c93_cdb(regs, cmd->cmd_len, cmd->cmnd);
+#else /* !CONFIG_SCSI_PC980155 */
+ {
+ int i;
+ *regs.SASR = WD_CDB_1;
+ for (i = 0; i < cmd->cmd_len; i++)
+ *regs.SCMD = cmd->cmnd[i];
+ }
+#endif /* CONFIG_SCSI_PC980155 */
/* The wd33c93 only knows about Group 0, 1, and 5 commands when
* it's doing a 'select-and-transfer'. To be safe, we write the
@@ -765,7 +778,7 @@
if (!(asr & ASR_INT) || (asr & ASR_BSY))
return;
- save_flags(flags);
+ local_save_flags(flags);
#ifdef PROC_STATISTICS
hostdata->int_cnt++;
@@ -831,7 +844,7 @@
* is here...
*/
- restore_flags(flags);
+ local_irq_restore(flags);
/* We are not connected to a target - check to see if there
* are commands waiting to be executed.
@@ -1085,7 +1098,7 @@
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
}
- restore_flags(flags);
+ local_irq_restore(flags);
break;
@@ -1117,7 +1130,7 @@
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
wd33c93_execute(instance);
}
else {
@@ -1200,7 +1213,7 @@
* there are commands waiting to be executed.
*/
/* look above for comments on scsi_done() */
- restore_flags(flags);
+ local_irq_restore(flags);
wd33c93_execute(instance);
break;
@@ -1228,7 +1241,7 @@
else
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->scsi_done(cmd);
- restore_flags(flags);
+ local_irq_restore(flags);
break;
case S_PRE_TMP_DISC:
case S_RUNNING_LEVEL2:
@@ -1693,7 +1706,7 @@
return 1;
}
-__setup("wd33c93", wd33c93_setup);
+__setup("wd33c93=", wd33c93_setup);
/* check_setup_args() returns index if key found, 0 if not
@@ -1831,10 +1844,9 @@
{ unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&wd_lock, flags);
reset_wd33c93(instance);
- restore_flags(flags);
+ spin_unlock_irqrestore(&wd_lock, flags);
}
printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",instance->host_no,
@@ -1929,8 +1941,7 @@
return len;
}
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&wd_lock, flags);
bp = buf;
*bp = '\0';
if (hd->proc & PR_VERSION) {
@@ -2005,7 +2016,7 @@
}
}
strcat(bp,"\n");
- restore_flags(flags);
+ spin_unlock_irqrestore(&wd_lock, flags);
*start = buf;
if (stop) {
stop = 0;
diff -urN linux/drivers/scsi/wd33c93.h linux98/drivers/scsi/wd33c93.h
--- linux/drivers/scsi/wd33c93.h Sat Oct 12 13:21:35 2002
+++ linux98/drivers/scsi/wd33c93.h Sat Oct 12 14:18:53 2002
@@ -186,8 +186,13 @@
/* This is what the 3393 chip looks like to us */
typedef struct {
+#if defined(CONFIG_SCSI_PC980155) || defined(CONFIG_SCSI_PC980155_MODULE)
+ volatile unsigned int *SASR;
+ volatile unsigned int *SCMD;
+#else
volatile unsigned char *SASR;
volatile unsigned char *SCMD;
+#endif
} wd33c93_regs;
diff -urN linux/include/scsi/scsicam.h linux98/include/scsi/scsicam.h
--- linux/include/scsi/scsicam.h Thu Jul 25 06:03:26 2002
+++ linux98/include/scsi/scsicam.h Fri Jul 26 11:32:39 2002
@@ -12,8 +12,13 @@
#ifndef SCSICAM_H
#define SCSICAM_H
+#include <linux/config.h>
extern int scsicam_bios_param (Disk *disk, struct block_device *bdev, int *ip);
extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int *secs);
extern unsigned char *scsi_bios_ptable(struct block_device *bdev);
+#ifdef CONFIG_PC9800
+extern int pc9800_scsi_bios_param(Disk *disk, struct block_device *bdev,
+ int *ip);
+#endif
#endif /* def SCSICAM_H */
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCHSET 17/23] add support for PC-9800 architecture (SCSI)
2002-10-28 17:30 [PATCHSET 17/23] add support for PC-9800 architecture (SCSI) Osamu Tomita
@ 2002-10-28 22:33 ` Alan Cox
2002-10-29 17:04 ` Osamu Tomita
2002-10-29 17:11 ` [PATCHSET 8/23] add support for PC-9800 architecture (fs) Osamu Tomita
0 siblings, 2 replies; 7+ messages in thread
From: Alan Cox @ 2002-10-28 22:33 UTC (permalink / raw)
To: Osamu Tomita; +Cc: LKML, Linus Torvalds
On Mon, 2002-10-28 at 17:30, Osamu Tomita wrote:
> This is a part 17/23 of patchset for add support NEC PC-9800 architecture,
> against 2.5.44.
If all the BIOS mapping for the PC9800 is the same then intead of
patching the drivers add an
if(pc98)
pci98_bios_param(...)
else
host->bios_param()
change in the scsi core code not in each driver
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHSET 17/23] add support for PC-9800 architecture (SCSI)
2002-10-28 22:33 ` Alan Cox
@ 2002-10-29 17:04 ` Osamu Tomita
2002-10-29 17:11 ` [PATCHSET 8/23] add support for PC-9800 architecture (fs) Osamu Tomita
1 sibling, 0 replies; 7+ messages in thread
From: Osamu Tomita @ 2002-10-29 17:04 UTC (permalink / raw)
To: Alan Cox; +Cc: LKML, Linus Torvalds
2002.10.29 07:33, Alan Cox wrote:
> On Mon, 2002-10-28 at 17:30, Osamu Tomita wrote:
> > This is a part 17/23 of patchset for add support NEC PC-9800
> architecture,
> > against 2.5.44.
>
> If all the BIOS mapping for the PC9800 is the same then intead of
> patching the drivers add an
>
> if(pc98)
> pci98_bios_param(...)
> else
> host->bios_param()
>
> change in the scsi core code not in each driver
>
Thanks. I've re-written patch. And I found some missing EXPORT_SYMBOL
in wd33c93.c. This patch include them. Here is a patch.
diff -urN linux/drivers/scsi/Config.in linux98/drivers/scsi/Config.in
--- linux/drivers/scsi/Config.in Sat Oct 12 13:22:05 2002
+++ linux98/drivers/scsi/Config.in Sun Oct 13 18:26:42 2002
@@ -258,6 +258,9 @@
# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)'
CONFIG_GVP_TURBO_SCSI
fi
fi
+if [ "$CONFIG_PC9800" = "y" ]; then
+ dep_tristate 'NEC PC-9801-55 SCSI support' CONFIG_SCSI_PC980155
$CONFIG_SCSI
+fi
endmenu
diff -urN linux/drivers/scsi/Makefile linux98/drivers/scsi/Makefile
--- linux/drivers/scsi/Makefile Sat Oct 19 13:02:28 2002
+++ linux98/drivers/scsi/Makefile Tue Oct 29 15:45:44 2002
@@ -18,7 +18,7 @@
CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__
-DGDTH_STATISTICS
CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
-export-objs := scsi_syms.o 53c700.o
+export-objs := scsi_syms.o 53c700.o wd33c93.o
subdir-$(CONFIG_PCMCIA) += pcmcia
@@ -31,6 +31,7 @@
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
+obj-$(CONFIG_SCSI_PC980155) += pc980155.o wd33c93.o
obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
diff -urN linux/drivers/scsi/pc980155.c linux98/drivers/scsi/pc980155.c
--- linux/drivers/scsi/pc980155.c Thu Jan 1 09:00:00 1970
+++ linux98/drivers/scsi/pc980155.c Sun Feb 3 12:08:14 2002
@@ -0,0 +1,262 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/module.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "pc980155.h"
+#include "pc980155regs.h"
+
+#define DEBUG
+
+#include<linux/stat.h>
+
+static inline void __print_debug_info(unsigned int);
+static inline void __print_debug_info(unsigned int a){}
+#define print_debug_info() __print_debug_info(base_io);
+
+#define NR_BASE_IOS 4
+static int nr_base_ios = NR_BASE_IOS;
+static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0,
0xcf0};
+static unsigned int SASR;
+static unsigned int SCMD;
+static wd33c93_regs regs = {&SASR, &SCMD};
+
+static struct Scsi_Host *pc980155_host = NULL;
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs
*regp);
+
+inline void pc980155_dma_enable(unsigned int base_io){
+ outb(0x01, REG_CWRITE);
+ WAIT();
+}
+inline void pc980155_dma_disable(unsigned int base_io){
+ outb(0x02, REG_CWRITE);
+ WAIT();
+}
+
+
+static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs
*regp)
+{
+ wd33c93_intr(pc980155_host);
+}
+
+static int dma_setup(Scsi_Cmnd *sc, int dir_in){
+ /*
+ * sc->SCp.this_residual : transfer count
+ * sc->SCp.ptr : distination address (virtual address)
+ * dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1)
+ *
+ * if success return 0
+ */
+
+ /*
+ * DMA WRITE MODE
+ * bit 7,6 01b single mode (this mode only)
+ * bit 5 inc/dec (default:0 = inc)
+ * bit 4 auto initialize (normaly:0 = off)
+ * bit 3,2 01b memory -> io
+ * 10b io -> memory
+ * 00b verify
+ * bit 1,0 channel
+ */
+ disable_dma(sc->host->dma_channel);
+ set_dma_mode(sc->host->dma_channel, 0x40 | (dir_in ? 0x04 : 0x08));
+ clear_dma_ff(sc->host->dma_channel);
+ set_dma_addr(sc->host->dma_channel, virt_to_phys(sc->SCp.ptr));
+ set_dma_count(sc->host->dma_channel, sc->SCp.this_residual);
+#if 0
+#ifdef DEBUG
+ printk("D%d(%x)D", sc->SCp.this_residual);
+#endif
+#endif
+ enable_dma(sc->host->dma_channel);
+
+ pc980155_dma_enable(sc->host->io_port);
+
+ return 0;
+}
+
+static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int
status){
+ /*
+ * instance: Hostadapter's instance
+ * sc: scsi command
+ * status: True if success
+ */
+
+ pc980155_dma_disable(sc->host->io_port);
+
+ disable_dma(sc->host->dma_channel);
+} +
+/* return non-zero on detection */
+static inline int pc980155_test_port(wd33c93_regs regs)
+{
+ /* Quick and dirty test for presence of the card. */
+ if (READ_AUX_STAT() == 0xff)
+ return 0;
+ return 1;
+}
+
+static inline int
+pc980155_getconfig(unsigned int base_io, wd33c93_regs regs,
+ unsigned char* irq, unsigned char* dma,
+ unsigned char* scsi_id)
+{
+ static unsigned char irqs[] = { 3, 5, 6, 9, 12, 13 };
+ unsigned char result;
+ + printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n",
+ base_io, *regs.SASR, *regs.SCMD);
+ result = read_wd33c93(regs, WD_RESETINT);
+ printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result);
+ *scsi_id = result & 0x07;
+ *irq = (result >> 3) & 0x07;
+ if (*irq > 5) {
+ printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ
(%d)"
+ " - other device here?\n", base_io, *irq);
+ return 0;
+ }
+
+ *irq = irqs[*irq];
+ result = inb(REG_STATRD);
+ WAIT();
+ *dma = result & 0x03;
+ if (*dma == 1) {
+ printk(KERN_ERR
+ "PC-9801-55 (base %#x): impossible DMA channl
(%d)"
+ " - other device here?\n", base_io, *dma);
+ return 0;
+ }
+#ifdef DEBUG
+ printk("PC-9801-55: end of getconfig\n");
+#endif
+ return 1;
+}
+
+/* return non-zero on detection */
+int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
+{
+ unsigned int base_io;
+ unsigned char irq, dma, scsi_id;
+ int i;
+#ifdef DEBUG
+ unsigned char debug;
+#endif
+ + for (i = 0; i < nr_base_ios; i++) {
+ base_io = base_ios[i];
+ SASR = REG_ADDRST;
+ SCMD = REG_CONTRL;
+
+ /* printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST); */
+ if (check_region(base_io, 6))
+ continue;
+ if (! pc980155_test_port(regs))
+ continue;
+
+ if (!pc980155_getconfig(base_io, regs, &irq, &dma,
&scsi_id))
+ continue;
+#ifdef DEBUG
+ printk("PC-9801-55: config: base io = %x, irq = %d, dma
channel = %d, scsi id = %d\n",
+ base_io, irq, dma, scsi_id);
+#endif
+ if (request_irq(irq, pc980155_intr_handle, 0,
"PC-9801-55",
+ NULL)) {
+ printk(KERN_ERR
+ "PC-9801-55: unable to allocate IRQ
%d\n",
+ irq);
+ continue;
+ }
+ if (request_dma(dma, "PC-9801-55")) {
+ printk(KERN_ERR "PC-9801-55: "
+ "unable to allocate DMA channel %d\n",
dma);
+ free_irq(irq, NULL);
+ continue;
+ }
+
+ request_region(base_io, 6, "PC-9801-55");
+ pc980155_host = scsi_register(tpnt, sizeof(struct
WD33C93_hostdata));
+ pc980155_host->this_id = scsi_id;
+ pc980155_host->io_port = base_io;
+ pc980155_host->n_io_port = 6;
+ pc980155_host->irq = irq;
+ pc980155_host->dma_channel = dma;
+
+#ifdef DEBUG
+ printk("PC-9801-55: scsi host found at %x irq = %d, use
dma channel %d.\n", base_io, irq, dma);
+ debug = read_aux_stat(regs);
+ printk("PC-9801-55: aux: %x ", debug);
+ debug = read_wd33c93(regs, 0x17);
+ printk("status: %x\n", debug);
+#endif
+
+ pc980155_int_enable(regs);
+ + wd33c93_init(pc980155_host, regs, dma_setup, dma_stop,
+ WD33C93_FS_12_15);
+ + return 1;
+ }
+
+ printk("PC-9801-55: not found\n");
+ return 0;
+}
+
+int pc980155_proc_info(char *buf, char **start, off_t off, int len,
+ int hostno, int in)
+{
+ /* NOT SUPPORTED YET! */
+
+ if (in) {
+ return -EPERM;
+ }
+ *start = buf;
+ return sprintf(buf, "Sorry, not supported yet.\n");
+}
+
+int pc980155_setup(char *str)
+{
+next:
+ if (!strncmp(str, "io:", 3)){
+ base_ios[0] = simple_strtoul(str+3,NULL,0);
+ nr_base_ios = 1;
+ while (*str > ' ' && *str != ',')
+ str++;
+ if (*str == ','){
+ str++;
+ goto next;
+ }
+ }
+ return 0;
+}
+
+int scsi_pc980155_release(struct Scsi_Host *pc980155_host)
+{
+#ifdef MODULE
+ pc980155_int_disable(regs);
+ release_region(pc980155_host->io_port,
pc980155_host->n_io_port);
+ free_irq(pc980155_host->irq, NULL);
+ free_dma(pc980155_host->dma_channel);
+ wd33c93_release();
+#endif
+ return 1;
+}
+
+__setup("pc980155=", pc980155_setup);
+
+Scsi_Host_Template driver_template = SCSI_PC980155;
+
+#include "scsi_module.c"
diff -urN linux/drivers/scsi/pc980155.h linux98/drivers/scsi/pc980155.h
--- linux/drivers/scsi/pc980155.h Thu Jan 1 09:00:00 1970
+++ linux98/drivers/scsi/pc980155.h Sun Feb 3 12:08:14 2002
@@ -0,0 +1,47 @@
+/*
+ * PC-9801-55 SCSI host adapter driver
+ *
+ * Copyright (C) 1997-2000 Kyoto University Microcomputer Club
+ * (Linux/98 project)
+ */
+
+#ifndef _SCSI_PC9801_55_H
+#define _SCSI_PC9801_55_H
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <scsi/scsicam.h>
+
+int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd33c93_abort(Scsi_Cmnd *);
+int wd33c93_reset(Scsi_Cmnd *, unsigned int);
+int scsi_pc980155_detect(Scsi_Host_Template *);
+int scsi_pc980155_release(struct Scsi_Host *);
+int pc980155_proc_info(char *, char **, off_t, int, int, int);
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+#define SCSI_PC980155 { proc_name:
"PC-9801-55", \
+ name: "SCSI PC-9801-55",
\
+ proc_info: pc980155_proc_info,
\
+ detect: scsi_pc980155_detect,
\
+ release: scsi_pc980155_release,
\
+ /* command: use queue command */
\
+ queuecommand: wd33c93_queuecommand,
\
+ abort: wd33c93_abort,
\
+ reset: wd33c93_reset,
\
+ bios_param: pc9800_scsi_bios_param,
\
+ can_queue: CAN_QUEUE,
\
+ this_id: 7,
\
+ sg_tablesize:
SG_ALL, \
+ cmd_per_lun: CMD_PER_LUN, /* dont
use link command */ \
+ unchecked_isa_dma: 1, /* use dma
**XXXX***/ \
+ use_clustering: ENABLE_CLUSTERING }
+
+#endif /* _SCSI_PC9801_55_H */
diff -urN linux/drivers/scsi/pc980155regs.h
linux98/drivers/scsi/pc980155regs.h
--- linux/drivers/scsi/pc980155regs.h Thu Jan 1 09:00:00 1970
+++ linux98/drivers/scsi/pc980155regs.h Mon Dec 3 18:44:10 2001
@@ -0,0 +1,89 @@
+#ifndef __PC980155REGS_H
+#define __PC980155REGS_H
+
+#include "wd33c93.h"
+
+#define REG_ADDRST (base_io+0)
+#define REG_CONTRL (base_io+2)
+#define REG_CWRITE (base_io+4)
+#define REG_STATRD (base_io+4)
+
+#define WD_MEMORYBANK 0x30
+#define WD_RESETINT 0x33
+
+#if 0
+#define WAIT() outb(0x00,0x5f)
+#else
+#define WAIT() do{}while(0)
+#endif
+
+static inline uchar read_wd33c93(const wd33c93_regs regs, uchar
reg_num)
+{
+ uchar data;
+ outb(reg_num, *regs.SASR);
+ WAIT();
+ data = inb(*regs.SCMD);
+ WAIT();
+ return data;
+}
+
+static inline uchar read_aux_stat(const wd33c93_regs regs)
+{
+ uchar result;
+ result = inb(*regs.SASR);
+ WAIT();
+ /* printk("PC-9801-55: regp->SASR(%x) = %x\n", regp->SASR, result);
*/
+ return result;
+}
+#define READ_AUX_STAT() read_aux_stat(regs)
+
+static inline void write_wd33c93(const wd33c93_regs regs, uchar
reg_num,
+ uchar value)
+{
+ outb(reg_num, *regs.SASR);
+ WAIT();
+ outb(value, *regs.SCMD);
+ WAIT();
+}
+
+
+#define write_wd33c93_cmd(regs,cmd) write_wd33c93(regs,WD_COMMAND,cmd)
+
+static inline void write_wd33c93_count(const wd33c93_regs regs,
+ unsigned long value)
+{
+ outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
+ WAIT();
+ outb((value >> 16) & 0xff, *regs.SCMD);
+ WAIT();
+ outb((value >> 8) & 0xff, *regs.SCMD);
+ WAIT();
+ outb( value & 0xff, *regs.SCMD);
+ WAIT();
+}
+
+
+static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
+{
+unsigned long value;
+
+ outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
+ value = inb(*regs.SCMD) << 16;
+ value |= inb(*regs.SCMD) << 8;
+ value |= inb(*regs.SCMD);
+ return value;
+}
+
+static inline void write_wd33c93_cdb(const wd33c93_regs regs, unsigned
int len,
+ unsigned char cmnd[])
+{
+ int i;
+ outb(WD_CDB_1, *regs.SASR);
+ for (i=0; i<len; i++)
+ outb(cmnd[i], *regs.SCMD);
+}
+
+#define pc980155_int_enable(regs) write_wd33c93(regs, WD_MEMORYBANK,
read_wd33c93(regs, WD_MEMORYBANK) | 0x04)
+#define pc980155_int_disable(regs) write_wd33c93(regs, WD_MEMORYBANK,
read_wd33c93(regs, WD_MEMORYBANK) & ~0x04)
+
+#endif
diff -urN linux/drivers/scsi/scsi_scan.c
linux98/drivers/scsi/scsi_scan.c
--- linux/drivers/scsi/scsi_scan.c Wed Aug 28 09:52:26 2002
+++ linux98/drivers/scsi/scsi_scan.c Wed Aug 28 13:09:39 2002
@@ -131,6 +131,7 @@
{"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /*
locks up */
{"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to
all lun */
{"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /*
responds to all lun */
+ {"NEC", "D3856", "0009", BLIST_NOLUN},
/*
* Other types of devices that have special flags.
diff -urN linux/drivers/scsi/scsi_syms.c
linux98/drivers/scsi/scsi_syms.c
--- linux/drivers/scsi/scsi_syms.c Sat Oct 19 13:01:53 2002
+++ linux98/drivers/scsi/scsi_syms.c Tue Oct 29 15:45:15 2002
@@ -97,6 +97,13 @@
EXPORT_SYMBOL(scsi_devicelist);
EXPORT_SYMBOL(scsi_device_types);
+/* For PC-9800 architecture support */
+EXPORT_SYMBOL(pc9800_scsi_bios_param);
+#ifdef CONFIG_PC9800
+extern Scsi_Disk * sd_get_sdisk(int);
+EXPORT_SYMBOL(sd_get_sdisk);
+#endif
+
/*
* Externalize timers so that HBAs can safely start/restart commands.
*/
diff -urN linux/drivers/scsi/scsicam.c linux98/drivers/scsi/scsicam.c
--- linux/drivers/scsi/scsicam.c Sat Oct 19 13:01:59 2002
+++ linux98/drivers/scsi/scsicam.c Tue Oct 29 14:43:29 2002
@@ -61,7 +61,14 @@
int ret_code;
int size = disk->capacity;
unsigned long temp_cyl;
- unsigned char *p = scsi_bios_ptable(bdev);
+ unsigned char *p;
+ extern int pc98;
+
+ if (pc98)
+ if (!pc9800_scsi_bios_param(disk, bdev, ip))
+ return 0;
+
+ p = scsi_bios_ptable(bdev);
if (!p)
return -1;
@@ -238,3 +245,80 @@
*hds = (unsigned int) heads;
return (rv);
}
+
+#include <asm/pc9800.h>
+
+/* XXX - For now, we assume the first (i.e. having the least host_no)
+ real (i.e. non-emulated) host adapter shall be BIOS-controlled one.
+ We *SHOULD* invent another way. */
+
+static inline struct Scsi_Host *first_real_host(void)
+{
+ struct Scsi_Host *h = NULL;
+
+ while ((h = scsi_host_get_next(h)))
+ if (!h->hostt->emulated)
+ break;
+
+ return h;
+}
+
+/* There is no standard device-to-name translation function. Sigh. */
+static inline void sd_devname(char *buf, kdev_t dev)
+{
+ int diskno = (major(dev) & SD_MAJOR_MASK) * 16 + (minor(dev) >>
4);
+
+ buf[0] = 'a' + diskno;
+ buf[1] = '\0';
+ if (diskno >= 26) {
+ buf[0] = 'a' + (diskno / 26 - 1);
+ buf[1] = 'a' + (diskno % 26);
+ buf[2] = '\0';
+ }
+}
+
+int pc9800_scsi_bios_param(Disk *disk, struct block_device *bdev, int
*ip)
+{
+ char namebuf[4];
+
+ sd_devname(namebuf, to_kdev_t(bdev->bd_dev));
+
+ if (first_real_host () == disk->device->host
+ && disk->device->id < 7
+ && __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS,
disk->device->id))
+ {
+ const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS)
+ + disk->device->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;
+ }
+ printk(KERN_INFO "sd%s: "
+ "BIOS parameters CHS:%d/%d/%d, %u bytes %s
sector\n",
+ namebuf, ip[2], ip[0], ip[1], 256 << ((p[3] >>
4) & 3),
+ p[3] & 0x80 ? "hard" : "soft");
+ return 0;
+ }
+
+ /* Assume PC-9801-92 compatible parameters for HAs without
BIOS. */
+ ip[0] = 8;
+ ip[1] = 32;
+ ip[2] = disk->capacity / (8 * 32);
+ if (ip[2] > 65535) { /* if capacity >= 8GB */
+ /* Recent on-board adapters seem to use this
parameter. */
+ ip[1] = 128;
+ ip[2] = disk->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;
+ }
+ }
+ printk(KERN_INFO "sd%s: BIOS parameters CHS:%d/%d/%d
(assumed)\n",
+ namebuf, ip[2], ip[0], ip[1]);
+ return 0;
+}
diff -urN linux/drivers/scsi/sd.c linux98/drivers/scsi/sd.c
--- linux/drivers/scsi/sd.c Sat Oct 19 13:02:27 2002
+++ linux98/drivers/scsi/sd.c Tue Oct 29 14:35:02 2002
@@ -124,7 +124,11 @@
static void sd_rw_intr(Scsi_Cmnd * SCpnt);
+#ifndef CONFIG_PC9800
static Scsi_Disk * sd_get_sdisk(int index);
+#else
+Scsi_Disk * sd_get_sdisk(int index);
+#endif
#if defined(CONFIG_PPC32)
/**
@@ -216,6 +220,7 @@
case HDIO_GETGEO: /* Return BIOS disk parameters */
{
struct hd_geometry *loc = (struct hd_geometry
*) arg;
+ extern int pc98;
if(!loc)
return -EINVAL;
@@ -230,7 +235,7 @@
/* override with calculated, extended
default, or driver values */
- if(host->hostt->bios_param != NULL)
+ if(host->hostt->bios_param != NULL && !pc98)
host->hostt->bios_param(sdkp,
inode->i_bdev,
&diskinfo[0]);
else
@@ -1613,7 +1618,11 @@
return (the_result == 0);
}
+#ifndef CONFIG_PC9800
static Scsi_Disk * sd_get_sdisk(int index)
+#else
+Scsi_Disk * sd_get_sdisk(int index)
+#endif
{
Scsi_Disk * sdkp = NULL;
unsigned long iflags;
diff -urN linux/drivers/scsi/wd33c93.c linux98/drivers/scsi/wd33c93.c
--- linux/drivers/scsi/wd33c93.c Sat Oct 19 13:02:24 2002
+++ linux98/drivers/scsi/wd33c93.c Tue Oct 29 15:44:15 2002
@@ -84,6 +84,7 @@
#include <linux/init.h>
#include <asm/irq.h>
#include <linux/blk.h>
+#include <linux/spinlock.h>
#include "scsi.h"
#include "hosts.h"
@@ -173,7 +174,11 @@
MODULE_PARM(setup_strings, "s");
#endif
+static spinlock_t wd_lock = SPIN_LOCK_UNLOCKED;
+#if defined(CONFIG_SCSI_PC980155) ||
defined(CONFIG_SCSI_PC980155_MODULE)
+#include "pc980155regs.h"
+#else /* !CONFIG_SCSI_PC980155 */
static inline uchar read_wd33c93(const wd33c93_regs regs, uchar
reg_num)
{
@@ -203,6 +208,7 @@
*regs.SCMD = cmd;
mb();
}
+#endif /* CONFIG_SCSI_PC980155 */
static inline uchar read_1_byte(const wd33c93_regs regs)
@@ -220,6 +226,7 @@
return x;
}
+#if !defined(CONFIG_SCSI_PC980155) &&
!defined(CONFIG_SCSI_PC980155_MODULE)
static void write_wd33c93_count(const wd33c93_regs regs, unsigned
long value)
{
@@ -244,6 +251,7 @@
mb();
return value;
}
+#endif /* !CONFIG_SCSI_PC980155 */
/* The 33c93 needs to be told which direction a command transfers
its
@@ -385,8 +393,7 @@
* sense data is not lost before REQUEST_SENSE executes.
*/
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&wd_lock, flags);
if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
cmd->host_scribble = (uchar *)hostdata->input_Q;
@@ -407,7 +414,7 @@
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
- restore_flags(flags);
+ spin_unlock_irqrestore(&wd_lock, flags);
return 0;
}
@@ -428,7 +435,6 @@
struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata
*)instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *cmd, *prev;
-int i;
DB(DB_EXECUTE,printk("EX("))
@@ -591,9 +597,16 @@
* (take advantage of auto-incrementing)
*/
- *regs.SASR = WD_CDB_1;
- for (i=0; i<cmd->cmd_len; i++)
- *regs.SCMD = cmd->cmnd[i];
+#if defined(CONFIG_SCSI_PC980155) ||
defined(CONFIG_SCSI_PC980155_MODULE)
+ write_wd33c93_cdb(regs, cmd->cmd_len, cmd->cmnd);
+#else /* !CONFIG_SCSI_PC980155 */
+ {
+ int i;
+ *regs.SASR = WD_CDB_1;
+ for (i = 0; i < cmd->cmd_len; i++)
+ *regs.SCMD = cmd->cmnd[i];
+ }
+#endif /* CONFIG_SCSI_PC980155 */
/* The wd33c93 only knows about Group 0, 1, and 5 commands when
* it's doing a 'select-and-transfer'. To be safe, we write the
@@ -765,7 +778,7 @@
if (!(asr & ASR_INT) || (asr & ASR_BSY))
return;
- save_flags(flags);
+ local_save_flags(flags);
#ifdef PROC_STATISTICS
hostdata->int_cnt++;
@@ -831,7 +844,7 @@
* is here...
*/
- restore_flags(flags);
+ local_irq_restore(flags);
/* We are not connected to a target - check to see if there
* are commands waiting to be executed.
@@ -1085,7 +1098,7 @@
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
}
- restore_flags(flags);
+ local_irq_restore(flags);
break;
@@ -1117,7 +1130,7 @@
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
wd33c93_execute(instance);
}
else {
@@ -1200,7 +1213,7 @@
* there are commands waiting to be executed.
*/
/* look above for comments on scsi_done() */
- restore_flags(flags);
+ local_irq_restore(flags);
wd33c93_execute(instance);
break;
@@ -1228,7 +1241,7 @@
else
cmd->result = cmd->SCp.Status | (cmd->SCp.Message
<< 8);
cmd->scsi_done(cmd);
- restore_flags(flags);
+ local_irq_restore(flags);
break;
case S_PRE_TMP_DISC:
case S_RUNNING_LEVEL2:
@@ -1693,7 +1706,7 @@
return 1;
}
-__setup("wd33c93", wd33c93_setup);
+__setup("wd33c93=", wd33c93_setup);
/* check_setup_args() returns index if key found, 0 if not
@@ -1831,10 +1844,9 @@
{ unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&wd_lock, flags);
reset_wd33c93(instance);
- restore_flags(flags);
+ spin_unlock_irqrestore(&wd_lock, flags);
}
printk("wd33c93-%d: chip=%s/%d no_sync=0x%x
no_dma=%d",instance->host_no,
@@ -1929,8 +1941,7 @@
return len;
}
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&wd_lock, flags);
bp = buf;
*bp = '\0';
if (hd->proc & PR_VERSION) {
@@ -2005,7 +2016,7 @@
}
}
strcat(bp,"\n");
- restore_flags(flags);
+ spin_unlock_irqrestore(&wd_lock, flags);
*start = buf;
if (stop) {
stop = 0;
@@ -2034,4 +2045,10 @@
MOD_DEC_USE_COUNT;
}
+EXPORT_SYMBOL(wd33c93_reset);
+EXPORT_SYMBOL(wd33c93_init);
+EXPORT_SYMBOL(wd33c93_release);
+EXPORT_SYMBOL(wd33c93_abort);
+EXPORT_SYMBOL(wd33c93_queuecommand);
+EXPORT_SYMBOL(wd33c93_intr);
MODULE_LICENSE("GPL");
diff -urN linux/drivers/scsi/wd33c93.h linux98/drivers/scsi/wd33c93.h
--- linux/drivers/scsi/wd33c93.h Sat Oct 12 13:21:35 2002
+++ linux98/drivers/scsi/wd33c93.h Sat Oct 12 14:18:53 2002
@@ -186,8 +186,13 @@
/* This is what the 3393 chip looks like to us */
typedef struct {
+#if defined(CONFIG_SCSI_PC980155) ||
defined(CONFIG_SCSI_PC980155_MODULE)
+ volatile unsigned int *SASR;
+ volatile unsigned int *SCMD;
+#else
volatile unsigned char *SASR;
volatile unsigned char *SCMD;
+#endif
} wd33c93_regs;
diff -urN linux/include/scsi/scsicam.h linux98/include/scsi/scsicam.h
--- linux/include/scsi/scsicam.h Sat Oct 19 13:01:49 2002
+++ linux98/include/scsi/scsicam.h Tue Oct 29 15:58:00 2002
@@ -16,4 +16,6 @@
extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int
*secs);
extern unsigned char *scsi_bios_ptable(struct block_device *bdev);
+extern int pc9800_scsi_bios_param(Disk *disk, struct block_device
*bdev,
+ int *ip);
#endif /* def SCSICAM_H */
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCHSET 8/23] add support for PC-9800 architecture (fs)
2002-10-28 22:33 ` Alan Cox
2002-10-29 17:04 ` Osamu Tomita
@ 2002-10-29 17:11 ` Osamu Tomita
2002-10-29 17:54 ` Jeff Garzik
1 sibling, 1 reply; 7+ messages in thread
From: Osamu Tomita @ 2002-10-29 17:11 UTC (permalink / raw)
To: Alan Cox; +Cc: LKML, Linus Torvalds
2002.10.29 07:33, Alan Cox wrote:
> On Mon, 2002-10-28 at 17:30, Osamu Tomita wrote:
> > This is a part 17/23 of patchset for add support NEC PC-9800
> architecture,
> > against 2.5.44.
>
> If all the BIOS mapping for the PC9800 is the same then intead of
> patching the drivers add an
>
> if(pc98)
> pci98_bios_param(...)
> else
> host->bios_param()
>
> change in the scsi core code not in each driver
This is your advice to scsi patch. fs/partion/nec98.c call bios_param()
same as scsi driver. So I changed this file too.
diff -urN linux/fs/fat/inode.c linux98/fs/fat/inode.c
--- linux/fs/fat/inode.c Wed Oct 16 13:20:44 2002
+++ linux98/fs/fat/inode.c Wed Oct 16 15:01:51 2002
@@ -10,6 +10,7 @@
* Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/slab.h>
@@ -979,7 +980,13 @@
error = first;
goto out_fail;
}
- if (FAT_FIRST_ENT(sb, media) != first) {
+#ifndef CONFIG_PC9800
+ if (FAT_FIRST_ENT(sb, media) != first)
+#else
+ if (FAT_FIRST_ENT(sb, media) != first
+ && (media != 0xf8 || (first & 0xff) != 0xfe))
+#endif
+ {
if (!silent) {
printk("FAT: invalid first entry of FAT "
"(0x%x != 0x%x)\n",
diff -urN linux/fs/partitions/Config.in linux98/fs/partitions/Config.in
--- linux/fs/partitions/Config.in Sat Oct 19 13:02:28 2002
+++ linux98/fs/partitions/Config.in Sat Oct 19 16:58:53 2002
@@ -29,6 +29,10 @@
if [ "$CONFIG_LDM_PARTITION" = "y" ]; then
bool ' Windows LDM extra logging' CONFIG_LDM_DEBUG
fi
+ bool ' NEC PC-9800 partition table support' CONFIG_NEC98_PARTITION
+ if [ "$CONFIG_NEC98_PARTITION" = "y" ]; then
+ bool ' BSD disklabel support for NEC PC-9800 type partitions'
CONFIG_NEC98_BSD_DISKLABEL
+ fi
bool ' SGI partition support' CONFIG_SGI_PARTITION
bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION
bool ' Sun partition tables support' CONFIG_SUN_PARTITION
@@ -37,11 +41,15 @@
if [ "$CONFIG_ALPHA" = "y" ]; then
define_bool CONFIG_OSF_PARTITION y
fi
+ if [ "$CONFIG_PC9800" = "y" ]; then
+ define_bool CONFIG_NEC98_PARTITION y
+ else
if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
"$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
"$CONFIG_ARM" != "y" -a "$CONFIG_SGI_IP27" != "y" ]; then
define_bool CONFIG_MSDOS_PARTITION y
fi
+ fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then
define_bool CONFIG_AMIGA_PARTITION y
fi
diff -urN linux/fs/partitions/Makefile linux98/fs/partitions/Makefile
--- linux/fs/partitions/Makefile Sat Oct 19 13:01:50 2002
+++ linux98/fs/partitions/Makefile Sat Oct 19 17:00:39 2002
@@ -18,6 +18,7 @@
obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
obj-$(CONFIG_IBM_PARTITION) += ibm.o
obj-$(CONFIG_EFI_PARTITION) += efi.o
+obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
include $(TOPDIR)/Rules.make
diff -urN linux/fs/partitions/check.c linux98/fs/partitions/check.c
--- linux/fs/partitions/check.c Sat Oct 19 13:02:30 2002
+++ linux98/fs/partitions/check.c Sat Oct 19 17:02:58 2002
@@ -28,6 +28,7 @@
#include "ldm.h"
#include "mac.h"
#include "msdos.h"
+#include "nec98.h"
#include "osf.h"
#include "sgi.h"
#include "sun.h"
@@ -51,6 +52,9 @@
#ifdef CONFIG_LDM_PARTITION
ldm_partition, /* this must come before msdos */
#endif
+#ifdef CONFIG_NEC98_PARTITION
+ nec98_partition, /* must be come before
`msdos_partition' */
+#endif
#ifdef CONFIG_MSDOS_PARTITION
msdos_partition,
#endif
diff -urN linux/fs/partitions/msdos.c linux98/fs/partitions/msdos.c
--- linux/fs/partitions/msdos.c Sat Oct 12 13:22:10 2002
+++ linux98/fs/partitions/msdos.c Sun Oct 13 22:23:58 2002
@@ -20,6 +20,11 @@
*/
#include <linux/config.h>
+
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+# define CONFIG_BSD_DISKLABEL
+#endif
+
#include <linux/buffer_head.h> /* for
invalidate_bdev() */
#ifdef CONFIG_BLK_DEV_IDE
@@ -37,6 +42,7 @@
#include "msdos.h"
#include "efi.h"
+#if !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION)
/*
* Many architectures don't like unaligned accesses, which is
* frequently the case with the nr_sects and start_sect partition
@@ -171,6 +177,7 @@
done:
put_dev_sector(sect);
}
+#endif /* !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION) */
/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
indicates linux swap. Be careful before believing this is
Solaris. */
@@ -179,6 +186,7 @@
parse_solaris_x86(struct parsed_partitions *state, struct
block_device *bdev,
u32 offset, u32 size, int origin)
{
+#if !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION)
#ifdef CONFIG_SOLARIS_X86_PARTITION
Sector sect;
struct solaris_x86_vtoc *v;
@@ -212,6 +220,7 @@
put_dev_sector(sect);
printk(" >\n");
#endif
+#endif /* !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION) */
}
#ifdef CONFIG_BSD_DISKLABEL
@@ -219,7 +228,11 @@
* Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See parse_extended() for more information.
*/
+#ifndef CONFIG_NEC98_BSD_DISKLABEL
static void
+#else
+void
+#endif
parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin, char *flavour,
int max_partitions)
@@ -292,6 +305,7 @@
#endif
}
+#if !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION)
/*
* Create devices for Unixware partitions listed in a disklabel,
under a
* dos-like partition. See parse_extended() for more information.
@@ -461,3 +475,4 @@
put_dev_sector(sect);
return 1;
}
+#endif /* !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION) */
diff -urN linux/fs/partitions/nec98.c linux98/fs/partitions/nec98.c
--- linux/fs/partitions/nec98.c Thu Jan 1 09:00:00 1970
+++ linux98/fs/partitions/nec98.c Tue Oct 29 22:04:53 2002
@@ -0,0 +1,277 @@
+/*
+ * NEC PC-9800 series partition supports
+ *
+ * Copyright (C) 1999 Kyoto University Microcomputer Club
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+#define CONFIG_BSD_DISKLABEL
+#endif
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/blk.h>
+#include <linux/major.h>
+
+#include "check.h"
+#include "nec98.h"
+
+/* #ifdef CONFIG_BLK_DEV_IDEDISK */
+#include <linux/ide.h>
+/* #endif */
+
+/* #ifdef CONFIG_BLK_DEV_SD */
+#include "../../drivers/scsi/scsi.h"
+#include "../../drivers/scsi/sd.h"
+#include "../../drivers/scsi/hosts.h"
+#include <scsi/scsicam.h>
+/* #endif */
+
+struct nec98_partition {
+ __u8 mid; /* 0x80 - active */
+ __u8 sid; /* 0x80 - bootable */
+ __u16 pad1; /* dummy for padding */
+ __u8 ipl_sector; /* IPL sector */
+ __u8 ipl_head; /* IPL head */
+ __u16 ipl_cyl; /* IPL cylinder */
+ __u8 sector; /* starting sector */
+ __u8 head; /* starting head */
+ __u16 cyl; /* starting cylinder */
+ __u8 end_sector; /* end sector */
+ __u8 end_head; /* end head */
+ __u16 end_cyl; /* end cylinder */
+ unsigned char name[16];
+} __attribute__((__packed__));
+
+#define NEC98_BSD_PARTITION_MID 0x14
+#define NEC98_BSD_PARTITION_SID 0x44
+#define MID_SID_16(mid, sid) (((mid) & 0xFF) | (((sid) & 0xFF) << 8))
+#define NEC98_BSD_PARTITION_MID_SID \
+ MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
+#define NEC98_VALID_PTABLE_ENTRY(P) \
+ (!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
+
+static inline int
+is_valid_nec98_partition_table(const struct nec98_partition *ptable,
+ __u8 nsectors, __u8 nheads)
+{
+ int i;
+ int valid = 0;
+
+ for (i = 0; i < 16; i++) {
+ if (!*(__u16 *)&ptable[i])
+ continue; /* empty slot */
+ if (ptable[i].pad1 /* `pad1' contains junk */
+ || ptable[i].ipl_sector >= nsectors
+ || ptable[i].sector >= nsectors
+ || ptable[i].end_sector >= nsectors
+ || ptable[i].ipl_head >= nheads
+ || ptable[i].head >= nheads
+ || ptable[i].end_head >= nheads
+ || ptable[i].cyl > ptable[i].end_cyl)
+ return 0;
+ valid = 1; /* We have a valid partition. */
+ }
+ /* If no valid PC-9800-style partitions found,
+ the disk may have other type of partition table. */
+ return valid;
+}
+
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+extern void parse_bsd(struct parsed_partitions *state,
+ struct block_device *bdev,
+ u32 offset, u32 size, int origin, char *flavour,
+ int max_partitions);
+#endif
+
+int nec98_partition(struct parsed_partitions *state, struct
block_device *bdev)
+{
+ unsigned int nr;
+ int g_head, g_sect;
+ Sector sect;
+ const struct nec98_partition *part;
+ unsigned char *data;
+ int sector_size = bdev_hardsect_size(bdev);
+ int major = major(to_kdev_t(bdev->bd_dev));
+ int minor = minor(to_kdev_t(bdev->bd_dev));
+
+ switch (major) {
+#if defined CONFIG_BLK_DEV_HD_ONLY
+ case HD_MAJOR:
+ {
+ extern struct hd_i_struct hd_info[2];
+
+ g_head = hd_info[minor >> 6].head;
+ g_sect = hd_info[minor >> 6].sect;
+ break;
+ }
+#endif /* CONFIG_BLK_DEV_HD_ONLY */
+#if defined CONFIG_BLK_DEV_SD || defined CONFIG_BLK_DEV_SD_MODULE
+ case SCSI_DISK0_MAJOR:
+ case SCSI_DISK1_MAJOR:
+ case SCSI_DISK2_MAJOR:
+ case SCSI_DISK3_MAJOR:
+ case SCSI_DISK4_MAJOR:
+ case SCSI_DISK5_MAJOR:
+ case SCSI_DISK6_MAJOR:
+ case SCSI_DISK7_MAJOR:
+ {
+ extern Scsi_Disk * sd_get_sdisk(int);
+#define SCSI_DEVICE_NR(device) (((major(device) & SD_MAJOR_MASK) << (8
- 4)) + (minor(device) >> 4))
+ Scsi_Disk *disk =
sd_get_sdisk(SCSI_DEVICE_NR(to_kdev_t(bdev->bd_dev)));
+ int diskinfo[3] = { 0, 0, 0 };
+
+ scsicam_bios_param(disk, bdev, diskinfo);
+
+ if ((g_head = diskinfo[0]) <= 0)
+ g_head = 8;
+ if ((g_sect = diskinfo[1]) <= 0)
+ g_sect = 17;
+ break;
+ }
+#endif /* CONFIG_BLK_DEV_SD(_MODULE) */
+#if defined CONFIG_BLK_DEV_IDEDISK || defined
CONFIG_BLK_DEV_IDEDISK_MODULE
+ case IDE0_MAJOR:
+ case IDE1_MAJOR:
+ case IDE2_MAJOR:
+ case IDE3_MAJOR:
+ case IDE4_MAJOR:
+ case IDE5_MAJOR:
+ case IDE6_MAJOR:
+ case IDE7_MAJOR:
+ case IDE8_MAJOR:
+ case IDE9_MAJOR:
+ {
+ ide_drive_t *drive;
+ unsigned int h;
+
+ for (h = 0; h < MAX_HWIFS; ++h) {
+ ide_hwif_t *hwif = &ide_hwifs[h];
+ if (hwif->present && major == hwif->major) {
+ unsigned unit = minor >> PARTN_BITS;
+ if (unit < MAX_DRIVES) {
+ drive = &hwif->drives[unit];
+ if (drive->present) {
+ g_head = drive->head;
+ g_sect = drive->sect;
+ goto found;
+ }
+ }
+ break;
+ }
+ }
+ }
+#endif /* CONFIG_BLK_DEV_IDEDISK(_MODULE) */
+ default:
+ printk(" unsupported disk (major = %u)\n", major);
+ return 0;
+ }
+
+ found:
+ data = read_dev_sector(bdev, 0, §);
+ if (!data) {
+ if (warn_no_part)
+ printk(" unable to read partition table\n");
+ return -1;
+ }
+
+ /* magic(?) check */
+ if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
+ put_dev_sector(sect);
+ return 0;
+ }
+
+ put_dev_sector(sect);
+ data = read_dev_sector(bdev, 1, §);
+ if (!data) {
+ if (warn_no_part)
+ printk(" unable to read partition table\n");
+ return -1;
+ }
+
+ if (!is_valid_nec98_partition_table((struct nec98_partition
*)data,
+ g_sect, g_head)) {
+#if 0
+ if (warn_no_part)
+ printk(" partition table consistency check
failed"
+ " (not PC-9800 disk?)\n");
+#endif
+ put_dev_sector(sect);
+ return 0;
+ }
+
+ part = (const struct nec98_partition *)data;
+ for (nr = 0; nr < 16; nr++, part++) {
+ unsigned int start_sect, end_sect;
+
+ if (part->mid == 0 || part->sid == 0)
+ continue;
+
+ if (nr)
+ printk(" ");
+
+ { /* Print partition name. Fdisk98 might put NUL
+ characters in partition name... */
+
+ int j;
+ unsigned char *p;
+ unsigned char buf[sizeof (part->name) * 2 + 1];
+
+ for (p = buf, j = 0; j < sizeof (part->name);
j++, p++)
+ if ((*p = part->name[j]) < ' ') {
+ *p++ = '^';
+ *p = part->name[j] + '@';
+ }
+
+ *p = 0;
+ printk(" <%s>", buf);
+ }
+ start_sect = (part->cyl * g_head + part->head) * g_sect
+ + part->sector;
+ end_sect = (part->end_cyl + 1) * g_head * g_sect;
+ if (end_sect <= start_sect) {
+ printk(" (invalid partition info)\n");
+ continue;
+ }
+
+ put_partition(state, nr + 1, start_sect, end_sect -
start_sect);
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+ if ((*(__u16 *)&part->mid & 0x7F7F)
+ == NEC98_BSD_PARTITION_MID_SID) {
+ printk("!");
+ /* NEC98_BSD_PARTITION_MID_SID is not valid
SYSIND for
+ IBM PC's MS-DOS partition table, so we
simply pass
+ it to bsd_disklabel_partition;
+ it will just print `<bsd: ... >'. */
+ parse_bsd(state, bdev, start_sect,
+ end_sect - start_sect, nr + 1,
+ "bsd98", BSD_MAXPARTITIONS);
+ }
+#endif
+ { /* Pretty size printing. */
+ /* XXX sector size? */
+ unsigned int psize = (end_sect - start_sect) /
2;
+ int unit_char = 'K';
+
+ if (psize > 99999) {
+ psize >>= 10;
+ unit_char = 'M';
+ }
+ printk(" %5d%cB (%5d-%5d)\n",
+ psize, unit_char, part->cyl,
part->end_cyl);
+ }
+ }
+
+ put_dev_sector(sect);
+
+ return nr ? 1 : 0;
+}
+\f
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux/fs/partitions/nec98.h linux98/fs/partitions/nec98.h
--- linux/fs/partitions/nec98.h Thu Jan 1 09:00:00 1970
+++ linux98/fs/partitions/nec98.h Fri Jul 26 11:10:08 2002
@@ -0,0 +1,10 @@
+/*
+ * NEC PC-9800 series partition supports
+ *
+ * Copyright (C) 1998-2000 Kyoto University Microcomputer Club
+ */
+
+#define NEC98_PTABLE_MAGIC 0xAA55
+
+extern int nec98_partition(struct parsed_partitions *state,
+ struct block_device *bdev);
^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCHSET 8/23] add support for PC-9800 architecture (fs)
@ 2002-10-30 0:18 Osamu Tomita
0 siblings, 0 replies; 7+ messages in thread
From: Osamu Tomita @ 2002-10-30 0:18 UTC (permalink / raw)
To: 'Jeff Garzik '
Cc: 'Alan Cox ', 'LKML ', 'Linus Torvalds '
Thanks.
-----Original Message-----
From: Jeff Garzik
To: Osamu Tomita
Cc: Alan Cox; LKML; Linus Torvalds
Sent: 2002/10/30 2:54
Subject: Re: [PATCHSET 8/23] add support for PC-9800 architecture (fs)
> A general suggestion... some of your patches add headers to include/*
> directories, when they are only included from one location in the tree.
> For that case, it is preferred to place the header in the same
> directory as the code which includes the header.
I see. I'll serach file that you said, and move it.
Regards,
Osamu Tomita
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCHSET 8/23] add support for PC-9800 architecture (fs)
@ 2002-10-28 17:30 Osamu Tomita
0 siblings, 0 replies; 7+ messages in thread
From: Osamu Tomita @ 2002-10-28 17:30 UTC (permalink / raw)
To: LKML; +Cc: Linus Torvalds
This is part 8/23 of patchset for add support NEC PC-9800 architecture,
against 2.5.44.
Summary:
file system modules
- add support PC-9800 partition table.
- small hack for access FAT partition made by PC-9800 DOS.
diffstat:
fs/fat/inode.c | 9 +
fs/partitions/Config.in | 8 +
fs/partitions/Makefile | 1
fs/partitions/check.c | 4
fs/partitions/msdos.c | 15 ++
fs/partitions/nec98.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++++
fs/partitions/nec98.h | 10 +
7 files changed, 327 insertions(+), 1 deletion(-)
patch:
diff -urN linux/fs/fat/inode.c linux98/fs/fat/inode.c
--- linux/fs/fat/inode.c Wed Oct 16 13:20:44 2002
+++ linux98/fs/fat/inode.c Wed Oct 16 15:01:51 2002
@@ -10,6 +10,7 @@
* Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/slab.h>
@@ -979,7 +980,13 @@
error = first;
goto out_fail;
}
- if (FAT_FIRST_ENT(sb, media) != first) {
+#ifndef CONFIG_PC9800
+ if (FAT_FIRST_ENT(sb, media) != first)
+#else
+ if (FAT_FIRST_ENT(sb, media) != first
+ && (media != 0xf8 || (first & 0xff) != 0xfe))
+#endif
+ {
if (!silent) {
printk("FAT: invalid first entry of FAT "
"(0x%x != 0x%x)\n",
diff -urN linux/fs/partitions/Config.in linux98/fs/partitions/Config.in
--- linux/fs/partitions/Config.in Sat Oct 19 13:02:28 2002
+++ linux98/fs/partitions/Config.in Sat Oct 19 16:58:53 2002
@@ -29,6 +29,10 @@
if [ "$CONFIG_LDM_PARTITION" = "y" ]; then
bool ' Windows LDM extra logging' CONFIG_LDM_DEBUG
fi
+ bool ' NEC PC-9800 partition table support' CONFIG_NEC98_PARTITION
+ if [ "$CONFIG_NEC98_PARTITION" = "y" ]; then
+ bool ' BSD disklabel support for NEC PC-9800 type partitions' CONFIG_NEC98_BSD_DISKLABEL
+ fi
bool ' SGI partition support' CONFIG_SGI_PARTITION
bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION
bool ' Sun partition tables support' CONFIG_SUN_PARTITION
@@ -37,11 +41,15 @@
if [ "$CONFIG_ALPHA" = "y" ]; then
define_bool CONFIG_OSF_PARTITION y
fi
+ if [ "$CONFIG_PC9800" = "y" ]; then
+ define_bool CONFIG_NEC98_PARTITION y
+ else
if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
"$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
"$CONFIG_ARM" != "y" -a "$CONFIG_SGI_IP27" != "y" ]; then
define_bool CONFIG_MSDOS_PARTITION y
fi
+ fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then
define_bool CONFIG_AMIGA_PARTITION y
fi
diff -urN linux/fs/partitions/Makefile linux98/fs/partitions/Makefile
--- linux/fs/partitions/Makefile Sat Oct 19 13:01:50 2002
+++ linux98/fs/partitions/Makefile Sat Oct 19 17:00:39 2002
@@ -18,6 +18,7 @@
obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
obj-$(CONFIG_IBM_PARTITION) += ibm.o
obj-$(CONFIG_EFI_PARTITION) += efi.o
+obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
include $(TOPDIR)/Rules.make
diff -urN linux/fs/partitions/check.c linux98/fs/partitions/check.c
--- linux/fs/partitions/check.c Sat Oct 19 13:02:30 2002
+++ linux98/fs/partitions/check.c Sat Oct 19 17:02:58 2002
@@ -28,6 +28,7 @@
#include "ldm.h"
#include "mac.h"
#include "msdos.h"
+#include "nec98.h"
#include "osf.h"
#include "sgi.h"
#include "sun.h"
@@ -51,6 +52,9 @@
#ifdef CONFIG_LDM_PARTITION
ldm_partition, /* this must come before msdos */
#endif
+#ifdef CONFIG_NEC98_PARTITION
+ nec98_partition, /* must be come before `msdos_partition' */
+#endif
#ifdef CONFIG_MSDOS_PARTITION
msdos_partition,
#endif
diff -urN linux/fs/partitions/msdos.c linux98/fs/partitions/msdos.c
--- linux/fs/partitions/msdos.c Sat Oct 12 13:22:10 2002
+++ linux98/fs/partitions/msdos.c Sun Oct 13 22:23:58 2002
@@ -20,6 +20,11 @@
*/
#include <linux/config.h>
+
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+# define CONFIG_BSD_DISKLABEL
+#endif
+
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#ifdef CONFIG_BLK_DEV_IDE
@@ -37,6 +42,7 @@
#include "msdos.h"
#include "efi.h"
+#if !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION)
/*
* Many architectures don't like unaligned accesses, which is
* frequently the case with the nr_sects and start_sect partition
@@ -171,6 +177,7 @@
done:
put_dev_sector(sect);
}
+#endif /* !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION) */
/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
indicates linux swap. Be careful before believing this is Solaris. */
@@ -179,6 +186,7 @@
parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
+#if !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION)
#ifdef CONFIG_SOLARIS_X86_PARTITION
Sector sect;
struct solaris_x86_vtoc *v;
@@ -212,6 +220,7 @@
put_dev_sector(sect);
printk(" >\n");
#endif
+#endif /* !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION) */
}
#ifdef CONFIG_BSD_DISKLABEL
@@ -219,7 +228,11 @@
* Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See parse_extended() for more information.
*/
+#ifndef CONFIG_NEC98_BSD_DISKLABEL
static void
+#else
+void
+#endif
parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin, char *flavour,
int max_partitions)
@@ -292,6 +305,7 @@
#endif
}
+#if !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION)
/*
* Create devices for Unixware partitions listed in a disklabel, under a
* dos-like partition. See parse_extended() for more information.
@@ -461,3 +475,4 @@
put_dev_sector(sect);
return 1;
}
+#endif /* !defined(CONFIG_PC9800) || defined(CONFIG_MSDOS_PARTITION) */
diff -urN linux/fs/partitions/nec98.c linux98/fs/partitions/nec98.c
--- linux/fs/partitions/nec98.c Thu Jan 1 09:00:00 1970
+++ linux98/fs/partitions/nec98.c Sat Oct 19 21:13:20 2002
@@ -0,0 +1,281 @@
+/*
+ * NEC PC-9800 series partition supports
+ *
+ * Copyright (C) 1999 Kyoto University Microcomputer Club
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+#define CONFIG_BSD_DISKLABEL
+#endif
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/blk.h>
+#include <linux/major.h>
+
+#include "check.h"
+#include "nec98.h"
+
+/* #ifdef CONFIG_BLK_DEV_IDEDISK */
+#include <linux/ide.h>
+/* #endif */
+
+/* #ifdef CONFIG_BLK_DEV_SD */
+#include "../../drivers/scsi/scsi.h"
+#include "../../drivers/scsi/sd.h"
+#include "../../drivers/scsi/hosts.h"
+#include <scsi/scsicam.h>
+/* #endif */
+
+struct nec98_partition {
+ __u8 mid; /* 0x80 - active */
+ __u8 sid; /* 0x80 - bootable */
+ __u16 pad1; /* dummy for padding */
+ __u8 ipl_sector; /* IPL sector */
+ __u8 ipl_head; /* IPL head */
+ __u16 ipl_cyl; /* IPL cylinder */
+ __u8 sector; /* starting sector */
+ __u8 head; /* starting head */
+ __u16 cyl; /* starting cylinder */
+ __u8 end_sector; /* end sector */
+ __u8 end_head; /* end head */
+ __u16 end_cyl; /* end cylinder */
+ unsigned char name[16];
+} __attribute__((__packed__));
+
+#define NEC98_BSD_PARTITION_MID 0x14
+#define NEC98_BSD_PARTITION_SID 0x44
+#define MID_SID_16(mid, sid) (((mid) & 0xFF) | (((sid) & 0xFF) << 8))
+#define NEC98_BSD_PARTITION_MID_SID \
+ MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
+#define NEC98_VALID_PTABLE_ENTRY(P) \
+ (!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
+
+static inline int
+is_valid_nec98_partition_table(const struct nec98_partition *ptable,
+ __u8 nsectors, __u8 nheads)
+{
+ int i;
+ int valid = 0;
+
+ for (i = 0; i < 16; i++) {
+ if (!*(__u16 *)&ptable[i])
+ continue; /* empty slot */
+ if (ptable[i].pad1 /* `pad1' contains junk */
+ || ptable[i].ipl_sector >= nsectors
+ || ptable[i].sector >= nsectors
+ || ptable[i].end_sector >= nsectors
+ || ptable[i].ipl_head >= nheads
+ || ptable[i].head >= nheads
+ || ptable[i].end_head >= nheads
+ || ptable[i].cyl > ptable[i].end_cyl)
+ return 0;
+ valid = 1; /* We have a valid partition. */
+ }
+ /* If no valid PC-9800-style partitions found,
+ the disk may have other type of partition table. */
+ return valid;
+}
+
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+extern void parse_bsd(struct parsed_partitions *state,
+ struct block_device *bdev,
+ u32 offset, u32 size, int origin, char *flavour,
+ int max_partitions);
+#endif
+
+int nec98_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+ unsigned int nr;
+ int g_head, g_sect;
+ Sector sect;
+ const struct nec98_partition *part;
+ unsigned char *data;
+ int sector_size = bdev_hardsect_size(bdev);
+ int major = major(to_kdev_t(bdev->bd_dev));
+ int minor = minor(to_kdev_t(bdev->bd_dev));
+
+ switch (major) {
+#if defined CONFIG_BLK_DEV_HD_ONLY
+ case HD_MAJOR:
+ {
+ extern struct hd_i_struct hd_info[2];
+
+ g_head = hd_info[minor >> 6].head;
+ g_sect = hd_info[minor >> 6].sect;
+ break;
+ }
+#endif /* CONFIG_BLK_DEV_HD_ONLY */
+#if defined CONFIG_BLK_DEV_SD || defined CONFIG_BLK_DEV_SD_MODULE
+ case SCSI_DISK0_MAJOR:
+ case SCSI_DISK1_MAJOR:
+ case SCSI_DISK2_MAJOR:
+ case SCSI_DISK3_MAJOR:
+ case SCSI_DISK4_MAJOR:
+ case SCSI_DISK5_MAJOR:
+ case SCSI_DISK6_MAJOR:
+ case SCSI_DISK7_MAJOR:
+ {
+ extern Scsi_Disk * sd_get_sdisk(int);
+#define SCSI_DEVICE_NR(device) (((major(device) & SD_MAJOR_MASK) << (8 - 4)) + (minor(device) >> 4))
+ Scsi_Disk *disk = sd_get_sdisk(SCSI_DEVICE_NR(to_kdev_t(bdev->bd_dev)));
+ struct Scsi_Host *host = disk->device->host;
+ int diskinfo[3] = { 0, 0, 0 };
+
+ if(host->hostt->bios_param)
+ host->hostt->bios_param(disk, bdev, diskinfo);
+ else
+ scsicam_bios_param(disk, bdev, diskinfo);
+
+ if ((g_head = diskinfo[0]) <= 0)
+ g_head = 8;
+ if ((g_sect = diskinfo[1]) <= 0)
+ g_sect = 17;
+ break;
+ }
+#endif /* CONFIG_BLK_DEV_SD(_MODULE) */
+#if defined CONFIG_BLK_DEV_IDEDISK || defined CONFIG_BLK_DEV_IDEDISK_MODULE
+ case IDE0_MAJOR:
+ case IDE1_MAJOR:
+ case IDE2_MAJOR:
+ case IDE3_MAJOR:
+ case IDE4_MAJOR:
+ case IDE5_MAJOR:
+ case IDE6_MAJOR:
+ case IDE7_MAJOR:
+ case IDE8_MAJOR:
+ case IDE9_MAJOR:
+ {
+ ide_drive_t *drive;
+ unsigned int h;
+
+ for (h = 0; h < MAX_HWIFS; ++h) {
+ ide_hwif_t *hwif = &ide_hwifs[h];
+ if (hwif->present && major == hwif->major) {
+ unsigned unit = minor >> PARTN_BITS;
+ if (unit < MAX_DRIVES) {
+ drive = &hwif->drives[unit];
+ if (drive->present) {
+ g_head = drive->head;
+ g_sect = drive->sect;
+ goto found;
+ }
+ }
+ break;
+ }
+ }
+ }
+#endif /* CONFIG_BLK_DEV_IDEDISK(_MODULE) */
+ default:
+ printk(" unsupported disk (major = %u)\n", major);
+ return 0;
+ }
+
+ found:
+ data = read_dev_sector(bdev, 0, §);
+ if (!data) {
+ if (warn_no_part)
+ printk(" unable to read partition table\n");
+ return -1;
+ }
+
+ /* magic(?) check */
+ if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
+ put_dev_sector(sect);
+ return 0;
+ }
+
+ put_dev_sector(sect);
+ data = read_dev_sector(bdev, 1, §);
+ if (!data) {
+ if (warn_no_part)
+ printk(" unable to read partition table\n");
+ return -1;
+ }
+
+ if (!is_valid_nec98_partition_table((struct nec98_partition *)data,
+ g_sect, g_head)) {
+#if 0
+ if (warn_no_part)
+ printk(" partition table consistency check failed"
+ " (not PC-9800 disk?)\n");
+#endif
+ put_dev_sector(sect);
+ return 0;
+ }
+
+ part = (const struct nec98_partition *)data;
+ for (nr = 0; nr < 16; nr++, part++) {
+ unsigned int start_sect, end_sect;
+
+ if (part->mid == 0 || part->sid == 0)
+ continue;
+
+ if (nr)
+ printk(" ");
+
+ { /* Print partition name. Fdisk98 might put NUL
+ characters in partition name... */
+
+ int j;
+ unsigned char *p;
+ unsigned char buf[sizeof (part->name) * 2 + 1];
+
+ for (p = buf, j = 0; j < sizeof (part->name); j++, p++)
+ if ((*p = part->name[j]) < ' ') {
+ *p++ = '^';
+ *p = part->name[j] + '@';
+ }
+
+ *p = 0;
+ printk(" <%s>", buf);
+ }
+ start_sect = (part->cyl * g_head + part->head) * g_sect
+ + part->sector;
+ end_sect = (part->end_cyl + 1) * g_head * g_sect;
+ if (end_sect <= start_sect) {
+ printk(" (invalid partition info)\n");
+ continue;
+ }
+
+ put_partition(state, nr + 1, start_sect, end_sect - start_sect);
+#ifdef CONFIG_NEC98_BSD_DISKLABEL
+ if ((*(__u16 *)&part->mid & 0x7F7F)
+ == NEC98_BSD_PARTITION_MID_SID) {
+ printk("!");
+ /* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
+ IBM PC's MS-DOS partition table, so we simply pass
+ it to bsd_disklabel_partition;
+ it will just print `<bsd: ... >'. */
+ parse_bsd(state, bdev, start_sect,
+ end_sect - start_sect, nr + 1,
+ "bsd98", BSD_MAXPARTITIONS);
+ }
+#endif
+ { /* Pretty size printing. */
+ /* XXX sector size? */
+ unsigned int psize = (end_sect - start_sect) / 2;
+ int unit_char = 'K';
+
+ if (psize > 99999) {
+ psize >>= 10;
+ unit_char = 'M';
+ }
+ printk(" %5d%cB (%5d-%5d)\n",
+ psize, unit_char, part->cyl, part->end_cyl);
+ }
+ }
+
+ put_dev_sector(sect);
+
+ return nr ? 1 : 0;
+}
+\f
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux/fs/partitions/nec98.h linux98/fs/partitions/nec98.h
--- linux/fs/partitions/nec98.h Thu Jan 1 09:00:00 1970
+++ linux98/fs/partitions/nec98.h Fri Jul 26 11:10:08 2002
@@ -0,0 +1,10 @@
+/*
+ * NEC PC-9800 series partition supports
+ *
+ * Copyright (C) 1998-2000 Kyoto University Microcomputer Club
+ */
+
+#define NEC98_PTABLE_MAGIC 0xAA55
+
+extern int nec98_partition(struct parsed_partitions *state,
+ struct block_device *bdev);
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2002-10-30 0:11 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-10-28 17:30 [PATCHSET 17/23] add support for PC-9800 architecture (SCSI) Osamu Tomita
2002-10-28 22:33 ` Alan Cox
2002-10-29 17:04 ` Osamu Tomita
2002-10-29 17:11 ` [PATCHSET 8/23] add support for PC-9800 architecture (fs) Osamu Tomita
2002-10-29 17:54 ` Jeff Garzik
-- strict thread matches above, loose matches on Subject: below --
2002-10-30 0:18 Osamu Tomita
2002-10-28 17:30 Osamu Tomita
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox