3 * drivers/scsi/pc980155.c
5 * PC-9801-55 SCSI host adapter driver
7 * Copyright (C) 1997-2003 Kyoto University Microcomputer Club
9 * Tomoharu Ugawa <ohirune@kmc.gr.jp>
13 #include <linux/module.h>
14 #include <linux/blkdev.h>
15 #include <linux/ioport.h>
16 #include <linux/interrupt.h>
17 #include <linux/types.h>
18 #include <linux/delay.h>
27 extern int pc98_bios_param(struct scsi_device *, struct block_device *,
29 static int scsi_pc980155_detect(Scsi_Host_Template *);
30 static int scsi_pc980155_release(struct Scsi_Host *);
40 #undef PC_9801_55_DEBUG
41 #undef PC_9801_55_DEBUG_VERBOSE
44 static int nr_base_ios = NR_BASE_IOS;
45 static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0, 0xcf0};
46 static wd33c93_regs init_regs;
49 static struct Scsi_Host *pc980155_host = NULL;
51 static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp);
53 static inline void pc980155_dma_enable(unsigned int base_io)
55 outb(0x01, REG_CWRITE);
58 static inline void pc980155_dma_disable(unsigned int base_io)
60 outb(0x02, REG_CWRITE);
64 static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp)
66 wd33c93_intr(pc980155_host);
69 static int dma_setup(Scsi_Cmnd *sc, int dir_in)
72 * sc->SCp.this_residual : transfer count
73 * sc->SCp.ptr : distination address (virtual address)
74 * dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1)
81 * bit 7,6 01b single mode (this mode only)
82 * bit 5 inc/dec (default:0 = inc)
83 * bit 4 auto initialize (normaly:0 = off)
84 * bit 3,2 01b memory -> io
89 disable_dma(sc->device->host->dma_channel);
90 set_dma_mode(sc->device->host->dma_channel,
91 0x40 | (dir_in ? 0x04 : 0x08));
92 clear_dma_ff(sc->device->host->dma_channel);
93 set_dma_addr(sc->device->host->dma_channel, virt_to_phys(sc->SCp.ptr));
94 set_dma_count(sc->device->host->dma_channel, sc->SCp.this_residual);
95 #ifdef PC_9801_55_DEBUG
96 printk("D%d(%x)D", sc->device->host->dma_channel,
97 sc->SCp.this_residual);
99 enable_dma(sc->device->host->dma_channel);
100 pc980155_dma_enable(sc->device->host->io_port);
104 static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int status)
107 * instance: Hostadapter's instance
109 * status: True if success
111 pc980155_dma_disable(sc->device->host->io_port);
112 disable_dma(sc->device->host->dma_channel);
115 /* return non-zero on detection */
116 static inline int pc980155_test_port(wd33c93_regs regs)
118 /* Quick and dirty test for presence of the card. */
119 if (inb(regs.SASR) == 0xff)
125 static inline int pc980155_getconfig(unsigned int base_io, wd33c93_regs regs,
126 unsigned char* irq, unsigned char* dma,
127 unsigned char* scsi_id)
129 static unsigned char irqs[] = {3, 5, 6, 9, 12, 13};
130 unsigned char result;
132 printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n",
133 base_io, regs.SASR, regs.SCMD);
134 result = read_pc980155_resetint(regs);
135 printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result);
136 *scsi_id = result & 0x07;
137 *irq = (result >> 3) & 0x07;
139 printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ (%d)"
140 " - other device here?\n", base_io, *irq);
145 result = inb(REG_STATRD);
146 *dma = result & 0x03;
149 "PC-9801-55 (base %#x): impossible DMA channl (%d)"
150 " - other device here?\n", base_io, *dma);
153 #ifdef PC_9801_55_DEBUG
154 printk("PC-9801-55: end of getconfig\n");
159 /* return non-zero on detection */
160 static int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
162 unsigned int base_io;
163 unsigned char irq, dma, scsi_id;
165 #ifdef PC_9801_55_DEBUG
174 for (i = 0; i < nr_base_ios; i++) {
175 base_io = base_ios[i];
176 init_regs.SASR = REG_ADDRST;
177 init_regs.SCMD = REG_CONTRL;
178 #ifdef PC_9801_55_DEBUG
179 printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST);
181 if (!request_region(base_io, 6, "PC-9801-55"))
184 if (pc980155_test_port(init_regs) &&
185 pc980155_getconfig(base_io, init_regs,
186 &irq, &dma, &scsi_id))
189 release_region(base_io, 6);
192 printk("PC-9801-55: not found\n");
196 #ifdef PC_9801_55_DEBUG
197 printk("PC-9801-55: config: base io = %x, irq = %d, dma channel = %d, scsi id = %d\n", base_io, irq, dma, scsi_id);
199 if (request_irq(irq, pc980155_intr_handle, 0, "PC-9801-55", NULL)) {
200 printk(KERN_ERR "PC-9801-55: unable to allocate IRQ %d\n", irq);
204 if (request_dma(dma, "PC-9801-55")) {
205 printk(KERN_ERR "PC-9801-55: unable to allocate DMA channel %d\n", dma);
209 pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
211 pc980155_host->this_id = scsi_id;
212 pc980155_host->io_port = base_io;
213 pc980155_host->n_io_port = 6;
214 pc980155_host->irq = irq;
215 pc980155_host->dma_channel = dma;
216 printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma);
217 pc980155_int_enable(init_regs);
218 wd33c93_init(pc980155_host, init_regs, dma_setup, dma_stop,
223 printk(KERN_ERR "PC-9801-55: failed to register device\n");
228 release_region(base_io, 6);
232 static int scsi_pc980155_release(struct Scsi_Host *shost)
234 struct WD33C93_hostdata *hostdata
235 = (struct WD33C93_hostdata *)shost->hostdata;
237 pc980155_int_disable(hostdata->regs);
238 release_region(shost->io_port, shost->n_io_port);
239 free_irq(shost->irq, NULL);
240 free_dma(shost->dma_channel);
245 static int pc980155_bus_reset(Scsi_Cmnd *cmd)
247 struct WD33C93_hostdata *hostdata
248 = (struct WD33C93_hostdata *)cmd->device->host->hostdata;
250 pc980155_int_disable(hostdata->regs);
251 pc980155_assert_bus_reset(hostdata->regs);
253 pc980155_negate_bus_reset(hostdata->regs);
254 (void) inb(hostdata->regs.SASR);
255 (void) read_pc980155(hostdata->regs, WD_SCSI_STATUS);
256 pc980155_int_enable(hostdata->regs);
257 wd33c93_host_reset(cmd);
263 static int __init pc980155_setup(char *str)
267 str = get_options(str, ARRAY_SIZE(ints), ints);
272 __setup("pc980155_io=", pc980155_setup);
275 MODULE_PARM(io, "i");
276 MODULE_AUTHOR("Tomoharu Ugawa <ohirune@kmc.gr.jp>");
277 MODULE_DESCRIPTION("PC-9801-55 SCSI host adapter driver");
278 MODULE_LICENSE("GPL");
280 static Scsi_Host_Template driver_template = {
281 .proc_info = wd33c93_proc_info,
282 .name = "SCSI PC-9801-55",
283 .detect = scsi_pc980155_detect,
284 .release = scsi_pc980155_release,
285 .queuecommand = wd33c93_queuecommand,
286 .eh_abort_handler = wd33c93_abort,
287 .eh_bus_reset_handler = pc980155_bus_reset,
288 .eh_host_reset_handler = wd33c93_host_reset,
289 .bios_param = pc98_bios_param,
290 .can_queue = CAN_QUEUE,
292 .sg_tablesize = SG_ALL,
293 .cmd_per_lun = CMD_PER_LUN, /* dont use link command */
294 .unchecked_isa_dma = 1, /* use dma **XXXX***/
295 .use_clustering = ENABLE_CLUSTERING,
296 .proc_name = "PC_9801_55",
299 #include "scsi_module.c"