OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [fd_mcs.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver
2
 *
3
 * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net)
4
 *
5
 * This driver is cloned from fdomain.* to specifically support
6
 * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s
7
 * also equipped with IBM Fast SCSI Adapter/A which is an OEM
8
 * of MCS 700.
9
 *
10
 * This driver also supports Reply SB16/SCSI card (the SCSI part).
11
 *
12
 * What makes this driver different is that this driver is MCA only
13
 * and it supports multiple adapters in the same system, IRQ
14
 * sharing, some driver statistics, and maps highest SCSI id to sda.
15
 * All cards are auto-detected.
16
 *
17
 * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4
18
 *
19
 * LILO command-line options:
20
 *   fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>]
21
 *
22
 * ********************************************************
23
 * Please see Copyrights/Comments in fdomain.* for credits.
24
 * Following is from fdomain.c for acknowledgement:
25
 *
26
 * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
27
 * Revised: Wed Oct  2 11:10:55 1996 by r.faith@ieee.org
28
 * Author: Rickard E. Faith, faith@cs.unc.edu
29
 * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
30
 *
31
 * $Id: fd_mcs.c,v 1.1.1.1 2004-04-15 02:10:51 phoenix Exp $
32
 
33
 * This program is free software; you can redistribute it and/or modify it
34
 * under the terms of the GNU General Public License as published by the
35
 * Free Software Foundation; either version 2, or (at your option) any
36
 * later version.
37
 
38
 * This program is distributed in the hope that it will be useful, but
39
 * WITHOUT ANY WARRANTY; without even the implied warranty of
40
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41
 * General Public License for more details.
42
 
43
 * You should have received a copy of the GNU General Public License along
44
 * with this program; if not, write to the Free Software Foundation, Inc.,
45
 * 675 Mass Ave, Cambridge, MA 02139, USA.
46
 
47
 **************************************************************************
48
 
49
 NOTES ON USER DEFINABLE OPTIONS:
50
 
51
 DEBUG: This turns on the printing of various debug information.
52
 
53
 ENABLE_PARITY: This turns on SCSI parity checking.  With the current
54
 driver, all attached devices must support SCSI parity.  If none of your
55
 devices support parity, then you can probably get the driver to work by
56
 turning this option off.  I have no way of testing this, however, and it
57
 would appear that no one ever uses this option.
58
 
59
 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
60
 18C30 chip have a 2k cache).  When this many 512 byte blocks are filled by
61
 the SCSI device, an interrupt will be raised.  Therefore, this could be as
62
 low as 0, or as high as 16.  Note, however, that values which are too high
63
 or too low seem to prevent any interrupts from occurring, and thereby lock
64
 up the machine.  I have found that 2 is a good number, but throughput may
65
 be increased by changing this value to values which are close to 2.
66
 Please let me know if you try any different values.
67
 [*****Now a runtime option*****]
68
 
69
 RESELECTION: This is no longer an option, since I gave up trying to
70
 implement it in version 4.x of this driver.  It did not improve
71
 performance at all and made the driver unstable (because I never found one
72
 of the two race conditions which were introduced by the multiple
73
 outstanding command code).  The instability seems a very high price to pay
74
 just so that you don't have to wait for the tape to rewind.  If you want
75
 this feature implemented, send me patches.  I'll be happy to send a copy
76
 of my (broken) driver to anyone who would like to see a copy.
77
 
78
 **************************************************************************/
79
 
80
#include <linux/module.h>
81
 
82
#include <linux/sched.h>
83
#include <linux/blk.h>
84
#include <linux/errno.h>
85
#include <linux/string.h>
86
#include <linux/ioport.h>
87
#include <linux/proc_fs.h>
88
#include <linux/delay.h>
89
#include <linux/mca.h>
90
#include <linux/spinlock.h>
91
#include <asm/io.h>
92
#include <asm/system.h>
93
 
94
#include "scsi.h"
95
#include "hosts.h"
96
#include "fd_mcs.h"
97
 
98
#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
99
 
100
/* START OF USER DEFINABLE OPTIONS */
101
 
102
#define DEBUG            0      /* Enable debugging output */
103
#define ENABLE_PARITY    1      /* Enable SCSI Parity */
104
#define DO_DETECT        0      /* Do device detection here (see scsi.c) */
105
 
106
/* END OF USER DEFINABLE OPTIONS */
107
 
108
#if DEBUG
109
#define EVERY_ACCESS     0      /* Write a line on every scsi access */
110
#define ERRORS_ONLY      1      /* Only write a line if there is an error */
111
#define DEBUG_DETECT     1      /* Debug fd_mcs_detect() */
112
#define DEBUG_MESSAGES   1      /* Debug MESSAGE IN phase */
113
#define DEBUG_ABORT      1      /* Debug abort() routine */
114
#define DEBUG_RESET      1      /* Debug reset() routine */
115
#define DEBUG_RACE       1      /* Debug interrupt-driven race condition */
116
#else
117
#define EVERY_ACCESS     0      /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
118
#define ERRORS_ONLY      0
119
#define DEBUG_DETECT     0
120
#define DEBUG_MESSAGES   0
121
#define DEBUG_ABORT      0
122
#define DEBUG_RESET      0
123
#define DEBUG_RACE       0
124
#endif
125
 
126
/* Errors are reported on the line, so we don't need to report them again */
127
#if EVERY_ACCESS
128
#undef ERRORS_ONLY
129
#define ERRORS_ONLY      0
130
#endif
131
 
132
#if ENABLE_PARITY
133
#define PARITY_MASK      0x08
134
#else
135
#define PARITY_MASK      0x00
136
#endif
137
 
138
enum chip_type {
139
  unknown          = 0x00,
140
  tmc1800          = 0x01,
141
  tmc18c50         = 0x02,
142
  tmc18c30         = 0x03,
143
};
144
 
145
enum {
146
  in_arbitration   = 0x02,
147
  in_selection     = 0x04,
148
  in_other         = 0x08,
149
  disconnect       = 0x10,
150
  aborted          = 0x20,
151
  sent_ident       = 0x40,
152
};
153
 
154
enum in_port_type {
155
  Read_SCSI_Data   =  0,
156
  SCSI_Status      =  1,
157
  TMC_Status       =  2,
158
  FIFO_Status      =  3,        /* tmc18c50/tmc18c30 only */
159
  Interrupt_Cond   =  4,        /* tmc18c50/tmc18c30 only */
160
  LSB_ID_Code      =  5,
161
  MSB_ID_Code      =  6,
162
  Read_Loopback    =  7,
163
  SCSI_Data_NoACK  =  8,
164
  Interrupt_Status =  9,
165
  Configuration1   = 10,
166
  Configuration2   = 11,        /* tmc18c50/tmc18c30 only */
167
  Read_FIFO        = 12,
168
  FIFO_Data_Count  = 14
169
};
170
 
