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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [psi240i.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*+M*************************************************************************
2
 * Perceptive Solutions, Inc. PSI-240I device driver proc support for Linux.
3
 *
4
 * Copyright (c) 1997 Perceptive Solutions, Inc.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2, or (at your option)
9
 * any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; see the file COPYING.  If not, write to
18
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
 *
20
 *
21
 *      File Name:              psi240i.c
22
 *
23
 *      Description:    SCSI driver for the PSI240I EIDE interface card.
24
 *
25
 *-M*************************************************************************/
26
 
27
#include <linux/module.h>
28
 
29
#include <linux/kernel.h>
30
#include <linux/head.h>
31
#include <linux/types.h>
32
#include <linux/string.h>
33
#include <linux/ioport.h>
34
#include <linux/delay.h>
35
#include <linux/sched.h>
36
#include <linux/proc_fs.h>
37
#include <asm/dma.h>
38
#include <asm/system.h>
39
#include <asm/io.h>
40
#include <linux/blk.h>
41
#include "scsi.h"
42
#include "hosts.h"
43
 
44
#include "psi240i.h"
45
#include "psi_chip.h"
46
 
47
#include<linux/stat.h>
48
 
49
struct proc_dir_entry Proc_Scsi_Psi240i =
50
        { PROC_SCSI_PSI240I, 7, "psi240i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
51
 
52
//#define DEBUG 1
53
 
54
#ifdef DEBUG
55
#define DEB(x) x
56
#else
57
#define DEB(x)
58
#endif
59
 
60
#define MAXBOARDS 2     /* Increase this and the sizes of the arrays below, if you need more. */
61
 
62
#define PORT_DATA                               0
63
#define PORT_ERROR                              1
64
#define PORT_SECTOR_COUNT               2
65
#define PORT_LBA_0                              3
66
#define PORT_LBA_8                              4
67
#define PORT_LBA_16                             5
68
#define PORT_LBA_24                             6
69
#define PORT_STAT_CMD                   7
70
#define PORT_SEL_FAIL                   8
71
#define PORT_IRQ_STATUS                 9
72
#define PORT_ADDRESS                    10
73
#define PORT_FAIL                               11
74
#define PORT_ALT_STAT                   12
75
 
76
typedef struct
77
        {
78
        UCHAR                   device;                         // device code
79
        UCHAR                   byte6;                          // device select register image
80
        UCHAR                   spigot;                         // spigot number
81
        UCHAR                   expectingIRQ;           // flag for expecting and interrupt
82
        USHORT                  sectors;                        // number of sectors per track
83
        USHORT                  heads;                          // number of heads
84
        USHORT                  cylinders;                      // number of cylinders for this device
85
        USHORT                  spareword;                      // placeholder
86
        ULONG                   blocks;                         // number of blocks on device
87
        }       OUR_DEVICE, *POUR_DEVICE;
88
 
89
typedef struct
90
        {
91
        USHORT           ports[13];
92
        OUR_DEVICE       device[8];
93
        Scsi_Cmnd       *pSCmnd;
94
        IDE_STRUCT       ide;
95
        ULONG            startSector;
96
        USHORT           sectorCount;
97
        Scsi_Cmnd       *SCpnt;
98
        VOID            *buffer;
99
        USHORT           expectingIRQ;
100
        }       ADAPTER240I, *PADAPTER240I;
101
 
102
#define HOSTDATA(host) ((PADAPTER240I)&host->hostdata)
103
 
104
static struct   Scsi_Host *PsiHost[6] = {NULL,};  /* One for each IRQ level (10-15) */
105
static                  IDENTIFY_DATA   identifyData;
106
static                  SETUP                   ChipSetup;
107
 
108
static  USHORT  portAddr[6] = {CHIP_ADRS_0, CHIP_ADRS_1, CHIP_ADRS_2, CHIP_ADRS_3, CHIP_ADRS_4, CHIP_ADRS_5};
109
 
110
/****************************************************************
111
 *      Name:   WriteData       :LOCAL
112
 *
113
 *      Description:    Write data to device.
114
 *
115
 *      Parameters:             padapter - Pointer adapter data structure.
116
 *
117
 *      Returns:                TRUE if drive does not assert DRQ in time.
118
 *
119
 ****************************************************************/
120
static int WriteData (PADAPTER240I padapter)
121
        {
122
        ULONG   timer;
123
        USHORT *pports = padapter->ports;
124
 
125
        timer = jiffies + TIMEOUT_DRQ;                                                          // calculate the timeout value
126
        do  {
127
                if ( inb_p (pports[PORT_STAT_CMD]) & IDE_STATUS_DRQ )
128
                        {
129
                        outsw (pports[PORT_DATA], padapter->buffer, (USHORT)padapter->ide.ide.ide[2] * 256);
130
                        return 0;
131
                        }
132
                }       while ( timer > jiffies );                                                                      // test for timeout
133
 
134
        padapter->ide.ide.ides.cmd = 0;                                                                  // null out the command byte
135
        return 1;
136
        }
137
/****************************************************************
138
 *      Name:   IdeCmd  :LOCAL
139
 *
140
 *      Description:    Process a queued command from the SCSI manager.
141
 *
142
 *      Parameters:             padapter - Pointer adapter data structure.
143
 *
144
 *      Returns:                Zero if no error or status register contents on error.
145
 *
146
 ****************************************************************/
147
static UCHAR IdeCmd (PADAPTER240I padapter)
148
        {
149
        ULONG   timer;
150
        USHORT *pports = padapter->ports;
151
        UCHAR   status;
152
 
153
        outb_p (padapter->ide.ide.ides.spigot, pports[PORT_SEL_FAIL]);  // select the spigot
154
        outb_p (padapter->ide.ide.ide[6], pports[PORT_LBA_24]);                 // select the drive
155
        timer = jiffies + TIMEOUT_READY;                                                        // calculate the timeout value
156
        do  {
157
                status = inb_p (padapter->ports[PORT_STAT_CMD]);
158
                if ( status & IDE_STATUS_DRDY )
159
                        {
160
                        outb_p (padapter->ide.ide.ide[2], pports[PORT_SECTOR_COUNT]);
161
                        outb_p (padapter->ide.ide.ide[3], pports[PORT_LBA_0]);
162
                        outb_p (padapter->ide.ide.ide[4], pports[PORT_LBA_8]);
163
                        outb_p (padapter->ide.ide.ide[5], pports[PORT_LBA_16]);
164
                        padapter->expectingIRQ = 1;
165
                        outb_p (padapter->ide.ide.ide[7], pports[PORT_STAT_CMD]);
166
 
167
                        if ( padapter->ide.ide.ides.cmd == IDE_CMD_WRITE_MULTIPLE )
168
                                return (WriteData (padapter));
169
 
170
                        return 0;
171
                        }
172
                }       while ( timer > jiffies );                                                                      // test for timeout
173
 
174
        padapter->ide.ide.ides.cmd = 0;                                                                  // null out the command byte
175
        return status;
176
        }
177
/****************************************************************
178
 *      Name:   SetupTransfer   :LOCAL
179
 *
180
 *      Description:    Setup a data transfer command.
181
 *
182
 *      Parameters:             padapter - Pointer adapter data structure.
183
 *                                      drive    - Drive/head register upper nibble only.
184
 *
185
 *      Returns:                TRUE if no data to transfer.
186
 *
187
 ****************************************************************/
188
static int SetupTransfer (PADAPTER240I padapter, UCHAR drive)
189
        {
190
        if ( padapter->sectorCount )
191
                {
192
                *(ULONG *)padapter->ide.ide.ides.lba = padapter->startSector;
193
                padapter->ide.ide.ide[6] |= drive;
194
                padapter->ide.ide.ides.sectors = ( padapter->sectorCount > SECTORSXFER ) ? SECTORSXFER : padapter->sectorCount;
195
                padapter->sectorCount -= padapter->ide.ide.ides.sectors;        // bump the start and count for next xfer
196
                padapter->startSector += padapter->ide.ide.ides.sectors;
197
                return 0;
198
                }
199
        else
200
                {
201
                padapter->ide.ide.ides.cmd = 0;                                                          // null out the command byte
202
                padapter->SCpnt = NULL;
203
                return 1;
204
                }
205
        }
206
/****************************************************************
207
 *      Name:   DecodeError     :LOCAL
208
 *
209
 *      Description:    Decode and process device errors.
210
 *
211
 *      Parameters:             pshost - Pointer to host data block.
212
 *                                      status - Status register code.
213
 *
214
 *      Returns:                The driver status code.
215
 *
216
 ****************************************************************/
217
static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status)
218
        {
219
        PADAPTER240I    padapter = HOSTDATA(pshost);
220
        UCHAR                   error;
221
 
222
        padapter->expectingIRQ = 0;
223
        padapter->SCpnt = NULL;
224
        if ( status & IDE_STATUS_WRITE_FAULT )
225
                {
226
                return DID_PARITY << 16;
227
                }
228
        if ( status & IDE_STATUS_BUSY )
229
                return DID_BUS_BUSY << 16;
230
 
231
        error = inb_p (padapter->ports[PORT_ERROR]);
232
        DEB(printk ("\npsi240i error register: %x", error));
233
        switch ( error )
234
                {
235
                case IDE_ERROR_AMNF:
236
                case IDE_ERROR_TKONF:
237
                case IDE_ERROR_ABRT:
238
                case IDE_ERROR_IDFN:
239
                case IDE_ERROR_UNC:
240
                case IDE_ERROR_BBK:
241
                default:
242
                        return DID_ERROR << 16;
243
                }
244
        return DID_ERROR << 16;
245
        }
246
/****************************************************************
247
 *      Name:   Irq_Handler     :LOCAL
248
 *
249
 *      Description:    Interrupt handler.
250
 *
251
 *      Parameters:             irq             - Hardware IRQ number.
252
 *                                      dev_id  -
253
 *                                      regs    -
254
 *
255
 *      Returns:                TRUE if drive is not ready in time.
256
 *
257
 ****************************************************************/
258
static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
259
        {
260
        struct Scsi_Host   *shost;                      // Pointer to host data block
261
        PADAPTER240I            padapter;               // Pointer to adapter control structure
262
        USHORT                     *pports;                     // I/O port array
263
        Scsi_Cmnd                  *SCpnt;
264
        UCHAR                           status;
265
        int                                     z;
266
 
267
        DEB(printk ("\npsi240i recieved interrupt\n"));
268
 
269
        shost = PsiHost[irq - 10];
270
        if ( !shost )
271
                panic ("Splunge!");
272
 
273
        padapter = HOSTDATA(shost);
274
        pports = padapter->ports;
275
        SCpnt = padapter->SCpnt;
276
 
277
        if ( !padapter->expectingIRQ )
278
                {
279
                DEB(printk ("\npsi240i Unsolicited interrupt\n"));
280
                return;
281
                }
282
        padapter->expectingIRQ = 0;
283
 
284
        status = inb_p (padapter->ports[PORT_STAT_CMD]);                        // read the device status
285
        if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
286
                goto irqerror;
287
 
288
        DEB(printk ("\npsi240i processing interrupt"));
289
        switch ( padapter->ide.ide.ides.cmd )                                                   // decide how to handle the interrupt
290
                {
291
                case IDE_CMD_READ_MULTIPLE:
292
                        if ( status & IDE_STATUS_DRQ )
293
                                {
294
                                insw (pports[PORT_DATA], padapter->buffer, (USHORT)padapter->ide.ide.ides.sectors * 256);
295
                                padapter->buffer += padapter->ide.ide.ides.sectors * 512;
296
                                if ( SetupTransfer (padapter, padapter->ide.ide.ide[6] & 0xF0) )
297
                                        {
298
                                        SCpnt->result = DID_OK << 16;
299
                                        padapter->SCpnt = NULL;
300
                                        SCpnt->scsi_done (SCpnt);
301
                                        return;
302
                                        }
303
                                if ( !(status = IdeCmd (padapter)) )
304
                                        return;
305
                                }
306
                        break;
307
 
308
                case IDE_CMD_WRITE_MULTIPLE:
309
                        padapter->buffer += padapter->ide.ide.ides.sectors * 512;
310
                        if ( SetupTransfer (padapter, padapter->ide.ide.ide[6] & 0xF0) )
311
                                {
312
                                SCpnt->result = DID_OK << 16;
313
                                padapter->SCpnt = NULL;
314
                                SCpnt->scsi_done (SCpnt);
315
                                return;
316
                                }
317
                        if ( !(status = IdeCmd (padapter)) )
318
                                return;
319
                        break;
320
 
321
                case IDE_COMMAND_IDENTIFY:
322
                        {
323
                        PINQUIRYDATA    pinquiryData  = SCpnt->request_buffer;
324
 
325
                        if ( status & IDE_STATUS_DRQ )
326
                                {
327
                                insw (pports[PORT_DATA], &identifyData, sizeof (identifyData) >> 1);
328
 
329
                                memset (pinquiryData, 0, SCpnt->request_bufflen);                // Zero INQUIRY data structure.
330
                                pinquiryData->DeviceType = 0;
331
                                pinquiryData->Versions = 2;
332
                                pinquiryData->AdditionalLength = 35 - 4;
333
 
334
                                // Fill in vendor identification fields.
335
                                for ( z = 0;  z < 20;  z += 2 )
336
                                        {
337
                                        pinquiryData->VendorId[z]         = ((UCHAR *)identifyData.ModelNumber)[z + 1];
338
                                        pinquiryData->VendorId[z + 1] = ((UCHAR *)identifyData.ModelNumber)[z];
339
                                        }
340
 
341
                                // Initialize unused portion of product id.
342
                                for ( z = 0;  z < 4;  z++ )
343
                                        pinquiryData->ProductId[12 + z] = ' ';
344
 
345
                                // Move firmware revision from IDENTIFY data to
346
                                // product revision in INQUIRY data.
347
                                for ( z = 0;  z < 4;  z += 2 )
348
                                        {
349
                                        pinquiryData->ProductRevisionLevel[z]    = ((UCHAR *)identifyData.FirmwareRevision)[z + 1];
350
                                        pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)identifyData.FirmwareRevision)[z];
351
                                        }
352
 
353
                                SCpnt->result = DID_OK << 16;
354
                                padapter->SCpnt = NULL;
355
                                SCpnt->scsi_done (SCpnt);
356
                                return;
357
                                }
358
                        break;
359
                        }
360
 
361
                default:
362
                        SCpnt->result = DID_OK << 16;
363
                        padapter->SCpnt = NULL;
364
                        SCpnt->scsi_done (SCpnt);
365
                        return;
366
                }
