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 typedefstruct
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 typedefstruct
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 intWriteData(PADAPTER240I padapter)
122 ULONG timer;
123 USHORT *pports = padapter->ports;
125 timer = jiffies + TIMEOUT_DRQ;// calculate the timeout value
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 return0;
132 }while(time_after(timer, jiffies) );// test for timeout
134 padapter->ide.ide.ides.cmd =0;// null out the command byte
135 return1;
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
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 return0;
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 intSetupTransfer(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 return0;
199 else
201 padapter->ide.ide.ides.cmd =0;// null out the command byte
202 padapter->SCpnt = NULL;
203 return1;
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 voidIrq_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 voiddo_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 intPsi240i_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 return0;
411 else
413 printk("psi240i_queuecommand: %02X: done can't be NULL\n", *cdb);
414 return0;
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 return0;
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 return0;
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 return0;
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 return0;
494 DEB(printk("psi240i_queuecommand: %02X, %02X now waiting for interrupt ", *cdb, padapter->ide.ide.ides.cmd));
495 return0;
498 static voidinternal_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 intPsi240i_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 voidReadChipMemory(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 intPsi240i_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("\nbyte6 = %X",HOSTDATA(pshost)->device[unit].byte6));
638 DEB(printk("\nspigot = %X",HOSTDATA(pshost)->device[unit].spigot));
639 DEB(printk("\nsectors = %X",HOSTDATA(pshost)->device[unit].sectors));
640 DEB(printk("\nheads = %X",HOSTDATA(pshost)->device[unit].heads));
641 DEB(printk("\ncylinders = %X",HOSTDATA(pshost)->device[unit].cylinders));
642 DEB(printk("\nblocks = %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 intPsi240i_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 intPsi240i_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 intPsi240i_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 return0;
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
close