171
enum out_port_type {
172
  Write_SCSI_Data  =  0,
173
  SCSI_Cntl        =  1,
174
  Interrupt_Cntl   =  2,
175
  SCSI_Mode_Cntl   =  3,
176
  TMC_Cntl         =  4,
177
  Memory_Cntl      =  5,        /* tmc18c50/tmc18c30 only */
178
  Write_Loopback   =  7,
179
  IO_Control       = 11,        /* tmc18c30 only */
180
  Write_FIFO       = 12
181
};
182
 
183
struct fd_hostdata {
184
  unsigned long     _bios_base;
185
  int               _bios_major;
186
  int               _bios_minor;
187
  volatile int      _in_command;
188
  Scsi_Cmnd         *_current_SC;
189
  enum chip_type    _chip;
190
  int               _adapter_mask;
191
  int               _fifo_count; /* Number of 512 byte blocks before INTR */
192
 
193
  char              _adapter_name[64];
194
#if DEBUG_RACE
195
  volatile int      _in_interrupt_flag;
196
#endif
197
 
198
  int               _SCSI_Mode_Cntl_port;
199
  int               _FIFO_Data_Count_port;
200
  int               _Interrupt_Cntl_port;
201
  int               _Interrupt_Status_port;
202
  int               _Interrupt_Cond_port;
203
  int               _Read_FIFO_port;
204
  int               _Read_SCSI_Data_port;
205
  int               _SCSI_Cntl_port;
206
  int               _SCSI_Data_NoACK_port;
207
  int               _SCSI_Status_port;
208
  int               _TMC_Cntl_port;
209
  int               _TMC_Status_port;
210
  int               _Write_FIFO_port;
211
  int               _Write_SCSI_Data_port;
212
 
213
  int               _FIFO_Size; /* = 0x2000;  8k FIFO for
214
                                   pre-tmc18c30 chips */
215
  /* simple stats */
216
  int               _Bytes_Read;
217
  int               _Bytes_Written;
218
  int               _INTR_Processed;
219
};
220
 
221
#define FD_MAX_HOSTS 3          /* enough? */
222
 
223
#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
224
#define bios_base             (HOSTDATA(shpnt)->_bios_base)
225
#define bios_major            (HOSTDATA(shpnt)->_bios_major)
226
#define bios_minor            (HOSTDATA(shpnt)->_bios_minor)
227
#define in_command            (HOSTDATA(shpnt)->_in_command)
228
#define current_SC            (HOSTDATA(shpnt)->_current_SC)
229
#define chip                  (HOSTDATA(shpnt)->_chip)
230
#define adapter_mask          (HOSTDATA(shpnt)->_adapter_mask)
231
#define FIFO_COUNT            (HOSTDATA(shpnt)->_fifo_count)
232
#define adapter_name          (HOSTDATA(shpnt)->_adapter_name)
233
#if DEBUG_RACE
234
#define in_interrupt_flag     (HOSTDATA(shpnt)->_in_interrupt_flag)
235
#endif                       
236
#define SCSI_Mode_Cntl_port   (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
237
#define FIFO_Data_Count_port  (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
238
#define Interrupt_Cntl_port   (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
239
#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
240
#define Interrupt_Cond_port   (HOSTDATA(shpnt)->_Interrupt_Cond_port)
241
#define Read_FIFO_port        (HOSTDATA(shpnt)->_Read_FIFO_port)
242
#define Read_SCSI_Data_port   (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
243
#define SCSI_Cntl_port        (HOSTDATA(shpnt)->_SCSI_Cntl_port)
244
#define SCSI_Data_NoACK_port  (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
245
#define SCSI_Status_port      (HOSTDATA(shpnt)->_SCSI_Status_port)
246
#define TMC_Cntl_port         (HOSTDATA(shpnt)->_TMC_Cntl_port)
247
#define TMC_Status_port       (HOSTDATA(shpnt)->_TMC_Status_port)
248
#define Write_FIFO_port       (HOSTDATA(shpnt)->_Write_FIFO_port)
249
#define Write_SCSI_Data_port  (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
250
#define FIFO_Size             (HOSTDATA(shpnt)->_FIFO_Size)
251
#define Bytes_Read            (HOSTDATA(shpnt)->_Bytes_Read)
252
#define Bytes_Written         (HOSTDATA(shpnt)->_Bytes_Written)
253
#define INTR_Processed        (HOSTDATA(shpnt)->_INTR_Processed)
254
 
255
struct fd_mcs_adapters_struct {
256
  char* name;
257
  int id;
258
  enum chip_type fd_chip;
259
  int fifo_size;
260
  int fifo_count;
261
};
262
 
263
#define REPLY_ID 0x5137
264
 
265
static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
266
  { "Future Domain SCSI Adapter MCS-700(18C50)",
267
    0x60e9,
268
    tmc18c50,
269
    0x2000,
270
    4 },
271
  { "Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
272
    0x6127,
273
    tmc1800,
274
    0x2000,
275
    4 },
276
  { "Reply Sound Blaster/SCSI Adapter",
277
    REPLY_ID,
278
    tmc18c30,
279
    0x800,
280
    2 },
281
};
282
 
283
#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct)
284
 
285
static void fd_mcs_intr( int irq, void *dev_id, struct pt_regs * regs );
286
 
287
static unsigned long addresses[] = {0xc8000, 0xca000, 0xce000, 0xde000};
288
static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
289
static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
290
 
291
/* host information */
292
static int found = 0;
293
static struct Scsi_Host *hosts[FD_MAX_HOSTS+1] = { NULL };
294
 
295
static int user_fifo_count = 0;
296
static int user_fifo_size = 0;
297
 
298
void fd_mcs_setup( char *str, int *ints )
299
{
300
  static int done_setup = 0;
301
 
302
  if (done_setup++ || ints[0] < 1 || ints[0] > 2 ||
303
      ints[1] < 1 || ints[1] > 16) {
304
    printk( "fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n" );
305
  }
306
 
307
  user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
308
  user_fifo_size  = ints[0] >= 2 ? ints[2] : 0;
309
}
310
 
311
static void print_banner( struct Scsi_Host *shpnt )
312
{
313
  printk( "scsi%d <fd_mcs>: ", shpnt->host_no);
314
 
315
  if (bios_base) {
316
    printk( "BIOS at 0x%lX", bios_base);
317
  } else {
318
    printk( "No BIOS");
319
  }
320
 
321
  printk( ", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n",
322
          shpnt->this_id,
323
          chip == tmc18c50 ? "TMC-18C50"
324
             : (chip == tmc18c30 ? "TMC-18C30" :
325
                (chip == tmc1800 ? "TMC-1800" : "Unknown")),
326
          shpnt->irq,
327
          shpnt->io_port );
328
}
329
 
330
 
331
static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
332
{
333
  do {
334
    udelay(10*1000);
335
  } while (--amount);
336
}
337
 
338
inline static void fd_mcs_make_bus_idle( struct Scsi_Host *shpnt )
339
{
340
  outb( 0, SCSI_Cntl_port );
341
  outb( 0, SCSI_Mode_Cntl_port );
342
  if (chip == tmc18c50 || chip == tmc18c30)
343
    outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
344
  else
345
    outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
346
}
347
 