367
 
368
irqerror:;
369
        DEB(printk ("\npsi240i error  Device Status: %X\n", status));
370
        SCpnt->result = DecodeError (shost, status);
371
        SCpnt->scsi_done (SCpnt);
372
        }
373
/****************************************************************
374
 *      Name:   Psi240i_QueueCommand
375
 *
376
 *      Description:    Process a queued command from the SCSI manager.
377
 *
378
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
379
 *                                      done  - Pointer to done function to call.
380
 *
381
 *      Returns:                Status code.
382
 *
383
 ****************************************************************/
384
int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
385
        {
386
        UCHAR              *cdb = (UCHAR *)SCpnt->cmnd;                                 // Pointer to SCSI CDB
387
        PADAPTER240I    padapter = HOSTDATA(SCpnt->host);                       // Pointer to adapter control structure
388
        POUR_DEVICE             pdev     = &padapter->device[SCpnt->target];// Pointer to device information
389
        UCHAR                   rc;                                                                                     // command return code
390
 
391
        SCpnt->scsi_done = done;
392
        padapter->ide.ide.ides.spigot = pdev->spigot;
393
        padapter->buffer = SCpnt->request_buffer;
394
        if (done)
395
                {
396
                if ( !pdev->device || SCpnt->lun )
397
                        {
398
                        SCpnt->result = DID_BAD_TARGET << 16;
399
                        done (SCpnt);
400
                        return 0;
401
                        }
402
                }
403
        else
404
                {
405
                printk("psi240i_queuecommand: %02X: done can't be NULL\n", *cdb);
406
                return 0;
407
                }
408
 
409
        switch ( *cdb )
410
                {
411
                case SCSIOP_INQUIRY:                                    // inquiry CDB
412
                        {
413
                        padapter->ide.ide.ide[6] = pdev->byte6;
414
                        padapter->ide.ide.ides.cmd = IDE_COMMAND_IDENTIFY;
415
                        break;
416
                        }
417
 
418
                case SCSIOP_TEST_UNIT_READY:                    // test unit ready CDB
419
                        SCpnt->result = DID_OK << 16;
420
                        done (SCpnt);
421
                        return 0;
422
 
423
                case SCSIOP_READ_CAPACITY:                              // read capctiy CDB
424
                        {
425
                        PREAD_CAPACITY_DATA     pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
426
 
427
                        pdata->blksiz = 0x20000;
428
                        XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
429
                        SCpnt->result = DID_OK << 16;
430
                        done (SCpnt);
431
                        return 0;
432
                        }
433
 
434
                case SCSIOP_VERIFY:                                             // verify CDB
435
                        *(ULONG *)padapter->ide.ide.ides.lba = XSCSI2LONG (&cdb[2]);
436
                        padapter->ide.ide.ide[6] |= pdev->byte6;
437
                        padapter->ide.ide.ide[2] = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
438
                        padapter->ide.ide.ides.cmd = IDE_COMMAND_VERIFY;
439
                        break;
440
 
441
                case SCSIOP_READ:                                               // read10 CDB
442
                        padapter->startSector = XSCSI2LONG (&cdb[2]);
443
                        padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
444
                        SetupTransfer (padapter, pdev->byte6);
445
                        padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
446
                        break;
447
 
448
                case SCSIOP_READ6:                                              // read6  CDB
449
                        padapter->startSector = SCSI2LONG (&cdb[1]);
450
                        padapter->sectorCount = cdb[4];
451
                        SetupTransfer (padapter, pdev->byte6);
452
                        padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
453
                        break;
454
 
455
                case SCSIOP_WRITE:                                              // write10 CDB
456
                        padapter->startSector = XSCSI2LONG (&cdb[2]);
457
                        padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
458
                        SetupTransfer (padapter, pdev->byte6);
459
                        padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
460
                        break;
461
                case SCSIOP_WRITE6:                                             // write6  CDB
462
                        padapter->startSector = SCSI2LONG (&cdb[1]);
463
                        padapter->sectorCount = cdb[4];
464
                        SetupTransfer (padapter, pdev->byte6);
465
                        padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
466
                        break;
467
 
468
                default:
469
                        DEB (printk ("psi240i_queuecommand: Unsupported command %02X\n", *cdb));
470
                        SCpnt->result = DID_ERROR << 16;
471
                        done (SCpnt);
472
                        return 0;
473
                }
474
 
475
        padapter->SCpnt = SCpnt;                                                                        // Save this command data
476
 
477
        rc = IdeCmd (padapter);
478
        if ( rc )
479
                {
480
                padapter->expectingIRQ = 0;
481
                DEB (printk ("psi240i_queuecommand: %02X, %02X: Device failed to respond for command\n", *cdb, padapter->ide.ide.ides.cmd));
482
                SCpnt->result = DID_ERROR << 16;
483
                done (SCpnt);
484
                return 0;
485
                }
486
        DEB (printk("psi240i_queuecommand: %02X, %02X now waiting for interrupt ", *cdb, padapter->ide.ide.ides.cmd));
487
        return 0;
488
        }
