1139747Simp/*====================================================================== 24Srgrimes 34Srgrimes NinjaSCSI-3 / NinjaSCSI-32Bi PCMCIA SCSI host adapter card driver 44Srgrimes By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp> 58876Srgrimes 64Srgrimes Ver.2.8 Support 32bit MMIO mode 74Srgrimes Support Synchronous Data Transfer Request (SDTR) mode 84Srgrimes Ver.2.0 Support 32bit PIO mode 94Srgrimes Ver.1.1.2 Fix for scatter list buffer exceeds 104Srgrimes Ver.1.1 Support scatter list 118876Srgrimes Ver.0.1 Initial version 128876Srgrimes 134Srgrimes This software may be used and distributed according to the terms of 144Srgrimes the GNU General Public License. 158876Srgrimes 164Srgrimes======================================================================*/ 178876Srgrimes 184Srgrimes/*********************************************************************** 194Srgrimes This driver is for these PCcards. 204Srgrimes 214Srgrimes I-O DATA PCSC-F (Workbit NinjaSCSI-3) 228876Srgrimes "WBT", "NinjaSCSI-3", "R1.0" 234Srgrimes I-O DATA CBSC-II (Workbit NinjaSCSI-32Bi in 16bit mode) 244Srgrimes "IO DATA", "CBSC16 ", "1" 254Srgrimes 264Srgrimes***********************************************************************/ 274Srgrimes 284Srgrimes#include <linux/module.h> 294Srgrimes#include <linux/kernel.h> 304Srgrimes#include <linux/init.h> 314Srgrimes#include <linux/slab.h> 324Srgrimes#include <linux/string.h> 33116176Sobrien#include <linux/timer.h> 34116176Sobrien#include <linux/ioport.h> 35116176Sobrien#include <linux/delay.h> 36116176Sobrien#include <linux/interrupt.h> 372056Swollman#include <linux/major.h> 3842654Sjdp#include <linux/blkdev.h> 3986998Sdd#include <linux/stat.h> 40131952Smarcel 4186998Sdd#include <asm/io.h> 4286998Sdd#include <asm/irq.h> 4317848Spst 4486998Sdd#include <scsi/scsi.h> 452056Swollman#include <scsi/scsi_cmnd.h> 4649558Sphk#include <scsi/scsi_host.h> 47126399Sphk#include <scsi/scsi_ioctl.h> 4812734Sbde 492056Swollman#include <pcmcia/cistpl.h> 5012473Sbde#include <pcmcia/cisreg.h> 514Srgrimes#include <pcmcia/ds.h> 524Srgrimes 534Srgrimes#include "nsp_cs.h" 54118990Smarcel 5579418SjulianMODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>"); 564SrgrimesMODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module"); 574SrgrimesMODULE_LICENSE("GPL"); 584Srgrimes 594Srgrimes#include "nsp_io.h" 604Srgrimes 6118296Sbde/*====================================================================*/ 624Srgrimes/* Parameters that can be set with 'insmod' */ 634Srgrimes 644Srgrimesstatic int nsp_burst_mode = BURST_MEM32; 654Srgrimesmodule_param(nsp_burst_mode, int, 0); 6678161SpeterMODULE_PARM_DESC(nsp_burst_mode, "Burst transfer mode (0=io8, 1=io32, 2=mem32(default))"); 6778161Speter 6878161Speter/* Release IO ports after configuration? */ 6912515Sphkstatic bool free_ports = 0; 70132002Smarcelmodule_param(free_ports, bool, 0); 7186998SddMODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))"); 7285944Speter 73132482Smarcelstatic struct scsi_pointer *nsp_priv(struct scsi_cmnd *cmd) 74150819Srwatson{ 75126399Sphk return scsi_cmd_priv(cmd); 7617848Spst} 77148919Sobrien 78148919Sobrienstatic struct scsi_host_template nsp_driver_template = { 79148919Sobrien .proc_name = "nsp_cs", 8018296Sbde .show_info = nsp_show_info, 81148919Sobrien .name = "WorkBit NinjaSCSI-3/32Bi(16bit)", 82148919Sobrien .info = nsp_info, 83148919Sobrien .queuecommand = nsp_queuecommand, 84148919Sobrien/* .eh_abort_handler = nsp_eh_abort,*/ 85148919Sobrien .eh_bus_reset_handler = nsp_eh_bus_reset, 86156412Sjhb .eh_host_reset_handler = nsp_eh_host_reset, 87156412Sjhb .can_queue = 1, 88156412Sjhb .this_id = NSP_INITIATOR_ID, 89156412Sjhb .sg_tablesize = SG_ALL, 90148919Sobrien .dma_boundary = PAGE_SIZE - 1, 91156412Sjhb .cmd_size = sizeof(struct scsi_pointer), 92148919Sobrien}; 93148919Sobrien 94148919Sobrienstatic nsp_hw_data nsp_data_base; /* attach <-> detect glue */ 95148919Sobrien 96148919Sobrien 97148919Sobrien 98156412Sjhb/* 99156412Sjhb * debug, error print 100156412Sjhb */ 101156412Sjhb#ifndef NSP_DEBUG 102156412Sjhb# define NSP_DEBUG_MASK 0x000000 103156412Sjhb# define nsp_msg(type, args...) nsp_cs_message("", 0, (type), args) 104156412Sjhb# define nsp_dbg(mask, args...) /* */ 105148919Sobrien#else 106148919Sobrien# define NSP_DEBUG_MASK 0xffffff 107148919Sobrien# define nsp_msg(type, args...) \ 108148919Sobrien nsp_cs_message (__func__, __LINE__, (type), args) 109148919Sobrien# define nsp_dbg(mask, args...) \ 110148919Sobrien nsp_cs_dmessage(__func__, __LINE__, (mask), args) 111148919Sobrien#endif 112148919Sobrien 113148919Sobrien#define NSP_DEBUG_QUEUECOMMAND BIT(0) 114148919Sobrien#define NSP_DEBUG_REGISTER BIT(1) 115148919Sobrien#define NSP_DEBUG_AUTOSCSI BIT(2) 116163135Sbde#define NSP_DEBUG_INTR BIT(3) 117148919Sobrien#define NSP_DEBUG_SGLIST BIT(4) 118148919Sobrien#define NSP_DEBUG_BUSFREE BIT(5) 119148919Sobrien#define NSP_DEBUG_CDB_CONTENTS BIT(6) 120148919Sobrien#define NSP_DEBUG_RESELECTION BIT(7) 121148919Sobrien#define NSP_DEBUG_MSGINOCCUR BIT(8) 122148919Sobrien#define NSP_DEBUG_EEPROM BIT(9) 123148919Sobrien#define NSP_DEBUG_MSGOUTOCCUR BIT(10) 124148919Sobrien#define NSP_DEBUG_BUSRESET BIT(11) 125148919Sobrien#define NSP_DEBUG_RESTART BIT(12) 126148919Sobrien#define NSP_DEBUG_SYNC BIT(13) 127148919Sobrien#define NSP_DEBUG_WAIT BIT(14) 128148919Sobrien#define NSP_DEBUG_TARGETFLAG BIT(15) 129163135Sbde#define NSP_DEBUG_PROC BIT(16) 130151622Sjhb#define NSP_DEBUG_INIT BIT(17) 131148919Sobrien#define NSP_DEBUG_DATA_IO BIT(18) 132151622Sjhb#define NSP_SPECIAL_PRINT_REGISTER BIT(20) 133148919Sobrien 134156412Sjhb#define NSP_DEBUG_BUF_LEN 150 135148919Sobrien 136148919Sobrienstatic inline void nsp_inc_resid(struct scsi_cmnd *SCpnt, int residInc) 137163135Sbde{ 138148919Sobrien scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) + residInc); 139148919Sobrien} 140148919Sobrien 141148919Sobrien__printf(4, 5) 142148919Sobrienstatic void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...) 143148919Sobrien{ 144148919Sobrien va_list args; 145156412Sjhb char buf[NSP_DEBUG_BUF_LEN]; 146156412Sjhb 147156412Sjhb va_start(args, fmt); 148156412Sjhb vsnprintf(buf, sizeof(buf), fmt, args); 149156412Sjhb va_end(args); 150156412Sjhb 151148919Sobrien#ifndef NSP_DEBUG 152148919Sobrien printk("%snsp_cs: %s\n", type, buf); 1534Srgrimes#else 1544Srgrimes printk("%snsp_cs: %s (%d): %s\n", type, func, line, buf); 1554Srgrimes#endif 1564Srgrimes} 1574Srgrimes 15812515Sphk#ifdef NSP_DEBUG 1594Srgrimesstatic void nsp_cs_dmessage(const char *func, int line, int mask, char *fmt, ...) 1604Srgrimes{ 1614Srgrimes va_list args; 1624Srgrimes char buf[NSP_DEBUG_BUF_LEN]; 1634Srgrimes 1644Srgrimes va_start(args, fmt); 1654Srgrimes vsnprintf(buf, sizeof(buf), fmt, args); 1664Srgrimes va_end(args); 1674Srgrimes 1684Srgrimes if (mask & NSP_DEBUG_MASK) { 1694Srgrimes printk("nsp_cs-debug: 0x%x %s (%d): %s\n", mask, func, line, buf); 1704Srgrimes } 1714Srgrimes} 1724Srgrimes#endif 1734Srgrimes 1744Srgrimes/***********************************************************/ 1754Srgrimes 1764Srgrimes/*==================================================== 1774Srgrimes * Clenaup parameters and call done() functions. 1784Srgrimes * You must be set SCpnt->result before call this function. 1794Srgrimes */ 1804Srgrimesstatic void nsp_scsi_done(struct scsi_cmnd *SCpnt) 181156412Sjhb{ 182156412Sjhb nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 183156412Sjhb 184156412Sjhb data->CurrentSC = NULL; 185156412Sjhb 18692756Salfred scsi_done(SCpnt); 187156412Sjhb} 18812473Sbde 1894Srgrimesstatic int nsp_queuecommand_lck(struct scsi_cmnd *const SCpnt) 190156412Sjhb{ 1914Srgrimes struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt); 192156412Sjhb#ifdef NSP_DEBUG 193156412Sjhb /*unsigned int host_id = SCpnt->device->host->this_id;*/ 1944Srgrimes /*unsigned int base = SCpnt->device->host->io_port;*/ 195156412Sjhb unsigned char target = scmd_id(SCpnt); 1964Srgrimes#endif 197156412Sjhb nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 1984Srgrimes 199156412Sjhb nsp_dbg(NSP_DEBUG_QUEUECOMMAND, 200156412Sjhb "SCpnt=0x%p target=%d lun=%llu sglist=0x%p bufflen=%d sg_count=%d", 2014Srgrimes SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt), 202156412Sjhb scsi_bufflen(SCpnt), scsi_sg_count(SCpnt)); 203156412Sjhb //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC); 204156412Sjhb 2054Srgrimes if (data->CurrentSC != NULL) { 206156412Sjhb nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen"); 207156412Sjhb SCpnt->result = DID_BAD_TARGET << 16; 208156412Sjhb nsp_scsi_done(SCpnt); 209156412Sjhb return 0; 2104Srgrimes } 2114Srgrimes 2124Srgrimes#if 0 213156412Sjhb /* XXX: pcmcia-cs generates SCSI command with "scsi_info" utility. 214156412Sjhb This makes kernel crash when suspending... */ 2154Srgrimes if (data->ScsiInfo->stop != 0) { 2164Srgrimes nsp_msg(KERN_INFO, "suspending device. reject command."); 217156412Sjhb SCpnt->result = DID_BAD_TARGET << 16; 218156412Sjhb nsp_scsi_done(SCpnt); 219156412Sjhb return SCSI_MLQUEUE_HOST_BUSY; 220156412Sjhb } 221156412Sjhb#endif 222156412Sjhb 223156412Sjhb show_command(SCpnt); 2244Srgrimes 2254Srgrimes data->CurrentSC = SCpnt; 226156412Sjhb 22718296Sbde scsi_pointer->Status = SAM_STAT_CHECK_CONDITION; 228156412Sjhb scsi_pointer->Message = 0; 229156412Sjhb scsi_pointer->have_data_in = IO_UNKNOWN; 230156412Sjhb scsi_pointer->sent_command = 0; 231156412Sjhb scsi_pointer->phase = PH_UNDETERMINED; 232156412Sjhb scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); 233156412Sjhb 234156412Sjhb /* setup scratch area 235156412Sjhb SCp.ptr : buffer pointer 236156412Sjhb SCp.this_residual : buffer length 237156412Sjhb SCp.buffer : next buffer 238156412Sjhb SCp.buffers_residual : left buffers in list 239156412Sjhb SCp.phase : current state of the command */ 240156412Sjhb if (scsi_bufflen(SCpnt)) { 241156412Sjhb scsi_pointer->buffer = scsi_sglist(SCpnt); 242156412Sjhb scsi_pointer->ptr = BUFFER_ADDR(SCpnt); 243156412Sjhb scsi_pointer->this_residual = scsi_pointer->buffer->length; 24418296Sbde scsi_pointer->buffers_residual = scsi_sg_count(SCpnt) - 1; 245156412Sjhb } else { 246156412Sjhb scsi_pointer->ptr = NULL; 247156412Sjhb scsi_pointer->this_residual = 0; 248156412Sjhb scsi_pointer->buffer = NULL; 249156412Sjhb scsi_pointer->buffers_residual = 0; 250156412Sjhb } 251156412Sjhb 252156412Sjhb if (!nsphw_start_selection(SCpnt)) { 25318296Sbde nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail"); 2544Srgrimes SCpnt->result = DID_BUS_BUSY << 16; 255156412Sjhb nsp_scsi_done(SCpnt); 2564Srgrimes return 0; 2574Srgrimes } 2584Srgrimes 2594Srgrimes 2604Srgrimes //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "out"); 2614Srgrimes#ifdef NSP_DEBUG 2624Srgrimes data->CmdId++; 26312515Sphk#endif 264156412Sjhb return 0; 265156412Sjhb} 2664Srgrimes 2674Srgrimesstatic DEF_SCSI_QCMD(nsp_queuecommand) 26818296Sbde 2694Srgrimes/* 270156412Sjhb * setup PIO FIFO transfer mode and enable/disable to data out 2714Srgrimes */ 272163134Sbdestatic void nsp_setup_fifo(nsp_hw_data *data, bool enabled) 2734Srgrimes{ 274156412Sjhb unsigned int base = data->BaseAddress; 27518296Sbde unsigned char transfer_mode_reg; 276156412Sjhb 277156412Sjhb //nsp_dbg(NSP_DEBUG_DATA_IO, "enabled=%d", enabled); 27818296Sbde 279163134Sbde if (enabled) { 28018296Sbde transfer_mode_reg = TRANSFER_GO | BRAIND; 2814Srgrimes } else { 2824Srgrimes transfer_mode_reg = 0; 28312515Sphk } 284156412Sjhb 2854Srgrimes transfer_mode_reg |= data->TransferMode; 286156412Sjhb 2874Srgrimes nsp_index_write(base, TRANSFERMODE, transfer_mode_reg); 2884Srgrimes} 2894Srgrimes 2904Srgrimesstatic void nsphw_init_sync(nsp_hw_data *data) 2914Srgrimes{ 292798Swollman sync_data tmp_sync = { .SyncNegotiation = SYNC_NOT_YET, 2934Srgrimes .SyncPeriod = 0, 2944Srgrimes .SyncOffset = 0 2954Srgrimes }; 2964Srgrimes int i; 2974Srgrimes 2984Srgrimes /* setup sync data */ 2994Srgrimes for ( i = 0; i < ARRAY_SIZE(data->Sync); i++ ) { 3004Srgrimes data->Sync[i] = tmp_sync; 3014Srgrimes } 3024Srgrimes} 3034Srgrimes 3044Srgrimes/* 30510348Sbde * Initialize Ninja hardware 3064Srgrimes */ 3074Srgrimesstatic void nsphw_init(nsp_hw_data *data) 3084Srgrimes{ 3094Srgrimes unsigned int base = data->BaseAddress; 3104Srgrimes 3114Srgrimes nsp_dbg(NSP_DEBUG_INIT, "in base=0x%x", base); 3124Srgrimes 3134Srgrimes data->ScsiClockDiv = CLOCK_40M | FAST_20; 3144Srgrimes data->CurrentSC = NULL; 3154Srgrimes data->FifoCount = 0; 3164Srgrimes data->TransferMode = MODE_IO8; 3174Srgrimes 3184Srgrimes nsphw_init_sync(data); 3194Srgrimes 3204Srgrimes /* block all interrupts */ 3214Srgrimes nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK); 3224Srgrimes 3234Srgrimes /* setup SCSI interface */ 3244Srgrimes nsp_write(base, IFSELECT, IF_IFSEL); 3254Srgrimes 3264Srgrimes nsp_index_write(base, SCSIIRQMODE, 0); 3274Srgrimes 3284Srgrimes nsp_index_write(base, TRANSFERMODE, MODE_IO8); 3294Srgrimes nsp_index_write(base, CLOCKDIV, data->ScsiClockDiv); 3304Srgrimes 331156412Sjhb nsp_index_write(base, PARITYCTRL, 0); 3324Srgrimes nsp_index_write(base, POINTERCLR, POINTER_CLEAR | 3334Srgrimes ACK_COUNTER_CLEAR | 3344Srgrimes REQ_COUNTER_CLEAR | 3354Srgrimes HOST_COUNTER_CLEAR); 3364Srgrimes 337156412Sjhb /* setup fifo asic */ 3384Srgrimes nsp_write(base, IFSELECT, IF_REGSEL); 3394Srgrimes nsp_index_write(base, TERMPWRCTRL, 0); 340156412Sjhb if ((nsp_index_read(base, OTHERCONTROL) & TPWR_SENSE) == 0) { 3414Srgrimes nsp_msg(KERN_INFO, "terminator power on"); 3424Srgrimes nsp_index_write(base, TERMPWRCTRL, POWER_ON); 3434Srgrimes } 3444Srgrimes 3454Srgrimes nsp_index_write(base, TIMERCOUNT, 0); 3464Srgrimes nsp_index_write(base, TIMERCOUNT, 0); /* requires 2 times!! */ 3474Srgrimes 3484Srgrimes nsp_index_write(base, SYNCREG, 0); 3494Srgrimes nsp_index_write(base, ACKWIDTH, 0); 3504Srgrimes 3514Srgrimes /* enable interrupts and ack them */ 3524Srgrimes nsp_index_write(base, SCSIIRQMODE, SCSI_PHASE_CHANGE_EI | 3534Srgrimes RESELECT_EI | 3544Srgrimes SCSI_RESET_IRQ_EI ); 3554Srgrimes nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR); 3564Srgrimes 3574Srgrimes nsp_setup_fifo(data, false); 3584Srgrimes} 3594Srgrimes 3604Srgrimes/* 3614Srgrimes * Start selection phase 3624Srgrimes */ 3634Srgrimesstatic bool nsphw_start_selection(struct scsi_cmnd *const SCpnt) 3644Srgrimes{ 3654Srgrimes struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt); 3664Srgrimes unsigned int host_id = SCpnt->device->host->this_id; 3674Srgrimes unsigned int base = SCpnt->device->host->io_port; 3684Srgrimes unsigned char target = scmd_id(SCpnt); 3694Srgrimes nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 3704Srgrimes int time_out; 3714Srgrimes unsigned char phase, arbit; 3724Srgrimes 3734Srgrimes //nsp_dbg(NSP_DEBUG_RESELECTION, "in"); 3744Srgrimes 3754Srgrimes phase = nsp_index_read(base, SCSIBUSMON); 3764Srgrimes if(phase != BUSMON_BUS_FREE) { 3774Srgrimes //nsp_dbg(NSP_DEBUG_RESELECTION, "bus busy"); 3784Srgrimes return false; 3794Srgrimes } 3804Srgrimes 3814Srgrimes /* start arbitration */ 3824Srgrimes //nsp_dbg(NSP_DEBUG_RESELECTION, "start arbit"); 3834Srgrimes scsi_pointer->phase = PH_ARBSTART; 3844Srgrimes nsp_index_write(base, SETARBIT, ARBIT_GO); 3854Srgrimes 3864Srgrimes time_out = 1000; 3874Srgrimes do { 3884Srgrimes /* XXX: what a stupid chip! */ 3894Srgrimes arbit = nsp_index_read(base, ARBITSTATUS); 3904Srgrimes //nsp_dbg(NSP_DEBUG_RESELECTION, "arbit=%d, wait_count=%d", arbit, wait_count); 3914Srgrimes udelay(1); /* hold 1.2us */ 3924Srgrimes } while((arbit & (ARBIT_WIN | ARBIT_FAIL)) == 0 && 3934Srgrimes (time_out-- != 0)); 3944Srgrimes 3954Srgrimes if (!(arbit & ARBIT_WIN)) { 3964Srgrimes //nsp_dbg(NSP_DEBUG_RESELECTION, "arbit fail"); 3974Srgrimes nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR); 398160312Sjhb return false; 3994Srgrimes } 400160312Sjhb 4014Srgrimes /* assert select line */ 4024Srgrimes //nsp_dbg(NSP_DEBUG_RESELECTION, "assert SEL line"); 4034Srgrimes scsi_pointer->phase = PH_SELSTART; 4044Srgrimes udelay(3); /* wait 2.4us */ 4054Srgrimes nsp_index_write(base, SCSIDATALATCH, BIT(host_id) | BIT(target)); 4064Srgrimes nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_BSY | SCSI_ATN); 4074Srgrimes udelay(2); /* wait >1.2us */ 4084Srgrimes nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_BSY | SCSI_DATAOUT_ENB | SCSI_ATN); 4094Srgrimes nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR); 4104Srgrimes /*udelay(1);*/ /* wait >90ns */ 4114Srgrimes nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_DATAOUT_ENB | SCSI_ATN); 4124Srgrimes 4134Srgrimes /* check selection timeout */ 4144Srgrimes nsp_start_timer(SCpnt, 1000/51); 4154Srgrimes data->SelectionTimeOut = 1; 4164Srgrimes 4174Srgrimes return true; 4184Srgrimes} 4194Srgrimes 4204Srgrimesstruct nsp_sync_table { 4214Srgrimes unsigned int min_period; 4224Srgrimes unsigned int max_period; 4234Srgrimes unsigned int chip_period; 4244Srgrimes unsigned int ack_width; 42533296Sbde}; 42633296Sbde 42733296Sbdestatic struct nsp_sync_table nsp_sync_table_40M[] = { 42833296Sbde {0x0c, 0x0c, 0x1, 0}, /* 20MB 50ns*/ 4296204Sphk {0x19, 0x19, 0x3, 1}, /* 10MB 100ns*/ 430160505Sjhb {0x1a, 0x25, 0x5, 2}, /* 7.5MB 150ns*/ 4317170Sdg {0x26, 0x32, 0x7, 3}, /* 5MB 200ns*/ 4326204Sphk { 0, 0, 0, 0}, 4336204Sphk}; 4346204Sphk 4354Srgrimesstatic struct nsp_sync_table nsp_sync_table_20M[] = { 4364Srgrimes {0x19, 0x19, 0x1, 0}, /* 10MB 100ns*/ 4374Srgrimes {0x1a, 0x25, 0x2, 0}, /* 7.5MB 150ns*/ 4384Srgrimes {0x26, 0x32, 0x3, 1}, /* 5MB 200ns*/ 4394Srgrimes { 0, 0, 0, 0}, 4404Srgrimes}; 4414Srgrimes 4424Srgrimes/* 4434Srgrimes * setup synchronous data transfer mode 4444Srgrimes */ 4454Srgrimesstatic int nsp_analyze_sdtr(struct scsi_cmnd *SCpnt) 4464Srgrimes{ 4474Srgrimes unsigned char target = scmd_id(SCpnt); 4484Srgrimes// unsigned char lun = SCpnt->device->lun; 4494Srgrimes nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 4504Srgrimes sync_data *sync = &(data->Sync[target]); 451156412Sjhb struct nsp_sync_table *sync_table; 4524Srgrimes unsigned int period, offset; 4534Srgrimes 4544Srgrimes nsp_dbg(NSP_DEBUG_SYNC, "in"); 4554Srgrimes 4564Srgrimes period = sync->SyncPeriod; 457103746Smarkm offset = sync->SyncOffset; 4584Srgrimes 4594Srgrimes nsp_dbg(NSP_DEBUG_SYNC, "period=0x%x, offset=0x%x", period, offset); 46079884Skris 4614Srgrimes if ((data->ScsiClockDiv & (BIT(0)|BIT(1))) == CLOCK_20M) { 462131952Smarcel sync_table = nsp_sync_table_20M; 4634Srgrimes } else { 4644Srgrimes sync_table = nsp_sync_table_40M; 4654Srgrimes } 4664Srgrimes 4674Srgrimes for (; sync_table->max_period != 0; sync_table++) { 4684Srgrimes if ( period >= sync_table->min_period && 4694Srgrimes period <= sync_table->max_period ) { 470147745Smarcel break; 471147745Smarcel } 472147745Smarcel } 473147745Smarcel 474147745Smarcel if (period != 0 && sync_table->max_period == 0) { 475147745Smarcel /* 476147745Smarcel * No proper period/offset found 477147745Smarcel */ 478147745Smarcel nsp_dbg(NSP_DEBUG_SYNC, "no proper period/offset"); 479147745Smarcel 480147745Smarcel sync->SyncPeriod = 0; 481147745Smarcel sync->SyncOffset = 0; 482147745Smarcel sync->SyncRegister = 0; 483147745Smarcel sync->AckWidth = 0; 484147745Smarcel 485147745Smarcel return false; 486147745Smarcel } 487147745Smarcel 488147745Smarcel sync->SyncRegister = (sync_table->chip_period << SYNCREG_PERIOD_SHIFT) | 48912515Sphk (offset & SYNCREG_OFFSET_MASK); 49010348Sbde sync->AckWidth = sync_table->ack_width; 49110348Sbde 49210348Sbde nsp_dbg(NSP_DEBUG_SYNC, "sync_reg=0x%x, ack_width=0x%x", sync->SyncRegister, sync->AckWidth); 49310348Sbde 49410348Sbde return true; 4954Srgrimes} 4964Srgrimes 497147745Smarcel 4984Srgrimes/* 4994Srgrimes * start ninja hardware timer 5004Srgrimes */ 5014Srgrimesstatic void nsp_start_timer(struct scsi_cmnd *SCpnt, int time) 5024Srgrimes{ 5034Srgrimes unsigned int base = SCpnt->device->host->io_port; 5044Srgrimes nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 5054Srgrimes 5064Srgrimes //nsp_dbg(NSP_DEBUG_INTR, "in SCpnt=0x%p, time=%d", SCpnt, time); 5074Srgrimes data->TimerCount = time; 5084Srgrimes nsp_index_write(base, TIMERCOUNT, time); 5094Srgrimes} 5104Srgrimes 5114Srgrimes/* 5124Srgrimes * wait for bus phase change 513147745Smarcel */ 514147745Smarcelstatic int nsp_negate_signal(struct scsi_cmnd *SCpnt, unsigned char mask, 5154Srgrimes char *str) 5164Srgrimes{ 5174Srgrimes unsigned int base = SCpnt->device->host->io_port; 5184Srgrimes unsigned char reg; 5194Srgrimes int time_out; 5204Srgrimes 5214Srgrimes //nsp_dbg(NSP_DEBUG_INTR, "in"); 5224Srgrimes 5234Srgrimes time_out = 100; 5244Srgrimes 5254Srgrimes do { 5264Srgrimes reg = nsp_index_read(base, SCSIBUSMON); 5274Srgrimes if (reg == 0xff) { 5284Srgrimes break; 5294Srgrimes } 5304Srgrimes } while ((--time_out != 0) && (reg & mask) != 0); 5314Srgrimes 5324Srgrimes if (time_out == 0) { 5334Srgrimes nsp_msg(KERN_DEBUG, " %s signal off timeout", str); 534160505Sjhb } 5354Srgrimes 536147745Smarcel return 0; 537147745Smarcel} 5384Srgrimes 53917848Spst/* 54017848Spst * expect Ninja Irq 54186998Sdd */ 54286998Sddstatic int nsp_expect_signal(struct scsi_cmnd *SCpnt, 54386998Sdd unsigned char current_phase, 54486998Sdd unsigned char mask) 54586998Sdd{ 54686998Sdd unsigned int base = SCpnt->device->host->io_port; 54786998Sdd int time_out; 54886998Sdd unsigned char phase, i_src; 54986998Sdd 55086998Sdd //nsp_dbg(NSP_DEBUG_INTR, "current_phase=0x%x, mask=0x%x", current_phase, mask); 55186998Sdd 55286998Sdd time_out = 100; 55386998Sdd do { 55486998Sdd phase = nsp_index_read(base, SCSIBUSMON); 55586998Sdd if (phase == 0xff) { 55686998Sdd //nsp_dbg(NSP_DEBUG_INTR, "ret -1"); 55786998Sdd return -1; 55886998Sdd } 55986998Sdd i_src = nsp_read(base, IRQSTATUS); 56086998Sdd if (i_src & IRQSTATUS_SCSI) { 56186998Sdd //nsp_dbg(NSP_DEBUG_INTR, "ret 0 found scsi signal"); 56286998Sdd return 0; 56386998Sdd } 56486998Sdd if ((phase & mask) != 0 && (phase & BUSMON_PHASE_MASK) == current_phase) { 56586998Sdd //nsp_dbg(NSP_DEBUG_INTR, "ret 1 phase=0x%x", phase); 56686998Sdd return 1; 56786998Sdd } 56886998Sdd } while(time_out-- != 0); 56986998Sdd 57086998Sdd //nsp_dbg(NSP_DEBUG_INTR, "timeout"); 57186998Sdd return -1; 57286998Sdd} 57386998Sdd 57486998Sdd/* 57586998Sdd * transfer SCSI message 57686998Sdd */ 57786998Sddstatic int nsp_xfer(struct scsi_cmnd *const SCpnt, int phase) 57889442Smjacob{ 57986998Sdd struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt); 58086998Sdd unsigned int base = SCpnt->device->host->io_port; 58186998Sdd nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 58289442Smjacob char *buf = data->MsgBuffer; 58386998Sdd int len = min(MSGBUF_SIZE, data->MsgLen); 58486998Sdd int ptr; 58586998Sdd int ret; 58686998Sdd 58786998Sdd //nsp_dbg(NSP_DEBUG_DATA_IO, "in"); 58886998Sdd for (ptr = 0; len > 0; len--, ptr++) { 58986998Sdd 59086998Sdd ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ); 59186998Sdd if (ret <= 0) { 59286998Sdd nsp_dbg(NSP_DEBUG_DATA_IO, "xfer quit"); 59386998Sdd return 0; 59485944Speter } 59585944Speter 59685944Speter /* if last byte, negate ATN */ 59785944Speter if (len == 1 && scsi_pointer->phase == PH_MSG_OUT) { 59885944Speter nsp_index_write(base, SCSIBUSCTRL, AUTODIRECTION | ACKENB); 59985944Speter } 60085944Speter 60185944Speter /* read & write message */ 60285944Speter if (phase & BUSMON_IO) { 603126399Sphk nsp_dbg(NSP_DEBUG_DATA_IO, "read msg"); 604126399Sphk buf[ptr] = nsp_index_read(base, SCSIDATAWITHACK); 605126399Sphk } else { 606126399Sphk nsp_dbg(NSP_DEBUG_DATA_IO, "write msg"); 607126399Sphk nsp_index_write(base, SCSIDATAWITHACK, buf[ptr]); 608126399Sphk } 609126399Sphk nsp_negate_signal(SCpnt, BUSMON_ACK, "xfer<ack>"); 610126399Sphk 611126399Sphk } 612126399Sphk return len; 613126399Sphk} 614126399Sphk 615126399Sphk/* 616126399Sphk * get extra SCSI data from fifo 617126399Sphk */ 618126399Sphkstatic int nsp_dataphase_bypass(struct scsi_cmnd *const SCpnt) 619126399Sphk{ 620126399Sphk struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt); 621132002Smarcel nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 622132002Smarcel unsigned int count; 623132002Smarcel 624132002Smarcel //nsp_dbg(NSP_DEBUG_DATA_IO, "in"); 625132002Smarcel 626132002Smarcel if (scsi_pointer->have_data_in != IO_IN) { 627132002Smarcel return 0; 628132002Smarcel } 629132002Smarcel 630132002Smarcel count = nsp_fifo_count(SCpnt); 631132482Smarcel if (data->FifoCount == count) { 632132482Smarcel //nsp_dbg(NSP_DEBUG_DATA_IO, "not use bypass quirk"); 633132482Smarcel return 0; 634132482Smarcel } 635132482Smarcel 636132482Smarcel /* 637138038Srwatson * XXX: NSP_QUIRK 638132482Smarcel * data phase skip only occures in case of SCSI_LOW_READ 639132482Smarcel */ 640132482Smarcel nsp_dbg(NSP_DEBUG_DATA_IO, "use bypass quirk"); 641132482Smarcel scsi_pointer->phase = PH_DATA; 642132482Smarcel nsp_pio_read(SCpnt); 643132482Smarcel nsp_setup_fifo(data, false); 644132482Smarcel 645132482Smarcel return 0; 646132482Smarcel} 647132482Smarcel 648132482Smarcel/* 649132482Smarcel * accept reselection 650132482Smarcel */ 651132482Smarcelstatic void nsp_reselected(struct scsi_cmnd *SCpnt) 652132482Smarcel{ 653132482Smarcel unsigned int base = SCpnt->device->host->io_port; 654132482Smarcel unsigned int host_id = SCpnt->device->host->this_id; 655132482Smarcel //nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 656132482Smarcel unsigned char bus_reg; 657132482Smarcel unsigned char id_reg, tmp; 658132482Smarcel int target; 659132482Smarcel 660132482Smarcel nsp_dbg(NSP_DEBUG_RESELECTION, "in"); 661132482Smarcel 662132482Smarcel id_reg = nsp_index_read(base, RESELECTID); 663132482Smarcel tmp = id_reg & (~BIT(host_id)); 664132482Smarcel target = 0; 665132482Smarcel while(tmp != 0) { 666132482Smarcel if (tmp & BIT(0)) { 667132482Smarcel break; 668132482Smarcel } 669132482Smarcel tmp >>= 1; 670138038Srwatson target++; 671138038Srwatson } 672138038Srwatson 673138038Srwatson if (scmd_id(SCpnt) != target) { 674138038Srwatson nsp_msg(KERN_ERR, "XXX: reselect ID must be %d in this implementation.", target); 675132482Smarcel } 676132482Smarcel 677150819Srwatson nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>"); 678150819Srwatson 679150819Srwatson nsp_nexus(SCpnt); 680150819Srwatson bus_reg = nsp_index_read(base, SCSIBUSCTRL) & ~(SCSI_BSY | SCSI_ATN); 681150819Srwatson nsp_index_write(base, SCSIBUSCTRL, bus_reg); 682150819Srwatson nsp_index_write(base, SCSIBUSCTRL, bus_reg | AUTODIRECTION | ACKENB); 683150819Srwatson} 684150819Srwatson 685157951Sjhb/* 686150819Srwatson * count how many data transferd 687150819Srwatson */ 688150819Srwatsonstatic int nsp_fifo_count(struct scsi_cmnd *SCpnt) 689150819Srwatson{ 690160312Sjhb unsigned int base = SCpnt->device->host->io_port; 691150842Scognet unsigned int count; 692150819Srwatson unsigned int l, m, h; 693150819Srwatson 694150819Srwatson nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER); 695 696 l = nsp_index_read(base, TRANSFERCOUNT); 697 m = nsp_index_read(base, TRANSFERCOUNT); 698 h = nsp_index_read(base, TRANSFERCOUNT); 699 nsp_index_read(base, TRANSFERCOUNT); /* required this! */ 700 701 count = (h << 16) | (m << 8) | (l << 0); 702 703 //nsp_dbg(NSP_DEBUG_DATA_IO, "count=0x%x", count); 704 705 return count; 706} 707 708/* fifo size */ 709#define RFIFO_CRIT 64 710#define WFIFO_CRIT 64 711 712/* 713 * read data in DATA IN phase 714 */ 715static void nsp_pio_read(struct scsi_cmnd *const SCpnt) 716{ 717 struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt); 718 unsigned int base = SCpnt->device->host->io_port; 719 unsigned long mmio_base = SCpnt->device->host->base; 720 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 721 long time_out; 722 int ocount, res; 723 unsigned char stat, fifo_stat; 724 725 ocount = data->FifoCount; 726 727 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", 728 SCpnt, scsi_get_resid(SCpnt), ocount, scsi_pointer->ptr, 729 scsi_pointer->this_residual, scsi_pointer->buffer, 730 scsi_pointer->buffers_residual); 731 732 time_out = 1000; 733 734 while ((time_out-- != 0) && 735 (scsi_pointer->this_residual > 0 || 736 scsi_pointer->buffers_residual > 0)) { 737 738 stat = nsp_index_read(base, SCSIBUSMON); 739 stat &= BUSMON_PHASE_MASK; 740 741 742 res = nsp_fifo_count(SCpnt) - ocount; 743 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", scsi_pointer->ptr, scsi_pointer->this_residual, ocount, res); 744 if (res == 0) { /* if some data available ? */ 745 if (stat == BUSPHASE_DATA_IN) { /* phase changed? */ 746 //nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", scsi_pointer->this_residual); 747 continue; 748 } else { 749 nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x", stat); 750 break; 751 } 752 } 753 754 fifo_stat = nsp_read(base, FIFOSTATUS); 755 if ((fifo_stat & FIFOSTATUS_FULL_EMPTY) == 0 && 756 stat == BUSPHASE_DATA_IN) { 757 continue; 758 } 759 760 res = min(res, scsi_pointer->this_residual); 761 762 switch (data->TransferMode) { 763 case MODE_IO32: 764 res &= ~(BIT(1)|BIT(0)); /* align 4 */ 765 nsp_fifo32_read(base, scsi_pointer->ptr, res >> 2); 766 break; 767 case MODE_IO8: 768 nsp_fifo8_read(base, scsi_pointer->ptr, res); 769 break; 770 771 case MODE_MEM32: 772 res &= ~(BIT(1)|BIT(0)); /* align 4 */ 773 nsp_mmio_fifo32_read(mmio_base, scsi_pointer->ptr, 774 res >> 2); 775 break; 776 777 default: 778 nsp_dbg(NSP_DEBUG_DATA_IO, "unknown read mode"); 779 return; 780 } 781 782 nsp_inc_resid(SCpnt, -res); 783 scsi_pointer->ptr += res; 784 scsi_pointer->this_residual -= res; 785 ocount += res; 786 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this_residual=0x%x ocount=0x%x", scsi_pointer->ptr, scsi_pointer->this_residual, ocount); 787 788 /* go to next scatter list if available */ 789 if (scsi_pointer->this_residual == 0 && 790 scsi_pointer->buffers_residual != 0 ) { 791 //nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next timeout=%d", time_out); 792 scsi_pointer->buffers_residual--; 793 scsi_pointer->buffer = sg_next(scsi_pointer->buffer); 794 scsi_pointer->ptr = BUFFER_ADDR(SCpnt); 795 scsi_pointer->this_residual = 796 scsi_pointer->buffer->length; 797 time_out = 1000; 798 799 //nsp_dbg(NSP_DEBUG_DATA_IO, "page: 0x%p, off: 0x%x", scsi_pointer->buffer->page, scsi_pointer->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 scsi_get_resid(SCpnt), scsi_pointer->this_residual, 808 scsi_pointer->buffers_residual); 809 } 810 nsp_dbg(NSP_DEBUG_DATA_IO, "read ocount=0x%x", ocount); 811 nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId, 812 scsi_get_resid(SCpnt)); 813} 814 815/* 816 * write data in DATA OUT phase 817 */ 818static void nsp_pio_write(struct scsi_cmnd *SCpnt) 819{ 820 struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt); 821 unsigned int base = SCpnt->device->host->io_port; 822 unsigned long mmio_base = SCpnt->device->host->base; 823 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 824 int time_out; 825 int ocount, res; 826 unsigned char stat; 827 828 ocount = data->FifoCount; 829 830 nsp_dbg(NSP_DEBUG_DATA_IO, "in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x", 831 data->FifoCount, scsi_pointer->ptr, scsi_pointer->this_residual, 832 scsi_pointer->buffer, scsi_pointer->buffers_residual, 833 scsi_get_resid(SCpnt)); 834 835 time_out = 1000; 836 837 while ((time_out-- != 0) && 838 (scsi_pointer->this_residual > 0 || 839 scsi_pointer->buffers_residual > 0)) { 840 stat = nsp_index_read(base, SCSIBUSMON); 841 stat &= BUSMON_PHASE_MASK; 842 843 if (stat != BUSPHASE_DATA_OUT) { 844 res = ocount - nsp_fifo_count(SCpnt); 845 846 nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x, res=%d\n", stat, res); 847 /* Put back pointer */ 848 nsp_inc_resid(SCpnt, res); 849 scsi_pointer->ptr -= res; 850 scsi_pointer->this_residual += res; 851 ocount -= res; 852 853 break; 854 } 855 856 res = ocount - nsp_fifo_count(SCpnt); 857 if (res > 0) { /* write all data? */ 858 nsp_dbg(NSP_DEBUG_DATA_IO, "wait for all data out. ocount=0x%x res=%d", ocount, res); 859 continue; 860 } 861 862 res = min(scsi_pointer->this_residual, WFIFO_CRIT); 863 864 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x res=0x%x", scsi_pointer->ptr, scsi_pointer->this_residual, res); 865 switch (data->TransferMode) { 866 case MODE_IO32: 867 res &= ~(BIT(1)|BIT(0)); /* align 4 */ 868 nsp_fifo32_write(base, scsi_pointer->ptr, res >> 2); 869 break; 870 case MODE_IO8: 871 nsp_fifo8_write(base, scsi_pointer->ptr, res); 872 break; 873 874 case MODE_MEM32: 875 res &= ~(BIT(1)|BIT(0)); /* align 4 */ 876 nsp_mmio_fifo32_write(mmio_base, scsi_pointer->ptr, 877 res >> 2); 878 break; 879 880 default: 881 nsp_dbg(NSP_DEBUG_DATA_IO, "unknown write mode"); 882 break; 883 } 884 885 nsp_inc_resid(SCpnt, -res); 886 scsi_pointer->ptr += res; 887 scsi_pointer->this_residual -= res; 888 ocount += res; 889 890 /* go to next scatter list if available */ 891 if (scsi_pointer->this_residual == 0 && 892 scsi_pointer->buffers_residual != 0 ) { 893 //nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next"); 894 scsi_pointer->buffers_residual--; 895 scsi_pointer->buffer = sg_next(scsi_pointer->buffer); 896 scsi_pointer->ptr = BUFFER_ADDR(SCpnt); 897 scsi_pointer->this_residual = 898 scsi_pointer->buffer->length; 899 time_out = 1000; 900 } 901 } 902 903 data->FifoCount = ocount; 904 905 if (time_out < 0) { 906 nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x", 907 scsi_get_resid(SCpnt)); 908 } 909 nsp_dbg(NSP_DEBUG_DATA_IO, "write ocount=0x%x", ocount); 910 nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId, 911 scsi_get_resid(SCpnt)); 912} 913#undef RFIFO_CRIT 914#undef WFIFO_CRIT 915 916/* 917 * setup synchronous/asynchronous data transfer mode 918 */ 919static int nsp_nexus(struct scsi_cmnd *SCpnt) 920{ 921 unsigned int base = SCpnt->device->host->io_port; 922 unsigned char target = scmd_id(SCpnt); 923// unsigned char lun = SCpnt->device->lun; 924 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 925 sync_data *sync = &(data->Sync[target]); 926 927 //nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p", SCpnt); 928 929 /* setup synch transfer registers */ 930 nsp_index_write(base, SYNCREG, sync->SyncRegister); 931 nsp_index_write(base, ACKWIDTH, sync->AckWidth); 932 933 if (scsi_get_resid(SCpnt) % 4 != 0 || 934 scsi_get_resid(SCpnt) <= PAGE_SIZE ) { 935 data->TransferMode = MODE_IO8; 936 } else if (nsp_burst_mode == BURST_MEM32) { 937 data->TransferMode = MODE_MEM32; 938 } else if (nsp_burst_mode == BURST_IO32) { 939 data->TransferMode = MODE_IO32; 940 } else { 941 data->TransferMode = MODE_IO8; 942 } 943 944 /* setup pdma fifo */ 945 nsp_setup_fifo(data, true); 946 947 /* clear ack counter */ 948 data->FifoCount = 0; 949 nsp_index_write(base, POINTERCLR, POINTER_CLEAR | 950 ACK_COUNTER_CLEAR | 951 REQ_COUNTER_CLEAR | 952 HOST_COUNTER_CLEAR); 953 954 return 0; 955} 956 957#include "nsp_message.c" 958/* 959 * interrupt handler 960 */ 961static irqreturn_t nspintr(int irq, void *dev_id) 962{ 963 unsigned int base; 964 unsigned char irq_status, irq_phase, phase; 965 struct scsi_cmnd *tmpSC; 966 struct scsi_pointer *scsi_pointer; 967 unsigned char target, lun; 968 unsigned int *sync_neg; 969 int i, tmp; 970 nsp_hw_data *data; 971 972 973 //nsp_dbg(NSP_DEBUG_INTR, "dev_id=0x%p", dev_id); 974 //nsp_dbg(NSP_DEBUG_INTR, "host=0x%p", ((scsi_info_t *)dev_id)->host); 975 976 if ( dev_id != NULL && 977 ((scsi_info_t *)dev_id)->host != NULL ) { 978 scsi_info_t *info = (scsi_info_t *)dev_id; 979 980 data = (nsp_hw_data *)info->host->hostdata; 981 } else { 982 nsp_dbg(NSP_DEBUG_INTR, "host data wrong"); 983 return IRQ_NONE; 984 } 985 986 //nsp_dbg(NSP_DEBUG_INTR, "&nsp_data_base=0x%p, dev_id=0x%p", &nsp_data_base, dev_id); 987 988 base = data->BaseAddress; 989 //nsp_dbg(NSP_DEBUG_INTR, "base=0x%x", base); 990 991 /* 992 * interrupt check 993 */ 994 nsp_write(base, IRQCONTROL, IRQCONTROL_IRQDISABLE); 995 irq_status = nsp_read(base, IRQSTATUS); 996 //nsp_dbg(NSP_DEBUG_INTR, "irq_status=0x%x", irq_status); 997 if ((irq_status == 0xff) || ((irq_status & IRQSTATUS_MASK) == 0)) { 998 nsp_write(base, IRQCONTROL, 0); 999 //nsp_dbg(NSP_DEBUG_INTR, "no irq/shared irq"); 1000 return IRQ_NONE; 1001 } 1002 1003 /* XXX: IMPORTANT 1004 * Do not read an irq_phase register if no scsi phase interrupt. 1005 * Unless, you should lose a scsi phase interrupt. 1006 */ 1007 phase = nsp_index_read(base, SCSIBUSMON); 1008 if((irq_status & IRQSTATUS_SCSI) != 0) { 1009 irq_phase = nsp_index_read(base, IRQPHASESENCE); 1010 } else { 1011 irq_phase = 0; 1012 } 1013 1014 //nsp_dbg(NSP_DEBUG_INTR, "irq_phase=0x%x", irq_phase); 1015 1016 /* 1017 * timer interrupt handler (scsi vs timer interrupts) 1018 */ 1019 //nsp_dbg(NSP_DEBUG_INTR, "timercount=%d", data->TimerCount); 1020 if (data->TimerCount != 0) { 1021 //nsp_dbg(NSP_DEBUG_INTR, "stop timer"); 1022 nsp_index_write(base, TIMERCOUNT, 0); 1023 nsp_index_write(base, TIMERCOUNT, 0); 1024 data->TimerCount = 0; 1025 } 1026 1027 if ((irq_status & IRQSTATUS_MASK) == IRQSTATUS_TIMER && 1028 data->SelectionTimeOut == 0) { 1029 //nsp_dbg(NSP_DEBUG_INTR, "timer start"); 1030 nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR); 1031 return IRQ_HANDLED; 1032 } 1033 1034 nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR); 1035 1036 if ((irq_status & IRQSTATUS_SCSI) && 1037 (irq_phase & SCSI_RESET_IRQ)) { 1038 nsp_msg(KERN_ERR, "bus reset (power off?)"); 1039 1040 nsphw_init(data); 1041 nsp_bus_reset(data); 1042 1043 if(data->CurrentSC != NULL) { 1044 tmpSC = data->CurrentSC; 1045 scsi_pointer = nsp_priv(tmpSC); 1046 tmpSC->result = (DID_RESET << 16) | 1047 ((scsi_pointer->Message & 0xff) << 8) | 1048 ((scsi_pointer->Status & 0xff) << 0); 1049 nsp_scsi_done(tmpSC); 1050 } 1051 return IRQ_HANDLED; 1052 } 1053 1054 if (data->CurrentSC == NULL) { 1055 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); 1056 nsphw_init(data); 1057 nsp_bus_reset(data); 1058 return IRQ_HANDLED; 1059 } 1060 1061 tmpSC = data->CurrentSC; 1062 scsi_pointer = nsp_priv(tmpSC); 1063 target = tmpSC->device->id; 1064 lun = tmpSC->device->lun; 1065 sync_neg = &(data->Sync[target].SyncNegotiation); 1066 1067 /* 1068 * parse hardware SCSI irq reasons register 1069 */ 1070 if (irq_status & IRQSTATUS_SCSI) { 1071 if (irq_phase & RESELECT_IRQ) { 1072 nsp_dbg(NSP_DEBUG_INTR, "reselect"); 1073 nsp_write(base, IRQCONTROL, IRQCONTROL_RESELECT_CLEAR); 1074 nsp_reselected(tmpSC); 1075 return IRQ_HANDLED; 1076 } 1077 1078 if ((irq_phase & (PHASE_CHANGE_IRQ | LATCHED_BUS_FREE)) == 0) { 1079 return IRQ_HANDLED; 1080 } 1081 } 1082 1083 //show_phase(tmpSC); 1084 1085 switch (scsi_pointer->phase) { 1086 case PH_SELSTART: 1087 // *sync_neg = SYNC_NOT_YET; 1088 if ((phase & BUSMON_BSY) == 0) { 1089 //nsp_dbg(NSP_DEBUG_INTR, "selection count=%d", data->SelectionTimeOut); 1090 if (data->SelectionTimeOut >= NSP_SELTIMEOUT) { 1091 nsp_dbg(NSP_DEBUG_INTR, "selection time out"); 1092 data->SelectionTimeOut = 0; 1093 nsp_index_write(base, SCSIBUSCTRL, 0); 1094 1095 tmpSC->result = DID_TIME_OUT << 16; 1096 nsp_scsi_done(tmpSC); 1097 1098 return IRQ_HANDLED; 1099 } 1100 data->SelectionTimeOut += 1; 1101 nsp_start_timer(tmpSC, 1000/51); 1102 return IRQ_HANDLED; 1103 } 1104 1105 /* attention assert */ 1106 //nsp_dbg(NSP_DEBUG_INTR, "attention assert"); 1107 data->SelectionTimeOut = 0; 1108 scsi_pointer->phase = PH_SELECTED; 1109 nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN); 1110 udelay(1); 1111 nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN | AUTODIRECTION | ACKENB); 1112 return IRQ_HANDLED; 1113 1114 case PH_RESELECT: 1115 //nsp_dbg(NSP_DEBUG_INTR, "phase reselect"); 1116 // *sync_neg = SYNC_NOT_YET; 1117 if ((phase & BUSMON_PHASE_MASK) != BUSPHASE_MESSAGE_IN) { 1118 1119 tmpSC->result = DID_ABORT << 16; 1120 nsp_scsi_done(tmpSC); 1121 return IRQ_HANDLED; 1122 } 1123 fallthrough; 1124 default: 1125 if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) { 1126 return IRQ_HANDLED; 1127 } 1128 break; 1129 } 1130 1131 /* 1132 * SCSI sequencer 1133 */ 1134 //nsp_dbg(NSP_DEBUG_INTR, "start scsi seq"); 1135 1136 /* normal disconnect */ 1137 if ((scsi_pointer->phase == PH_MSG_IN || 1138 scsi_pointer->phase == PH_MSG_OUT) && 1139 (irq_phase & LATCHED_BUS_FREE) != 0) { 1140 nsp_dbg(NSP_DEBUG_INTR, "normal disconnect irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase); 1141 1142 //*sync_neg = SYNC_NOT_YET; 1143 1144 /* all command complete and return status */ 1145 if (scsi_pointer->Message == COMMAND_COMPLETE) { 1146 tmpSC->result = (DID_OK << 16) | 1147 ((scsi_pointer->Message & 0xff) << 8) | 1148 ((scsi_pointer->Status & 0xff) << 0); 1149 nsp_dbg(NSP_DEBUG_INTR, "command complete result=0x%x", tmpSC->result); 1150 nsp_scsi_done(tmpSC); 1151 1152 return IRQ_HANDLED; 1153 } 1154 1155 return IRQ_HANDLED; 1156 } 1157 1158 1159 /* check unexpected bus free state */ 1160 if (phase == 0) { 1161 nsp_msg(KERN_DEBUG, "unexpected bus free. irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase); 1162 1163 *sync_neg = SYNC_NG; 1164 tmpSC->result = DID_ERROR << 16; 1165 nsp_scsi_done(tmpSC); 1166 return IRQ_HANDLED; 1167 } 1168 1169 switch (phase & BUSMON_PHASE_MASK) { 1170 case BUSPHASE_COMMAND: 1171 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_COMMAND"); 1172 if ((phase & BUSMON_REQ) == 0) { 1173 nsp_dbg(NSP_DEBUG_INTR, "REQ == 0"); 1174 return IRQ_HANDLED; 1175 } 1176 1177 scsi_pointer->phase = PH_COMMAND; 1178 1179 nsp_nexus(tmpSC); 1180 1181 /* write scsi command */ 1182 nsp_dbg(NSP_DEBUG_INTR, "cmd_len=%d", tmpSC->cmd_len); 1183 nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER); 1184 for (i = 0; i < tmpSC->cmd_len; i++) { 1185 nsp_index_write(base, COMMANDDATA, tmpSC->cmnd[i]); 1186 } 1187 nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER | AUTO_COMMAND_GO); 1188 break; 1189 1190 case BUSPHASE_DATA_OUT: 1191 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_OUT"); 1192 1193 scsi_pointer->phase = PH_DATA; 1194 scsi_pointer->have_data_in = IO_OUT; 1195 1196 nsp_pio_write(tmpSC); 1197 1198 break; 1199 1200 case BUSPHASE_DATA_IN: 1201 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_IN"); 1202 1203 scsi_pointer->phase = PH_DATA; 1204 scsi_pointer->have_data_in = IO_IN; 1205 1206 nsp_pio_read(tmpSC); 1207 1208 break; 1209 1210 case BUSPHASE_STATUS: 1211 nsp_dataphase_bypass(tmpSC); 1212 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_STATUS"); 1213 1214 scsi_pointer->phase = PH_STATUS; 1215 1216 scsi_pointer->Status = nsp_index_read(base, SCSIDATAWITHACK); 1217 nsp_dbg(NSP_DEBUG_INTR, "message=0x%x status=0x%x", 1218 scsi_pointer->Message, scsi_pointer->Status); 1219 1220 break; 1221 1222 case BUSPHASE_MESSAGE_OUT: 1223 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_OUT"); 1224 if ((phase & BUSMON_REQ) == 0) { 1225 goto timer_out; 1226 } 1227 1228 scsi_pointer->phase = PH_MSG_OUT; 1229 1230 //*sync_neg = SYNC_NOT_YET; 1231 1232 data->MsgLen = i = 0; 1233 data->MsgBuffer[i] = IDENTIFY(true, lun); i++; 1234 1235 if (*sync_neg == SYNC_NOT_YET) { 1236 data->Sync[target].SyncPeriod = 0; 1237 data->Sync[target].SyncOffset = 0; 1238 1239 /**/ 1240 data->MsgBuffer[i] = EXTENDED_MESSAGE; i++; 1241 data->MsgBuffer[i] = 3; i++; 1242 data->MsgBuffer[i] = EXTENDED_SDTR; i++; 1243 data->MsgBuffer[i] = 0x0c; i++; 1244 data->MsgBuffer[i] = 15; i++; 1245 /**/ 1246 } 1247 data->MsgLen = i; 1248 1249 nsp_analyze_sdtr(tmpSC); 1250 show_message(data); 1251 nsp_message_out(tmpSC); 1252 break; 1253 1254 case BUSPHASE_MESSAGE_IN: 1255 nsp_dataphase_bypass(tmpSC); 1256 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_IN"); 1257 if ((phase & BUSMON_REQ) == 0) { 1258 goto timer_out; 1259 } 1260 1261 scsi_pointer->phase = PH_MSG_IN; 1262 nsp_message_in(tmpSC); 1263 1264 /**/ 1265 if (*sync_neg == SYNC_NOT_YET) { 1266 //nsp_dbg(NSP_DEBUG_INTR, "sync target=%d,lun=%d",target,lun); 1267 1268 if (data->MsgLen >= 5 && 1269 data->MsgBuffer[0] == EXTENDED_MESSAGE && 1270 data->MsgBuffer[1] == 3 && 1271 data->MsgBuffer[2] == EXTENDED_SDTR ) { 1272 data->Sync[target].SyncPeriod = data->MsgBuffer[3]; 1273 data->Sync[target].SyncOffset = data->MsgBuffer[4]; 1274 //nsp_dbg(NSP_DEBUG_INTR, "sync ok, %d %d", data->MsgBuffer[3], data->MsgBuffer[4]); 1275 *sync_neg = SYNC_OK; 1276 } else { 1277 data->Sync[target].SyncPeriod = 0; 1278 data->Sync[target].SyncOffset = 0; 1279 *sync_neg = SYNC_NG; 1280 } 1281 nsp_analyze_sdtr(tmpSC); 1282 } 1283 /**/ 1284 1285 /* search last messeage byte */ 1286 tmp = -1; 1287 for (i = 0; i < data->MsgLen; i++) { 1288 tmp = data->MsgBuffer[i]; 1289 if (data->MsgBuffer[i] == EXTENDED_MESSAGE) { 1290 i += (1 + data->MsgBuffer[i+1]); 1291 } 1292 } 1293 scsi_pointer->Message = tmp; 1294 1295 nsp_dbg(NSP_DEBUG_INTR, "message=0x%x len=%d", 1296 scsi_pointer->Message, data->MsgLen); 1297 show_message(data); 1298 1299 break; 1300 1301 case BUSPHASE_SELECT: 1302 default: 1303 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE other"); 1304 1305 break; 1306 } 1307 1308 //nsp_dbg(NSP_DEBUG_INTR, "out"); 1309 return IRQ_HANDLED; 1310 1311timer_out: 1312 nsp_start_timer(tmpSC, 1000/102); 1313 return IRQ_HANDLED; 1314} 1315 1316#ifdef NSP_DEBUG 1317#include "nsp_debug.c" 1318#endif /* NSP_DEBUG */ 1319 1320/*----------------------------------------------------------------*/ 1321/* look for ninja3 card and init if found */ 1322/*----------------------------------------------------------------*/ 1323static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht) 1324{ 1325 struct Scsi_Host *host; /* registered host structure */ 1326 nsp_hw_data *data_b = &nsp_data_base, *data; 1327 1328 nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id); 1329 host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data)); 1330 if (host == NULL) { 1331 nsp_dbg(NSP_DEBUG_INIT, "host failed"); 1332 return NULL; 1333 } 1334 1335 memcpy(host->hostdata, data_b, sizeof(nsp_hw_data)); 1336 data = (nsp_hw_data *)host->hostdata; 1337 data->ScsiInfo->host = host; 1338#ifdef NSP_DEBUG 1339 data->CmdId = 0; 1340#endif 1341 1342 nsp_dbg(NSP_DEBUG_INIT, "irq=%d,%d", data_b->IrqNumber, ((nsp_hw_data *)host->hostdata)->IrqNumber); 1343 1344 host->unique_id = data->BaseAddress; 1345 host->io_port = data->BaseAddress; 1346 host->n_io_port = data->NumAddress; 1347 host->irq = data->IrqNumber; 1348 host->base = data->MmioAddress; 1349 1350 spin_lock_init(&(data->Lock)); 1351 1352 snprintf(data->nspinfo, 1353 sizeof(data->nspinfo), 1354 "NinjaSCSI-3/32Bi Driver $Revision: 1.23 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d", 1355 host->io_port, host->io_port + host->n_io_port - 1, 1356 host->base, 1357 host->irq); 1358 sht->name = data->nspinfo; 1359 1360 nsp_dbg(NSP_DEBUG_INIT, "end"); 1361 1362 1363 return host; /* detect done. */ 1364} 1365 1366/*----------------------------------------------------------------*/ 1367/* return info string */ 1368/*----------------------------------------------------------------*/ 1369static const char *nsp_info(struct Scsi_Host *shpnt) 1370{ 1371 nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata; 1372 1373 return data->nspinfo; 1374} 1375 1376static int nsp_show_info(struct seq_file *m, struct Scsi_Host *host) 1377{ 1378 int id; 1379 int speed; 1380 unsigned long flags; 1381 nsp_hw_data *data; 1382 int hostno; 1383 1384 hostno = host->host_no; 1385 data = (nsp_hw_data *)host->hostdata; 1386 1387 seq_puts(m, "NinjaSCSI status\n\n" 1388 "Driver version: $Revision: 1.23 $\n"); 1389 seq_printf(m, "SCSI host No.: %d\n", hostno); 1390 seq_printf(m, "IRQ: %d\n", host->irq); 1391 seq_printf(m, "IO: 0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1); 1392 seq_printf(m, "MMIO(virtual address): 0x%lx-0x%lx\n", host->base, host->base + data->MmioLength - 1); 1393 seq_printf(m, "sg_tablesize: %d\n", host->sg_tablesize); 1394 1395 seq_puts(m, "burst transfer mode: "); 1396 switch (nsp_burst_mode) { 1397 case BURST_IO8: 1398 seq_puts(m, "io8"); 1399 break; 1400 case BURST_IO32: 1401 seq_puts(m, "io32"); 1402 break; 1403 case BURST_MEM32: 1404 seq_puts(m, "mem32"); 1405 break; 1406 default: 1407 seq_puts(m, "???"); 1408 break; 1409 } 1410 seq_putc(m, '\n'); 1411 1412 1413 spin_lock_irqsave(&(data->Lock), flags); 1414 seq_printf(m, "CurrentSC: 0x%p\n\n", data->CurrentSC); 1415 spin_unlock_irqrestore(&(data->Lock), flags); 1416 1417 seq_puts(m, "SDTR status\n"); 1418 for(id = 0; id < ARRAY_SIZE(data->Sync); id++) { 1419 1420 seq_printf(m, "id %d: ", id); 1421 1422 if (id == host->this_id) { 1423 seq_puts(m, "----- NinjaSCSI-3 host adapter\n"); 1424 continue; 1425 } 1426 1427 switch(data->Sync[id].SyncNegotiation) { 1428 case SYNC_OK: 1429 seq_puts(m, " sync"); 1430 break; 1431 case SYNC_NG: 1432 seq_puts(m, "async"); 1433 break; 1434 case SYNC_NOT_YET: 1435 seq_puts(m, " none"); 1436 break; 1437 default: 1438 seq_puts(m, "?????"); 1439 break; 1440 } 1441 1442 if (data->Sync[id].SyncPeriod != 0) { 1443 speed = 1000000 / (data->Sync[id].SyncPeriod * 4); 1444 1445 seq_printf(m, " transfer %d.%dMB/s, offset %d", 1446 speed / 1000, 1447 speed % 1000, 1448 data->Sync[id].SyncOffset 1449 ); 1450 } 1451 seq_putc(m, '\n'); 1452 } 1453 return 0; 1454} 1455 1456/*---------------------------------------------------------------*/ 1457/* error handler */ 1458/*---------------------------------------------------------------*/ 1459 1460/* 1461static int nsp_eh_abort(struct scsi_cmnd *SCpnt) 1462{ 1463 nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt); 1464 1465 return nsp_eh_bus_reset(SCpnt); 1466}*/ 1467 1468static int nsp_bus_reset(nsp_hw_data *data) 1469{ 1470 unsigned int base = data->BaseAddress; 1471 int i; 1472 1473 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK); 1474 1475 nsp_index_write(base, SCSIBUSCTRL, SCSI_RST); 1476 mdelay(100); /* 100ms */ 1477 nsp_index_write(base, SCSIBUSCTRL, 0); 1478 for(i = 0; i < 5; i++) { 1479 nsp_index_read(base, IRQPHASESENCE); /* dummy read */ 1480 } 1481 1482 nsphw_init_sync(data); 1483 1484 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR); 1485 1486 return SUCCESS; 1487} 1488 1489static int nsp_eh_bus_reset(struct scsi_cmnd *SCpnt) 1490{ 1491 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 1492 1493 nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt); 1494 1495 return nsp_bus_reset(data); 1496} 1497 1498static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt) 1499{ 1500 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 1501 1502 nsp_dbg(NSP_DEBUG_BUSRESET, "in"); 1503 1504 nsphw_init(data); 1505 1506 return SUCCESS; 1507} 1508 1509 1510/********************************************************************** 1511 PCMCIA functions 1512**********************************************************************/ 1513 1514static int nsp_cs_probe(struct pcmcia_device *link) 1515{ 1516 scsi_info_t *info; 1517 nsp_hw_data *data = &nsp_data_base; 1518 int ret; 1519 1520 nsp_dbg(NSP_DEBUG_INIT, "in"); 1521 1522 /* Create new SCSI device */ 1523 info = kzalloc(sizeof(*info), GFP_KERNEL); 1524 if (info == NULL) { return -ENOMEM; } 1525 info->p_dev = link; 1526 link->priv = info; 1527 data->ScsiInfo = info; 1528 1529 nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info); 1530 1531 ret = nsp_cs_config(link); 1532 1533 nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); 1534 return ret; 1535} /* nsp_cs_attach */ 1536 1537 1538static void nsp_cs_detach(struct pcmcia_device *link) 1539{ 1540 nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); 1541 1542 ((scsi_info_t *)link->priv)->stop = 1; 1543 nsp_cs_release(link); 1544 1545 kfree(link->priv); 1546 link->priv = NULL; 1547} /* nsp_cs_detach */ 1548 1549 1550static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) 1551{ 1552 nsp_hw_data *data = priv_data; 1553 1554 if (p_dev->config_index == 0) 1555 return -ENODEV; 1556 1557 /* This reserves IO space but doesn't actually enable it */ 1558 if (pcmcia_request_io(p_dev) != 0) 1559 goto next_entry; 1560 1561 if (resource_size(p_dev->resource[2])) { 1562 p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 | 1563 WIN_MEMORY_TYPE_CM | 1564 WIN_ENABLE); 1565 if (p_dev->resource[2]->end < 0x1000) 1566 p_dev->resource[2]->end = 0x1000; 1567 if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0) 1568 goto next_entry; 1569 if (pcmcia_map_mem_page(p_dev, p_dev->resource[2], 1570 p_dev->card_addr) != 0) 1571 goto next_entry; 1572 1573 data->MmioAddress = (unsigned long) 1574 ioremap(p_dev->resource[2]->start, 1575 resource_size(p_dev->resource[2])); 1576 if (!data->MmioAddress) 1577 goto next_entry; 1578 1579 data->MmioLength = resource_size(p_dev->resource[2]); 1580 } 1581 /* If we got this far, we're cool! */ 1582 return 0; 1583 1584next_entry: 1585 nsp_dbg(NSP_DEBUG_INIT, "next"); 1586 pcmcia_disable_device(p_dev); 1587 return -ENODEV; 1588} 1589 1590static int nsp_cs_config(struct pcmcia_device *link) 1591{ 1592 int ret; 1593 scsi_info_t *info = link->priv; 1594 struct Scsi_Host *host; 1595 nsp_hw_data *data = &nsp_data_base; 1596 1597 nsp_dbg(NSP_DEBUG_INIT, "in"); 1598 1599 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC | 1600 CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM | 1601 CONF_AUTO_SET_IO; 1602 1603 ret = pcmcia_loop_config(link, nsp_cs_config_check, data); 1604 if (ret) 1605 goto cs_failed; 1606 1607 if (pcmcia_request_irq(link, nspintr)) 1608 goto cs_failed; 1609 1610 ret = pcmcia_enable_device(link); 1611 if (ret) 1612 goto cs_failed; 1613 1614 if (free_ports) { 1615 if (link->resource[0]) { 1616 release_region(link->resource[0]->start, 1617 resource_size(link->resource[0])); 1618 } 1619 if (link->resource[1]) { 1620 release_region(link->resource[1]->start, 1621 resource_size(link->resource[1])); 1622 } 1623 } 1624 1625 /* Set port and IRQ */ 1626 data->BaseAddress = link->resource[0]->start; 1627 data->NumAddress = resource_size(link->resource[0]); 1628 data->IrqNumber = link->irq; 1629 1630 nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d", 1631 data->BaseAddress, data->NumAddress, data->IrqNumber); 1632 1633 nsphw_init(data); 1634 1635 host = nsp_detect(&nsp_driver_template); 1636 1637 if (host == NULL) { 1638 nsp_dbg(NSP_DEBUG_INIT, "detect failed"); 1639 goto cs_failed; 1640 } 1641 1642 1643 ret = scsi_add_host (host, NULL); 1644 if (ret) 1645 goto cs_failed; 1646 1647 scsi_scan_host(host); 1648 1649 info->host = host; 1650 1651 return 0; 1652 1653 cs_failed: 1654 nsp_dbg(NSP_DEBUG_INIT, "config fail"); 1655 nsp_cs_release(link); 1656 1657 return -ENODEV; 1658} /* nsp_cs_config */ 1659 1660 1661static void nsp_cs_release(struct pcmcia_device *link) 1662{ 1663 scsi_info_t *info = link->priv; 1664 nsp_hw_data *data = NULL; 1665 1666 if (info->host == NULL) { 1667 nsp_msg(KERN_DEBUG, "unexpected card release call."); 1668 } else { 1669 data = (nsp_hw_data *)info->host->hostdata; 1670 } 1671 1672 nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); 1673 1674 /* Unlink the device chain */ 1675 if (info->host != NULL) { 1676 scsi_remove_host(info->host); 1677 } 1678 1679 if (resource_size(link->resource[2])) { 1680 if (data != NULL) { 1681 iounmap((void *)(data->MmioAddress)); 1682 } 1683 } 1684 pcmcia_disable_device(link); 1685 1686 if (info->host != NULL) { 1687 scsi_host_put(info->host); 1688 } 1689} /* nsp_cs_release */ 1690 1691static int nsp_cs_suspend(struct pcmcia_device *link) 1692{ 1693 scsi_info_t *info = link->priv; 1694 nsp_hw_data *data; 1695 1696 nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); 1697 1698 if (info->host != NULL) { 1699 nsp_msg(KERN_INFO, "clear SDTR status"); 1700 1701 data = (nsp_hw_data *)info->host->hostdata; 1702 1703 nsphw_init_sync(data); 1704 } 1705 1706 info->stop = 1; 1707 1708 return 0; 1709} 1710 1711static int nsp_cs_resume(struct pcmcia_device *link) 1712{ 1713 scsi_info_t *info = link->priv; 1714 nsp_hw_data *data; 1715 1716 nsp_dbg(NSP_DEBUG_INIT, "event: resume"); 1717 1718 info->stop = 0; 1719 1720 if (info->host != NULL) { 1721 nsp_msg(KERN_INFO, "reset host and bus"); 1722 1723 data = (nsp_hw_data *)info->host->hostdata; 1724 1725 nsphw_init (data); 1726 nsp_bus_reset(data); 1727 } 1728 1729 return 0; 1730} 1731 1732/*======================================================================* 1733 * module entry point 1734 *====================================================================*/ 1735static const struct pcmcia_device_id nsp_cs_ids[] = { 1736 PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16 ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a), 1737 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a), 1738 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-002", "1", 0x534c02bc, 0xcb09d5b2, 0x51de003a), 1739 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-003", "1", 0x534c02bc, 0xbc0ee524, 0x51de003a), 1740 PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-004", "1", 0x534c02bc, 0x226a7087, 0x51de003a), 1741 PCMCIA_DEVICE_PROD_ID123("WBT", "NinjaSCSI-3", "R1.0", 0xc7ba805f, 0xfdc7c97d, 0x6973710e), 1742 PCMCIA_DEVICE_PROD_ID123("WORKBIT", "UltraNinja-16", "1", 0x28191418, 0xb70f4b09, 0x51de003a), 1743 PCMCIA_DEVICE_NULL 1744}; 1745MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids); 1746 1747static struct pcmcia_driver nsp_driver = { 1748 .owner = THIS_MODULE, 1749 .name = "nsp_cs", 1750 .probe = nsp_cs_probe, 1751 .remove = nsp_cs_detach, 1752 .id_table = nsp_cs_ids, 1753 .suspend = nsp_cs_suspend, 1754 .resume = nsp_cs_resume, 1755}; 1756module_pcmcia_driver(nsp_driver); 1757 1758/* end */ 1759