348
int fd_mcs_detect( Scsi_Host_Template *tpnt )
349
{
350
  int loop;
351
  struct Scsi_Host *shpnt;
352
 
353
  /* get id, port, bios, irq */
354
  int slot;
355
  u_char pos2, pos3, pos4;
356
  int id, port, irq;
357
  unsigned long bios;
358
 
359
  /* if not MCA machine, return */
360
  if (!MCA_bus)
361
    return 0;
362
 
363
  /* changeable? */
364
  id = 7;
365
 
366
  for( loop = 0; loop < FD_BRDS; loop++ ) {
367
    slot = 0;
368
    while ( MCA_NOTFOUND !=
369
            (slot = mca_find_adapter(fd_mcs_adapters[loop].id,
370
                                     slot)) ) {
371
 
372
      /* if we get this far, an adapter has been detected and is
373
         enabled */
374
 
375
      printk("scsi  <fd_mcs>: %s at slot %d\n",
376
             fd_mcs_adapters[loop].name, slot + 1 );
377
 
378
      pos2 = mca_read_stored_pos( slot, 2 );
379
      pos3 = mca_read_stored_pos( slot, 3 );
380
      pos4 = mca_read_stored_pos( slot, 4);
381
 
382
      /* ready for next probe */
383
      slot++;
384
 
385
      if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
386
        static int reply_irq[] = {10, 11, 14, 15};
387
 
388
        bios = 0;                /* no bios */
389
 
390
        if (pos2 & 0x2)
391
          port = ports[pos4 & 0x3];
392
        else
393
          continue;
394
 
395
        /* can't really disable it, same as irq=10 */
396
        irq = reply_irq[((pos4 >> 2) & 0x1) + 2*((pos4 >> 4) & 0x1)];
397
      } else {
398
        bios = addresses[pos2 >> 6];
399
        port = ports[(pos2 >> 4) & 0x03];
400
        irq = ints[(pos2 >> 1) & 0x07];
401
      }
402
 
403
      if (irq) {
404
        /* claim the slot */
405
        mca_set_adapter_name( slot-1, fd_mcs_adapters[loop].name );
406
 
407
        /* check irq/region */
408
        if (check_region(port, 0x10) ||
409
            request_irq(irq, fd_mcs_intr,
410
                        SA_SHIRQ, "fd_mcs", hosts)) {
411
          printk( "fd_mcs: check_region() || request_irq() failed, Skip it\n");
412
 
413
          continue;
414
        }
415
 
416
        /* register */
417
        if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
418
          printk( "fd_mcs: scsi_register() failed\n");
419
          continue;
420
        }
421
 
422
        /* request I/O region */
423
        request_region( port, 0x10, "fd_mcs" );
424
 
425
        /* save name */
426
        strcpy(adapter_name, fd_mcs_adapters[loop].name);
427
 
428
        /* chip/fifo */
429
        chip = fd_mcs_adapters[loop].fd_chip;
430
        /* use boot time value if available */
431
        FIFO_COUNT =
432
          user_fifo_count?user_fifo_count:fd_mcs_adapters[loop].fifo_count;
433
        FIFO_Size =
434
          user_fifo_size?user_fifo_size:fd_mcs_adapters[loop].fifo_size;
435
 
436
#ifdef NOT_USED
437
        /* *************************************************** */
438
        /* Try to toggle 32-bit mode.  This only
439
           works on an 18c30 chip.  (User reports
440
           say this works, so we should switch to
441
           it in the near future.) */
442
        outb( 0x80, port + IO_Control );
443
        if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
444
          outb( 0x00, port + IO_Control );
445
          if ((inb( port + Configuration2 ) & 0x80) == 0x00) {
446
            chip = tmc18c30;
447
            FIFO_Size = 0x800;  /* 2k FIFO */
448
 
449
            printk("FIRST: chip=%s, fifo_size=0x%x\n",
450
                   (chip == tmc18c30)?"tmc18c30":"tmc18c50", FIFO_Size);
451
          }
452
        }
453
 
454
        /* That should have worked, but appears to
455
           have problems.  Let's assume it is an
456
           18c30 if the RAM is disabled. */
457
 
458
        if (inb( port + Configuration2 ) & 0x02) {
459
          chip      = tmc18c30;
460
          FIFO_Size = 0x800;    /* 2k FIFO */
461
 
462
          printk("SECOND: chip=%s, fifo_size=0x%x\n",
463
                 (chip == tmc18c30)?"tmc18c30":"tmc18c50", FIFO_Size);
464
        }
465
        /* *************************************************** */
466
#endif
467
 
468
        /* IBM/ANSI scsi scan ordering */
469
        /* Stick this back in when the scsi.c changes are there */
470
        shpnt->reverse_ordering = 1;
471
 
472
 
473
        /* saving info */
474
        hosts[found++] = shpnt;
475
 
476
        shpnt->this_id = id;
477
        shpnt->irq = irq;
478
        shpnt->io_port = port;
479
        shpnt->n_io_port = 0x10;
480
 
481
        /* save */
482
        bios_base    = bios;
483
        adapter_mask = (1 << id);
484
 
485
        /* save more */
486
        SCSI_Mode_Cntl_port   = port + SCSI_Mode_Cntl;
487
        FIFO_Data_Count_port  = port + FIFO_Data_Count;
488
        Interrupt_Cntl_port   = port + Interrupt_Cntl;
489
        Interrupt_Status_port = port + Interrupt_Status;
490
        Interrupt_Cond_port   = port + Interrupt_Cond;
491
        Read_FIFO_port        = port + Read_FIFO;
492
        Read_SCSI_Data_port   = port + Read_SCSI_Data;
493
        SCSI_Cntl_port        = port + SCSI_Cntl;
494
        SCSI_Data_NoACK_port  = port + SCSI_Data_NoACK;
495
        SCSI_Status_port      = port + SCSI_Status;
496
        TMC_Cntl_port         = port + TMC_Cntl;
497
        TMC_Status_port       = port + TMC_Status;
498
        Write_FIFO_port       = port + Write_FIFO;
499
        Write_SCSI_Data_port  = port + Write_SCSI_Data;
500
 
501
        Bytes_Read     = 0;
502
        Bytes_Written  = 0;
503
        INTR_Processed = 0;
504
 
505
        /* say something */
506
        print_banner( shpnt );
507
 
508
        /* reset */
509
        outb( 1, SCSI_Cntl_port );
510
        do_pause( 2 );
511
        outb( 0, SCSI_Cntl_port );
512
        do_pause( 115 );
513
        outb( 0, SCSI_Mode_Cntl_port );
514
        outb( PARITY_MASK, TMC_Cntl_port );
515
        /* done reset */
516
 
517
#if DO_DETECT
518
        /* scan devices attached */
519
        {
520
          const int     buflen = 255;
521
          int           i, j, retcode;
522
          Scsi_Cmnd     SCinit;
523
          unsigned char do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
524
          unsigned char do_request_sense[] = { REQUEST_SENSE,
525
                                               0, 0, 0, buflen, 0 };
526
          unsigned char do_read_capacity[] = { READ_CAPACITY,
527
                                               0, 0, 0, 0, 0, 0, 0, 0, 0 };
528
          unsigned char buf[buflen];
529
 
530
          SCinit.request_buffer  = SCinit.buffer = buf;
531
          SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
532
          SCinit.use_sg          = 0;
533
          SCinit.lun             = 0;
534
          SCinit.host            = shpnt;
535
 
536
          printk( "fd_mcs: detection routine scanning for devices:\n" );
537
          for (i = 0; i < 8; i++) {
538
            if (i == shpnt->this_id)    /* Skip host adapter */
539
              continue;
540
            SCinit.target = i;
541
            memcpy(SCinit.cmnd, do_request_sense,
542
                   sizeof(do_request_sense));
543
            retcode = fd_mcs_command(&SCinit);
544
            if (!retcode) {
545
              memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
546
              retcode = fd_mcs_command(&SCinit);
547
              if (!retcode) {
548
                printk( "     SCSI ID %d: ", i );
549
                for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
550
                  printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
551
                memcpy(SCinit.cmnd, do_read_capacity,
552
                       sizeof(do_read_capacity));
553
                retcode = fd_mcs_command(&SCinit);
554
                if (!retcode) {
555
                  unsigned long blocks, size, capacity;
556
 
557
                  blocks = (buf[0] << 24) | (buf[1] << 16)
558
                    | (buf[2] << 8) | buf[3];
559
                  size = (buf[4] << 24) | (buf[5] << 16) |
560
                    (buf[6] << 8) | buf[7];
561
                  capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
562
 
563
                  printk( "%lu MB (%lu byte blocks)\n",
564
                          ((capacity + 5L) / 10L), size );
565
                }
566
              }
567
            }
568
          }
569
        }
570
#endif
571
      }