489
 
490
static void internal_done(Scsi_Cmnd * SCpnt)
491
        {
492
        SCpnt->SCp.Status++;
493
        }
494
/****************************************************************
495
 *      Name:   Psi240i_Command
496
 *
497
 *      Description:    Process a command from the SCSI manager.
498
 *
499
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
500
 *
501
 *      Returns:                Status code.
502
 *
503
 ****************************************************************/
504
int Psi240i_Command (Scsi_Cmnd *SCpnt)
505
        {
506
        DEB(printk("psi240i_command: ..calling psi240i_queuecommand\n"));
507
 
508
        Psi240i_QueueCommand (SCpnt, internal_done);
509
 
510
    SCpnt->SCp.Status = 0;
511
        while (!SCpnt->SCp.Status)
512
                barrier ();
513
        return SCpnt->result;
514
        }
515
/***************************************************************************
516
 *      Name:                   ReadChipMemory
517
 *
518
 *      Description:    Read information from controller memory.
519
 *
520
 *      Parameters:             psetup  - Pointer to memory image of setup information.
521
 *                                      base    - base address of memory.
522
 *                                      length  - lenght of data space in bytes.
523
 *                                      port    - I/O address of data port.
524
 *
525
 *      Returns:                Nothing.
526
 *
527
 **************************************************************************/
