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