572
    }
573
 
574
    if (found == FD_MAX_HOSTS) {
575
      printk( "fd_mcs: detecting reached max=%d host adapters.\n",
576
              FD_MAX_HOSTS);
577
      break;
578
    }
579
  }
580
 
581
  return found;
582
}
583
 
584
const char *fd_mcs_info(struct Scsi_Host *shpnt)
585
{
586
  return adapter_name;
587
}
588
 
589
static int TOTAL_INTR = 0;
590
 
591
/*
592
 * inout : decides on the direction of the dataflow and the meaning of the
593
 *         variables
594
 * buffer: If inout==FALSE data is being written to it else read from it
595
 * *start: If inout==FALSE start of the valid data in the buffer
596
 * offset: If inout==FALSE offset from the beginning of the imaginary file
597
 *         from which we start writing into the buffer
598
 * length: If inout==FALSE max number of bytes to be written into the buffer
599
 *         else number of bytes in the buffer
600
 */
601
int fd_mcs_proc_info( char *buffer, char **start, off_t offset,
602
                      int length, int hostno, int inout )
603
{
604
  struct Scsi_Host *shpnt;
605
  int    len = 0;
606
  int    i;
607
 
608
  if (inout)
609
    return(-ENOSYS);
610
 
611
  *start = buffer + offset;
612
 
613
  for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
614
  shpnt = hosts[i];
615
 
616
  if (!shpnt) {
617
    return(-ENOENT);
618
  } else {
619
    len += sprintf(buffer+len, "Future Domain MCS-600/700 Driver %s\n",
620
                   DRIVER_VERSION);
621
 
622
    len += sprintf(buffer+len, "HOST #%d: %s\n",
623
                   hostno, adapter_name);
624
 
625
    len += sprintf(buffer+len, "FIFO Size=0x%x, FIFO Count=%d\n",
626
                   FIFO_Size, FIFO_COUNT);
627
 
628
    len += sprintf(buffer+len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n",
629
                   TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
630
  }
631
 
632
  if ((len -= offset) <= 0)
633
    return 0;
634
  if (len > length)
635
    len = length;
636
  return len;
637
}
638
 
639
static int fd_mcs_select(struct Scsi_Host *shpnt, int target )
640
{
641
  int           status;
642
  unsigned long timeout;
643
 
644
  outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
645
  outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
646
 
647
  /* Stop arbitration and enable parity */
648
  outb( PARITY_MASK, TMC_Cntl_port );
649
 
650
  timeout = 350;                /* 350mS -- because of timeouts
651
                                   (was 250mS) */
652
 
653
  do {
654
    status = inb( SCSI_Status_port ); /* Read adapter status */
655
    if (status & 1) {                   /* Busy asserted */
656
      /* Enable SCSI Bus (on error, should make bus idle with 0) */
657
      outb( 0x80, SCSI_Cntl_port );
658
      return 0;
659
    }
660
    udelay(1000);               /* wait one msec */
661
  } while (--timeout);
662
 
663
  /* Make bus idle */
664
  fd_mcs_make_bus_idle(shpnt);
665
#if EVERY_ACCESS
666
  if (!target) printk( "Selection failed\n" );
667
#endif
668
#if ERRORS_ONLY
669
  if (!target) {
670
    static int flag = 0;
671
 
672
    if (!flag) /* Skip first failure for all chips. */
673
      ++flag;
674
    else
675
      printk( "fd_mcs: Selection failed\n" );
676
  }
677
#endif
678
  return 1;
679
}
680
 
681
static void my_done( struct Scsi_Host *shpnt, int error )
682
{
683
  if (in_command) {
684
    in_command = 0;
685
    outb( 0x00, Interrupt_Cntl_port );
686
    fd_mcs_make_bus_idle(shpnt);
687
    current_SC->result = error;
688
    current_SC->scsi_done( current_SC );
689
  } else {
690
    panic( "fd_mcs: my_done() called outside of command\n" );
691
  }
692
#if DEBUG_RACE
693
  in_interrupt_flag = 0;
694
#endif
695
}
696
 
697
/* only my_done needs to be protected  */
698
static void fd_mcs_intr( int irq, void *dev_id, struct pt_regs * regs )
699
{
700
  unsigned long flags;
701
  int      status;
702
  int      done = 0;
703
  unsigned data_count, tmp_count;
704
 
705
  int i = 0;
706
  struct Scsi_Host *shpnt;
707
 
708
  TOTAL_INTR++;
709
 
710
  /* search for one adapter-response on shared interrupt */
711
  while ((shpnt = hosts[i++])) {
712
    if ((inb(TMC_Status_port)) & 1)
713
      break;
714
  }
715
 
716
  /* return if some other device on this IRQ caused the interrupt */
717
  if (!shpnt) {
718
    return;
719
  }
720
 
721
  INTR_Processed++;
722
 
723
  outb( 0x00, Interrupt_Cntl_port );
724
 
725
  /* Abort calls my_done, so we do nothing here. */
726
  if (current_SC->SCp.phase & aborted) {
727
#if DEBUG_ABORT
728
    printk( "Interrupt after abort, ignoring\n" );
729
#endif
730
    /* return; */
731
  }
732
 
733
#if DEBUG_RACE
734
  ++in_interrupt_flag;
735
#endif
736
 
737
  if (current_SC->SCp.phase & in_arbitration) {
738
    status = inb( TMC_Status_port );        /* Read adapter status */
739
    if (!(status & 0x02)) {
740
#if EVERY_ACCESS
741
      printk( " AFAIL " );
742
#endif
743
      spin_lock_irqsave(&io_request_lock, flags);
744
      my_done( shpnt, DID_BUS_BUSY << 16 );
745
      spin_unlock_irqrestore(&io_request_lock, flags);
746
      return;
747
    }
748
    current_SC->SCp.phase = in_selection;
749
 
750
    outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
751
 
752
    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
753
    outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
754
 
755
    /* Stop arbitration and enable parity */
756
    outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
757
#if DEBUG_RACE
758
    in_interrupt_flag = 0;
759
#endif
760
    return;
761
  } else if (current_SC->SCp.phase & in_selection) {
762
    status = inb( SCSI_Status_port );
763
    if (!(status & 0x01)) {
764
      /* Try again, for slow devices */
765
      if (fd_mcs_select(shpnt, current_SC->target )) {
766
#if EVERY_ACCESS
767
        printk( " SFAIL " );
768
#endif
769
        spin_lock_irqsave(&io_request_lock, flags);
770
        my_done( shpnt, DID_NO_CONNECT << 16 );
771
        spin_unlock_irqrestore(&io_request_lock, flags);
772
        return;
773
      } else {
774
#if EVERY_ACCESS
775
        printk( " AltSel " );
776
#endif
777
        /* Stop arbitration and enable parity */
778
        outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
779
      }
780
    }
781
    current_SC->SCp.phase = in_other;
782
    outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
783
    outb( 0x80, SCSI_Cntl_port );
784
#if DEBUG_RACE
785
    in_interrupt_flag = 0;
786
#endif
787
    return;
788
  }
789
 
790
  /* current_SC->SCp.phase == in_other: this is the body of the routine */
791
 
792
  status = inb( SCSI_Status_port );
793
 
794
  if (status & 0x10) {  /* REQ */
795
 
796
    switch (status & 0x0e) {
797
 
798
    case 0x08:          /* COMMAND OUT */
799
      outb( current_SC->cmnd[current_SC->SCp.sent_command++],
800
            Write_SCSI_Data_port );
801
#if EVERY_ACCESS
802
      printk( "CMD = %x,",
803
              current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
804
#endif
805
      break;
806
    case 0x00:          /* DATA OUT -- tmc18c50/tmc18c30 only */
807
      if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
808
        current_SC->SCp.have_data_in = -1;
809
        outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
810
      }
811
      break;
812
    case 0x04:          /* DATA IN -- tmc18c50/tmc18c30 only */
813
      if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
814
        current_SC->SCp.have_data_in = 1;
815
        outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
816
      }
817
      break;
818
    case 0x0c:          /* STATUS IN */
819
      current_SC->SCp.Status = inb( Read_SCSI_Data_port );
820
#if EVERY_ACCESS
821
      printk( "Status = %x, ", current_SC->SCp.Status );
822
#endif
823
#if ERRORS_ONLY
824
      if (current_SC->SCp.Status
825
          && current_SC->SCp.Status != 2
826
          && current_SC->SCp.Status != 8) {
827
        printk( "ERROR fd_mcs: target = %d, command = %x, status = %x\n",
828
                current_SC->target,
829
                current_SC->cmnd[0],
830
                current_SC->SCp.Status );
831
      }
832
#endif
833
      break;
834
    case 0x0a:          /* MESSAGE OUT */
835
      outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
836
      break;
837
    case 0x0e:          /* MESSAGE IN */
838
      current_SC->SCp.Message = inb( Read_SCSI_Data_port );
839
#if EVERY_ACCESS
840
      printk( "Message = %x, ", current_SC->SCp.Message );
841
#endif
842
      if (!current_SC->SCp.Message) ++done;
843
#if DEBUG_MESSAGES || EVERY_ACCESS
844
      if (current_SC->SCp.Message) {
845
        printk( "fd_mcs: message = %x\n", current_SC->SCp.Message );
846
      }
847
#endif
848
      break;
849
    }
850
  }
851
 
852
  if (chip == tmc1800
853
      && !current_SC->SCp.have_data_in
854
      && (current_SC->SCp.sent_command
855
          >= current_SC->cmd_len)) {
856
    /* We have to get the FIFO direction
857
       correct, so I've made a table based
858
       on the SCSI Standard of which commands
859
       appear to require a DATA OUT phase.
860
       */
861
    /*
862
      p. 94: Command for all device types
863
      CHANGE DEFINITION            40 DATA OUT
864
      COMPARE                      39 DATA OUT
865
      COPY                         18 DATA OUT
866
      COPY AND VERIFY              3a DATA OUT
867
      INQUIRY                      12
868
      LOG SELECT                   4c DATA OUT
869
      LOG SENSE                    4d
870
      MODE SELECT (6)              15 DATA OUT
871
      MODE SELECT (10)             55 DATA OUT
872
      MODE SENSE (6)               1a
873
      MODE SENSE (10)              5a
874
      READ BUFFER                  3c
875
      RECEIVE DIAGNOSTIC RESULTS   1c
876
      REQUEST SENSE                03
877
      SEND DIAGNOSTIC              1d DATA OUT
878
      TEST UNIT READY              00
879
      WRITE BUFFER                 3b DATA OUT
880
 
881
      p.178: Commands for direct-access devices (not listed on p. 94)
882
      FORMAT UNIT                  04 DATA OUT
883
      LOCK-UNLOCK CACHE            36
884
      PRE-FETCH                    34
885
      PREVENT-ALLOW MEDIUM REMOVAL 1e
886
      READ (6)/RECEIVE             08
887
      READ (10)                    3c
888
      READ CAPACITY                25
889
      READ DEFECT DATA (10)        37
890
      READ LONG                    3e
891
      REASSIGN BLOCKS              07 DATA OUT
892
      RELEASE                      17
893
      RESERVE                      16 DATA OUT
894
      REZERO UNIT/REWIND           01
895
      SEARCH DATA EQUAL (10)       31 DATA OUT
896
      SEARCH DATA HIGH (10)        30 DATA OUT
897
      SEARCH DATA LOW (10)         32 DATA OUT
898
      SEEK (6)                     0b
899
      SEEK (10)                    2b
900
      SET LIMITS (10)              33
901
      START STOP UNIT              1b
902
      SYNCHRONIZE CACHE            35
903
      VERIFY (10)                  2f
904
      WRITE (6)/PRINT/SEND         0a DATA OUT
905
      WRITE (10)/SEND              2a DATA OUT
906
      WRITE AND VERIFY (10)        2e DATA OUT
907
      WRITE LONG                   3f DATA OUT
908
      WRITE SAME                   41 DATA OUT ?
909
 
910
      p. 261: Commands for sequential-access devices (not previously listed)
911
      ERASE                        19
912
      LOAD UNLOAD                  1b
913
      LOCATE                       2b
914
      READ BLOCK LIMITS            05
915
      READ POSITION                34
916
      READ REVERSE                 0f
917
      RECOVER BUFFERED DATA        14
918
      SPACE                        11
919
      WRITE FILEMARKS              10 ?
920
 
921
      p. 298: Commands for printer devices (not previously listed)
922
      ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
923
      SLEW AND PRINT               0b DATA OUT  -- same as seek
924
      STOP PRINT                   1b
925
      SYNCHRONIZE BUFFER           10
926
 
927
      p. 315: Commands for processor devices (not previously listed)
928
 
929
      p. 321: Commands for write-once devices (not previously listed)
930
      MEDIUM SCAN                  38
931
      READ (12)                    a8
932
      SEARCH DATA EQUAL (12)       b1 DATA OUT
933
      SEARCH DATA HIGH (12)        b0 DATA OUT
934
      SEARCH DATA LOW (12)         b2 DATA OUT
935
      SET LIMITS (12)              b3
936
      VERIFY (12)                  af
937
      WRITE (12)                   aa DATA OUT
938
      WRITE AND VERIFY (12)        ae DATA OUT
939
 
940
      p. 332: Commands for CD-ROM devices (not previously listed)
941
      PAUSE/RESUME                 4b
942
      PLAY AUDIO (10)              45
943
      PLAY AUDIO (12)              a5
944
      PLAY AUDIO MSF               47
945
      PLAY TRACK RELATIVE (10)     49
946
      PLAY TRACK RELATIVE (12)     a9
947
      READ HEADER                  44
948
      READ SUB-CHANNEL             42
949
      READ TOC                     43
950
 
951
      p. 370: Commands for scanner devices (not previously listed)
952
      GET DATA BUFFER STATUS       34
953
      GET WINDOW                   25
954
      OBJECT POSITION              31
955
      SCAN                         1b
956
      SET WINDOW                   24 DATA OUT
957
 
958
      p. 391: Commands for optical memory devices (not listed)
959
      ERASE (10)                   2c
960
      ERASE (12)                   ac
961
      MEDIUM SCAN                  38 DATA OUT
962
      READ DEFECT DATA (12)        b7
963
      READ GENERATION              29
964
      READ UPDATED BLOCK           2d
965
      UPDATE BLOCK                 3d DATA OUT
966
 
967
      p. 419: Commands for medium changer devices (not listed)
968
      EXCHANGE MEDIUM              46
969
      INITIALIZE ELEMENT STATUS    07
970
      MOVE MEDIUM                  a5
971
      POSITION TO ELEMENT          2b
972
      READ ELEMENT STATUS          b8
973
      REQUEST VOL. ELEMENT ADDRESS b5
974
      SEND VOLUME TAG              b6 DATA OUT
975
 
976
      p. 454: Commands for communications devices (not listed previously)
977
      GET MESSAGE (6)              08
978
      GET MESSAGE (10)             28
979
      GET MESSAGE (12)             a8
980
      */
981
 
982
    switch (current_SC->cmnd[0]) {
983
    case CHANGE_DEFINITION: case COMPARE:         case COPY:
984
    case COPY_VERIFY:       case LOG_SELECT:      case MODE_SELECT:
985
    case MODE_SELECT_10:    case SEND_DIAGNOSTIC: case WRITE_BUFFER:
986
 
987
    case FORMAT_UNIT:       case REASSIGN_BLOCKS: case RESERVE:
988
    case SEARCH_EQUAL:      case SEARCH_HIGH:     case SEARCH_LOW:
989
    case WRITE_6:           case WRITE_10:        case WRITE_VERIFY:
990
    case 0x3f:              case 0x41:
991
 
992
    case 0xb1:              case 0xb0:            case 0xb2:
993
    case 0xaa:              case 0xae:
994
 
995
    case 0x24:
996
 
997
    case 0x38:              case 0x3d:
998
 
999
    case 0xb6:
1000
 
1001
    case 0xea:          /* alternate number for WRITE LONG */
1002
 
1003
      current_SC->SCp.have_data_in = -1;
1004
      outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1005
      break;
1006
 
1007
    case 0x00:
1008
    default:
1009
 
1010
      current_SC->SCp.have_data_in = 1;
1011
      outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1012
      break;
1013
    }
1014
  }
1015
 
1016
  if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
1017
    while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
1018
#if EVERY_ACCESS
1019
      printk( "DC=%d, ", data_count ) ;
1020
#endif
1021
      if (data_count > current_SC->SCp.this_residual)
1022
        data_count = current_SC->SCp.this_residual;
1023
      if (data_count > 0) {
1024
#if EVERY_ACCESS
1025
        printk( "%d OUT, ", data_count );
1026
#endif
1027
        if (data_count == 1) {
1028
          Bytes_Written++;
1029
 
1030
          outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1031
          --current_SC->SCp.this_residual;
1032
        } else {
1033
          data_count >>= 1;
1034
          tmp_count = data_count << 1;
1035
          outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1036
          current_SC->SCp.ptr += tmp_count;
1037
          Bytes_Written += tmp_count;
1038
          current_SC->SCp.this_residual -= tmp_count;
1039
        }
1040
      }
1041
      if (!current_SC->SCp.this_residual) {
1042
        if (current_SC->SCp.buffers_residual) {
1043
          --current_SC->SCp.buffers_residual;
1044
          ++current_SC->SCp.buffer;
1045
          current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1046
          current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1047
        } else
1048
          break;
1049
      }
1050
    }
