blob: 0d4c04e1f3de3f941655ec67a023992e77d46f04 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*======================================================================
2
3 NinjaSCSI-3 / NinjaSCSI-32Bi PCMCIA SCSI host adapter card driver
4 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
5
6 Ver.2.8 Support 32bit MMIO mode
7 Support Synchronous Data Transfer Request (SDTR) mode
8 Ver.2.0 Support 32bit PIO mode
9 Ver.1.1.2 Fix for scatter list buffer exceeds
10 Ver.1.1 Support scatter list
11 Ver.0.1 Initial version
12
13 This software may be used and distributed according to the terms of
14 the GNU General Public License.
15
16======================================================================*/
17
18/***********************************************************************
19 This driver is for these PCcards.
20
21 I-O DATA PCSC-F (Workbit NinjaSCSI-3)
22 "WBT", "NinjaSCSI-3", "R1.0"
23 I-O DATA CBSC-II (Workbit NinjaSCSI-32Bi in 16bit mode)
24 "IO DATA", "CBSC16 ", "1"
25
26***********************************************************************/
27
28/* $Id: nsp_cs.c,v 1.23 2003/08/18 11:09:19 elca Exp $ */
29
30#include <linux/version.h>
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/init.h>
34#include <linux/sched.h>
35#include <linux/slab.h>
36#include <linux/string.h>
37#include <linux/timer.h>
38#include <linux/ioport.h>
39#include <linux/delay.h>
40#include <linux/interrupt.h>
41#include <linux/major.h>
42#include <linux/blkdev.h>
43#include <linux/stat.h>
44
45#include <asm/io.h>
46#include <asm/irq.h>
47
48#include <../drivers/scsi/scsi.h>
49#include <scsi/scsi_host.h>
50
51#include <scsi/scsi.h>
52#include <scsi/scsi_ioctl.h>
53
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <pcmcia/cs_types.h>
55#include <pcmcia/cs.h>
56#include <pcmcia/cistpl.h>
57#include <pcmcia/cisreg.h>
58#include <pcmcia/ds.h>
59
60#include "nsp_cs.h"
61
62MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
63MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.23 $");
64MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
65#ifdef MODULE_LICENSE
66MODULE_LICENSE("GPL");
67#endif
68
69#include "nsp_io.h"
70
71/*====================================================================*/
72/* Parameters that can be set with 'insmod' */
73
74static int nsp_burst_mode = BURST_MEM32;
75module_param(nsp_burst_mode, int, 0);
76MODULE_PARM_DESC(nsp_burst_mode, "Burst transfer mode (0=io8, 1=io32, 2=mem32(default))");
77
78/* Release IO ports after configuration? */
79static int free_ports = 0;
80module_param(free_ports, bool, 0);
81MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))");
82
83/* /usr/src/linux/drivers/scsi/hosts.h */
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +010084static struct scsi_host_template nsp_driver_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 .proc_name = "nsp_cs",
86 .proc_info = nsp_proc_info,
87 .name = "WorkBit NinjaSCSI-3/32Bi(16bit)",
88#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
89 .detect = nsp_detect_old,
90 .release = nsp_release_old,
91#endif
92 .info = nsp_info,
93 .queuecommand = nsp_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -070094/* .eh_abort_handler = nsp_eh_abort,*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 .eh_bus_reset_handler = nsp_eh_bus_reset,
96 .eh_host_reset_handler = nsp_eh_host_reset,
97 .can_queue = 1,
98 .this_id = NSP_INITIATOR_ID,
99 .sg_tablesize = SG_ALL,
100 .cmd_per_lun = 1,
101 .use_clustering = DISABLE_CLUSTERING,
102#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
103 .use_new_eh_code = 1,
104#endif
105};
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
108
109
110
111/*
112 * debug, error print
113 */
114#ifndef NSP_DEBUG
115# define NSP_DEBUG_MASK 0x000000
116# define nsp_msg(type, args...) nsp_cs_message("", 0, (type), args)
117# define nsp_dbg(mask, args...) /* */
118#else
119# define NSP_DEBUG_MASK 0xffffff
120# define nsp_msg(type, args...) \
121 nsp_cs_message (__FUNCTION__, __LINE__, (type), args)
122# define nsp_dbg(mask, args...) \
123 nsp_cs_dmessage(__FUNCTION__, __LINE__, (mask), args)
124#endif
125
126#define NSP_DEBUG_QUEUECOMMAND BIT(0)
127#define NSP_DEBUG_REGISTER BIT(1)
128#define NSP_DEBUG_AUTOSCSI BIT(2)
129#define NSP_DEBUG_INTR BIT(3)
130#define NSP_DEBUG_SGLIST BIT(4)
131#define NSP_DEBUG_BUSFREE BIT(5)
132#define NSP_DEBUG_CDB_CONTENTS BIT(6)
133#define NSP_DEBUG_RESELECTION BIT(7)
134#define NSP_DEBUG_MSGINOCCUR BIT(8)
135#define NSP_DEBUG_EEPROM BIT(9)
136#define NSP_DEBUG_MSGOUTOCCUR BIT(10)
137#define NSP_DEBUG_BUSRESET BIT(11)
138#define NSP_DEBUG_RESTART BIT(12)
139#define NSP_DEBUG_SYNC BIT(13)
140#define NSP_DEBUG_WAIT BIT(14)
141#define NSP_DEBUG_TARGETFLAG BIT(15)
142#define NSP_DEBUG_PROC BIT(16)
143#define NSP_DEBUG_INIT BIT(17)
144#define NSP_DEBUG_DATA_IO BIT(18)
145#define NSP_SPECIAL_PRINT_REGISTER BIT(20)
146
147#define NSP_DEBUG_BUF_LEN 150
148
149static void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...)
150{
151 va_list args;
152 char buf[NSP_DEBUG_BUF_LEN];
153
154 va_start(args, fmt);
155 vsnprintf(buf, sizeof(buf), fmt, args);
156 va_end(args);
157
158#ifndef NSP_DEBUG
159 printk("%snsp_cs: %s\n", type, buf);
160#else
161 printk("%snsp_cs: %s (%d): %s\n", type, func, line, buf);
162#endif
163}
164
165#ifdef NSP_DEBUG
166static void nsp_cs_dmessage(const char *func, int line, int mask, char *fmt, ...)
167{
168 va_list args;
169 char buf[NSP_DEBUG_BUF_LEN];
170
171 va_start(args, fmt);
172 vsnprintf(buf, sizeof(buf), fmt, args);
173 va_end(args);
174
175 if (mask & NSP_DEBUG_MASK) {
176 printk("nsp_cs-debug: 0x%x %s (%d): %s\n", mask, func, line, buf);
177 }
178}
179#endif
180
181/***********************************************************/
182
183/*====================================================
184 * Clenaup parameters and call done() functions.
185 * You must be set SCpnt->result before call this function.
186 */
187static void nsp_scsi_done(Scsi_Cmnd *SCpnt)
188{
189 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
190
191 data->CurrentSC = NULL;
192
193 SCpnt->scsi_done(SCpnt);
194}
195
196static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
197{
198#ifdef NSP_DEBUG
199 /*unsigned int host_id = SCpnt->device->host->this_id;*/
200 /*unsigned int base = SCpnt->device->host->io_port;*/
Jeff Garzik422c0d62005-10-24 18:05:09 -0400201 unsigned char target = scmd_id(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#endif
203 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
204
205 nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "SCpnt=0x%p target=%d lun=%d buff=0x%p bufflen=%d use_sg=%d",
206 SCpnt, target, SCpnt->device->lun, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->use_sg);
207 //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC);
208
209 SCpnt->scsi_done = done;
210
211 if (data->CurrentSC != NULL) {
212 nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");
213 SCpnt->result = DID_BAD_TARGET << 16;
214 nsp_scsi_done(SCpnt);
215 return 0;
216 }
217
218#if 0
219 /* XXX: pcmcia-cs generates SCSI command with "scsi_info" utility.
220 This makes kernel crash when suspending... */
221 if (data->ScsiInfo->stop != 0) {
222 nsp_msg(KERN_INFO, "suspending device. reject command.");
223 SCpnt->result = DID_BAD_TARGET << 16;
224 nsp_scsi_done(SCpnt);
225 return SCSI_MLQUEUE_HOST_BUSY;
226 }
227#endif
228
229 show_command(SCpnt);
230
231 data->CurrentSC = SCpnt;
232
233 SCpnt->SCp.Status = CHECK_CONDITION;
234 SCpnt->SCp.Message = 0;
235 SCpnt->SCp.have_data_in = IO_UNKNOWN;
236 SCpnt->SCp.sent_command = 0;
237 SCpnt->SCp.phase = PH_UNDETERMINED;
238 SCpnt->resid = SCpnt->request_bufflen;
239
240 /* setup scratch area
241 SCp.ptr : buffer pointer
242 SCp.this_residual : buffer length
243 SCp.buffer : next buffer
244 SCp.buffers_residual : left buffers in list
245 SCp.phase : current state of the command */
246 if (SCpnt->use_sg) {
247 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
248 SCpnt->SCp.ptr = BUFFER_ADDR;
249 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
250 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
251 } else {
252 SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
253 SCpnt->SCp.this_residual = SCpnt->request_bufflen;
254 SCpnt->SCp.buffer = NULL;
255 SCpnt->SCp.buffers_residual = 0;
256 }
257
258 if (nsphw_start_selection(SCpnt) == FALSE) {
259 nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");
260 SCpnt->result = DID_BUS_BUSY << 16;
261 nsp_scsi_done(SCpnt);
262 return 0;
263 }
264
265
266 //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "out");
267#ifdef NSP_DEBUG
268 data->CmdId++;
269#endif
270 return 0;
271}
272
273/*
274 * setup PIO FIFO transfer mode and enable/disable to data out
275 */
276static void nsp_setup_fifo(nsp_hw_data *data, int enabled)
277{
278 unsigned int base = data->BaseAddress;
279 unsigned char transfer_mode_reg;
280
281 //nsp_dbg(NSP_DEBUG_DATA_IO, "enabled=%d", enabled);
282
283 if (enabled != FALSE) {
284 transfer_mode_reg = TRANSFER_GO | BRAIND;
285 } else {
286 transfer_mode_reg = 0;
287 }
288
289 transfer_mode_reg |= data->TransferMode;
290
291 nsp_index_write(base, TRANSFERMODE, transfer_mode_reg);
292}
293
294static void nsphw_init_sync(nsp_hw_data *data)
295{
296 sync_data tmp_sync = { .SyncNegotiation = SYNC_NOT_YET,
297 .SyncPeriod = 0,
298 .SyncOffset = 0
299 };
300 int i;
301
302 /* setup sync data */
303 for ( i = 0; i < ARRAY_SIZE(data->Sync); i++ ) {
304 data->Sync[i] = tmp_sync;
305 }
306}
307
308/*
309 * Initialize Ninja hardware
310 */
311static int nsphw_init(nsp_hw_data *data)
312{
313 unsigned int base = data->BaseAddress;
314
315 nsp_dbg(NSP_DEBUG_INIT, "in base=0x%x", base);
316
317 data->ScsiClockDiv = CLOCK_40M | FAST_20;
318 data->CurrentSC = NULL;
319 data->FifoCount = 0;
320 data->TransferMode = MODE_IO8;
321
322 nsphw_init_sync(data);
323
324 /* block all interrupts */
325 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);
326
327 /* setup SCSI interface */
328 nsp_write(base, IFSELECT, IF_IFSEL);
329
330 nsp_index_write(base, SCSIIRQMODE, 0);
331
332 nsp_index_write(base, TRANSFERMODE, MODE_IO8);
333 nsp_index_write(base, CLOCKDIV, data->ScsiClockDiv);
334
335 nsp_index_write(base, PARITYCTRL, 0);
336 nsp_index_write(base, POINTERCLR, POINTER_CLEAR |
337 ACK_COUNTER_CLEAR |
338 REQ_COUNTER_CLEAR |
339 HOST_COUNTER_CLEAR);
340
341 /* setup fifo asic */
342 nsp_write(base, IFSELECT, IF_REGSEL);
343 nsp_index_write(base, TERMPWRCTRL, 0);
344 if ((nsp_index_read(base, OTHERCONTROL) & TPWR_SENSE) == 0) {
345 nsp_msg(KERN_INFO, "terminator power on");
346 nsp_index_write(base, TERMPWRCTRL, POWER_ON);
347 }
348
349 nsp_index_write(base, TIMERCOUNT, 0);
350 nsp_index_write(base, TIMERCOUNT, 0); /* requires 2 times!! */
351
352 nsp_index_write(base, SYNCREG, 0);
353 nsp_index_write(base, ACKWIDTH, 0);
354
355 /* enable interrupts and ack them */
356 nsp_index_write(base, SCSIIRQMODE, SCSI_PHASE_CHANGE_EI |
357 RESELECT_EI |
358 SCSI_RESET_IRQ_EI );
359 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR);
360
361 nsp_setup_fifo(data, FALSE);
362
363 return TRUE;
364}
365
366/*
367 * Start selection phase
368 */
369static int nsphw_start_selection(Scsi_Cmnd *SCpnt)
370{
371 unsigned int host_id = SCpnt->device->host->this_id;
372 unsigned int base = SCpnt->device->host->io_port;
Jeff Garzik422c0d62005-10-24 18:05:09 -0400373 unsigned char target = scmd_id(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
375 int time_out;
376 unsigned char phase, arbit;
377
378 //nsp_dbg(NSP_DEBUG_RESELECTION, "in");
379
380 phase = nsp_index_read(base, SCSIBUSMON);
381 if(phase != BUSMON_BUS_FREE) {
382 //nsp_dbg(NSP_DEBUG_RESELECTION, "bus busy");
383 return FALSE;
384 }
385
386 /* start arbitration */
387 //nsp_dbg(NSP_DEBUG_RESELECTION, "start arbit");
388 SCpnt->SCp.phase = PH_ARBSTART;
389 nsp_index_write(base, SETARBIT, ARBIT_GO);
390
391 time_out = 1000;
392 do {
393 /* XXX: what a stupid chip! */
394 arbit = nsp_index_read(base, ARBITSTATUS);
395 //nsp_dbg(NSP_DEBUG_RESELECTION, "arbit=%d, wait_count=%d", arbit, wait_count);
396 udelay(1); /* hold 1.2us */
397 } while((arbit & (ARBIT_WIN | ARBIT_FAIL)) == 0 &&
398 (time_out-- != 0));
399
400 if (!(arbit & ARBIT_WIN)) {
401 //nsp_dbg(NSP_DEBUG_RESELECTION, "arbit fail");
402 nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR);
403 return FALSE;
404 }
405
406 /* assert select line */
407 //nsp_dbg(NSP_DEBUG_RESELECTION, "assert SEL line");
408 SCpnt->SCp.phase = PH_SELSTART;
409 udelay(3); /* wait 2.4us */
410 nsp_index_write(base, SCSIDATALATCH, BIT(host_id) | BIT(target));
411 nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_BSY | SCSI_ATN);
412 udelay(2); /* wait >1.2us */
413 nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_BSY | SCSI_DATAOUT_ENB | SCSI_ATN);
414 nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR);
415 /*udelay(1);*/ /* wait >90ns */
416 nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_DATAOUT_ENB | SCSI_ATN);
417
418 /* check selection timeout */
419 nsp_start_timer(SCpnt, 1000/51);
420 data->SelectionTimeOut = 1;
421
422 return TRUE;
423}
424
425struct nsp_sync_table {
426 unsigned int min_period;
427 unsigned int max_period;
428 unsigned int chip_period;
429 unsigned int ack_width;
430};
431
432static struct nsp_sync_table nsp_sync_table_40M[] = {
433 {0x0c, 0x0c, 0x1, 0}, /* 20MB 50ns*/
434 {0x19, 0x19, 0x3, 1}, /* 10MB 100ns*/
435 {0x1a, 0x25, 0x5, 2}, /* 7.5MB 150ns*/
436 {0x26, 0x32, 0x7, 3}, /* 5MB 200ns*/
437 { 0, 0, 0, 0},
438};
439
440static struct nsp_sync_table nsp_sync_table_20M[] = {
441 {0x19, 0x19, 0x1, 0}, /* 10MB 100ns*/
442 {0x1a, 0x25, 0x2, 0}, /* 7.5MB 150ns*/
443 {0x26, 0x32, 0x3, 1}, /* 5MB 200ns*/
444 { 0, 0, 0, 0},
445};
446
447/*
448 * setup synchronous data transfer mode
449 */
450static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt)
451{
Jeff Garzik422c0d62005-10-24 18:05:09 -0400452 unsigned char target = scmd_id(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453// unsigned char lun = SCpnt->device->lun;
454 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
455 sync_data *sync = &(data->Sync[target]);
456 struct nsp_sync_table *sync_table;
457 unsigned int period, offset;
458 int i;
459
460
461 nsp_dbg(NSP_DEBUG_SYNC, "in");
462
463 period = sync->SyncPeriod;
464 offset = sync->SyncOffset;
465
466 nsp_dbg(NSP_DEBUG_SYNC, "period=0x%x, offset=0x%x", period, offset);
467
468 if ((data->ScsiClockDiv & (BIT(0)|BIT(1))) == CLOCK_20M) {
469 sync_table = nsp_sync_table_20M;
470 } else {
471 sync_table = nsp_sync_table_40M;
472 }
473
474 for ( i = 0; sync_table->max_period != 0; i++, sync_table++) {
475 if ( period >= sync_table->min_period &&
476 period <= sync_table->max_period ) {
477 break;
478 }
479 }
480
481 if (period != 0 && sync_table->max_period == 0) {
482 /*
483 * No proper period/offset found
484 */
485 nsp_dbg(NSP_DEBUG_SYNC, "no proper period/offset");
486
487 sync->SyncPeriod = 0;
488 sync->SyncOffset = 0;
489 sync->SyncRegister = 0;
490 sync->AckWidth = 0;
491
492 return FALSE;
493 }
494
495 sync->SyncRegister = (sync_table->chip_period << SYNCREG_PERIOD_SHIFT) |
496 (offset & SYNCREG_OFFSET_MASK);
497 sync->AckWidth = sync_table->ack_width;
498
499 nsp_dbg(NSP_DEBUG_SYNC, "sync_reg=0x%x, ack_width=0x%x", sync->SyncRegister, sync->AckWidth);
500
501 return TRUE;
502}
503
504
505/*
506 * start ninja hardware timer
507 */
508static void nsp_start_timer(Scsi_Cmnd *SCpnt, int time)
509{
510 unsigned int base = SCpnt->device->host->io_port;
511 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
512
513 //nsp_dbg(NSP_DEBUG_INTR, "in SCpnt=0x%p, time=%d", SCpnt, time);
514 data->TimerCount = time;
515 nsp_index_write(base, TIMERCOUNT, time);
516}
517
518/*
519 * wait for bus phase change
520 */
521static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
522{
523 unsigned int base = SCpnt->device->host->io_port;
524 unsigned char reg;
525 int time_out;
526
527 //nsp_dbg(NSP_DEBUG_INTR, "in");
528
529 time_out = 100;
530
531 do {
532 reg = nsp_index_read(base, SCSIBUSMON);
533 if (reg == 0xff) {
534 break;
535 }
536 } while ((time_out-- != 0) && (reg & mask) != 0);
537
538 if (time_out == 0) {
539 nsp_msg(KERN_DEBUG, " %s signal off timeut", str);
540 }
541
542 return 0;
543}
544
545/*
546 * expect Ninja Irq
547 */
548static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
549 unsigned char current_phase,
550 unsigned char mask)
551{
552 unsigned int base = SCpnt->device->host->io_port;
553 int time_out;
554 unsigned char phase, i_src;
555
556 //nsp_dbg(NSP_DEBUG_INTR, "current_phase=0x%x, mask=0x%x", current_phase, mask);
557
558 time_out = 100;
559 do {
560 phase = nsp_index_read(base, SCSIBUSMON);
561 if (phase == 0xff) {
562 //nsp_dbg(NSP_DEBUG_INTR, "ret -1");
563 return -1;
564 }
565 i_src = nsp_read(base, IRQSTATUS);
566 if (i_src & IRQSTATUS_SCSI) {
567 //nsp_dbg(NSP_DEBUG_INTR, "ret 0 found scsi signal");
568 return 0;
569 }
570 if ((phase & mask) != 0 && (phase & BUSMON_PHASE_MASK) == current_phase) {
571 //nsp_dbg(NSP_DEBUG_INTR, "ret 1 phase=0x%x", phase);
572 return 1;
573 }
574 } while(time_out-- != 0);
575
576 //nsp_dbg(NSP_DEBUG_INTR, "timeout");
577 return -1;
578}
579
580/*
581 * transfer SCSI message
582 */
583static int nsp_xfer(Scsi_Cmnd *SCpnt, int phase)
584{
585 unsigned int base = SCpnt->device->host->io_port;
586 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
587 char *buf = data->MsgBuffer;
588 int len = min(MSGBUF_SIZE, data->MsgLen);
589 int ptr;
590 int ret;
591
592 //nsp_dbg(NSP_DEBUG_DATA_IO, "in");
593 for (ptr = 0; len > 0; len--, ptr++) {
594
595 ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);
596 if (ret <= 0) {
597 nsp_dbg(NSP_DEBUG_DATA_IO, "xfer quit");
598 return 0;
599 }
600
601 /* if last byte, negate ATN */
602 if (len == 1 && SCpnt->SCp.phase == PH_MSG_OUT) {
603 nsp_index_write(base, SCSIBUSCTRL, AUTODIRECTION | ACKENB);
604 }
605
606 /* read & write message */
607 if (phase & BUSMON_IO) {
608 nsp_dbg(NSP_DEBUG_DATA_IO, "read msg");
609 buf[ptr] = nsp_index_read(base, SCSIDATAWITHACK);
610 } else {
611 nsp_dbg(NSP_DEBUG_DATA_IO, "write msg");
612 nsp_index_write(base, SCSIDATAWITHACK, buf[ptr]);
613 }
614 nsp_negate_signal(SCpnt, BUSMON_ACK, "xfer<ack>");
615
616 }
617 return len;
618}
619
620/*
621 * get extra SCSI data from fifo
622 */
623static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt)
624{
625 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
626 unsigned int count;
627
628 //nsp_dbg(NSP_DEBUG_DATA_IO, "in");
629
630 if (SCpnt->SCp.have_data_in != IO_IN) {
631 return 0;
632 }
633
634 count = nsp_fifo_count(SCpnt);
635 if (data->FifoCount == count) {
636 //nsp_dbg(NSP_DEBUG_DATA_IO, "not use bypass quirk");
637 return 0;
638 }
639
640 /*
641 * XXX: NSP_QUIRK
642 * data phase skip only occures in case of SCSI_LOW_READ
643 */
644 nsp_dbg(NSP_DEBUG_DATA_IO, "use bypass quirk");
645 SCpnt->SCp.phase = PH_DATA;
646 nsp_pio_read(SCpnt);
647 nsp_setup_fifo(data, FALSE);
648
649 return 0;
650}
651
652/*
653 * accept reselection
654 */
655static int nsp_reselected(Scsi_Cmnd *SCpnt)
656{
657 unsigned int base = SCpnt->device->host->io_port;
658 unsigned int host_id = SCpnt->device->host->this_id;
659 //nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
660 unsigned char bus_reg;
661 unsigned char id_reg, tmp;
662 int target;
663
664 nsp_dbg(NSP_DEBUG_RESELECTION, "in");
665
666 id_reg = nsp_index_read(base, RESELECTID);
667 tmp = id_reg & (~BIT(host_id));
668 target = 0;
669 while(tmp != 0) {
670 if (tmp & BIT(0)) {
671 break;
672 }
673 tmp >>= 1;
674 target++;
675 }
676
Jeff Garzik422c0d62005-10-24 18:05:09 -0400677 if (scmd_id(SCpnt) != target) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 nsp_msg(KERN_ERR, "XXX: reselect ID must be %d in this implementation.", target);
679 }
680
681 nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");
682
683 nsp_nexus(SCpnt);
684 bus_reg = nsp_index_read(base, SCSIBUSCTRL) & ~(SCSI_BSY | SCSI_ATN);
685 nsp_index_write(base, SCSIBUSCTRL, bus_reg);
686 nsp_index_write(base, SCSIBUSCTRL, bus_reg | AUTODIRECTION | ACKENB);
687
688 return TRUE;
689}
690
691/*
692 * count how many data transferd
693 */
694static int nsp_fifo_count(Scsi_Cmnd *SCpnt)
695{
696 unsigned int base = SCpnt->device->host->io_port;
697 unsigned int count;
698 unsigned int l, m, h, dummy;
699
700 nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER);
701
702 l = nsp_index_read(base, TRANSFERCOUNT);
703 m = nsp_index_read(base, TRANSFERCOUNT);
704 h = nsp_index_read(base, TRANSFERCOUNT);
705 dummy = nsp_index_read(base, TRANSFERCOUNT); /* required this! */
706
707 count = (h << 16) | (m << 8) | (l << 0);
708
709 //nsp_dbg(NSP_DEBUG_DATA_IO, "count=0x%x", count);
710
711 return count;
712}
713
714/* fifo size */
715#define RFIFO_CRIT 64
716#define WFIFO_CRIT 64
717
718/*
719 * read data in DATA IN phase
720 */
721static void nsp_pio_read(Scsi_Cmnd *SCpnt)
722{
723 unsigned int base = SCpnt->device->host->io_port;
724 unsigned long mmio_base = SCpnt->device->host->base;
725 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
726 long time_out;
727 int ocount, res;
728 unsigned char stat, fifo_stat;
729
730 ocount = data->FifoCount;
731
732 nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d",
733 SCpnt, SCpnt->resid, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);
734
735 time_out = 1000;
736
737 while ((time_out-- != 0) &&
738 (SCpnt->SCp.this_residual > 0 || SCpnt->SCp.buffers_residual > 0 ) ) {
739
740 stat = nsp_index_read(base, SCSIBUSMON);
741 stat &= BUSMON_PHASE_MASK;
742
743
744 res = nsp_fifo_count(SCpnt) - ocount;
745 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount, res);
746 if (res == 0) { /* if some data avilable ? */
747 if (stat == BUSPHASE_DATA_IN) { /* phase changed? */
748 //nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", SCpnt->SCp.this_residual);
749 continue;
750 } else {
751 nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x", stat);
752 break;
753 }
754 }
755
756 fifo_stat = nsp_read(base, FIFOSTATUS);
757 if ((fifo_stat & FIFOSTATUS_FULL_EMPTY) == 0 &&
758 stat == BUSPHASE_DATA_IN) {
759 continue;
760 }
761
762 res = min(res, SCpnt->SCp.this_residual);
763
764 switch (data->TransferMode) {
765 case MODE_IO32:
766 res &= ~(BIT(1)|BIT(0)); /* align 4 */
767 nsp_fifo32_read(base, SCpnt->SCp.ptr, res >> 2);
768 break;
769 case MODE_IO8:
770 nsp_fifo8_read (base, SCpnt->SCp.ptr, res );
771 break;
772
773 case MODE_MEM32:
774 res &= ~(BIT(1)|BIT(0)); /* align 4 */
775 nsp_mmio_fifo32_read(mmio_base, SCpnt->SCp.ptr, res >> 2);
776 break;
777
778 default:
779 nsp_dbg(NSP_DEBUG_DATA_IO, "unknown read mode");
780 return;
781 }
782
783 SCpnt->resid -= res;
784 SCpnt->SCp.ptr += res;
785 SCpnt->SCp.this_residual -= res;
786 ocount += res;
787 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this_residual=0x%x ocount=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount);
788
789 /* go to next scatter list if available */
790 if (SCpnt->SCp.this_residual == 0 &&
791 SCpnt->SCp.buffers_residual != 0 ) {
792 //nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next timeout=%d", time_out);
793 SCpnt->SCp.buffers_residual--;
794 SCpnt->SCp.buffer++;
795 SCpnt->SCp.ptr = BUFFER_ADDR;
796 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
797 time_out = 1000;
798
799 //nsp_dbg(NSP_DEBUG_DATA_IO, "page: 0x%p, off: 0x%x", SCpnt->SCp.buffer->page, SCpnt->SCp.buffer->offset);
800 }
801 }
802
803 data->FifoCount = ocount;
804
805 if (time_out == 0) {
806 nsp_msg(KERN_DEBUG, "pio read timeout resid=%d this_residual=%d buffers_residual=%d",
807 SCpnt->resid, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual);
808 }
809 nsp_dbg(NSP_DEBUG_DATA_IO, "read ocount=0x%x", ocount);
810 nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);
811}
812
813/*
814 * write data in DATA OUT phase
815 */
816static void nsp_pio_write(Scsi_Cmnd *SCpnt)
817{
818 unsigned int base = SCpnt->device->host->io_port;
819 unsigned long mmio_base = SCpnt->device->host->base;
820 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
821 int time_out;
822 int ocount, res;
823 unsigned char stat;
824
825 ocount = data->FifoCount;
826
827 nsp_dbg(NSP_DEBUG_DATA_IO, "in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x",
828 data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, SCpnt->resid);
829
830 time_out = 1000;
831
832 while ((time_out-- != 0) &&
833 (SCpnt->SCp.this_residual > 0 || SCpnt->SCp.buffers_residual > 0)) {
834 stat = nsp_index_read(base, SCSIBUSMON);
835 stat &= BUSMON_PHASE_MASK;
836
837 if (stat != BUSPHASE_DATA_OUT) {
838 res = ocount - nsp_fifo_count(SCpnt);
839
840 nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x, res=%d\n", stat, res);
841 /* Put back pointer */
842 SCpnt->resid += res;
843 SCpnt->SCp.ptr -= res;
844 SCpnt->SCp.this_residual += res;
845 ocount -= res;
846
847 break;
848 }
849
850 res = ocount - nsp_fifo_count(SCpnt);
851 if (res > 0) { /* write all data? */
852 nsp_dbg(NSP_DEBUG_DATA_IO, "wait for all data out. ocount=0x%x res=%d", ocount, res);
853 continue;
854 }
855
856 res = min(SCpnt->SCp.this_residual, WFIFO_CRIT);
857
858 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, res);
859 switch (data->TransferMode) {
860 case MODE_IO32:
861 res &= ~(BIT(1)|BIT(0)); /* align 4 */
862 nsp_fifo32_write(base, SCpnt->SCp.ptr, res >> 2);
863 break;
864 case MODE_IO8:
865 nsp_fifo8_write (base, SCpnt->SCp.ptr, res );
866 break;
867
868 case MODE_MEM32:
869 res &= ~(BIT(1)|BIT(0)); /* align 4 */
870 nsp_mmio_fifo32_write(mmio_base, SCpnt->SCp.ptr, res >> 2);
871 break;
872
873 default:
874 nsp_dbg(NSP_DEBUG_DATA_IO, "unknown write mode");
875 break;
876 }
877
878 SCpnt->resid -= res;
879 SCpnt->SCp.ptr += res;
880 SCpnt->SCp.this_residual -= res;
881 ocount += res;
882
883 /* go to next scatter list if available */
884 if (SCpnt->SCp.this_residual == 0 &&
885 SCpnt->SCp.buffers_residual != 0 ) {
886 //nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next");
887 SCpnt->SCp.buffers_residual--;
888 SCpnt->SCp.buffer++;
889 SCpnt->SCp.ptr = BUFFER_ADDR;
890 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
891 time_out = 1000;
892 }
893 }
894
895 data->FifoCount = ocount;
896
897 if (time_out == 0) {
898 nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x", SCpnt->resid);
899 }
900 nsp_dbg(NSP_DEBUG_DATA_IO, "write ocount=0x%x", ocount);
901 nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);
902}
903#undef RFIFO_CRIT
904#undef WFIFO_CRIT
905
906/*
907 * setup synchronous/asynchronous data transfer mode
908 */
909static int nsp_nexus(Scsi_Cmnd *SCpnt)
910{
911 unsigned int base = SCpnt->device->host->io_port;
Jeff Garzik422c0d62005-10-24 18:05:09 -0400912 unsigned char target = scmd_id(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913// unsigned char lun = SCpnt->device->lun;
914 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
915 sync_data *sync = &(data->Sync[target]);
916
917 //nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p", SCpnt);
918
919 /* setup synch transfer registers */
920 nsp_index_write(base, SYNCREG, sync->SyncRegister);
921 nsp_index_write(base, ACKWIDTH, sync->AckWidth);
922
923 if (SCpnt->use_sg == 0 ||
924 SCpnt->resid % 4 != 0 ||
925 SCpnt->resid <= PAGE_SIZE ) {
926 data->TransferMode = MODE_IO8;
927 } else if (nsp_burst_mode == BURST_MEM32) {
928 data->TransferMode = MODE_MEM32;
929 } else if (nsp_burst_mode == BURST_IO32) {
930 data->TransferMode = MODE_IO32;
931 } else {
932 data->TransferMode = MODE_IO8;
933 }
934
935 /* setup pdma fifo */
936 nsp_setup_fifo(data, TRUE);
937
938 /* clear ack counter */
939 data->FifoCount = 0;
940 nsp_index_write(base, POINTERCLR, POINTER_CLEAR |
941 ACK_COUNTER_CLEAR |
942 REQ_COUNTER_CLEAR |
943 HOST_COUNTER_CLEAR);
944
945 return 0;
946}
947
948#include "nsp_message.c"
949/*
950 * interrupt handler
951 */
952static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs)
953{
954 unsigned int base;
955 unsigned char irq_status, irq_phase, phase;
956 Scsi_Cmnd *tmpSC;
957 unsigned char target, lun;
958 unsigned int *sync_neg;
959 int i, tmp;
960 nsp_hw_data *data;
961
962
963 //nsp_dbg(NSP_DEBUG_INTR, "dev_id=0x%p", dev_id);
964 //nsp_dbg(NSP_DEBUG_INTR, "host=0x%p", ((scsi_info_t *)dev_id)->host);
965
966 if ( dev_id != NULL &&
967 ((scsi_info_t *)dev_id)->host != NULL ) {
968 scsi_info_t *info = (scsi_info_t *)dev_id;
969
970 data = (nsp_hw_data *)info->host->hostdata;
971 } else {
972 nsp_dbg(NSP_DEBUG_INTR, "host data wrong");
973 return IRQ_NONE;
974 }
975
976 //nsp_dbg(NSP_DEBUG_INTR, "&nsp_data_base=0x%p, dev_id=0x%p", &nsp_data_base, dev_id);
977
978 base = data->BaseAddress;
979 //nsp_dbg(NSP_DEBUG_INTR, "base=0x%x", base);
980
981 /*
982 * interrupt check
983 */
984 nsp_write(base, IRQCONTROL, IRQCONTROL_IRQDISABLE);
985 irq_status = nsp_read(base, IRQSTATUS);
986 //nsp_dbg(NSP_DEBUG_INTR, "irq_status=0x%x", irq_status);
987 if ((irq_status == 0xff) || ((irq_status & IRQSTATUS_MASK) == 0)) {
988 nsp_write(base, IRQCONTROL, 0);
989 //nsp_dbg(NSP_DEBUG_INTR, "no irq/shared irq");
990 return IRQ_NONE;
991 }
992
993 /* XXX: IMPORTANT
994 * Do not read an irq_phase register if no scsi phase interrupt.
995 * Unless, you should lose a scsi phase interrupt.
996 */
997 phase = nsp_index_read(base, SCSIBUSMON);
998 if((irq_status & IRQSTATUS_SCSI) != 0) {
999 irq_phase = nsp_index_read(base, IRQPHASESENCE);
1000 } else {
1001 irq_phase = 0;
1002 }
1003
1004 //nsp_dbg(NSP_DEBUG_INTR, "irq_phase=0x%x", irq_phase);
1005
1006 /*
1007 * timer interrupt handler (scsi vs timer interrupts)
1008 */
1009 //nsp_dbg(NSP_DEBUG_INTR, "timercount=%d", data->TimerCount);
1010 if (data->TimerCount != 0) {
1011 //nsp_dbg(NSP_DEBUG_INTR, "stop timer");
1012 nsp_index_write(base, TIMERCOUNT, 0);
1013 nsp_index_write(base, TIMERCOUNT, 0);
1014 data->TimerCount = 0;
1015 }
1016
1017 if ((irq_status & IRQSTATUS_MASK) == IRQSTATUS_TIMER &&
1018 data->SelectionTimeOut == 0) {
1019 //nsp_dbg(NSP_DEBUG_INTR, "timer start");
1020 nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR);
1021 return IRQ_HANDLED;
1022 }
1023
1024 nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR);
1025
1026 if ((irq_status & IRQSTATUS_SCSI) &&
1027 (irq_phase & SCSI_RESET_IRQ)) {
1028 nsp_msg(KERN_ERR, "bus reset (power off?)");
1029
1030 nsphw_init(data);
1031 nsp_bus_reset(data);
1032
1033 if(data->CurrentSC != NULL) {
1034 tmpSC = data->CurrentSC;
1035 tmpSC->result = (DID_RESET << 16) |
1036 ((tmpSC->SCp.Message & 0xff) << 8) |
1037 ((tmpSC->SCp.Status & 0xff) << 0);
1038 nsp_scsi_done(tmpSC);
1039 }
1040 return IRQ_HANDLED;
1041 }
1042
1043 if (data->CurrentSC == NULL) {
1044 nsp_msg(KERN_ERR, "CurrentSC==NULL irq_status=0x%x phase=0x%x irq_phase=0x%x this can't be happen. reset everything", irq_status, phase, irq_phase);
1045 nsphw_init(data);
1046 nsp_bus_reset(data);
1047 return IRQ_HANDLED;
1048 }
1049
1050 tmpSC = data->CurrentSC;
1051 target = tmpSC->device->id;
1052 lun = tmpSC->device->lun;
1053 sync_neg = &(data->Sync[target].SyncNegotiation);
1054
1055 /*
1056 * parse hardware SCSI irq reasons register
1057 */
1058 if (irq_status & IRQSTATUS_SCSI) {
1059 if (irq_phase & RESELECT_IRQ) {
1060 nsp_dbg(NSP_DEBUG_INTR, "reselect");
1061 nsp_write(base, IRQCONTROL, IRQCONTROL_RESELECT_CLEAR);
1062 if (nsp_reselected(tmpSC) != FALSE) {
1063 return IRQ_HANDLED;
1064 }
1065 }
1066
1067 if ((irq_phase & (PHASE_CHANGE_IRQ | LATCHED_BUS_FREE)) == 0) {
1068 return IRQ_HANDLED;
1069 }
1070 }
1071
1072 //show_phase(tmpSC);
1073
1074 switch(tmpSC->SCp.phase) {
1075 case PH_SELSTART:
1076 // *sync_neg = SYNC_NOT_YET;
1077 if ((phase & BUSMON_BSY) == 0) {
1078 //nsp_dbg(NSP_DEBUG_INTR, "selection count=%d", data->SelectionTimeOut);
1079 if (data->SelectionTimeOut >= NSP_SELTIMEOUT) {
1080 nsp_dbg(NSP_DEBUG_INTR, "selection time out");
1081 data->SelectionTimeOut = 0;
1082 nsp_index_write(base, SCSIBUSCTRL, 0);
1083
1084 tmpSC->result = DID_TIME_OUT << 16;
1085 nsp_scsi_done(tmpSC);
1086
1087 return IRQ_HANDLED;
1088 }
1089 data->SelectionTimeOut += 1;
1090 nsp_start_timer(tmpSC, 1000/51);
1091 return IRQ_HANDLED;
1092 }
1093
1094 /* attention assert */
1095 //nsp_dbg(NSP_DEBUG_INTR, "attention assert");
1096 data->SelectionTimeOut = 0;
1097 tmpSC->SCp.phase = PH_SELECTED;
1098 nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN);
1099 udelay(1);
1100 nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN | AUTODIRECTION | ACKENB);
1101 return IRQ_HANDLED;
1102
1103 break;
1104
1105 case PH_RESELECT:
1106 //nsp_dbg(NSP_DEBUG_INTR, "phase reselect");
1107 // *sync_neg = SYNC_NOT_YET;
1108 if ((phase & BUSMON_PHASE_MASK) != BUSPHASE_MESSAGE_IN) {
1109
1110 tmpSC->result = DID_ABORT << 16;
1111 nsp_scsi_done(tmpSC);
1112 return IRQ_HANDLED;
1113 }
1114 /* fall thru */
1115 default:
1116 if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) {
1117 return IRQ_HANDLED;
1118 }
1119 break;
1120 }
1121
1122 /*
1123 * SCSI sequencer
1124 */
1125 //nsp_dbg(NSP_DEBUG_INTR, "start scsi seq");
1126
1127 /* normal disconnect */
1128 if (((tmpSC->SCp.phase == PH_MSG_IN) || (tmpSC->SCp.phase == PH_MSG_OUT)) &&
1129 (irq_phase & LATCHED_BUS_FREE) != 0 ) {
1130 nsp_dbg(NSP_DEBUG_INTR, "normal disconnect irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);
1131
1132 //*sync_neg = SYNC_NOT_YET;
1133
1134 if ((tmpSC->SCp.Message == MSG_COMMAND_COMPLETE)) { /* all command complete and return status */
1135 tmpSC->result = (DID_OK << 16) |
1136 ((tmpSC->SCp.Message & 0xff) << 8) |
1137 ((tmpSC->SCp.Status & 0xff) << 0);
1138 nsp_dbg(NSP_DEBUG_INTR, "command complete result=0x%x", tmpSC->result);
1139 nsp_scsi_done(tmpSC);
1140
1141 return IRQ_HANDLED;
1142 }
1143
1144 return IRQ_HANDLED;
1145 }
1146
1147
1148 /* check unexpected bus free state */
1149 if (phase == 0) {
1150 nsp_msg(KERN_DEBUG, "unexpected bus free. irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);
1151
1152 *sync_neg = SYNC_NG;
1153 tmpSC->result = DID_ERROR << 16;
1154 nsp_scsi_done(tmpSC);
1155 return IRQ_HANDLED;
1156 }
1157
1158 switch (phase & BUSMON_PHASE_MASK) {
1159 case BUSPHASE_COMMAND:
1160 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_COMMAND");
1161 if ((phase & BUSMON_REQ) == 0) {
1162 nsp_dbg(NSP_DEBUG_INTR, "REQ == 0");
1163 return IRQ_HANDLED;
1164 }
1165
1166 tmpSC->SCp.phase = PH_COMMAND;
1167
1168 nsp_nexus(tmpSC);
1169
1170 /* write scsi command */
1171 nsp_dbg(NSP_DEBUG_INTR, "cmd_len=%d", tmpSC->cmd_len);
1172 nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER);
1173 for (i = 0; i < tmpSC->cmd_len; i++) {
1174 nsp_index_write(base, COMMANDDATA, tmpSC->cmnd[i]);
1175 }
1176 nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER | AUTO_COMMAND_GO);
1177 break;
1178
1179 case BUSPHASE_DATA_OUT:
1180 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_OUT");
1181
1182 tmpSC->SCp.phase = PH_DATA;
1183 tmpSC->SCp.have_data_in = IO_OUT;
1184
1185 nsp_pio_write(tmpSC);
1186
1187 break;
1188
1189 case BUSPHASE_DATA_IN:
1190 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_IN");
1191
1192 tmpSC->SCp.phase = PH_DATA;
1193 tmpSC->SCp.have_data_in = IO_IN;
1194
1195 nsp_pio_read(tmpSC);
1196
1197 break;
1198
1199 case BUSPHASE_STATUS:
1200 nsp_dataphase_bypass(tmpSC);
1201 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_STATUS");
1202
1203 tmpSC->SCp.phase = PH_STATUS;
1204
1205 tmpSC->SCp.Status = nsp_index_read(base, SCSIDATAWITHACK);
1206 nsp_dbg(NSP_DEBUG_INTR, "message=0x%x status=0x%x", tmpSC->SCp.Message, tmpSC->SCp.Status);
1207
1208 break;
1209
1210 case BUSPHASE_MESSAGE_OUT:
1211 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_OUT");
1212 if ((phase & BUSMON_REQ) == 0) {
1213 goto timer_out;
1214 }
1215
1216 tmpSC->SCp.phase = PH_MSG_OUT;
1217
1218 //*sync_neg = SYNC_NOT_YET;
1219
1220 data->MsgLen = i = 0;
1221 data->MsgBuffer[i] = IDENTIFY(TRUE, lun); i++;
1222
1223 if (*sync_neg == SYNC_NOT_YET) {
1224 data->Sync[target].SyncPeriod = 0;
1225 data->Sync[target].SyncOffset = 0;
1226
1227 /**/
1228 data->MsgBuffer[i] = MSG_EXTENDED; i++;
1229 data->MsgBuffer[i] = 3; i++;
1230 data->MsgBuffer[i] = MSG_EXT_SDTR; i++;
1231 data->MsgBuffer[i] = 0x0c; i++;
1232 data->MsgBuffer[i] = 15; i++;
1233 /**/
1234 }
1235 data->MsgLen = i;
1236
1237 nsp_analyze_sdtr(tmpSC);
1238 show_message(data);
1239 nsp_message_out(tmpSC);
1240 break;
1241
1242 case BUSPHASE_MESSAGE_IN:
1243 nsp_dataphase_bypass(tmpSC);
1244 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_IN");
1245 if ((phase & BUSMON_REQ) == 0) {
1246 goto timer_out;
1247 }
1248
1249 tmpSC->SCp.phase = PH_MSG_IN;
1250 nsp_message_in(tmpSC);
1251
1252 /**/
1253 if (*sync_neg == SYNC_NOT_YET) {
1254 //nsp_dbg(NSP_DEBUG_INTR, "sync target=%d,lun=%d",target,lun);
1255
1256 if (data->MsgLen >= 5 &&
1257 data->MsgBuffer[0] == MSG_EXTENDED &&
1258 data->MsgBuffer[1] == 3 &&
1259 data->MsgBuffer[2] == MSG_EXT_SDTR ) {
1260 data->Sync[target].SyncPeriod = data->MsgBuffer[3];
1261 data->Sync[target].SyncOffset = data->MsgBuffer[4];
1262 //nsp_dbg(NSP_DEBUG_INTR, "sync ok, %d %d", data->MsgBuffer[3], data->MsgBuffer[4]);
1263 *sync_neg = SYNC_OK;
1264 } else {
1265 data->Sync[target].SyncPeriod = 0;
1266 data->Sync[target].SyncOffset = 0;
1267 *sync_neg = SYNC_NG;
1268 }
1269 nsp_analyze_sdtr(tmpSC);
1270 }
1271 /**/
1272
1273 /* search last messeage byte */
1274 tmp = -1;
1275 for (i = 0; i < data->MsgLen; i++) {
1276 tmp = data->MsgBuffer[i];
1277 if (data->MsgBuffer[i] == MSG_EXTENDED) {
1278 i += (1 + data->MsgBuffer[i+1]);
1279 }
1280 }
1281 tmpSC->SCp.Message = tmp;
1282
1283 nsp_dbg(NSP_DEBUG_INTR, "message=0x%x len=%d", tmpSC->SCp.Message, data->MsgLen);
1284 show_message(data);
1285
1286 break;
1287
1288 case BUSPHASE_SELECT:
1289 default:
1290 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE other");
1291
1292 break;
1293 }
1294
1295 //nsp_dbg(NSP_DEBUG_INTR, "out");
1296 return IRQ_HANDLED;
1297
1298timer_out:
1299 nsp_start_timer(tmpSC, 1000/102);
1300 return IRQ_HANDLED;
1301}
1302
1303#ifdef NSP_DEBUG
1304#include "nsp_debug.c"
1305#endif /* NSP_DEBUG */
1306
1307/*----------------------------------------------------------------*/
1308/* look for ninja3 card and init if found */
1309/*----------------------------------------------------------------*/
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001310static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311{
1312 struct Scsi_Host *host; /* registered host structure */
1313 nsp_hw_data *data_b = &nsp_data_base, *data;
1314
1315 nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id);
1316#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1317 host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data));
1318#else
1319 host = scsi_register(sht, sizeof(nsp_hw_data));
1320#endif
1321 if (host == NULL) {
1322 nsp_dbg(NSP_DEBUG_INIT, "host failed");
1323 return NULL;
1324 }
1325
1326 memcpy(host->hostdata, data_b, sizeof(nsp_hw_data));
1327 data = (nsp_hw_data *)host->hostdata;
1328 data->ScsiInfo->host = host;
1329#ifdef NSP_DEBUG
1330 data->CmdId = 0;
1331#endif
1332
1333 nsp_dbg(NSP_DEBUG_INIT, "irq=%d,%d", data_b->IrqNumber, ((nsp_hw_data *)host->hostdata)->IrqNumber);
1334
1335 host->unique_id = data->BaseAddress;
1336 host->io_port = data->BaseAddress;
1337 host->n_io_port = data->NumAddress;
1338 host->irq = data->IrqNumber;
1339 host->base = data->MmioAddress;
1340
1341 spin_lock_init(&(data->Lock));
1342
1343 snprintf(data->nspinfo,
1344 sizeof(data->nspinfo),
1345 "NinjaSCSI-3/32Bi Driver $Revision: 1.23 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d",
1346 host->io_port, host->io_port + host->n_io_port - 1,
1347 host->base,
1348 host->irq);
1349 sht->name = data->nspinfo;
1350
1351 nsp_dbg(NSP_DEBUG_INIT, "end");
1352
1353
1354 return host; /* detect done. */
1355}
1356
1357#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001358static int nsp_detect_old(struct scsi_host_template *sht)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359{
1360 if (nsp_detect(sht) == NULL) {
1361 return 0;
1362 } else {
1363 //MOD_INC_USE_COUNT;
1364 return 1;
1365 }
1366}
1367
1368
1369static int nsp_release_old(struct Scsi_Host *shpnt)
1370{
1371 //nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;
1372
1373 /* PCMCIA Card Service dose same things below. */
1374 /* So we do nothing. */
1375 //if (shpnt->irq) {
1376 // free_irq(shpnt->irq, data->ScsiInfo);
1377 //}
1378 //if (shpnt->io_port) {
1379 // release_region(shpnt->io_port, shpnt->n_io_port);
1380 //}
1381
1382 //MOD_DEC_USE_COUNT;
1383
1384 return 0;
1385}
1386#endif
1387
1388/*----------------------------------------------------------------*/
1389/* return info string */
1390/*----------------------------------------------------------------*/
1391static const char *nsp_info(struct Scsi_Host *shpnt)
1392{
1393 nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;
1394
1395 return data->nspinfo;
1396}
1397
1398#undef SPRINTF
1399#define SPRINTF(args...) \
1400 do { \
1401 if(length > (pos - buffer)) { \
1402 pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
1403 nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\
1404 } \
1405 } while(0)
1406static int
1407nsp_proc_info(
1408#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1409 struct Scsi_Host *host,
1410#endif
1411 char *buffer,
1412 char **start,
1413 off_t offset,
1414 int length,
1415#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1416 int hostno,
1417#endif
1418 int inout)
1419{
1420 int id;
1421 char *pos = buffer;
1422 int thislength;
1423 int speed;
1424 unsigned long flags;
1425 nsp_hw_data *data;
1426#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1427 struct Scsi_Host *host;
1428#else
1429 int hostno;
1430#endif
1431 if (inout) {
1432 return -EINVAL;
1433 }
1434
1435#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1436 hostno = host->host_no;
1437#else
1438 /* search this HBA host */
1439 host = scsi_host_hn_get(hostno);
1440 if (host == NULL) {
1441 return -ESRCH;
1442 }
1443#endif
1444 data = (nsp_hw_data *)host->hostdata;
1445
1446
1447 SPRINTF("NinjaSCSI status\n\n");
1448 SPRINTF("Driver version: $Revision: 1.23 $\n");
1449 SPRINTF("SCSI host No.: %d\n", hostno);
1450 SPRINTF("IRQ: %d\n", host->irq);
1451 SPRINTF("IO: 0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1);
1452 SPRINTF("MMIO(virtual address): 0x%lx-0x%lx\n", host->base, host->base + data->MmioLength - 1);
1453 SPRINTF("sg_tablesize: %d\n", host->sg_tablesize);
1454
1455 SPRINTF("burst transfer mode: ");
1456 switch (nsp_burst_mode) {
1457 case BURST_IO8:
1458 SPRINTF("io8");
1459 break;
1460 case BURST_IO32:
1461 SPRINTF("io32");
1462 break;
1463 case BURST_MEM32:
1464 SPRINTF("mem32");
1465 break;
1466 default:
1467 SPRINTF("???");
1468 break;
1469 }
1470 SPRINTF("\n");
1471
1472
1473 spin_lock_irqsave(&(data->Lock), flags);
1474 SPRINTF("CurrentSC: 0x%p\n\n", data->CurrentSC);
1475 spin_unlock_irqrestore(&(data->Lock), flags);
1476
1477 SPRINTF("SDTR status\n");
1478 for(id = 0; id < ARRAY_SIZE(data->Sync); id++) {
1479
1480 SPRINTF("id %d: ", id);
1481
1482 if (id == host->this_id) {
1483 SPRINTF("----- NinjaSCSI-3 host adapter\n");
1484 continue;
1485 }
1486
1487 switch(data->Sync[id].SyncNegotiation) {
1488 case SYNC_OK:
1489 SPRINTF(" sync");
1490 break;
1491 case SYNC_NG:
1492 SPRINTF("async");
1493 break;
1494 case SYNC_NOT_YET:
1495 SPRINTF(" none");
1496 break;
1497 default:
1498 SPRINTF("?????");
1499 break;
1500 }
1501
1502 if (data->Sync[id].SyncPeriod != 0) {
1503 speed = 1000000 / (data->Sync[id].SyncPeriod * 4);
1504
1505 SPRINTF(" transfer %d.%dMB/s, offset %d",
1506 speed / 1000,
1507 speed % 1000,
1508 data->Sync[id].SyncOffset
1509 );
1510 }
1511 SPRINTF("\n");
1512 }
1513
1514 thislength = pos - (buffer + offset);
1515
1516 if(thislength < 0) {
1517 *start = NULL;
1518 return 0;
1519 }
1520
1521
1522 thislength = min(thislength, length);
1523 *start = buffer + offset;
1524
1525 return thislength;
1526}
1527#undef SPRINTF
1528
1529/*---------------------------------------------------------------*/
1530/* error handler */
1531/*---------------------------------------------------------------*/
1532
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533/*
1534static int nsp_eh_abort(Scsi_Cmnd *SCpnt)
1535{
1536 nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);
1537
1538 return nsp_eh_bus_reset(SCpnt);
1539}*/
1540
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541static int nsp_bus_reset(nsp_hw_data *data)
1542{
1543 unsigned int base = data->BaseAddress;
1544 int i;
1545
1546 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);
1547
1548 nsp_index_write(base, SCSIBUSCTRL, SCSI_RST);
1549 mdelay(100); /* 100ms */
1550 nsp_index_write(base, SCSIBUSCTRL, 0);
1551 for(i = 0; i < 5; i++) {
1552 nsp_index_read(base, IRQPHASESENCE); /* dummy read */
1553 }
1554
1555 nsphw_init_sync(data);
1556
1557 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR);
1558
1559 return SUCCESS;
1560}
1561
1562static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt)
1563{
1564 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
1565
1566 nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);
1567
1568 return nsp_bus_reset(data);
1569}
1570
1571static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
1572{
1573 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
1574
1575 nsp_dbg(NSP_DEBUG_BUSRESET, "in");
1576
1577 nsphw_init(data);
1578
1579 return SUCCESS;
1580}
1581
1582
1583/**********************************************************************
1584 PCMCIA functions
1585**********************************************************************/
1586
1587/*======================================================================
1588 nsp_cs_attach() creates an "instance" of the driver, allocating
1589 local data structures for one device. The device is registered
1590 with Card Services.
1591
1592 The dev_link structure is initialized, but we don't actually
1593 configure the card at this point -- we wait until we receive a
1594 card insertion event.
1595======================================================================*/
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001596static int nsp_cs_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597{
1598 scsi_info_t *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 nsp_hw_data *data = &nsp_data_base;
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001600 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602 nsp_dbg(NSP_DEBUG_INIT, "in");
1603
1604 /* Create new SCSI device */
1605 info = kmalloc(sizeof(*info), GFP_KERNEL);
Dominik Brodowskif8cfa612005-11-14 21:25:51 +01001606 if (info == NULL) { return -ENOMEM; }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 memset(info, 0, sizeof(*info));
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001608 info->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 link->priv = info;
1610 data->ScsiInfo = info;
1611
1612 nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
1613
1614 /* The io structure describes IO port mapping */
1615 link->io.NumPorts1 = 0x10;
1616 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
1617 link->io.IOAddrLines = 10; /* not used */
1618
1619 /* Interrupt setup */
1620 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
1621 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
1622
1623 /* Interrupt handler */
1624 link->irq.Handler = &nspintr;
1625 link->irq.Instance = info;
James Bottomleyc4e00fa2006-07-03 09:41:12 -05001626 link->irq.Attributes |= IRQF_SHARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
1628 /* General socket configuration */
1629 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 link->conf.IntType = INT_MEMORY_AND_IO;
1631 link->conf.Present = PRESENT_OPTION;
1632
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001633 ret = nsp_cs_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
1635 nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001636 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637} /* nsp_cs_attach */
1638
1639
1640/*======================================================================
1641 This deletes a driver "instance". The device is de-registered
1642 with Card Services. If it has been released, all local data
1643 structures are freed. Otherwise, the structures will be freed
1644 when the device is released.
1645======================================================================*/
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001646static void nsp_cs_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
1649
Dominik Brodowskie2d40962006-03-02 00:09:29 +01001650 ((scsi_info_t *)link->priv)->stop = 1;
1651 nsp_cs_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 kfree(link->priv);
1654 link->priv = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655} /* nsp_cs_detach */
1656
1657
1658/*======================================================================
1659 nsp_cs_config() is scheduled to run after a CARD_INSERTION event
1660 is received, to configure the PCMCIA socket, and to make the
1661 ethernet device available to the system.
1662======================================================================*/
1663#define CS_CHECK(fn, ret) \
1664do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
1665/*====================================================================*/
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001666static int nsp_cs_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667{
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001668 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 scsi_info_t *info = link->priv;
1670 tuple_t tuple;
1671 cisparse_t parse;
1672 int last_ret, last_fn;
1673 unsigned char tuple_data[64];
1674 config_info_t conf;
1675 win_req_t req;
1676 memreq_t map;
1677 cistpl_cftable_entry_t dflt = { 0 };
1678 struct Scsi_Host *host;
1679 nsp_hw_data *data = &nsp_data_base;
1680#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
Christoph Hellwigf64a1812005-10-31 18:32:08 +01001681 struct scsi_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 dev_node_t **tail, *node;
1683#endif
1684
1685 nsp_dbg(NSP_DEBUG_INIT, "in");
1686
1687 tuple.DesiredTuple = CISTPL_CONFIG;
1688 tuple.Attributes = 0;
1689 tuple.TupleData = tuple_data;
1690 tuple.TupleDataMax = sizeof(tuple_data);
1691 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001692 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
1693 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
1694 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 link->conf.ConfigBase = parse.config.base;
1696 link->conf.Present = parse.config.rmask[0];
1697
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 /* Look up the current Vcc */
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001699 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
1701 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001702 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 while (1) {
1704 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
1705
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001706 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
1707 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 goto next_entry;
1709
1710 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
1711 if (cfg->index == 0) { goto next_entry; }
1712 link->conf.ConfigIndex = cfg->index;
1713
1714 /* Does this card need audio output? */
1715 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
1716 link->conf.Attributes |= CONF_ENABLE_SPKR;
1717 link->conf.Status = CCSR_AUDIO_ENA;
1718 }
1719
1720 /* Use power settings for Vcc and Vpp if present */
1721 /* Note that the CIS values need to be rescaled */
1722 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
1723 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) {
1724 goto next_entry;
1725 }
1726 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
1727 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) {
1728 goto next_entry;
1729 }
1730 }
1731
1732 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
Dominik Brodowski70294b42006-01-15 12:43:16 +01001733 link->conf.Vpp =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
1735 } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
Dominik Brodowski70294b42006-01-15 12:43:16 +01001736 link->conf.Vpp =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
1738 }
1739
1740 /* Do we need to allocate an interrupt? */
1741 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) {
1742 link->conf.Attributes |= CONF_ENABLE_IRQ;
1743 }
1744
1745 /* IO window settings */
1746 link->io.NumPorts1 = link->io.NumPorts2 = 0;
1747 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
1748 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
1749 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
1750 if (!(io->flags & CISTPL_IO_8BIT))
1751 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
1752 if (!(io->flags & CISTPL_IO_16BIT))
1753 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
1754 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
1755 link->io.BasePort1 = io->win[0].base;
1756 link->io.NumPorts1 = io->win[0].len;
1757 if (io->nwin > 1) {
1758 link->io.Attributes2 = link->io.Attributes1;
1759 link->io.BasePort2 = io->win[1].base;
1760 link->io.NumPorts2 = io->win[1].len;
1761 }
1762 /* This reserves IO space but doesn't actually enable it */
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001763 if (pcmcia_request_io(link, &link->io) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 goto next_entry;
1765 }
1766
1767 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
1768 cistpl_mem_t *mem =
1769 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
1770 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
1771 req.Attributes |= WIN_ENABLE;
1772 req.Base = mem->win[0].host_addr;
1773 req.Size = mem->win[0].len;
1774 if (req.Size < 0x1000) {
1775 req.Size = 0x1000;
1776 }
1777 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001778 if (pcmcia_request_window(&link, &req, &link->win) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 goto next_entry;
1780 map.Page = 0; map.CardOffset = mem->win[0].card_addr;
1781 if (pcmcia_map_mem_page(link->win, &map) != 0)
1782 goto next_entry;
1783
1784 data->MmioAddress = (unsigned long)ioremap_nocache(req.Base, req.Size);
1785 data->MmioLength = req.Size;
1786 }
1787 /* If we got this far, we're cool! */
1788 break;
1789
1790 next_entry:
1791 nsp_dbg(NSP_DEBUG_INIT, "next");
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001792 pcmcia_disable_device(link);
1793 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 }
1795
1796 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001797 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001799 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
1801 if (free_ports) {
1802 if (link->io.BasePort1) {
1803 release_region(link->io.BasePort1, link->io.NumPorts1);
1804 }
1805 if (link->io.BasePort2) {
1806 release_region(link->io.BasePort2, link->io.NumPorts2);
1807 }
1808 }
1809
1810 /* Set port and IRQ */
1811 data->BaseAddress = link->io.BasePort1;
1812 data->NumAddress = link->io.NumPorts1;
1813 data->IrqNumber = link->irq.AssignedIRQ;
1814
1815 nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d",
1816 data->BaseAddress, data->NumAddress, data->IrqNumber);
1817
1818 if(nsphw_init(data) == FALSE) {
1819 goto cs_failed;
1820 }
1821
1822#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2))
1823 host = nsp_detect(&nsp_driver_template);
1824#else
1825 scsi_register_host(&nsp_driver_template);
1826 for (host = scsi_host_get_next(NULL); host != NULL;
1827 host = scsi_host_get_next(host)) {
1828 if (host->hostt == &nsp_driver_template) {
1829 break;
1830 }
1831 }
1832#endif
1833
1834 if (host == NULL) {
1835 nsp_dbg(NSP_DEBUG_INIT, "detect failed");
1836 goto cs_failed;
1837 }
1838
1839
1840#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001841 ret = scsi_add_host (host, NULL);
1842 if (ret)
1843 goto cs_failed;
1844
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 scsi_scan_host(host);
1846
1847 snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
Dominik Brodowskifd238232006-03-05 10:45:09 +01001848 link->dev_node = &info->node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 info->host = host;
1850
1851#else
1852 nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
Dominik Brodowskifd238232006-03-05 10:45:09 +01001853 tail = &link->dev_node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 info->ndev = 0;
1855
1856 nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
1857
1858 for (dev = host->host_queue; dev != NULL; dev = dev->next) {
1859 unsigned long id;
1860 id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) +
1861 ((dev->channel & 0x0f) << 8) +
1862 ((dev->host->host_no & 0x0f) << 12);
1863 node = &info->node[info->ndev];
1864 node->minor = 0;
1865 switch (dev->type) {
1866 case TYPE_TAPE:
1867 node->major = SCSI_TAPE_MAJOR;
1868 snprintf(node->dev_name, sizeof(node->dev_name), "st#%04lx", id);
1869 break;
1870 case TYPE_DISK:
1871 case TYPE_MOD:
1872 node->major = SCSI_DISK0_MAJOR;
1873 snprintf(node->dev_name, sizeof(node->dev_name), "sd#%04lx", id);
1874 break;
1875 case TYPE_ROM:
1876 case TYPE_WORM:
1877 node->major = SCSI_CDROM_MAJOR;
1878 snprintf(node->dev_name, sizeof(node->dev_name), "sr#%04lx", id);
1879 break;
1880 default:
1881 node->major = SCSI_GENERIC_MAJOR;
1882 snprintf(node->dev_name, sizeof(node->dev_name), "sg#%04lx", id);
1883 break;
1884 }
1885 *tail = node; tail = &node->next;
1886 info->ndev++;
1887 info->host = dev->host;
1888 }
1889
1890 *tail = NULL;
1891 if (info->ndev == 0) {
1892 nsp_msg(KERN_INFO, "no SCSI devices found");
1893 }
1894 nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
1895#endif
1896
1897 /* Finally, report what we've done */
Dominik Brodowski70294b42006-01-15 12:43:16 +01001898 printk(KERN_INFO "nsp_cs: index 0x%02x: ",
1899 link->conf.ConfigIndex);
1900 if (link->conf.Vpp) {
1901 printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 }
1903 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
1904 printk(", irq %d", link->irq.AssignedIRQ);
1905 }
1906 if (link->io.NumPorts1) {
1907 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
1908 link->io.BasePort1+link->io.NumPorts1-1);
1909 }
1910 if (link->io.NumPorts2)
1911 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
1912 link->io.BasePort2+link->io.NumPorts2-1);
1913 if (link->win)
1914 printk(", mem 0x%06lx-0x%06lx", req.Base,
1915 req.Base+req.Size-1);
1916 printk("\n");
1917
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001918 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
1920 cs_failed:
1921 nsp_dbg(NSP_DEBUG_INIT, "config fail");
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001922 cs_error(link, last_fn, last_ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 nsp_cs_release(link);
1924
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001925 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926} /* nsp_cs_config */
1927#undef CS_CHECK
1928
1929
1930/*======================================================================
1931 After a card is removed, nsp_cs_release() will unregister the net
1932 device, and release the PCMCIA configuration. If the device is
1933 still open, this will be postponed until it is closed.
1934======================================================================*/
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001935static void nsp_cs_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936{
1937 scsi_info_t *info = link->priv;
1938 nsp_hw_data *data = NULL;
1939
1940 if (info->host == NULL) {
1941 nsp_msg(KERN_DEBUG, "unexpected card release call.");
1942 } else {
1943 data = (nsp_hw_data *)info->host->hostdata;
1944 }
1945
1946 nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
1947
1948 /* Unlink the device chain */
1949#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
1950 if (info->host != NULL) {
1951 scsi_remove_host(info->host);
1952 }
1953#else
1954 scsi_unregister_host(&nsp_driver_template);
1955#endif
Dominik Brodowskifd238232006-03-05 10:45:09 +01001956 link->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
1958 if (link->win) {
1959 if (data != NULL) {
1960 iounmap((void *)(data->MmioAddress));
1961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001963 pcmcia_disable_device(link);
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +01001964
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
1966 if (info->host != NULL) {
1967 scsi_host_put(info->host);
1968 }
1969#endif
1970} /* nsp_cs_release */
1971
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001972static int nsp_cs_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001973{
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001974 scsi_info_t *info = link->priv;
1975 nsp_hw_data *data;
1976
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001977 nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
1978
1979 if (info->host != NULL) {
1980 nsp_msg(KERN_INFO, "clear SDTR status");
1981
1982 data = (nsp_hw_data *)info->host->hostdata;
1983
1984 nsphw_init_sync(data);
1985 }
1986
1987 info->stop = 1;
1988
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001989 return 0;
1990}
1991
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001992static int nsp_cs_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001993{
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001994 scsi_info_t *info = link->priv;
1995 nsp_hw_data *data;
1996
1997 nsp_dbg(NSP_DEBUG_INIT, "event: resume");
1998
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001999 info->stop = 0;
2000
2001 if (info->host != NULL) {
2002 nsp_msg(KERN_INFO, "reset host and bus");
2003
2004 data = (nsp_hw_data *)info->host->hostdata;
2005
2006 nsphw_init (data);
2007 nsp_bus_reset(data);
2008 }
2009
2010 return 0;
2011}
2012
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013/*======================================================================*
2014 * module entry point
2015 *====================================================================*/
2016#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
Dominik Brodowskiaba14102005-06-27 16:28:40 -07002017static struct pcmcia_device_id nsp_cs_ids[] = {
2018 PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16 ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a),
2019 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a),
2020 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-002", "1", 0x534c02bc, 0xcb09d5b2, 0x51de003a),
2021 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-003", "1", 0x534c02bc, 0xbc0ee524, 0x51de003a),
2022 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-004", "1", 0x534c02bc, 0x226a7087, 0x51de003a),
2023 PCMCIA_DEVICE_PROD_ID123("WBT", "NinjaSCSI-3", "R1.0", 0xc7ba805f, 0xfdc7c97d, 0x6973710e),
2024 PCMCIA_DEVICE_PROD_ID123("WORKBIT", "UltraNinja-16", "1", 0x28191418, 0xb70f4b09, 0x51de003a),
2025 PCMCIA_DEVICE_NULL
2026};
2027MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids);
2028
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029static struct pcmcia_driver nsp_driver = {
Dominik Brodowski1e212f32005-07-07 17:59:00 -07002030 .owner = THIS_MODULE,
2031 .drv = {
2032 .name = "nsp_cs",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02002034 .probe = nsp_cs_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +01002035 .remove = nsp_cs_detach,
Dominik Brodowskiaba14102005-06-27 16:28:40 -07002036 .id_table = nsp_cs_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +01002037 .suspend = nsp_cs_suspend,
2038 .resume = nsp_cs_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039};
2040#endif
2041
2042static int __init nsp_cs_init(void)
2043{
2044#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
2045 nsp_msg(KERN_INFO, "loading...");
2046
2047 return pcmcia_register_driver(&nsp_driver);
2048#else
2049 servinfo_t serv;
2050
2051 nsp_msg(KERN_INFO, "loading...");
2052 pcmcia_get_card_services_info(&serv);
Pavel Roskin2ffe6e22005-07-07 17:59:04 -07002053 if (serv.Revision != CS_RELEASE_CODE) {
2054 nsp_msg(KERN_DEBUG, "Card Services release does not match!");
2055 return -EINVAL;
2056 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);
2058
2059 nsp_dbg(NSP_DEBUG_INIT, "out");
2060 return 0;
2061#endif
2062}
2063
2064static void __exit nsp_cs_exit(void)
2065{
2066 nsp_msg(KERN_INFO, "unloading...");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 pcmcia_unregister_driver(&nsp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068}
2069
2070
2071module_init(nsp_cs_init)
2072module_exit(nsp_cs_exit)
2073
2074/* end */