Import 2.3.18pre1
[davej-history.git] / drivers / scsi / psi240i.c
blob2fa6995769227dec445e8e465ba93ae5efbe5552
1 /*+M*************************************************************************
2 * Perceptive Solutions, Inc. PSI-240I device driver proc support for Linux.
4 * Copyright (c) 1997 Perceptive Solutions, Inc.
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.
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.
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.
21 * File Name: psi240i.c
23 * Description: SCSI driver for the PSI240I EIDE interface card.
25 *-M*************************************************************************/
27 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/types.h>
31 #include <linux/string.h>
32 #include <linux/ioport.h>
33 #include <linux/delay.h>
34 #include <linux/sched.h>
35 #include <linux/proc_fs.h>
36 #include <linux/spinlock.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"
44 #include "psi240i.h"
45 #include "psi_chip.h"
47 #include<linux/stat.h>
49 struct proc_dir_entry Proc_Scsi_Psi240i =
50 { PROC_SCSI_PSI240I, 7, "psi240i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
52 //#define DEBUG 1
54 #ifdef DEBUG
55 #define DEB(x) x
56 #else
57 #define DEB(x)
58 #endif
60 #define MAXBOARDS 2 /* Increase this and the sizes of the arrays below, if you need more. */
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
76 typedef struct
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;
89 typedef struct
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;
102 #define HOSTDATA(host) ((PADAPTER240I)&host->hostdata)
104 static struct Scsi_Host *PsiHost[6] = {NULL,}; /* One for each IRQ level (10-15) */
105 static IDENTIFY_DATA identifyData;
106 static SETUP ChipSetup;
108 static USHORT portAddr[6] = {CHIP_ADRS_0, CHIP_ADRS_1, CHIP_ADRS_2, CHIP_ADRS_3, CHIP_ADRS_4, CHIP_ADRS_5};
110 /****************************************************************
111 * Name: WriteData :LOCAL
113 * Description: Write data to device.
115 * Parameters: padapter - Pointer adapter data structure.
117 * Returns: TRUE if drive does not assert DRQ in time.
119 ****************************************************************/
120 static int WriteData (PADAPTER240I padapter)
122 ULONG timer;
123 USHORT *pports = padapter->ports;
125 timer = jiffies + TIMEOUT_DRQ; // calculate the timeout value
126 do {
127 if ( inb_p (pports[PORT_STAT_CMD]) & IDE_STATUS_DRQ )
129 outsw (pports[PORT_DATA], padapter->buffer, (USHORT)padapter->ide.ide.ide[2] * 256);
130 return 0;
132 } while ( time_after(timer, jiffies) ); // test for timeout
134 padapter->ide.ide.ides.cmd = 0; // null out the command byte
135 return 1;
137 /****************************************************************
138 * Name: IdeCmd :LOCAL
140 * Description: Process a queued command from the SCSI manager.
142 * Parameters: padapter - Pointer adapter data structure.
144 * Returns: Zero if no error or status register contents on error.
146 ****************************************************************/
147 static UCHAR IdeCmd (PADAPTER240I padapter)
149 ULONG timer;
150 USHORT *pports = padapter->ports;
151 UCHAR status;
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 )
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]);
167 if ( padapter->ide.ide.ides.cmd == IDE_CMD_WRITE_MULTIPLE )
168 return (WriteData (padapter));
170 return 0;
172 } while ( time_after(timer, jiffies) ); // test for timeout
174 padapter->ide.ide.ides.cmd = 0; // null out the command byte
175 return status;
177 /****************************************************************
178 * Name: SetupTransfer :LOCAL
180 * Description: Setup a data transfer command.
182 * Parameters: padapter - Pointer adapter data structure.
183 * drive - Drive/head register upper nibble only.
185 * Returns: TRUE if no data to transfer.
187 ****************************************************************/
188 static int SetupTransfer (PADAPTER240I padapter, UCHAR drive)
190 if ( padapter->sectorCount )
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;
199 else
201 padapter->ide.ide.ides.cmd = 0; // null out the command byte
202 padapter->SCpnt = NULL;
203 return 1;
206 /****************************************************************
207 * Name: DecodeError :LOCAL
209 * Description: Decode and process device errors.
211 * Parameters: pshost - Pointer to host data block.
212 * status - Status register code.
214 * Returns: The driver status code.
216 ****************************************************************/
217 static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status)
219 PADAPTER240I padapter = HOSTDATA(pshost);
220 UCHAR error;
222 padapter->expectingIRQ = 0;
223 padapter->SCpnt = NULL;
224 if ( status & IDE_STATUS_WRITE_FAULT )
226 return DID_PARITY << 16;
228 if ( status & IDE_STATUS_BUSY )
229 return DID_BUS_BUSY << 16;
231 error = inb_p (padapter->ports[PORT_ERROR]);
232 DEB(printk ("\npsi240i error register: %x", error));
233 switch ( error )
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;
244 return DID_ERROR << 16;
246 /****************************************************************
247 * Name: Irq_Handler :LOCAL
249 * Description: Interrupt handler.
251 * Parameters: irq - Hardware IRQ number.
252 * dev_id -
253 * regs -
255 * Returns: TRUE if drive is not ready in time.
257 ****************************************************************/
258 static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
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;
267 DEB(printk ("\npsi240i received interrupt\n"));
269 shost = PsiHost[irq - 10];
270 if ( !shost )
271 panic ("Splunge!");
273 padapter = HOSTDATA(shost);
274 pports = padapter->ports;
275 SCpnt = padapter->SCpnt;
277 if ( !padapter->expectingIRQ )
279 DEB(printk ("\npsi240i Unsolicited interrupt\n"));
280 return;
282 padapter->expectingIRQ = 0;
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;
288 DEB(printk ("\npsi240i processing interrupt"));
289 switch ( padapter->ide.ide.ides.cmd ) // decide how to handle the interrupt
291 case IDE_CMD_READ_MULTIPLE:
292 if ( status & IDE_STATUS_DRQ )
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) )
298 SCpnt->result = DID_OK << 16;
299 padapter->SCpnt = NULL;
300 SCpnt->scsi_done (SCpnt);
301 return;
303 if ( !(status = IdeCmd (padapter)) )
304 return;
306 break;
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) )
312 SCpnt->result = DID_OK << 16;
313 padapter->SCpnt = NULL;
314 SCpnt->scsi_done (SCpnt);
315 return;
317 if ( !(status = IdeCmd (padapter)) )
318 return;
319 break;
321 case IDE_COMMAND_IDENTIFY:
323 PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
325 if ( status & IDE_STATUS_DRQ )
327 insw (pports[PORT_DATA], &identifyData, sizeof (identifyData) >> 1);
329 memset (pinquiryData, 0, SCpnt->request_bufflen); // Zero INQUIRY data structure.
330 pinquiryData->DeviceType = 0;
331 pinquiryData->Versions = 2;
332 pinquiryData->AdditionalLength = 35 - 4;
334 // Fill in vendor identification fields.
335 for ( z = 0; z < 20; z += 2 )
337 pinquiryData->VendorId[z] = ((UCHAR *)identifyData.ModelNumber)[z + 1];
338 pinquiryData->VendorId[z + 1] = ((UCHAR *)identifyData.ModelNumber)[z];
341 // Initialize unused portion of product id.
342 for ( z = 0; z < 4; z++ )
343 pinquiryData->ProductId[12 + z] = ' ';
345 // Move firmware revision from IDENTIFY data to
346 // product revision in INQUIRY data.
347 for ( z = 0; z < 4; z += 2 )
349 pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)identifyData.FirmwareRevision)[z + 1];
350 pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)identifyData.FirmwareRevision)[z];
353 SCpnt->result = DID_OK << 16;
354 padapter->SCpnt = NULL;
355 SCpnt->scsi_done (SCpnt);
356 return;
358 break;
361 default:
362 SCpnt->result = DID_OK << 16;
363 padapter->SCpnt = NULL;
364 SCpnt->scsi_done (SCpnt);
365 return;
368 irqerror:;
369 DEB(printk ("\npsi240i error Device Status: %X\n", status));
370 SCpnt->result = DecodeError (shost, status);
371 SCpnt->scsi_done (SCpnt);
373 static void do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
375 unsigned long flags;
377 spin_lock_irqsave(&io_request_lock, flags);
378 Irq_Handler(irq, dev_id, regs);
379 spin_unlock_irqrestore(&io_request_lock, flags);
381 /****************************************************************
382 * Name: Psi240i_QueueCommand
384 * Description: Process a queued command from the SCSI manager.
386 * Parameters: SCpnt - Pointer to SCSI command structure.
387 * done - Pointer to done function to call.
389 * Returns: Status code.
391 ****************************************************************/
392 int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
394 UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
395 PADAPTER240I padapter = HOSTDATA(SCpnt->host); // Pointer to adapter control structure
396 POUR_DEVICE pdev = &padapter->device[SCpnt->target];// Pointer to device information
397 UCHAR rc; // command return code
399 SCpnt->scsi_done = done;
400 padapter->ide.ide.ides.spigot = pdev->spigot;
401 padapter->buffer = SCpnt->request_buffer;
402 if (done)
404 if ( !pdev->device )
406 SCpnt->result = DID_BAD_TARGET << 16;
407 done (SCpnt);
408 return 0;
411 else
413 printk("psi240i_queuecommand: %02X: done can't be NULL\n", *cdb);
414 return 0;
417 switch ( *cdb )
419 case SCSIOP_INQUIRY: // inquiry CDB
421 padapter->ide.ide.ide[6] = pdev->byte6;
422 padapter->ide.ide.ides.cmd = IDE_COMMAND_IDENTIFY;
423 break;
426 case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
427 SCpnt->result = DID_OK << 16;
428 done (SCpnt);
429 return 0;
431 case SCSIOP_READ_CAPACITY: // read capctiy CDB
433 PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
435 pdata->blksiz = 0x20000;
436 XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
437 SCpnt->result = DID_OK << 16;
438 done (SCpnt);
439 return 0;
442 case SCSIOP_VERIFY: // verify CDB
443 *(ULONG *)padapter->ide.ide.ides.lba = XSCSI2LONG (&cdb[2]);
444 padapter->ide.ide.ide[6] |= pdev->byte6;
445 padapter->ide.ide.ide[2] = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
446 padapter->ide.ide.ides.cmd = IDE_COMMAND_VERIFY;
447 break;
449 case SCSIOP_READ: // read10 CDB
450 padapter->startSector = XSCSI2LONG (&cdb[2]);
451 padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
452 SetupTransfer (padapter, pdev->byte6);
453 padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
454 break;
456 case SCSIOP_READ6: // read6 CDB
457 padapter->startSector = SCSI2LONG (&cdb[1]);
458 padapter->sectorCount = cdb[4];
459 SetupTransfer (padapter, pdev->byte6);
460 padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
461 break;
463 case SCSIOP_WRITE: // write10 CDB
464 padapter->startSector = XSCSI2LONG (&cdb[2]);
465 padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
466 SetupTransfer (padapter, pdev->byte6);
467 padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
468 break;
469 case SCSIOP_WRITE6: // write6 CDB
470 padapter->startSector = SCSI2LONG (&cdb[1]);
471 padapter->sectorCount = cdb[4];
472 SetupTransfer (padapter, pdev->byte6);
473 padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
474 break;
476 default:
477 DEB (printk ("psi240i_queuecommand: Unsupported command %02X\n", *cdb));
478 SCpnt->result = DID_ERROR << 16;
479 done (SCpnt);
480 return 0;
483 padapter->SCpnt = SCpnt; // Save this command data
485 rc = IdeCmd (padapter);
486 if ( rc )
488 padapter->expectingIRQ = 0;
489 DEB (printk ("psi240i_queuecommand: %02X, %02X: Device failed to respond for command\n", *cdb, padapter->ide.ide.ides.cmd));
490 SCpnt->result = DID_ERROR << 16;
491 done (SCpnt);
492 return 0;
494 DEB (printk("psi240i_queuecommand: %02X, %02X now waiting for interrupt ", *cdb, padapter->ide.ide.ides.cmd));
495 return 0;
498 static void internal_done(Scsi_Cmnd * SCpnt)
500 SCpnt->SCp.Status++;
502 /****************************************************************
503 * Name: Psi240i_Command
505 * Description: Process a command from the SCSI manager.
507 * Parameters: SCpnt - Pointer to SCSI command structure.
509 * Returns: Status code.
511 ****************************************************************/
512 int Psi240i_Command (Scsi_Cmnd *SCpnt)
514 DEB(printk("psi240i_command: ..calling psi240i_queuecommand\n"));
516 Psi240i_QueueCommand (SCpnt, internal_done);
518 SCpnt->SCp.Status = 0;
519 while (!SCpnt->SCp.Status)
520 barrier ();
521 return SCpnt->result;
523 /***************************************************************************
524 * Name: ReadChipMemory
526 * Description: Read information from controller memory.
528 * Parameters: psetup - Pointer to memory image of setup information.
529 * base - base address of memory.
530 * length - lenght of data space in bytes.
531 * port - I/O address of data port.
533 * Returns: Nothing.
535 **************************************************************************/
536 void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port)
538 USHORT z, zz;
539 UCHAR *pd = (UCHAR *)pdata;
540 outb_p (SEL_NONE, port + REG_SEL_FAIL); // setup data port
541 zz = 0;
542 while ( zz < length )
544 outw_p (base, port + REG_ADDRESS); // setup address
546 for ( z = 0; z < 8; z++ )
548 if ( (zz + z) < length )
549 *pd++ = inb_p (port + z); // read data byte
551 zz += 8;
552 base += 8;
555 /****************************************************************
556 * Name: Psi240i_Detect
558 * Description: Detect and initialize our boards.
560 * Parameters: tpnt - Pointer to SCSI host template structure.
562 * Returns: Number of adapters found.
564 ****************************************************************/
565 int Psi240i_Detect (Scsi_Host_Template *tpnt)
567 int board;
568 int count = 0;
569 int unit;
570 int z;
571 USHORT port;
572 CHIP_CONFIG_N chipConfig;
573 CHIP_DEVICE_N chipDevice[8];
574 struct Scsi_Host *pshost;
575 ULONG flags;
577 for ( board = 0; board < 6; board++ ) // scan for I/O ports
579 port = portAddr[board]; // get base address to test
580 if ( check_region (port, 16) ) // test for I/O addresses available
581 continue; // nope
582 if ( inb_p (port + REG_FAIL) != CHIP_ID ) // do the first test for likley hood that it is us
583 continue;
584 outb_p (SEL_NONE, port + REG_SEL_FAIL); // setup EEPROM/RAM access
585 outw (0, port + REG_ADDRESS); // setup EEPROM address zero
586 if ( inb_p (port) != 0x55 ) // test 1st byte
587 continue; // nope
588 if ( inb_p (port + 1) != 0xAA ) // test 2nd byte
589 continue; // nope
591 // at this point our board is found and can be accessed. Now we need to initialize
592 // our informatation and register with the kernel.
595 ReadChipMemory (&chipConfig, CHIP_CONFIG, sizeof (chipConfig), port);
596 ReadChipMemory (&chipDevice, CHIP_DEVICE, sizeof (chipDevice), port);
597 ReadChipMemory (&ChipSetup, CHIP_EEPROM_DATA, sizeof (ChipSetup), port);
599 if ( !chipConfig.numDrives ) // if no devices on this board
600 continue;
602 pshost = scsi_register (tpnt, sizeof(ADAPTER240I));
604 save_flags (flags);
605 cli ();
606 if ( request_irq (chipConfig.irq, do_Irq_Handler, 0, "psi240i", NULL) )
608 printk ("Unable to allocate IRQ for PSI-240I controller.\n");
609 restore_flags (flags);
610 goto unregister;
613 PsiHost[chipConfig.irq - 10] = pshost;
614 pshost->unique_id = port;
615 pshost->io_port = port;
616 pshost->n_io_port = 16; /* Number of bytes of I/O space used */
617 pshost->irq = chipConfig.irq;
619 for ( z = 0; z < 11; z++ ) // build regester address array
620 HOSTDATA(pshost)->ports[z] = port + z;
621 HOSTDATA(pshost)->ports[11] = port + REG_FAIL;
622 HOSTDATA(pshost)->ports[12] = port + REG_ALT_STAT;
623 DEB (printk ("\nPorts ="));
624 DEB (for (z=0;z<13;z++) printk(" %#04X",HOSTDATA(pshost)->ports[z]););
626 for ( z = 0; z < chipConfig.numDrives; ++z )
628 unit = chipDevice[z].channel & 0x0F;
629 HOSTDATA(pshost)->device[unit].device = ChipSetup.setupDevice[unit].device;
630 HOSTDATA(pshost)->device[unit].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
631 HOSTDATA(pshost)->device[unit].spigot = (UCHAR)(1 << (unit >> 1));
632 HOSTDATA(pshost)->device[unit].sectors = ChipSetup.setupDevice[unit].sectors;
633 HOSTDATA(pshost)->device[unit].heads = ChipSetup.setupDevice[unit].heads;
634 HOSTDATA(pshost)->device[unit].cylinders = ChipSetup.setupDevice[unit].cylinders;
635 HOSTDATA(pshost)->device[unit].blocks = ChipSetup.setupDevice[unit].blocks;
636 DEB (printk ("\nHOSTDATA->device = %X", HOSTDATA(pshost)->device[unit].device));
637 DEB (printk ("\n byte6 = %X", HOSTDATA(pshost)->device[unit].byte6));
638 DEB (printk ("\n spigot = %X", HOSTDATA(pshost)->device[unit].spigot));
639 DEB (printk ("\n sectors = %X", HOSTDATA(pshost)->device[unit].sectors));
640 DEB (printk ("\n heads = %X", HOSTDATA(pshost)->device[unit].heads));
641 DEB (printk ("\n cylinders = %X", HOSTDATA(pshost)->device[unit].cylinders));
642 DEB (printk ("\n blocks = %lX", HOSTDATA(pshost)->device[unit].blocks));
645 restore_flags (flags);
646 printk("\nPSI-240I EIDE CONTROLLER: at I/O = %x IRQ = %d\n", port, chipConfig.irq);
647 printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
648 count++;
649 continue;
651 unregister:;
652 scsi_unregister (pshost);
654 return count;
656 /****************************************************************
657 * Name: Psi240i_Abort
659 * Description: Process the Abort command from the SCSI manager.
661 * Parameters: SCpnt - Pointer to SCSI command structure.
663 * Returns: Allways snooze.
665 ****************************************************************/
666 int Psi240i_Abort (Scsi_Cmnd *SCpnt)
668 DEB (printk ("psi240i_abort\n"));
669 return SCSI_ABORT_SNOOZE;
671 /****************************************************************
672 * Name: Psi240i_Reset
674 * Description: Process the Reset command from the SCSI manager.
676 * Parameters: SCpnt - Pointer to SCSI command structure.
677 * flags - Flags about the reset command
679 * Returns: No active command at this time, so this means
680 * that each time we got some kind of response the
681 * last time through. Tell the mid-level code to
682 * request sense information in order to decide what
683 * to do next.
685 ****************************************************************/
686 int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
688 return SCSI_RESET_PUNT;
691 #include "sd.h"
693 /****************************************************************
694 * Name: Psi240i_BiosParam
696 * Description: Process the biosparam request from the SCSI manager to
697 * return C/H/S data.
699 * Parameters: disk - Pointer to SCSI disk structure.
700 * dev - Major/minor number from kernel.
701 * geom - Pointer to integer array to place geometry data.
703 * Returns: zero.
705 ****************************************************************/
706 int Psi240i_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[])
708 POUR_DEVICE pdev;
710 pdev = &(HOSTDATA(disk->device->host)->device[disk->device->id]);
712 geom[0] = pdev->heads;
713 geom[1] = pdev->sectors;
714 geom[2] = pdev->cylinders;
715 return 0;
719 #ifdef MODULE
720 /* Eventually this will go into an include file, but this will be later */
721 Scsi_Host_Template driver_template = PSI240I;
723 #include "scsi_module.c"
724 #endif