1051
  } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
1052
    while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
1053
#if EVERY_ACCESS
1054
      printk( "DC=%d, ", data_count );
1055
#endif
1056
      if (data_count > current_SC->SCp.this_residual)
1057
        data_count = current_SC->SCp.this_residual;
1058
      if (data_count) {
1059
#if EVERY_ACCESS
1060
        printk( "%d IN, ", data_count );
1061
#endif
1062
        if (data_count == 1) {
1063
          Bytes_Read++;
1064
          *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1065
          --current_SC->SCp.this_residual;
1066
        } else {
1067
          data_count >>= 1; /* Number of words */
1068
          tmp_count = data_count << 1;
1069
          insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1070
          current_SC->SCp.ptr += tmp_count;
1071
          Bytes_Read += tmp_count;
1072
          current_SC->SCp.this_residual -= tmp_count;
1073
        }
1074
      }
1075
      if (!current_SC->SCp.this_residual
1076
          && current_SC->SCp.buffers_residual) {
1077
        --current_SC->SCp.buffers_residual;
1078
        ++current_SC->SCp.buffer;
1079
        current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1080
        current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1081
      }
1082
    }
1083
  }
1084
 
1085
  if (done) {
1086
#if EVERY_ACCESS
1087
    printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1088
#endif
1089
 
1090
#if ERRORS_ONLY
1091
    if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1092
      if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
1093
        unsigned char key;
1094
        unsigned char code;
1095
        unsigned char qualifier;
1096
 
1097
        key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
1098
          & 0x0f;
1099
        code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
1100
        qualifier = (unsigned char)(*((char *)current_SC->request_buffer
1101
                                      + 13));
1102
 
1103
        if (key != UNIT_ATTENTION
1104
            && !(key == NOT_READY
1105
                 && code == 0x04
1106
                 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1107
            && !(key == ILLEGAL_REQUEST && (code == 0x25
1108
                                            || code == 0x24
1109
                                            || !code)))
1110
 
1111
          printk( "fd_mcs: REQUEST SENSE "
1112
                  "Key = %x, Code = %x, Qualifier = %x\n",
1113
                  key, code, qualifier );
1114
      }
1115
    }
