psi240i.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:22k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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