528
void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port)
529
        {
530
        USHORT  z, zz;
531
        UCHAR   *pd = (UCHAR *)pdata;
532
        outb_p (SEL_NONE, port + REG_SEL_FAIL);                         // setup data port
533
        zz = 0;
534
        while ( zz < length )
535
                {
536
                outw_p (base, port + REG_ADDRESS);                              // setup address
537
 
538
                for ( z = 0;  z < 8;  z++ )
539
                        {
540
                        if ( (zz + z) < length )
541
                        *pd++ = inb_p (port + z);       // read data byte
542
                        }
543
                zz += 8;
544
                base += 8;
545
                }
546
        }
547
/****************************************************************
548
 *      Name:   Psi240i_Detect
549
 *
550
 *      Description:    Detect and initialize our boards.
551
 *
552
 *      Parameters:             tpnt - Pointer to SCSI host template structure.
553
 *
554
 *      Returns:                Number of adapters found.
555
 *
556
 ****************************************************************/
557
int Psi240i_Detect (Scsi_Host_Template *tpnt)
558
        {
559
        int                                     board;
560
        int                                     count = 0;
561
        int                                     unit;
562
        int                                     z;
563
        USHORT                          port;
564
        CHIP_CONFIG_N           chipConfig;
565
        CHIP_DEVICE_N           chipDevice[8];
566
        struct Scsi_Host   *pshost;
567
        ULONG                           flags;
568
 
569
        for ( board = 0;  board < 6;  board++ )                                  // scan for I/O ports
570
                {
571
                port = portAddr[board];                                                         // get base address to test
572
                if ( check_region (port, 16) )                                          // test for I/O addresses available
573
                        continue;                                                                               //   nope
574
                if ( inb_p (port + REG_FAIL) != CHIP_ID )                       // do the first test for likley hood that it is us
575
                        continue;
576
                outb_p (SEL_NONE, port + REG_SEL_FAIL);                         // setup EEPROM/RAM access
577
                outw (0, port + REG_ADDRESS);                                            // setup EEPROM address zero
578
                if ( inb_p (port) != 0x55 )                                                     // test 1st byte
579
                        continue;                                                                               //   nope
580
                if ( inb_p (port + 1) != 0xAA )                                         // test 2nd byte
581
                        continue;                                                                               //   nope
582
 
583
                // at this point our board is found and can be accessed.  Now we need to initialize
584
                // our informatation and register with the kernel.
585
 
586
 
587
                ReadChipMemory (&chipConfig, CHIP_CONFIG, sizeof (chipConfig), port);
588
                ReadChipMemory (&chipDevice, CHIP_DEVICE, sizeof (chipDevice), port);
589
                ReadChipMemory (&ChipSetup, CHIP_EEPROM_DATA, sizeof (ChipSetup), port);
590
 
591
                if ( !chipConfig.numDrives )                                            // if no devices on this board
592
                        continue;
593
 
594
                pshost = scsi_register (tpnt, sizeof(ADAPTER240I));
595
 
596
                save_flags (flags);
597
                cli ();
598
                if ( request_irq (chipConfig.irq, Irq_Handler, 0, "psi240i", NULL) )
599
                        {
600
                        printk ("Unable to allocate IRQ for PSI-240I controller.\n");
601
                        restore_flags (flags);
602
                        goto unregister;
603
                        }
604
 
605
                PsiHost[chipConfig.irq - 10] = pshost;
606
                pshost->unique_id = port;
607
                pshost->io_port = port;
608
                pshost->n_io_port = 16;  /* Number of bytes of I/O space used */
609
                pshost->irq = chipConfig.irq;
610
 
611
                for ( z = 0;  z < 11;  z++ )                                             // build regester address array
612
                        HOSTDATA(pshost)->ports[z] = port + z;
613
                HOSTDATA(pshost)->ports[11] = port + REG_FAIL;
614
                HOSTDATA(pshost)->ports[12] = port + REG_ALT_STAT;
615
                DEB (printk ("\nPorts ="));
616
                DEB (for (z=0;z<13;z++) printk(" %#04X",HOSTDATA(pshost)->ports[z]););
617
 
618
                for ( z = 0;  z < chipConfig.numDrives;  ++z )
619
                        {
620
                        unit = chipDevice[z].channel & 0x0F;
621
                        HOSTDATA(pshost)->device[unit].device    = ChipSetup.setupDevice[unit].device;
622
                        HOSTDATA(pshost)->device[unit].byte6     = (UCHAR)(((unit & 1) << 4) | 0xE0);
623
                        HOSTDATA(pshost)->device[unit].spigot    = (UCHAR)(1 << (unit >> 1));
624
                        HOSTDATA(pshost)->device[unit].sectors   = ChipSetup.setupDevice[unit].sectors;
625
                        HOSTDATA(pshost)->device[unit].heads     = ChipSetup.setupDevice[unit].heads;
626
                        HOSTDATA(pshost)->device[unit].cylinders = ChipSetup.setupDevice[unit].cylinders;
627
                        HOSTDATA(pshost)->device[unit].blocks    = ChipSetup.setupDevice[unit].blocks;
628
                        DEB (printk ("\nHOSTDATA->device    = %X", HOSTDATA(pshost)->device[unit].device));
629
                        DEB (printk ("\n          byte6     = %X", HOSTDATA(pshost)->device[unit].byte6));
630
                        DEB (printk ("\n          spigot    = %X", HOSTDATA(pshost)->device[unit].spigot));
631
                        DEB (printk ("\n          sectors   = %X", HOSTDATA(pshost)->device[unit].sectors));
632
                        DEB (printk ("\n          heads     = %X", HOSTDATA(pshost)->device[unit].heads));
633
                        DEB (printk ("\n          cylinders = %X", HOSTDATA(pshost)->device[unit].cylinders));
634
                        DEB (printk ("\n          blocks    = %lX", HOSTDATA(pshost)->device[unit].blocks));
635
                        }
636
 
637
                restore_flags (flags);
638
                printk("\nPSI-240I EIDE CONTROLLER: at I/O = %x  IRQ = %d\n", port, chipConfig.irq);
639
                printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
640
                count++;
641
                continue;
642
 
643
unregister:;
644
                scsi_unregister (pshost);
645
                }
646
        return count;
647
        }