1116
#endif
1117
#if EVERY_ACCESS
1118
    printk( "BEFORE MY_DONE. . ." );
1119
#endif
1120
    spin_lock_irqsave(&io_request_lock, flags);
1121
    my_done( shpnt,
1122
             (current_SC->SCp.Status & 0xff)
1123
             | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1124
    spin_unlock_irqrestore(&io_request_lock, flags);
1125
#if EVERY_ACCESS
1126
    printk( "RETURNING.\n" );
1127
#endif
1128
 
1129
  } else {
1130
    if (current_SC->SCp.phase & disconnect) {
1131
      outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1132
      outb( 0x00, SCSI_Cntl_port );
1133
    } else {
1134
      outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1135
    }
1136
  }
1137
#if DEBUG_RACE
1138
  in_interrupt_flag = 0;
1139
#endif
1140
  return;
1141
}
1142
 
1143
int fd_mcs_release(struct Scsi_Host *shpnt)
1144
{
1145
  int i, this_host, irq_usage;
1146
 
1147
  release_region(shpnt->io_port, shpnt->n_io_port);
1148
 
1149
  this_host = -1;
1150
  irq_usage = 0;
1151
  for (i = 0; i < found; i++) {
1152
    if (shpnt == hosts[i])
1153
      this_host = i;
1154
    if (shpnt->irq == hosts[i]->irq)
1155
      irq_usage++;
1156
  }
1157
 
1158
  /* only for the last one */
1159
  if (1 == irq_usage)
1160
    free_irq(shpnt->irq, hosts);
1161
 
1162
  found--;
1163
 
1164
  for (i = this_host; i < found; i++)
1165
    hosts[i] = hosts[i+1];
1166
 
1167
  hosts[found] = NULL;
1168
 
1169
  return 0;
1170
}
1171
 
