0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 #include <linux/module.h>
0071
0072 #include <linux/string.h>
0073 #include <linux/delay.h>
0074 #include <linux/init.h>
0075 #include <linux/interrupt.h>
0076 #include <linux/blkdev.h>
0077
0078 #include <scsi/scsi.h>
0079 #include <scsi/scsi_cmnd.h>
0080 #include <scsi/scsi_device.h>
0081 #include <scsi/scsi_host.h>
0082
0083 #include <asm/irq.h>
0084
0085 #include "wd33c93.h"
0086
0087 #define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns
0088
0089
0090 #define WD33C93_VERSION "1.26++"
0091 #define WD33C93_DATE "10/Feb/2007"
0092
0093 MODULE_AUTHOR("John Shifflett");
0094 MODULE_DESCRIPTION("Generic WD33C93 SCSI driver");
0095 MODULE_LICENSE("GPL");
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static char *setup_args[] = { "", "", "", "", "", "", "", "", "", "" };
0159
0160 static char *setup_strings;
0161 module_param(setup_strings, charp, 0);
0162
0163 static void wd33c93_execute(struct Scsi_Host *instance);
0164
0165 #ifdef CONFIG_WD33C93_PIO
0166 static inline uchar
0167 read_wd33c93(const wd33c93_regs regs, uchar reg_num)
0168 {
0169 uchar data;
0170
0171 outb(reg_num, regs.SASR);
0172 data = inb(regs.SCMD);
0173 return data;
0174 }
0175
0176 static inline unsigned long
0177 read_wd33c93_count(const wd33c93_regs regs)
0178 {
0179 unsigned long value;
0180
0181 outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
0182 value = inb(regs.SCMD) << 16;
0183 value |= inb(regs.SCMD) << 8;
0184 value |= inb(regs.SCMD);
0185 return value;
0186 }
0187
0188 static inline uchar
0189 read_aux_stat(const wd33c93_regs regs)
0190 {
0191 return inb(regs.SASR);
0192 }
0193
0194 static inline void
0195 write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
0196 {
0197 outb(reg_num, regs.SASR);
0198 outb(value, regs.SCMD);
0199 }
0200
0201 static inline void
0202 write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
0203 {
0204 outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
0205 outb((value >> 16) & 0xff, regs.SCMD);
0206 outb((value >> 8) & 0xff, regs.SCMD);
0207 outb( value & 0xff, regs.SCMD);
0208 }
0209
0210 #define write_wd33c93_cmd(regs, cmd) \
0211 write_wd33c93((regs), WD_COMMAND, (cmd))
0212
0213 static inline void
0214 write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
0215 {
0216 int i;
0217
0218 outb(WD_CDB_1, regs.SASR);
0219 for (i=0; i<len; i++)
0220 outb(cmnd[i], regs.SCMD);
0221 }
0222
0223 #else
0224 static inline uchar
0225 read_wd33c93(const wd33c93_regs regs, uchar reg_num)
0226 {
0227 *regs.SASR = reg_num;
0228 mb();
0229 return (*regs.SCMD);
0230 }
0231
0232 static unsigned long
0233 read_wd33c93_count(const wd33c93_regs regs)
0234 {
0235 unsigned long value;
0236
0237 *regs.SASR = WD_TRANSFER_COUNT_MSB;
0238 mb();
0239 value = *regs.SCMD << 16;
0240 value |= *regs.SCMD << 8;
0241 value |= *regs.SCMD;
0242 mb();
0243 return value;
0244 }
0245
0246 static inline uchar
0247 read_aux_stat(const wd33c93_regs regs)
0248 {
0249 return *regs.SASR;
0250 }
0251
0252 static inline void
0253 write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
0254 {
0255 *regs.SASR = reg_num;
0256 mb();
0257 *regs.SCMD = value;
0258 mb();
0259 }
0260
0261 static void
0262 write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
0263 {
0264 *regs.SASR = WD_TRANSFER_COUNT_MSB;
0265 mb();
0266 *regs.SCMD = value >> 16;
0267 *regs.SCMD = value >> 8;
0268 *regs.SCMD = value;
0269 mb();
0270 }
0271
0272 static inline void
0273 write_wd33c93_cmd(const wd33c93_regs regs, uchar cmd)
0274 {
0275 *regs.SASR = WD_COMMAND;
0276 mb();
0277 *regs.SCMD = cmd;
0278 mb();
0279 }
0280
0281 static inline void
0282 write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
0283 {
0284 int i;
0285
0286 *regs.SASR = WD_CDB_1;
0287 for (i = 0; i < len; i++)
0288 *regs.SCMD = cmnd[i];
0289 }
0290 #endif
0291
0292 static inline uchar
0293 read_1_byte(const wd33c93_regs regs)
0294 {
0295 uchar asr;
0296 uchar x = 0;
0297
0298 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
0299 write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO | 0x80);
0300 do {
0301 asr = read_aux_stat(regs);
0302 if (asr & ASR_DBR)
0303 x = read_wd33c93(regs, WD_DATA);
0304 } while (!(asr & ASR_INT));
0305 return x;
0306 }
0307
0308 static int
0309 round_period(unsigned int period, const struct sx_period *sx_table)
0310 {
0311 int x;
0312
0313 for (x = 1; sx_table[x].period_ns; x++) {
0314 if ((period <= sx_table[x - 0].period_ns) &&
0315 (period > sx_table[x - 1].period_ns)) {
0316 return x;
0317 }
0318 }
0319 return 7;
0320 }
0321
0322
0323
0324
0325 static uchar
0326 calc_sync_xfer(unsigned int period, unsigned int offset, unsigned int fast,
0327 const struct sx_period *sx_table)
0328 {
0329
0330
0331
0332 uchar result;
0333
0334 if (offset && fast) {
0335 fast = STR_FSS;
0336 period *= 2;
0337 } else {
0338 fast = 0;
0339 }
0340 period *= 4;
0341 result = sx_table[round_period(period,sx_table)].reg_value;
0342 result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
0343 result |= fast;
0344 return result;
0345 }
0346
0347
0348
0349
0350 static inline void
0351 calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast,
0352 uchar msg[2])
0353 {
0354
0355
0356
0357
0358 period /= 4;
0359 if (offset && fast)
0360 period /= 2;
0361 msg[0] = period;
0362 msg[1] = offset;
0363 }
0364
0365 static int wd33c93_queuecommand_lck(struct scsi_cmnd *cmd)
0366 {
0367 struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
0368 struct WD33C93_hostdata *hostdata;
0369 struct scsi_cmnd *tmp;
0370
0371 hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
0372
0373 DB(DB_QUEUE_COMMAND,
0374 printk("Q-%d-%02x( ", cmd->device->id, cmd->cmnd[0]))
0375
0376
0377
0378
0379
0380 cmd->host_scribble = NULL;
0381 cmd->result = 0;
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398 if (scsi_bufflen(cmd)) {
0399 scsi_pointer->buffer = scsi_sglist(cmd);
0400 scsi_pointer->buffers_residual = scsi_sg_count(cmd) - 1;
0401 scsi_pointer->ptr = sg_virt(scsi_pointer->buffer);
0402 scsi_pointer->this_residual = scsi_pointer->buffer->length;
0403 } else {
0404 scsi_pointer->buffer = NULL;
0405 scsi_pointer->buffers_residual = 0;
0406 scsi_pointer->ptr = NULL;
0407 scsi_pointer->this_residual = 0;
0408 }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 scsi_pointer->Status = ILLEGAL_STATUS_BYTE;
0428
0429
0430
0431
0432
0433
0434
0435 spin_lock_irq(&hostdata->lock);
0436
0437 if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
0438 cmd->host_scribble = (uchar *) hostdata->input_Q;
0439 hostdata->input_Q = cmd;
0440 } else {
0441 for (tmp = (struct scsi_cmnd *) hostdata->input_Q;
0442 tmp->host_scribble;
0443 tmp = (struct scsi_cmnd *) tmp->host_scribble) ;
0444 tmp->host_scribble = (uchar *) cmd;
0445 }
0446
0447
0448
0449
0450
0451 wd33c93_execute(cmd->device->host);
0452
0453 DB(DB_QUEUE_COMMAND, printk(")Q "))
0454
0455 spin_unlock_irq(&hostdata->lock);
0456 return 0;
0457 }
0458
0459 DEF_SCSI_QCMD(wd33c93_queuecommand)
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471 static void
0472 wd33c93_execute(struct Scsi_Host *instance)
0473 {
0474 struct scsi_pointer *scsi_pointer;
0475 struct WD33C93_hostdata *hostdata =
0476 (struct WD33C93_hostdata *) instance->hostdata;
0477 const wd33c93_regs regs = hostdata->regs;
0478 struct scsi_cmnd *cmd, *prev;
0479
0480 DB(DB_EXECUTE, printk("EX("))
0481 if (hostdata->selecting || hostdata->connected) {
0482 DB(DB_EXECUTE, printk(")EX-0 "))
0483 return;
0484 }
0485
0486
0487
0488
0489
0490
0491 cmd = (struct scsi_cmnd *) hostdata->input_Q;
0492 prev = NULL;
0493 while (cmd) {
0494 if (!(hostdata->busy[cmd->device->id] &
0495 (1 << (cmd->device->lun & 0xff))))
0496 break;
0497 prev = cmd;
0498 cmd = (struct scsi_cmnd *) cmd->host_scribble;
0499 }
0500
0501
0502
0503 if (!cmd) {
0504 DB(DB_EXECUTE, printk(")EX-1 "))
0505 return;
0506 }
0507
0508
0509
0510 if (prev)
0511 prev->host_scribble = cmd->host_scribble;
0512 else
0513 hostdata->input_Q = (struct scsi_cmnd *) cmd->host_scribble;
0514
0515 #ifdef PROC_STATISTICS
0516 hostdata->cmd_cnt[cmd->device->id]++;
0517 #endif
0518
0519
0520
0521
0522
0523 if (cmd->sc_data_direction == DMA_TO_DEVICE)
0524 write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
0525 else
0526 write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD);
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 scsi_pointer = WD33C93_scsi_pointer(cmd);
0552 scsi_pointer->phase = 0;
0553 if (hostdata->disconnect == DIS_NEVER)
0554 goto no;
0555 if (hostdata->disconnect == DIS_ALWAYS)
0556 goto yes;
0557 if (cmd->device->type == 1)
0558 goto yes;
0559 if (hostdata->disconnected_Q)
0560 goto yes;
0561 if (!(hostdata->input_Q))
0562 goto no;
0563 for (prev = (struct scsi_cmnd *) hostdata->input_Q; prev;
0564 prev = (struct scsi_cmnd *) prev->host_scribble) {
0565 if ((prev->device->id != cmd->device->id) ||
0566 (prev->device->lun != cmd->device->lun)) {
0567 for (prev = (struct scsi_cmnd *) hostdata->input_Q; prev;
0568 prev = (struct scsi_cmnd *) prev->host_scribble)
0569 WD33C93_scsi_pointer(prev)->phase = 1;
0570 goto yes;
0571 }
0572 }
0573
0574 goto no;
0575
0576 yes:
0577 scsi_pointer->phase = 1;
0578
0579 #ifdef PROC_STATISTICS
0580 hostdata->disc_allowed_cnt[cmd->device->id]++;
0581 #endif
0582
0583 no:
0584
0585 write_wd33c93(regs, WD_SOURCE_ID, scsi_pointer->phase ? SRCID_ER : 0);
0586
0587 write_wd33c93(regs, WD_TARGET_LUN, (u8)cmd->device->lun);
0588 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
0589 hostdata->sync_xfer[cmd->device->id]);
0590 hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
0591
0592 if ((hostdata->level2 == L2_NONE) ||
0593 (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) {
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603 hostdata->selecting = cmd;
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617 if (hostdata->sync_stat[cmd->device->id] == SS_UNSET)
0618 hostdata->sync_stat[cmd->device->id] = SS_FIRST;
0619 hostdata->state = S_SELECTING;
0620 write_wd33c93_count(regs, 0);
0621 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN);
0622 } else {
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632 hostdata->connected = cmd;
0633 write_wd33c93(regs, WD_COMMAND_PHASE, 0);
0634
0635
0636
0637
0638
0639 write_wd33c93_cdb(regs, cmd->cmd_len, cmd->cmnd);
0640
0641
0642
0643
0644
0645
0646
0647 write_wd33c93(regs, WD_OWN_ID, cmd->cmd_len);
0648
0649
0650
0651
0652
0653
0654 if (scsi_pointer->phase == 0 && hostdata->no_dma == 0) {
0655 if (hostdata->dma_setup(cmd,
0656 (cmd->sc_data_direction == DMA_TO_DEVICE) ?
0657 DATA_OUT_DIR : DATA_IN_DIR))
0658 write_wd33c93_count(regs, 0);
0659 else {
0660 write_wd33c93_count(regs,
0661 scsi_pointer->this_residual);
0662 write_wd33c93(regs, WD_CONTROL,
0663 CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
0664 hostdata->dma = D_DMA_RUNNING;
0665 }
0666 } else
0667 write_wd33c93_count(regs, 0);
0668
0669 hostdata->state = S_RUNNING_LEVEL2;
0670 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
0671 }
0672
0673
0674
0675
0676
0677
0678
0679
0680 DB(DB_EXECUTE,
0681 printk("%s)EX-2 ", scsi_pointer->phase ? "d:" : ""))
0682 }
0683
0684 static void
0685 transfer_pio(const wd33c93_regs regs, uchar * buf, int cnt,
0686 int data_in_dir, struct WD33C93_hostdata *hostdata)
0687 {
0688 uchar asr;
0689
0690 DB(DB_TRANSFER,
0691 printk("(%p,%d,%s:", buf, cnt, data_in_dir ? "in" : "out"))
0692
0693 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
0694 write_wd33c93_count(regs, cnt);
0695 write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO);
0696 if (data_in_dir) {
0697 do {
0698 asr = read_aux_stat(regs);
0699 if (asr & ASR_DBR)
0700 *buf++ = read_wd33c93(regs, WD_DATA);
0701 } while (!(asr & ASR_INT));
0702 } else {
0703 do {
0704 asr = read_aux_stat(regs);
0705 if (asr & ASR_DBR)
0706 write_wd33c93(regs, WD_DATA, *buf++);
0707 } while (!(asr & ASR_INT));
0708 }
0709
0710
0711
0712
0713
0714
0715
0716
0717 }
0718
0719 static void
0720 transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
0721 int data_in_dir)
0722 {
0723 struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
0724 struct WD33C93_hostdata *hostdata;
0725 unsigned long length;
0726
0727 hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737 if (!scsi_pointer->this_residual && scsi_pointer->buffers_residual) {
0738 scsi_pointer->buffer = sg_next(scsi_pointer->buffer);
0739 --scsi_pointer->buffers_residual;
0740 scsi_pointer->this_residual = scsi_pointer->buffer->length;
0741 scsi_pointer->ptr = sg_virt(scsi_pointer->buffer);
0742 }
0743 if (!scsi_pointer->this_residual)
0744 return;
0745
0746 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
0747 hostdata->sync_xfer[cmd->device->id]);
0748
0749
0750
0751
0752
0753 if (hostdata->no_dma || hostdata->dma_setup(cmd, data_in_dir)) {
0754 #ifdef PROC_STATISTICS
0755 hostdata->pio_cnt++;
0756 #endif
0757 transfer_pio(regs, (uchar *) scsi_pointer->ptr,
0758 scsi_pointer->this_residual, data_in_dir,
0759 hostdata);
0760 length = scsi_pointer->this_residual;
0761 scsi_pointer->this_residual = read_wd33c93_count(regs);
0762 scsi_pointer->ptr += length - scsi_pointer->this_residual;
0763 }
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774 else {
0775 #ifdef PROC_STATISTICS
0776 hostdata->dma_cnt++;
0777 #endif
0778 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
0779 write_wd33c93_count(regs, scsi_pointer->this_residual);
0780
0781 if ((hostdata->level2 >= L2_DATA) ||
0782 (hostdata->level2 == L2_BASIC && scsi_pointer->phase == 0)) {
0783 write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
0784 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
0785 hostdata->state = S_RUNNING_LEVEL2;
0786 } else
0787 write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO);
0788
0789 hostdata->dma = D_DMA_RUNNING;
0790 }
0791 }
0792
0793 void
0794 wd33c93_intr(struct Scsi_Host *instance)
0795 {
0796 struct scsi_pointer *scsi_pointer;
0797 struct WD33C93_hostdata *hostdata =
0798 (struct WD33C93_hostdata *) instance->hostdata;
0799 const wd33c93_regs regs = hostdata->regs;
0800 struct scsi_cmnd *patch, *cmd;
0801 uchar asr, sr, phs, id, lun, *ucp, msg;
0802 unsigned long length, flags;
0803
0804 asr = read_aux_stat(regs);
0805 if (!(asr & ASR_INT) || (asr & ASR_BSY))
0806 return;
0807
0808 spin_lock_irqsave(&hostdata->lock, flags);
0809
0810 #ifdef PROC_STATISTICS
0811 hostdata->int_cnt++;
0812 #endif
0813
0814 cmd = (struct scsi_cmnd *) hostdata->connected;
0815 scsi_pointer = WD33C93_scsi_pointer(cmd);
0816 sr = read_wd33c93(regs, WD_SCSI_STATUS);
0817 phs = read_wd33c93(regs, WD_COMMAND_PHASE);
0818
0819 DB(DB_INTR, printk("{%02x:%02x-", asr, sr))
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835 if (hostdata->dma == D_DMA_RUNNING) {
0836 DB(DB_TRANSFER,
0837 printk("[%p/%d:", scsi_pointer->ptr, scsi_pointer->this_residual))
0838 hostdata->dma_stop(cmd->device->host, cmd, 1);
0839 hostdata->dma = D_DMA_OFF;
0840 length = scsi_pointer->this_residual;
0841 scsi_pointer->this_residual = read_wd33c93_count(regs);
0842 scsi_pointer->ptr += length - scsi_pointer->this_residual;
0843 DB(DB_TRANSFER,
0844 printk("%p/%d]", scsi_pointer->ptr, scsi_pointer->this_residual))
0845 }
0846
0847
0848 switch (sr) {
0849 case CSR_TIMEOUT:
0850 DB(DB_INTR, printk("TIMEOUT"))
0851
0852 if (hostdata->state == S_RUNNING_LEVEL2)
0853 hostdata->connected = NULL;
0854 else {
0855 cmd = (struct scsi_cmnd *) hostdata->selecting;
0856 hostdata->selecting = NULL;
0857 }
0858
0859 cmd->result = DID_NO_CONNECT << 16;
0860 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
0861 hostdata->state = S_UNCONNECTED;
0862 scsi_done(cmd);
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874 spin_unlock_irqrestore(&hostdata->lock, flags);
0875
0876
0877
0878
0879
0880 wd33c93_execute(instance);
0881 break;
0882
0883
0884
0885 case CSR_SELECT:
0886 DB(DB_INTR, printk("SELECT"))
0887 hostdata->connected = cmd =
0888 (struct scsi_cmnd *) hostdata->selecting;
0889 hostdata->selecting = NULL;
0890
0891
0892
0893 hostdata->outgoing_msg[0] = IDENTIFY(0, cmd->device->lun);
0894 if (scsi_pointer->phase)
0895 hostdata->outgoing_msg[0] |= 0x40;
0896
0897 if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
0898
0899 hostdata->sync_stat[cmd->device->id] = SS_WAITING;
0900
0901
0902
0903
0904
0905
0906
0907 hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
0908 hostdata->outgoing_msg[2] = 3;
0909 hostdata->outgoing_msg[3] = EXTENDED_SDTR;
0910 if (hostdata->no_sync & (1 << cmd->device->id)) {
0911 calc_sync_msg(hostdata->default_sx_per, 0,
0912 0, hostdata->outgoing_msg + 4);
0913 } else {
0914 calc_sync_msg(optimum_sx_per(hostdata),
0915 OPTIMUM_SX_OFF,
0916 hostdata->fast,
0917 hostdata->outgoing_msg + 4);
0918 }
0919 hostdata->outgoing_len = 6;
0920 #ifdef SYNC_DEBUG
0921 ucp = hostdata->outgoing_msg + 1;
0922 printk(" sending SDTR %02x03%02x%02x%02x ",
0923 ucp[0], ucp[2], ucp[3], ucp[4]);
0924 #endif
0925 } else
0926 hostdata->outgoing_len = 1;
0927
0928 hostdata->state = S_CONNECTED;
0929 spin_unlock_irqrestore(&hostdata->lock, flags);
0930 break;
0931
0932 case CSR_XFER_DONE | PHS_DATA_IN:
0933 case CSR_UNEXP | PHS_DATA_IN:
0934 case CSR_SRV_REQ | PHS_DATA_IN:
0935 DB(DB_INTR,
0936 printk("IN-%d.%d", scsi_pointer->this_residual,
0937 scsi_pointer->buffers_residual))
0938 transfer_bytes(regs, cmd, DATA_IN_DIR);
0939 if (hostdata->state != S_RUNNING_LEVEL2)
0940 hostdata->state = S_CONNECTED;
0941 spin_unlock_irqrestore(&hostdata->lock, flags);
0942 break;
0943
0944 case CSR_XFER_DONE | PHS_DATA_OUT:
0945 case CSR_UNEXP | PHS_DATA_OUT:
0946 case CSR_SRV_REQ | PHS_DATA_OUT:
0947 DB(DB_INTR,
0948 printk("OUT-%d.%d", scsi_pointer->this_residual,
0949 scsi_pointer->buffers_residual))
0950 transfer_bytes(regs, cmd, DATA_OUT_DIR);
0951 if (hostdata->state != S_RUNNING_LEVEL2)
0952 hostdata->state = S_CONNECTED;
0953 spin_unlock_irqrestore(&hostdata->lock, flags);
0954 break;
0955
0956
0957
0958 case CSR_XFER_DONE | PHS_COMMAND:
0959 case CSR_UNEXP | PHS_COMMAND:
0960 case CSR_SRV_REQ | PHS_COMMAND:
0961 DB(DB_INTR, printk("CMND-%02x", cmd->cmnd[0]))
0962 transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR,
0963 hostdata);
0964 hostdata->state = S_CONNECTED;
0965 spin_unlock_irqrestore(&hostdata->lock, flags);
0966 break;
0967
0968 case CSR_XFER_DONE | PHS_STATUS:
0969 case CSR_UNEXP | PHS_STATUS:
0970 case CSR_SRV_REQ | PHS_STATUS:
0971 DB(DB_INTR, printk("STATUS="))
0972 scsi_pointer->Status = read_1_byte(regs);
0973 DB(DB_INTR, printk("%02x", scsi_pointer->Status))
0974 if (hostdata->level2 >= L2_BASIC) {
0975 sr = read_wd33c93(regs, WD_SCSI_STATUS);
0976 udelay(7);
0977 hostdata->state = S_RUNNING_LEVEL2;
0978 write_wd33c93(regs, WD_COMMAND_PHASE, 0x50);
0979 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
0980 } else {
0981 hostdata->state = S_CONNECTED;
0982 }
0983 spin_unlock_irqrestore(&hostdata->lock, flags);
0984 break;
0985
0986 case CSR_XFER_DONE | PHS_MESS_IN:
0987 case CSR_UNEXP | PHS_MESS_IN:
0988 case CSR_SRV_REQ | PHS_MESS_IN:
0989 DB(DB_INTR, printk("MSG_IN="))
0990
0991 msg = read_1_byte(regs);
0992 sr = read_wd33c93(regs, WD_SCSI_STATUS);
0993 udelay(7);
0994
0995 hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
0996 if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
0997 msg = EXTENDED_MESSAGE;
0998 else
0999 hostdata->incoming_ptr = 0;
1000
1001 scsi_pointer->Message = msg;
1002 switch (msg) {
1003
1004 case COMMAND_COMPLETE:
1005 DB(DB_INTR, printk("CCMP"))
1006 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1007 hostdata->state = S_PRE_CMP_DISC;
1008 break;
1009
1010 case SAVE_POINTERS:
1011 DB(DB_INTR, printk("SDP"))
1012 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1013 hostdata->state = S_CONNECTED;
1014 break;
1015
1016 case RESTORE_POINTERS:
1017 DB(DB_INTR, printk("RDP"))
1018 if (hostdata->level2 >= L2_BASIC) {
1019 write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
1020 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
1021 hostdata->state = S_RUNNING_LEVEL2;
1022 } else {
1023 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1024 hostdata->state = S_CONNECTED;
1025 }
1026 break;
1027
1028 case DISCONNECT:
1029 DB(DB_INTR, printk("DIS"))
1030 cmd->device->disconnect = 1;
1031 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1032 hostdata->state = S_PRE_TMP_DISC;
1033 break;
1034
1035 case MESSAGE_REJECT:
1036 DB(DB_INTR, printk("REJ"))
1037 #ifdef SYNC_DEBUG
1038 printk("-REJ-");
1039 #endif
1040 if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) {
1041 hostdata->sync_stat[cmd->device->id] = SS_SET;
1042
1043 hostdata->sync_xfer[cmd->device->id] =
1044 calc_sync_xfer(hostdata->default_sx_per
1045 / 4, 0, 0, hostdata->sx_table);
1046 }
1047 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1048 hostdata->state = S_CONNECTED;
1049 break;
1050
1051 case EXTENDED_MESSAGE:
1052 DB(DB_INTR, printk("EXT"))
1053
1054 ucp = hostdata->incoming_msg;
1055
1056 #ifdef SYNC_DEBUG
1057 printk("%02x", ucp[hostdata->incoming_ptr]);
1058 #endif
1059
1060
1061 if ((hostdata->incoming_ptr >= 2) &&
1062 (hostdata->incoming_ptr == (ucp[1] + 1))) {
1063
1064 switch (ucp[2]) {
1065 case EXTENDED_SDTR:
1066
1067 id = calc_sync_xfer(hostdata->
1068 default_sx_per / 4, 0,
1069 0, hostdata->sx_table);
1070 if (hostdata->sync_stat[cmd->device->id] !=
1071 SS_WAITING) {
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN);
1083 hostdata->outgoing_msg[0] =
1084 EXTENDED_MESSAGE;
1085 hostdata->outgoing_msg[1] = 3;
1086 hostdata->outgoing_msg[2] =
1087 EXTENDED_SDTR;
1088 calc_sync_msg(hostdata->
1089 default_sx_per, 0,
1090 0, hostdata->outgoing_msg + 3);
1091 hostdata->outgoing_len = 5;
1092 } else {
1093 if (ucp[4])
1094 id = calc_sync_xfer(ucp[3], ucp[4],
1095 hostdata->fast,
1096 hostdata->sx_table);
1097 else if (ucp[3])
1098 id = calc_sync_xfer(ucp[3], ucp[4],
1099 0, hostdata->sx_table);
1100 }
1101 hostdata->sync_xfer[cmd->device->id] = id;
1102 #ifdef SYNC_DEBUG
1103 printk(" sync_xfer=%02x\n",
1104 hostdata->sync_xfer[cmd->device->id]);
1105 #endif
1106 hostdata->sync_stat[cmd->device->id] =
1107 SS_SET;
1108 write_wd33c93_cmd(regs,
1109 WD_CMD_NEGATE_ACK);
1110 hostdata->state = S_CONNECTED;
1111 break;
1112 case EXTENDED_WDTR:
1113 write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN);
1114 printk("sending WDTR ");
1115 hostdata->outgoing_msg[0] =
1116 EXTENDED_MESSAGE;
1117 hostdata->outgoing_msg[1] = 2;
1118 hostdata->outgoing_msg[2] =
1119 EXTENDED_WDTR;
1120 hostdata->outgoing_msg[3] = 0;
1121 hostdata->outgoing_len = 4;
1122 write_wd33c93_cmd(regs,
1123 WD_CMD_NEGATE_ACK);
1124 hostdata->state = S_CONNECTED;
1125 break;
1126 default:
1127 write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN);
1128 printk
1129 ("Rejecting Unknown Extended Message(%02x). ",
1130 ucp[2]);
1131 hostdata->outgoing_msg[0] =
1132 MESSAGE_REJECT;
1133 hostdata->outgoing_len = 1;
1134 write_wd33c93_cmd(regs,
1135 WD_CMD_NEGATE_ACK);
1136 hostdata->state = S_CONNECTED;
1137 break;
1138 }
1139 hostdata->incoming_ptr = 0;
1140 }
1141
1142
1143
1144 else {
1145 hostdata->incoming_ptr++;
1146 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1147 hostdata->state = S_CONNECTED;
1148 }
1149 break;
1150
1151 default:
1152 printk("Rejecting Unknown Message(%02x) ", msg);
1153 write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN);
1154 hostdata->outgoing_msg[0] = MESSAGE_REJECT;
1155 hostdata->outgoing_len = 1;
1156 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1157 hostdata->state = S_CONNECTED;
1158 }
1159 spin_unlock_irqrestore(&hostdata->lock, flags);
1160 break;
1161
1162
1163
1164 case CSR_SEL_XFER_DONE:
1165
1166
1167
1168
1169
1170 write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
1171 if (phs == 0x60) {
1172 DB(DB_INTR, printk("SX-DONE"))
1173 scsi_pointer->Message = COMMAND_COMPLETE;
1174 lun = read_wd33c93(regs, WD_TARGET_LUN);
1175 DB(DB_INTR, printk(":%d.%d", scsi_pointer->Status, lun))
1176 hostdata->connected = NULL;
1177 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1178 hostdata->state = S_UNCONNECTED;
1179 if (scsi_pointer->Status == ILLEGAL_STATUS_BYTE)
1180 scsi_pointer->Status = lun;
1181 if (cmd->cmnd[0] == REQUEST_SENSE
1182 && scsi_pointer->Status != SAM_STAT_GOOD) {
1183 set_host_byte(cmd, DID_ERROR);
1184 } else {
1185 set_host_byte(cmd, DID_OK);
1186 scsi_msg_to_host_byte(cmd, scsi_pointer->Message);
1187 set_status_byte(cmd, scsi_pointer->Status);
1188 }
1189 scsi_done(cmd);
1190
1191
1192
1193
1194 spin_unlock_irqrestore(&hostdata->lock, flags);
1195 wd33c93_execute(instance);
1196 } else {
1197 printk
1198 ("%02x:%02x:%02x: Unknown SEL_XFER_DONE phase!!---",
1199 asr, sr, phs);
1200 spin_unlock_irqrestore(&hostdata->lock, flags);
1201 }
1202 break;
1203
1204
1205
1206 case CSR_SDP:
1207 DB(DB_INTR, printk("SDP"))
1208 hostdata->state = S_RUNNING_LEVEL2;
1209 write_wd33c93(regs, WD_COMMAND_PHASE, 0x41);
1210 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
1211 spin_unlock_irqrestore(&hostdata->lock, flags);
1212 break;
1213
1214 case CSR_XFER_DONE | PHS_MESS_OUT:
1215 case CSR_UNEXP | PHS_MESS_OUT:
1216 case CSR_SRV_REQ | PHS_MESS_OUT:
1217 DB(DB_INTR, printk("MSG_OUT="))
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231 if (hostdata->outgoing_len == 0) {
1232 hostdata->outgoing_len = 1;
1233 hostdata->outgoing_msg[0] = NOP;
1234 }
1235 transfer_pio(regs, hostdata->outgoing_msg,
1236 hostdata->outgoing_len, DATA_OUT_DIR, hostdata);
1237 DB(DB_INTR, printk("%02x", hostdata->outgoing_msg[0]))
1238 hostdata->outgoing_len = 0;
1239 hostdata->state = S_CONNECTED;
1240 spin_unlock_irqrestore(&hostdata->lock, flags);
1241 break;
1242
1243 case CSR_UNEXP_DISC:
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257 write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
1258 if (cmd == NULL) {
1259 printk(" - Already disconnected! ");
1260 hostdata->state = S_UNCONNECTED;
1261 spin_unlock_irqrestore(&hostdata->lock, flags);
1262 return;
1263 }
1264 DB(DB_INTR, printk("UNEXP_DISC"))
1265 hostdata->connected = NULL;
1266 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1267 hostdata->state = S_UNCONNECTED;
1268 if (cmd->cmnd[0] == REQUEST_SENSE &&
1269 scsi_pointer->Status != SAM_STAT_GOOD) {
1270 set_host_byte(cmd, DID_ERROR);
1271 } else {
1272 set_host_byte(cmd, DID_OK);
1273 scsi_msg_to_host_byte(cmd, scsi_pointer->Message);
1274 set_status_byte(cmd, scsi_pointer->Status);
1275 }
1276 scsi_done(cmd);
1277
1278
1279
1280
1281
1282 spin_unlock_irqrestore(&hostdata->lock, flags);
1283 wd33c93_execute(instance);
1284 break;
1285
1286 case CSR_DISC:
1287
1288
1289
1290
1291
1292 write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
1293 DB(DB_INTR, printk("DISC"))
1294 if (cmd == NULL) {
1295 printk(" - Already disconnected! ");
1296 hostdata->state = S_UNCONNECTED;
1297 }
1298 switch (hostdata->state) {
1299 case S_PRE_CMP_DISC:
1300 hostdata->connected = NULL;
1301 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1302 hostdata->state = S_UNCONNECTED;
1303 DB(DB_INTR, printk(":%d", scsi_pointer->Status))
1304 if (cmd->cmnd[0] == REQUEST_SENSE
1305 && scsi_pointer->Status != SAM_STAT_GOOD) {
1306 set_host_byte(cmd, DID_ERROR);
1307 } else {
1308 set_host_byte(cmd, DID_OK);
1309 scsi_msg_to_host_byte(cmd, scsi_pointer->Message);
1310 set_status_byte(cmd, scsi_pointer->Status);
1311 }
1312 scsi_done(cmd);
1313 break;
1314 case S_PRE_TMP_DISC:
1315 case S_RUNNING_LEVEL2:
1316 cmd->host_scribble = (uchar *) hostdata->disconnected_Q;
1317 hostdata->disconnected_Q = cmd;
1318 hostdata->connected = NULL;
1319 hostdata->state = S_UNCONNECTED;
1320
1321 #ifdef PROC_STATISTICS
1322 hostdata->disc_done_cnt[cmd->device->id]++;
1323 #endif
1324
1325 break;
1326 default:
1327 printk("*** Unexpected DISCONNECT interrupt! ***");
1328 hostdata->state = S_UNCONNECTED;
1329 }
1330
1331
1332
1333
1334 spin_unlock_irqrestore(&hostdata->lock, flags);
1335 wd33c93_execute(instance);
1336 break;
1337
1338 case CSR_RESEL_AM:
1339 case CSR_RESEL:
1340 DB(DB_INTR, printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
1341
1342
1343
1344
1345
1346
1347
1348
1349 if (hostdata->level2 <= L2_NONE) {
1350
1351 if (hostdata->selecting) {
1352 cmd = (struct scsi_cmnd *) hostdata->selecting;
1353 hostdata->selecting = NULL;
1354 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1355 cmd->host_scribble =
1356 (uchar *) hostdata->input_Q;
1357 hostdata->input_Q = cmd;
1358 }
1359 }
1360
1361 else {
1362
1363 if (cmd) {
1364 if (phs == 0x00) {
1365 hostdata->busy[cmd->device->id] &=
1366 ~(1 << (cmd->device->lun & 0xff));
1367 cmd->host_scribble =
1368 (uchar *) hostdata->input_Q;
1369 hostdata->input_Q = cmd;
1370 } else {
1371 printk
1372 ("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",
1373 asr, sr, phs);
1374 while (1)
1375 printk("\r");
1376 }
1377 }
1378
1379 }
1380
1381
1382
1383 id = read_wd33c93(regs, WD_SOURCE_ID);
1384 id &= SRCID_MASK;
1385
1386
1387
1388
1389
1390
1391 if (sr == CSR_RESEL_AM) {
1392 lun = read_wd33c93(regs, WD_DATA);
1393 if (hostdata->level2 < L2_RESELECT)
1394 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1395 lun &= 7;
1396 } else {
1397
1398 for (lun = 255; lun; lun--) {
1399 if ((asr = read_aux_stat(regs)) & ASR_INT)
1400 break;
1401 udelay(10);
1402 }
1403 if (!(asr & ASR_INT)) {
1404 printk
1405 ("wd33c93: Reselected without IDENTIFY\n");
1406 lun = 0;
1407 } else {
1408
1409 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1410 udelay(7);
1411 if (sr == (CSR_ABORT | PHS_MESS_IN) ||
1412 sr == (CSR_UNEXP | PHS_MESS_IN) ||
1413 sr == (CSR_SRV_REQ | PHS_MESS_IN)) {
1414
1415 lun = read_1_byte(regs);
1416
1417 asr = read_aux_stat(regs);
1418 if (!(asr & ASR_INT)) {
1419 udelay(10);
1420 asr = read_aux_stat(regs);
1421 if (!(asr & ASR_INT))
1422 printk
1423 ("wd33c93: No int after LUN on RESEL (%02x)\n",
1424 asr);
1425 }
1426 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1427 udelay(7);
1428 if (sr != CSR_MSGIN)
1429 printk
1430 ("wd33c93: Not paused with ACK on RESEL (%02x)\n",
1431 sr);
1432 lun &= 7;
1433 write_wd33c93_cmd(regs,
1434 WD_CMD_NEGATE_ACK);
1435 } else {
1436 printk
1437 ("wd33c93: Not MSG_IN on reselect (%02x)\n",
1438 sr);
1439 lun = 0;
1440 }
1441 }
1442 }
1443
1444
1445
1446 cmd = (struct scsi_cmnd *) hostdata->disconnected_Q;
1447 patch = NULL;
1448 while (cmd) {
1449 if (id == cmd->device->id && lun == (u8)cmd->device->lun)
1450 break;
1451 patch = cmd;
1452 cmd = (struct scsi_cmnd *) cmd->host_scribble;
1453 }
1454
1455
1456
1457 if (!cmd) {
1458 printk
1459 ("---TROUBLE: target %d.%d not in disconnect queue---",
1460 id, (u8)lun);
1461 spin_unlock_irqrestore(&hostdata->lock, flags);
1462 return;
1463 }
1464
1465
1466
1467 if (patch)
1468 patch->host_scribble = cmd->host_scribble;
1469 else
1470 hostdata->disconnected_Q =
1471 (struct scsi_cmnd *) cmd->host_scribble;
1472 hostdata->connected = cmd;
1473
1474
1475
1476
1477
1478
1479 if (cmd->sc_data_direction == DMA_TO_DEVICE)
1480 write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
1481 else
1482 write_wd33c93(regs, WD_DESTINATION_ID,
1483 cmd->device->id | DSTID_DPD);
1484 if (hostdata->level2 >= L2_RESELECT) {
1485 write_wd33c93_count(regs, 0);
1486 write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
1487 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
1488 hostdata->state = S_RUNNING_LEVEL2;
1489 } else
1490 hostdata->state = S_CONNECTED;
1491
1492 spin_unlock_irqrestore(&hostdata->lock, flags);
1493 break;
1494
1495 default:
1496 printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
1497 spin_unlock_irqrestore(&hostdata->lock, flags);
1498 }
1499
1500 DB(DB_INTR, printk("} "))
1501
1502 }
1503
1504 static void
1505 reset_wd33c93(struct Scsi_Host *instance)
1506 {
1507 struct WD33C93_hostdata *hostdata =
1508 (struct WD33C93_hostdata *) instance->hostdata;
1509 const wd33c93_regs regs = hostdata->regs;
1510 uchar sr;
1511
1512 #ifdef CONFIG_SGI_IP22
1513 {
1514 int busycount = 0;
1515 extern void sgiwd93_reset(unsigned long);
1516
1517 while ((read_aux_stat(regs) & ASR_BSY) && busycount++ < 100)
1518 udelay (10);
1519
1520
1521
1522
1523
1524
1525
1526
1527 if (read_aux_stat(regs) & ASR_BSY)
1528 sgiwd93_reset(instance->base);
1529 }
1530 #endif
1531
1532 write_wd33c93(regs, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
1533 instance->this_id | hostdata->clock_freq);
1534 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1535 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
1536 calc_sync_xfer(hostdata->default_sx_per / 4,
1537 DEFAULT_SX_OFF, 0, hostdata->sx_table));
1538 write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
1539
1540
1541 #ifdef CONFIG_MVME147_SCSI
1542 udelay(25);
1543 #endif
1544
1545 while (!(read_aux_stat(regs) & ASR_INT))
1546 ;
1547 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1548
1549 hostdata->microcode = read_wd33c93(regs, WD_CDB_1);
1550 if (sr == 0x00)
1551 hostdata->chip = C_WD33C93;
1552 else if (sr == 0x01) {
1553 write_wd33c93(regs, WD_QUEUE_TAG, 0xa5);
1554 sr = read_wd33c93(regs, WD_QUEUE_TAG);
1555 if (sr == 0xa5) {
1556 hostdata->chip = C_WD33C93B;
1557 write_wd33c93(regs, WD_QUEUE_TAG, 0);
1558 } else
1559 hostdata->chip = C_WD33C93A;
1560 } else
1561 hostdata->chip = C_UNKNOWN_CHIP;
1562
1563 if (hostdata->chip != C_WD33C93B)
1564 hostdata->fast = 0;
1565
1566 write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
1567 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1568 }
1569
1570 int
1571 wd33c93_host_reset(struct scsi_cmnd * SCpnt)
1572 {
1573 struct Scsi_Host *instance;
1574 struct WD33C93_hostdata *hostdata;
1575 int i;
1576
1577 instance = SCpnt->device->host;
1578 spin_lock_irq(instance->host_lock);
1579 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1580
1581 printk("scsi%d: reset. ", instance->host_no);
1582 disable_irq(instance->irq);
1583
1584 hostdata->dma_stop(instance, NULL, 0);
1585 for (i = 0; i < 8; i++) {
1586 hostdata->busy[i] = 0;
1587 hostdata->sync_xfer[i] =
1588 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
1589 0, hostdata->sx_table);
1590 hostdata->sync_stat[i] = SS_UNSET;
1591 }
1592 hostdata->input_Q = NULL;
1593 hostdata->selecting = NULL;
1594 hostdata->connected = NULL;
1595 hostdata->disconnected_Q = NULL;
1596 hostdata->state = S_UNCONNECTED;
1597 hostdata->dma = D_DMA_OFF;
1598 hostdata->incoming_ptr = 0;
1599 hostdata->outgoing_len = 0;
1600
1601 reset_wd33c93(instance);
1602 SCpnt->result = DID_RESET << 16;
1603 enable_irq(instance->irq);
1604 spin_unlock_irq(instance->host_lock);
1605 return SUCCESS;
1606 }
1607
1608 int
1609 wd33c93_abort(struct scsi_cmnd * cmd)
1610 {
1611 struct Scsi_Host *instance;
1612 struct WD33C93_hostdata *hostdata;
1613 wd33c93_regs regs;
1614 struct scsi_cmnd *tmp, *prev;
1615
1616 disable_irq(cmd->device->host->irq);
1617
1618 instance = cmd->device->host;
1619 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1620 regs = hostdata->regs;
1621
1622
1623
1624
1625
1626
1627 tmp = (struct scsi_cmnd *) hostdata->input_Q;
1628 prev = NULL;
1629 while (tmp) {
1630 if (tmp == cmd) {
1631 if (prev)
1632 prev->host_scribble = cmd->host_scribble;
1633 else
1634 hostdata->input_Q =
1635 (struct scsi_cmnd *) cmd->host_scribble;
1636 cmd->host_scribble = NULL;
1637 cmd->result = DID_ABORT << 16;
1638 printk
1639 ("scsi%d: Abort - removing command from input_Q. ",
1640 instance->host_no);
1641 enable_irq(cmd->device->host->irq);
1642 scsi_done(cmd);
1643 return SUCCESS;
1644 }
1645 prev = tmp;
1646 tmp = (struct scsi_cmnd *) tmp->host_scribble;
1647 }
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660 if (hostdata->connected == cmd) {
1661 uchar sr, asr;
1662 unsigned long timeout;
1663
1664 printk("scsi%d: Aborting connected command - ",
1665 instance->host_no);
1666
1667 printk("stopping DMA - ");
1668 if (hostdata->dma == D_DMA_RUNNING) {
1669 hostdata->dma_stop(instance, cmd, 0);
1670 hostdata->dma = D_DMA_OFF;
1671 }
1672
1673 printk("sending wd33c93 ABORT command - ");
1674 write_wd33c93(regs, WD_CONTROL,
1675 CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1676 write_wd33c93_cmd(regs, WD_CMD_ABORT);
1677
1678
1679
1680 printk("flushing fifo - ");
1681 timeout = 1000000;
1682 do {
1683 asr = read_aux_stat(regs);
1684 if (asr & ASR_DBR)
1685 read_wd33c93(regs, WD_DATA);
1686 } while (!(asr & ASR_INT) && timeout-- > 0);
1687 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1688 printk
1689 ("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
1690 asr, sr, read_wd33c93_count(regs), timeout);
1691
1692
1693
1694
1695
1696
1697
1698 printk("sending wd33c93 DISCONNECT command - ");
1699 write_wd33c93_cmd(regs, WD_CMD_DISCONNECT);
1700
1701 timeout = 1000000;
1702 asr = read_aux_stat(regs);
1703 while ((asr & ASR_CIP) && timeout-- > 0)
1704 asr = read_aux_stat(regs);
1705 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1706 printk("asr=%02x, sr=%02x.", asr, sr);
1707
1708 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1709 hostdata->connected = NULL;
1710 hostdata->state = S_UNCONNECTED;
1711 cmd->result = DID_ABORT << 16;
1712
1713
1714 wd33c93_execute(instance);
1715
1716 enable_irq(cmd->device->host->irq);
1717 scsi_done(cmd);
1718 return SUCCESS;
1719 }
1720
1721
1722
1723
1724
1725
1726
1727 tmp = (struct scsi_cmnd *) hostdata->disconnected_Q;
1728 while (tmp) {
1729 if (tmp == cmd) {
1730 printk
1731 ("scsi%d: Abort - command found on disconnected_Q - ",
1732 instance->host_no);
1733 printk("Abort SNOOZE. ");
1734 enable_irq(cmd->device->host->irq);
1735 return FAILED;
1736 }
1737 tmp = (struct scsi_cmnd *) tmp->host_scribble;
1738 }
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751 wd33c93_execute(instance);
1752
1753 enable_irq(cmd->device->host->irq);
1754 printk("scsi%d: warning : SCSI command probably completed successfully"
1755 " before abortion. ", instance->host_no);
1756 return FAILED;
1757 }
1758
1759 #define MAX_WD33C93_HOSTS 4
1760 #define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
1761 #define SETUP_BUFFER_SIZE 200
1762 static char setup_buffer[SETUP_BUFFER_SIZE];
1763 static char setup_used[MAX_SETUP_ARGS];
1764 static int done_setup = 0;
1765
1766 static int
1767 wd33c93_setup(char *str)
1768 {
1769 int i;
1770 char *p1, *p2;
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781 p1 = setup_buffer;
1782 *p1 = '\0';
1783 if (str)
1784 strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
1785 setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
1786 p1 = setup_buffer;
1787 i = 0;
1788 while (*p1 && (i < MAX_SETUP_ARGS)) {
1789 p2 = strchr(p1, ',');
1790 if (p2) {
1791 *p2 = '\0';
1792 if (p1 != p2)
1793 setup_args[i] = p1;
1794 p1 = p2 + 1;
1795 i++;
1796 } else {
1797 setup_args[i] = p1;
1798 break;
1799 }
1800 }
1801 for (i = 0; i < MAX_SETUP_ARGS; i++)
1802 setup_used[i] = 0;
1803 done_setup = 1;
1804
1805 return 1;
1806 }
1807 __setup("wd33c93=", wd33c93_setup);
1808
1809
1810
1811 static int
1812 check_setup_args(char *key, int *flags, int *val, char *buf)
1813 {
1814 int x;
1815 char *cp;
1816
1817 for (x = 0; x < MAX_SETUP_ARGS; x++) {
1818 if (setup_used[x])
1819 continue;
1820 if (!strncmp(setup_args[x], key, strlen(key)))
1821 break;
1822 if (!strncmp(setup_args[x], "next", strlen("next")))
1823 return 0;
1824 }
1825 if (x == MAX_SETUP_ARGS)
1826 return 0;
1827 setup_used[x] = 1;
1828 cp = setup_args[x] + strlen(key);
1829 *val = -1;
1830 if (*cp != ':')
1831 return ++x;
1832 cp++;
1833 if ((*cp >= '0') && (*cp <= '9')) {
1834 *val = simple_strtoul(cp, NULL, 0);
1835 }
1836 return ++x;
1837 }
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856 static inline unsigned int
1857 round_4(unsigned int x)
1858 {
1859 switch (x & 3) {
1860 case 1: --x;
1861 break;
1862 case 2: ++x;
1863 fallthrough;
1864 case 3: ++x;
1865 }
1866 return x;
1867 }
1868
1869 static void
1870 calc_sx_table(unsigned int mhz, struct sx_period sx_table[9])
1871 {
1872 unsigned int d, i;
1873 if (mhz < 11)
1874 d = 2;
1875 else if (mhz < 16)
1876 d = 3;
1877 else
1878 d = 4;
1879
1880 d = (100000 * d) / 2 / mhz;
1881
1882 sx_table[0].period_ns = 1;
1883 sx_table[0].reg_value = 0x20;
1884 for (i = 1; i < 8; i++) {
1885 sx_table[i].period_ns = round_4((i+1)*d / 100);
1886 sx_table[i].reg_value = (i+1)*0x10;
1887 }
1888 sx_table[7].reg_value = 0;
1889 sx_table[8].period_ns = 0;
1890 sx_table[8].reg_value = 0;
1891 }
1892
1893
1894
1895
1896 static uchar
1897 set_clk_freq(int freq, int *mhz)
1898 {
1899 int x = freq;
1900 if (WD33C93_FS_8_10 == freq)
1901 freq = 8;
1902 else if (WD33C93_FS_12_15 == freq)
1903 freq = 12;
1904 else if (WD33C93_FS_16_20 == freq)
1905 freq = 16;
1906 else if (freq > 7 && freq < 11)
1907 x = WD33C93_FS_8_10;
1908 else if (freq > 11 && freq < 16)
1909 x = WD33C93_FS_12_15;
1910 else if (freq > 15 && freq < 21)
1911 x = WD33C93_FS_16_20;
1912 else {
1913
1914 x = WD33C93_FS_8_10;
1915 freq = 8;
1916 }
1917 *mhz = freq;
1918 return x;
1919 }
1920
1921
1922
1923
1924 static inline void set_resync ( struct WD33C93_hostdata *hd, int mask )
1925 {
1926 int i;
1927 for (i = 0; i < 8; i++)
1928 if (mask & (1 << i))
1929 hd->sync_stat[i] = SS_UNSET;
1930 }
1931
1932 void
1933 wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1934 dma_setup_t setup, dma_stop_t stop, int clock_freq)
1935 {
1936 struct WD33C93_hostdata *hostdata;
1937 int i;
1938 int flags;
1939 int val;
1940 char buf[32];
1941
1942 if (!done_setup && setup_strings)
1943 wd33c93_setup(setup_strings);
1944
1945 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1946
1947 hostdata->regs = regs;
1948 hostdata->clock_freq = set_clk_freq(clock_freq, &i);
1949 calc_sx_table(i, hostdata->sx_table);
1950 hostdata->dma_setup = setup;
1951 hostdata->dma_stop = stop;
1952 hostdata->dma_bounce_buffer = NULL;
1953 hostdata->dma_bounce_len = 0;
1954 for (i = 0; i < 8; i++) {
1955 hostdata->busy[i] = 0;
1956 hostdata->sync_xfer[i] =
1957 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
1958 0, hostdata->sx_table);
1959 hostdata->sync_stat[i] = SS_UNSET;
1960 #ifdef PROC_STATISTICS
1961 hostdata->cmd_cnt[i] = 0;
1962 hostdata->disc_allowed_cnt[i] = 0;
1963 hostdata->disc_done_cnt[i] = 0;
1964 #endif
1965 }
1966 hostdata->input_Q = NULL;
1967 hostdata->selecting = NULL;
1968 hostdata->connected = NULL;
1969 hostdata->disconnected_Q = NULL;
1970 hostdata->state = S_UNCONNECTED;
1971 hostdata->dma = D_DMA_OFF;
1972 hostdata->level2 = L2_BASIC;
1973 hostdata->disconnect = DIS_ADAPTIVE;
1974 hostdata->args = DEBUG_DEFAULTS;
1975 hostdata->incoming_ptr = 0;
1976 hostdata->outgoing_len = 0;
1977 hostdata->default_sx_per = DEFAULT_SX_PER;
1978 hostdata->no_dma = 0;
1979
1980 #ifdef PROC_INTERFACE
1981 hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
1982 PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;
1983 #ifdef PROC_STATISTICS
1984 hostdata->dma_cnt = 0;
1985 hostdata->pio_cnt = 0;
1986 hostdata->int_cnt = 0;
1987 #endif
1988 #endif
1989
1990 if (check_setup_args("clock", &flags, &val, buf)) {
1991 hostdata->clock_freq = set_clk_freq(val, &val);
1992 calc_sx_table(val, hostdata->sx_table);
1993 }
1994
1995 if (check_setup_args("nosync", &flags, &val, buf))
1996 hostdata->no_sync = val;
1997
1998 if (check_setup_args("nodma", &flags, &val, buf))
1999 hostdata->no_dma = (val == -1) ? 1 : val;
2000
2001 if (check_setup_args("period", &flags, &val, buf))
2002 hostdata->default_sx_per =
2003 hostdata->sx_table[round_period((unsigned int) val,
2004 hostdata->sx_table)].period_ns;
2005
2006 if (check_setup_args("disconnect", &flags, &val, buf)) {
2007 if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
2008 hostdata->disconnect = val;
2009 else
2010 hostdata->disconnect = DIS_ADAPTIVE;
2011 }
2012
2013 if (check_setup_args("level2", &flags, &val, buf))
2014 hostdata->level2 = val;
2015
2016 if (check_setup_args("debug", &flags, &val, buf))
2017 hostdata->args = val & DB_MASK;
2018
2019 if (check_setup_args("burst", &flags, &val, buf))
2020 hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA;
2021
2022 if (WD33C93_FS_16_20 == hostdata->clock_freq
2023 && check_setup_args("fast", &flags, &val, buf))
2024 hostdata->fast = !!val;
2025
2026 if ((i = check_setup_args("next", &flags, &val, buf))) {
2027 while (i)
2028 setup_used[--i] = 1;
2029 }
2030 #ifdef PROC_INTERFACE
2031 if (check_setup_args("proc", &flags, &val, buf))
2032 hostdata->proc = val;
2033 #endif
2034
2035 spin_lock_irq(&hostdata->lock);
2036 reset_wd33c93(instance);
2037 spin_unlock_irq(&hostdata->lock);
2038
2039 printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",
2040 instance->host_no,
2041 (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip ==
2042 C_WD33C93A) ?
2043 "WD33c93A" : (hostdata->chip ==
2044 C_WD33C93B) ? "WD33c93B" : "unknown",
2045 hostdata->microcode, hostdata->no_sync, hostdata->no_dma);
2046 #ifdef DEBUGGING_ON
2047 printk(" debug_flags=0x%02x\n", hostdata->args);
2048 #else
2049 printk(" debugging=OFF\n");
2050 #endif
2051 printk(" setup_args=");
2052 for (i = 0; i < MAX_SETUP_ARGS; i++)
2053 printk("%s,", setup_args[i]);
2054 printk("\n");
2055 printk(" Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE);
2056 }
2057
2058 int wd33c93_write_info(struct Scsi_Host *instance, char *buf, int len)
2059 {
2060 #ifdef PROC_INTERFACE
2061 char *bp;
2062 struct WD33C93_hostdata *hd;
2063 int x;
2064
2065 hd = (struct WD33C93_hostdata *) instance->hostdata;
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081 buf[len] = '\0';
2082 for (bp = buf; *bp; ) {
2083 while (',' == *bp || ' ' == *bp)
2084 ++bp;
2085 if (!strncmp(bp, "debug:", 6)) {
2086 hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
2087 } else if (!strncmp(bp, "disconnect:", 11)) {
2088 x = simple_strtoul(bp+11, &bp, 0);
2089 if (x < DIS_NEVER || x > DIS_ALWAYS)
2090 x = DIS_ADAPTIVE;
2091 hd->disconnect = x;
2092 } else if (!strncmp(bp, "period:", 7)) {
2093 x = simple_strtoul(bp+7, &bp, 0);
2094 hd->default_sx_per =
2095 hd->sx_table[round_period((unsigned int) x,
2096 hd->sx_table)].period_ns;
2097 } else if (!strncmp(bp, "resync:", 7)) {
2098 set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
2099 } else if (!strncmp(bp, "proc:", 5)) {
2100 hd->proc = simple_strtoul(bp+5, &bp, 0);
2101 } else if (!strncmp(bp, "nodma:", 6)) {
2102 hd->no_dma = simple_strtoul(bp+6, &bp, 0);
2103 } else if (!strncmp(bp, "level2:", 7)) {
2104 hd->level2 = simple_strtoul(bp+7, &bp, 0);
2105 } else if (!strncmp(bp, "burst:", 6)) {
2106 hd->dma_mode =
2107 simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
2108 } else if (!strncmp(bp, "fast:", 5)) {
2109 x = !!simple_strtol(bp+5, &bp, 0);
2110 if (x != hd->fast)
2111 set_resync(hd, 0xff);
2112 hd->fast = x;
2113 } else if (!strncmp(bp, "nosync:", 7)) {
2114 x = simple_strtoul(bp+7, &bp, 0);
2115 set_resync(hd, x ^ hd->no_sync);
2116 hd->no_sync = x;
2117 } else {
2118 break;
2119 }
2120 }
2121 return len;
2122 #else
2123 return 0;
2124 #endif
2125 }
2126
2127 int
2128 wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance)
2129 {
2130 #ifdef PROC_INTERFACE
2131 struct WD33C93_hostdata *hd;
2132 struct scsi_cmnd *cmd;
2133 int x;
2134
2135 hd = (struct WD33C93_hostdata *) instance->hostdata;
2136
2137 spin_lock_irq(&hd->lock);
2138 if (hd->proc & PR_VERSION)
2139 seq_printf(m, "\nVersion %s - %s.",
2140 WD33C93_VERSION, WD33C93_DATE);
2141
2142 if (hd->proc & PR_INFO) {
2143 seq_printf(m, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
2144 " dma_mode=%02x fast=%d",
2145 hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
2146 seq_puts(m, "\nsync_xfer[] = ");
2147 for (x = 0; x < 7; x++)
2148 seq_printf(m, "\t%02x", hd->sync_xfer[x]);
2149 seq_puts(m, "\nsync_stat[] = ");
2150 for (x = 0; x < 7; x++)
2151 seq_printf(m, "\t%02x", hd->sync_stat[x]);
2152 }
2153 #ifdef PROC_STATISTICS
2154 if (hd->proc & PR_STATISTICS) {
2155 seq_puts(m, "\ncommands issued: ");
2156 for (x = 0; x < 7; x++)
2157 seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
2158 seq_puts(m, "\ndisconnects allowed:");
2159 for (x = 0; x < 7; x++)
2160 seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
2161 seq_puts(m, "\ndisconnects done: ");
2162 for (x = 0; x < 7; x++)
2163 seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
2164 seq_printf(m,
2165 "\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
2166 hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
2167 }
2168 #endif
2169 if (hd->proc & PR_CONNECTED) {
2170 seq_puts(m, "\nconnected: ");
2171 if (hd->connected) {
2172 cmd = (struct scsi_cmnd *) hd->connected;
2173 seq_printf(m, " %d:%llu(%02x)",
2174 cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2175 }
2176 }
2177 if (hd->proc & PR_INPUTQ) {
2178 seq_puts(m, "\ninput_Q: ");
2179 cmd = (struct scsi_cmnd *) hd->input_Q;
2180 while (cmd) {
2181 seq_printf(m, " %d:%llu(%02x)",
2182 cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2183 cmd = (struct scsi_cmnd *) cmd->host_scribble;
2184 }
2185 }
2186 if (hd->proc & PR_DISCQ) {
2187 seq_puts(m, "\ndisconnected_Q:");
2188 cmd = (struct scsi_cmnd *) hd->disconnected_Q;
2189 while (cmd) {
2190 seq_printf(m, " %d:%llu(%02x)",
2191 cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2192 cmd = (struct scsi_cmnd *) cmd->host_scribble;
2193 }
2194 }
2195 seq_putc(m, '\n');
2196 spin_unlock_irq(&hd->lock);
2197 #endif
2198 return 0;
2199 }
2200
2201 EXPORT_SYMBOL(wd33c93_host_reset);
2202 EXPORT_SYMBOL(wd33c93_init);
2203 EXPORT_SYMBOL(wd33c93_abort);
2204 EXPORT_SYMBOL(wd33c93_queuecommand);
2205 EXPORT_SYMBOL(wd33c93_intr);
2206 EXPORT_SYMBOL(wd33c93_show_info);
2207 EXPORT_SYMBOL(wd33c93_write_info);