648
/****************************************************************
649
 *      Name:   Psi240i_Abort
650
 *
651
 *      Description:    Process the Abort command from the SCSI manager.
652
 *
653
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
654
 *
655
 *      Returns:                Allways snooze.
656
 *
657
 ****************************************************************/
658
int Psi240i_Abort (Scsi_Cmnd *SCpnt)
659
        {
660
        DEB (printk ("psi240i_abort\n"));
661
        return SCSI_ABORT_SNOOZE;
662
        }
663
/****************************************************************
664
 *      Name:   Psi240i_Reset
665
 *
666
 *      Description:    Process the Reset command from the SCSI manager.
667
 *
668
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
669
 *                                      flags - Flags about the reset command
670
 *
671
 *      Returns:                No active command at this time, so this means
672
 *                                      that each time we got some kind of response the
673
 *                                      last time through.  Tell the mid-level code to
674
 *                                      request sense information in order to decide what
675
 *                                      to do next.
676
 *
677
 ****************************************************************/
678
int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
679
        {
680
        return SCSI_RESET_PUNT;
681
        }
682
 
683
#include "sd.h"
684
 
685
/****************************************************************
686
 *      Name:   Psi240i_BiosParam
687
 *
688
 *      Description:    Process the biosparam request from the SCSI manager to
689
 *                                      return C/H/S data.
690
 *
691
 *      Parameters:             disk - Pointer to SCSI disk structure.
692
 *                                      dev      - Major/minor number from kernel.
693
 *                                      geom - Pointer to integer array to place geometry data.
694
 *
695
 *      Returns:                zero.
696
 *
697
 ****************************************************************/
698
int Psi240i_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[])
699
        {
700
        POUR_DEVICE     pdev;
701
 
702
        pdev = &(HOSTDATA(disk->device->host)->device[disk->device->id]);
703
 
704
        geom[0] = pdev->heads;
705
        geom[1] = pdev->sectors;
706
        geom[2] = pdev->cylinders;
707
        return 0;
708
        }
709
 
710
 
711
#ifdef MODULE
712
/* Eventually this will go into an include file, but this will be later */
713
Scsi_Host_Template driver_template = PSI240I;
714
 
715
#include "scsi_module.c"
716
#endif
717
 

powered by: WebSVN 2.1.0

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