1172
int fd_mcs_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
1173
{
1174
  struct Scsi_Host *shpnt = SCpnt->host;
1175
 
1176
  if (in_command) {
1177
    panic( "fd_mcs: fd_mcs_queue() NOT REENTRANT!\n" );
1178
  }
1179
#if EVERY_ACCESS
1180
  printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1181
          SCpnt->target,
1182
          *(unsigned char *)SCpnt->cmnd,
1183
          SCpnt->use_sg,
1184
          SCpnt->request_bufflen );
1185
#endif
1186
 
1187
  fd_mcs_make_bus_idle(shpnt);
1188
 
1189
  SCpnt->scsi_done = done;      /* Save this for the done function */
1190
  current_SC       = SCpnt;
1191
 
1192
  /* Initialize static data */
1193
 
1194
  if (current_SC->use_sg) {
1195
    current_SC->SCp.buffer =
1196
      (struct scatterlist *)current_SC->request_buffer;
1197
    current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
1198
    current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
1199
    current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1200
  } else {
1201
    current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
1202
    current_SC->SCp.this_residual    = current_SC->request_bufflen;
1203
    current_SC->SCp.buffer           = NULL;
1204
    current_SC->SCp.buffers_residual = 0;
1205
  }
1206
 
1207
 
1208
  current_SC->SCp.Status              = 0;
1209
  current_SC->SCp.Message             = 0;
1210
  current_SC->SCp.have_data_in        = 0;
1211
  current_SC->SCp.sent_command        = 0;
1212
  current_SC->SCp.phase               = in_arbitration;
1213
 
1214
  /* Start arbitration */
1215
  outb( 0x00, Interrupt_Cntl_port );
1216
  outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
1217
  outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
1218
  in_command = 1;
1219
  outb( 0x20, Interrupt_Cntl_port );
1220
  outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
1221
 
1222
  return 0;
1223
}
1224
 
1225
static void internal_done( Scsi_Cmnd *SCpnt )
1226
{
1227
  /* flag it done */
1228
  SCpnt->host_scribble = (unsigned char *)1;
1229
}
1230
 
1231
int fd_mcs_command( Scsi_Cmnd *SCpnt )
1232
{
1233
  fd_mcs_queue( SCpnt, internal_done );
1234
  /* host_scribble is used for status here */
1235
  SCpnt->host_scribble = NULL;
1236
  while (!SCpnt->host_scribble)
1237
    barrier();
1238
  return SCpnt->result;
1239
}
1240
 
1241
#if DEBUG_ABORT || DEBUG_RESET
1242
static void fd_mcs_print_info( Scsi_Cmnd *SCpnt )
1243
{
1244
  unsigned int imr;
1245
  unsigned int irr;
1246
  unsigned int isr;
1247
  struct Scsi_Host *shpnt = SCpnt->host;
1248
 
1249
  if (!SCpnt || !SCpnt->host) {
1250
    printk( "fd_mcs: cannot provide detailed information\n" );
1251
  }
1252
 
1253
  printk( "%s\n", fd_mcs_info( SCpnt->host ) );
1254
  print_banner( SCpnt->host );
1255
  switch (SCpnt->SCp.phase) {
1256
  case in_arbitration: printk( "arbitration " ); break;
1257
  case in_selection:   printk( "selection " );   break;
1258
  case in_other:       printk( "other " );       break;
1259
  default:             printk( "unknown " );     break;
1260
  }
1261
 
1262
  printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1263
          SCpnt->SCp.phase,
1264
          SCpnt->target,
1265
          *(unsigned char *)SCpnt->cmnd,
1266
          SCpnt->use_sg,
1267
          SCpnt->request_bufflen );
1268
  printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1269
          SCpnt->SCp.sent_command,
1270
          SCpnt->SCp.have_data_in,
1271
          SCpnt->timeout );
1272
#if DEBUG_RACE
1273
  printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1274
#endif
1275
 
1276
  imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1277
  outb( 0x0a, 0xa0 );
1278
  irr = inb( 0xa0 ) << 8;
1279
  outb( 0x0a, 0x20 );
1280
  irr += inb( 0x20 );
1281
  outb( 0x0b, 0xa0 );
1282
  isr = inb( 0xa0 ) << 8;
1283
  outb( 0x0b, 0x20 );
1284
  isr += inb( 0x20 );
1285
 
1286
  /* Print out interesting information */
1287
  printk( "IMR = 0x%04x", imr );
1288
  if (imr & (1 << shpnt->irq))
1289
    printk( " (masked)" );
1290
  printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1291
 
1292
  printk( "SCSI Status      = 0x%02x\n", inb( SCSI_Status_port ) );
1293
  printk( "TMC Status       = 0x%02x", inb( TMC_Status_port ) );
1294
  if (inb( TMC_Status_port ) & 1)
1295
    printk( " (interrupt)" );
1296
  printk( "\n" );
1297
  printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1298
  if (inb( Interrupt_Status_port ) & 0x08)
1299
    printk( " (enabled)" );
1300
  printk( "\n" );
1301
  if (chip == tmc18c50 || chip == tmc18c30) {
1302
    printk( "FIFO Status      = 0x%02x\n", inb( shpnt->io_port + FIFO_Status ) );
1303
    printk( "Int. Condition   = 0x%02x\n",
1304
            inb( shpnt->io_port + Interrupt_Cond ) );
1305
  }
1306
  printk( "Configuration 1  = 0x%02x\n", inb( shpnt->io_port + Configuration1 ) );
1307
  if (chip == tmc18c50 || chip == tmc18c30)
1308
    printk( "Configuration 2  = 0x%02x\n",
1309
            inb( shpnt->io_port + Configuration2 ) );
1310
}
1311
#endif
1312
 
1313
int fd_mcs_abort( Scsi_Cmnd *SCpnt)
1314
{
1315
  struct Scsi_Host *shpnt = SCpnt->host;
1316
 
1317
  unsigned long flags;
1318
#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1319
  printk( "fd_mcs: abort " );
1320
#endif
1321
 
1322
  save_flags( flags );
1323
  cli();
1324
  if (!in_command) {
1325
#if EVERY_ACCESS || ERRORS_ONLY
1326
    printk( " (not in command)\n" );
1327
#endif
1328
    restore_flags( flags );
1329
    return SCSI_ABORT_NOT_RUNNING;
1330
  } else printk( "\n" );
1331
 
1332
#if DEBUG_ABORT
1333
  fd_mcs_print_info( SCpnt );
1334
#endif
1335
 
1336
  fd_mcs_make_bus_idle(shpnt);
1337
 
1338
  current_SC->SCp.phase |= aborted;
1339
 
1340
  current_SC->result = DID_ABORT << 16;
1341
 
1342
  restore_flags( flags );
1343
 
1344
  /* Aborts are not done well. . . */
1345
  spin_lock_irqsave(&io_request_lock, flags);
1346
  my_done( shpnt, DID_ABORT << 16 );
1347
  spin_unlock_irqrestore(&io_request_lock, flags);
1348
 
1349
  return SCSI_ABORT_SUCCESS;
1350
}
1351
 
1352
int fd_mcs_reset( Scsi_Cmnd *SCpnt, unsigned int reset_flags )
1353
{
1354
  struct Scsi_Host *shpnt = SCpnt->host;
1355
 
1356
#if DEBUG_RESET
1357
  static int called_once = 0;
1358
#endif
1359
 
1360
#if ERRORS_ONLY
1361
  if (SCpnt) printk( "fd_mcs: SCSI Bus Reset\n" );
1362
#endif
1363
 
1364
#if DEBUG_RESET
1365
  if (called_once) fd_mcs_print_info( current_SC );
1366
  called_once = 1;
1367
#endif
1368
 
1369
  outb( 1, SCSI_Cntl_port );
1370
  do_pause( 2 );
1371
  outb( 0, SCSI_Cntl_port );
1372
  do_pause( 115 );
1373
  outb( 0, SCSI_Mode_Cntl_port );
1374
  outb( PARITY_MASK, TMC_Cntl_port );
1375
 
1376
  /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1377
     is probably hosed at this point.  We will, however, try to keep
1378
     things going by informing the high-level code that we need help. */
1379
 
1380
  return SCSI_RESET_WAKEUP;
1381
}
1382
 
1383
#include "sd.h"
1384
#include <scsi/scsi_ioctl.h>
1385
 
1386
int fd_mcs_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
1387
{
1388
  int              drive;
1389
  unsigned char    buf[512 + sizeof( int ) * 2];
1390
  int               size      = disk->capacity;
1391
  int              *sizes    = (int *)buf;
1392
  unsigned char    *data     = (unsigned char *)(sizes + 2);
1393
  unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
1394
  int              retcode;
1395
 
1396
  /* BIOS >= 3.4 for MCA cards */
1397
  drive = MINOR(dev) / 16;
1398
 
1399
  /* This algorithm was provided by Future Domain (much thanks!). */
1400
 
1401
  sizes[0] = 0;           /* zero bytes out */
1402
  sizes[1] = 512;               /* one sector in */
1403
  memcpy( data, do_read, sizeof( do_read ) );
1404
  retcode = kernel_scsi_ioctl( disk->device,
1405
                               SCSI_IOCTL_SEND_COMMAND,
1406
                               (void *)buf );
1407
  if (!retcode                              /* SCSI command ok */
1408
      && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
1409
      && data[0x1c2]) {                     /* Partition type */
1410
 
1411
    /* The partition table layout is as follows:
1412
 
1413
         Start: 0x1b3h
1414
         Offset: 0 = partition status
1415
         1 = starting head
1416
         2 = starting sector and cylinder (word, encoded)
1417
         4 = partition type
1418
         5 = ending head
1419
         6 = ending sector and cylinder (word, encoded)
1420
         8 = starting absolute sector (double word)
1421
         c = number of sectors (double word)
1422
         Signature: 0x1fe = 0x55aa
1423
 
1424
         So, this algorithm assumes:
1425
         1) the first partition table is in use,
1426
         2) the data in the first entry is correct, and
1427
         3) partitions never divide cylinders
1428
 
1429
         Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1430
         as well as for Linux.  Note also, that Linux doesn't pay any
1431
         attention to the fields that are used by this algorithm -- it
1432
         only uses the absolute sector data.  Recent versions of Linux's
1433
         fdisk(1) will fill this data in correctly, and forthcoming
1434
         versions will check for consistency.
1435
 
1436
         Checking for a non-zero partition type is not part of the
1437
         Future Domain algorithm, but it seemed to be a reasonable thing
1438
         to do, especially in the Linux and BSD worlds. */
1439
 
1440
    info_array[0] = data[0x1c3] + 1;         /* heads */
1441
    info_array[1] = data[0x1c4] & 0x3f;     /* sectors */
1442
  } else {
1443
 
1444
    /* Note that this new method guarantees that there will always be
1445
         less than 1024 cylinders on a platter.  This is good for drives
1446
         up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1447
 
1448
    if ((unsigned int)size >= 0x7e0000U) {
1449
      info_array[0] = 0xff; /* heads   = 255 */
1450
      info_array[1] = 0x3f; /* sectors =  63 */
1451
    } else if ((unsigned int)size >= 0x200000U) {
1452
      info_array[0] = 0x80; /* heads   = 128 */
1453
      info_array[1] = 0x3f; /* sectors =  63 */
1454
    } else {
1455
      info_array[0] = 0x40; /* heads   =  64 */
1456
      info_array[1] = 0x20; /* sectors =  32 */
1457
    }
1458
  }
1459
  /* For both methods, compute the cylinders */
1460
  info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
1461
 
1462
 
1463
  return 0;
1464
}
1465
 
1466
/* Eventually this will go into an include file, but this will be later */
1467
static Scsi_Host_Template driver_template = FD_MCS;
1468
 
1469
#include "scsi_module.c"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.