pci2000.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /****************************************************************************
  2. * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
  3. *
  4. * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
  5. *
  6. * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
  7. * All Rights Reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that redistributions of source
  11. * code retain the above copyright notice and this comment without
  12. * modification.
  13. *
  14. * Technical updates and product information at:
  15. * http://www.psidisk.com
  16. *
  17. * Please send questions, comments, bug reports to:
  18. * tech@psidisk.com Technical Support
  19. *
  20. *
  21. * Revisions 1.10 Jan-21-1999
  22. * - Fixed sign on message to reflect proper controller name.
  23. * - Added support for RAID status monitoring and control.
  24. *
  25. * Revisions 1.11 Mar-22-1999
  26. * - Fixed control timeout to not lock up the entire system if
  27. * controller goes offline completely.
  28. *
  29. * Revisions 1.12 Mar-26-1999
  30. * - Fixed spinlock and PCI configuration.
  31. *
  32. * Revisions 1.20 Mar-27-2000
  33. * - Added support for dynamic DMA
  34. *
  35. ****************************************************************************/
  36. #define PCI2000_VERSION "1.20"
  37. #include <linux/blkdev.h>
  38. #include <linux/interrupt.h>
  39. #include <linux/module.h>
  40. #include <linux/kernel.h>
  41. #include <linux/types.h>
  42. #include <linux/string.h>
  43. #include <linux/pci.h>
  44. #include <linux/ioport.h>
  45. #include <linux/delay.h>
  46. #include <linux/sched.h>
  47. #include <linux/proc_fs.h>
  48. #include <linux/stat.h>
  49. #include <linux/spinlock.h>
  50. #include <asm/dma.h>
  51. #include <asm/system.h>
  52. #include <asm/io.h>
  53. #include "scsi.h"
  54. #include <scsi/scsi_host.h>
  55. #include "pci2000.h"
  56. #include "psi_roy.h"
  57. //#define DEBUG 1
  58. #ifdef DEBUG
  59. #define DEB(x) x
  60. #define STOP_HERE {int st;for(st=0;st<100;st++){st=1;}}
  61. #else
  62. #define DEB(x)
  63. #define STOP_HERE
  64. #endif
  65. typedef struct
  66. {
  67. unsigned int address;
  68. unsigned int length;
  69. } SCATGATH, *PSCATGATH;
  70. typedef struct
  71. {
  72. Scsi_Cmnd *SCpnt;
  73. PSCATGATH scatGath;
  74. dma_addr_t scatGathDma;
  75. UCHAR *cdb;
  76. dma_addr_t cdbDma;
  77. UCHAR tag;
  78. } DEV2000, *PDEV2000;
  79. typedef struct
  80. {
  81. ULONG basePort;
  82. ULONG mb0;
  83. ULONG mb1;
  84. ULONG mb2;
  85. ULONG mb3;
  86. ULONG mb4;
  87. ULONG cmd;
  88. ULONG tag;
  89. ULONG irqOwned;
  90. struct pci_dev *pdev;
  91. DEV2000 dev[MAX_BUS][MAX_UNITS];
  92. } ADAPTER2000, *PADAPTER2000;
  93. #define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
  94. #define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
  95. static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
  96. static int NumAdapters = 0;
  97. /****************************************************************
  98. * Name: WaitReady :LOCAL
  99. *
  100. * Description: Wait for controller ready.
  101. *
  102. * Parameters: padapter - Pointer adapter data structure.
  103. *
  104. * Returns: TRUE on not ready.
  105. *
  106. ****************************************************************/
  107. static int WaitReady (PADAPTER2000 padapter)
  108. {
  109. ULONG z;
  110. for ( z = 0; z < (TIMEOUT_COMMAND * 4); z++ )
  111. {
  112. if ( !inb_p (padapter->cmd) )
  113. return FALSE;
  114. udelay (250);
  115. };
  116. return TRUE;
  117. }
  118. /****************************************************************
  119. * Name: WaitReadyLong :LOCAL
  120. *
  121. * Description: Wait for controller ready.
  122. *
  123. * Parameters: padapter - Pointer adapter data structure.
  124. *
  125. * Returns: TRUE on not ready.
  126. *
  127. ****************************************************************/
  128. static int WaitReadyLong (PADAPTER2000 padapter)
  129. {
  130. ULONG z;
  131. for ( z = 0; z < (5000 * 4); z++ )
  132. {
  133. if ( !inb_p (padapter->cmd) )
  134. return FALSE;
  135. udelay (250);
  136. };
  137. return TRUE;
  138. }
  139. /****************************************************************
  140. * Name: OpDone :LOCAL
  141. *
  142. * Description: Clean up operation and issue done to caller.
  143. *
  144. * Parameters: SCpnt - Pointer to SCSI command structure.
  145. * status - Caller status.
  146. *
  147. * Returns: Nothing.
  148. *
  149. ****************************************************************/
  150. static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
  151. {
  152. SCpnt->result = status;
  153. SCpnt->scsi_done (SCpnt);
  154. }
  155. /****************************************************************
  156. * Name: Command :LOCAL
  157. *
  158. * Description: Issue queued command to the PCI-2000.
  159. *
  160. * Parameters: padapter - Pointer to adapter information structure.
  161. * cmd - PCI-2000 command byte.
  162. *
  163. * Returns: Non-zero command tag if operation is accepted.
  164. *
  165. ****************************************************************/
  166. static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
  167. {
  168. outb_p (cmd, padapter->cmd);
  169. if ( WaitReady (padapter) )
  170. return 0;
  171. if ( inw_p (padapter->mb0) )
  172. return 0;
  173. return inb_p (padapter->mb1);
  174. }
  175. /****************************************************************
  176. * Name: BuildSgList :LOCAL
  177. *
  178. * Description: Build the scatter gather list for controller.
  179. *
  180. * Parameters: SCpnt - Pointer to SCSI command structure.
  181. * padapter - Pointer to adapter information structure.
  182. * pdev - Pointer to adapter device structure.
  183. *
  184. * Returns: Non-zero in not scatter gather.
  185. *
  186. ****************************************************************/
  187. static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
  188. {
  189. int z;
  190. int zc;
  191. struct scatterlist *sg;
  192. if ( SCpnt->use_sg )
  193. {
  194. sg = (struct scatterlist *)SCpnt->request_buffer;
  195. zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, SCpnt->sc_data_direction);
  196. for ( z = 0; z < zc; z++ )
  197. {
  198. pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
  199. pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
  200. }
  201. outl (pdev->scatGathDma, padapter->mb2);
  202. outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
  203. return FALSE;
  204. }
  205. if ( !SCpnt->request_bufflen)
  206. {
  207. outl (0, padapter->mb2);
  208. outl (0, padapter->mb3);
  209. return TRUE;
  210. }
  211. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
  212. SCpnt->request_buffer, SCpnt->request_bufflen,
  213. SCpnt->sc_data_direction);
  214. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  215. outl (SCpnt->request_bufflen, padapter->mb3);
  216. return TRUE;
  217. }
  218. /*********************************************************************
  219. * Name: PsiRaidCmd
  220. *
  221. * Description: Execute a simple command.
  222. *
  223. * Parameters: padapter - Pointer to adapter control structure.
  224. * cmd - Roy command byte.
  225. *
  226. * Returns: Return error status.
  227. *
  228. ********************************************************************/
  229. static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
  230. {
  231. if ( WaitReady (padapter) ) // test for command register ready
  232. return DID_TIME_OUT;
  233. outb_p (cmd, padapter->cmd); // issue command
  234. if ( WaitReadyLong (padapter) ) // wait for adapter ready
  235. return DID_TIME_OUT;
  236. return DID_OK;
  237. }
  238. /****************************************************************
  239. * Name: Irq_Handler :LOCAL
  240. *
  241. * Description: Interrupt handler.
  242. *
  243. * Parameters: irq - Hardware IRQ number.
  244. * dev_id -
  245. * regs -
  246. *
  247. * Returns: TRUE if drive is not ready in time.
  248. *
  249. ****************************************************************/
  250. static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
  251. {
  252. struct Scsi_Host *shost = NULL; // Pointer to host data block
  253. PADAPTER2000 padapter; // Pointer to adapter control structure
  254. PDEV2000 pdev;
  255. Scsi_Cmnd *SCpnt;
  256. UCHAR tag = 0;
  257. UCHAR tag0;
  258. ULONG error;
  259. int pun;
  260. int bus;
  261. int z;
  262. unsigned long flags;
  263. int handled = 0;
  264. DEB(printk ("\npci2000 received interrupt "));
  265. for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
  266. {
  267. if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
  268. {
  269. tag = inb_p (HOSTDATA(PsiHost[z])->tag);
  270. if ( tag )
  271. {
  272. shost = PsiHost[z];
  273. break;
  274. }
  275. }
  276. }
  277. if ( !shost )
  278. {
  279. DEB (printk ("\npci2000: not my interrupt"));
  280. goto out;
  281. }
  282. handled = 1;
  283. spin_lock_irqsave(shost->host_lock, flags);
  284. padapter = HOSTDATA(shost);
  285. tag0 = tag & 0x7F; // mask off the error bit
  286. for ( bus = 0; bus < MAX_BUS; bus++ ) // scan the busses
  287. {
  288. for ( pun = 0; pun < MAX_UNITS; pun++ ) // scan the targets
  289. {
  290. pdev = &padapter->dev[bus][pun];
  291. if ( !pdev->tag )
  292. continue;
  293. if ( pdev->tag == tag0 ) // is this it?
  294. {
  295. pdev->tag = 0;
  296. SCpnt = pdev->SCpnt;
  297. goto unmapProceed;
  298. }
  299. }
  300. }
  301. outb_p (0xFF, padapter->tag); // clear the op interrupt
  302. outb_p (CMD_DONE, padapter->cmd); // complete the op
  303. goto irq_return; // done, but, with what?
  304. unmapProceed:;
  305. if ( !bus )
  306. {
  307. switch ( SCpnt->cmnd[0] )
  308. {
  309. case SCSIOP_TEST_UNIT_READY:
  310. pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
  311. goto irqProceed;
  312. case SCSIOP_READ_CAPACITY:
  313. pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
  314. goto irqProceed;
  315. case SCSIOP_VERIFY:
  316. case SCSIOP_START_STOP_UNIT:
  317. case SCSIOP_MEDIUM_REMOVAL:
  318. goto irqProceed;
  319. }
  320. }
  321. if ( SCpnt->SCp.have_data_in )
  322. pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, SCpnt->sc_data_direction);
  323. else
  324. {
  325. if ( SCpnt->use_sg )
  326. pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction);
  327. }
  328. irqProceed:;
  329. if ( tag & ERR08_TAGGED ) // is there an error here?
  330. {
  331. if ( WaitReady (padapter) )
  332. {
  333. OpDone (SCpnt, DID_TIME_OUT << 16);
  334. goto irq_return;
  335. }
  336. outb_p (tag0, padapter->mb0); // get real error code
  337. outb_p (CMD_ERROR, padapter->cmd);
  338. if ( WaitReady (padapter) ) // wait for controller to suck up the op
  339. {
  340. OpDone (SCpnt, DID_TIME_OUT << 16);
  341. goto irq_return;
  342. }
  343. error = inl (padapter->mb0); // get error data
  344. outb_p (0xFF, padapter->tag); // clear the op interrupt
  345. outb_p (CMD_DONE, padapter->cmd); // complete the op
  346. DEB (printk ("status: %lX ", error));
  347. if ( error == 0x00020002 ) // is this error a check condition?
  348. {
  349. if ( bus ) // are we doint SCSI commands?
  350. {
  351. OpDone (SCpnt, (DID_OK << 16) | 2);
  352. goto irq_return;
  353. }
  354. if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
  355. OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2); // test caller we have sense data too
  356. else
  357. OpDone (SCpnt, DID_ERROR << 16);
  358. goto irq_return;
  359. }
  360. OpDone (SCpnt, DID_ERROR << 16);
  361. goto irq_return;
  362. }
  363. outb_p (0xFF, padapter->tag); // clear the op interrupt
  364. outb_p (CMD_DONE, padapter->cmd); // complete the op
  365. OpDone (SCpnt, DID_OK << 16);
  366. irq_return:
  367. spin_unlock_irqrestore(shost->host_lock, flags);
  368. out:
  369. return IRQ_RETVAL(handled);
  370. }
  371. /****************************************************************
  372. * Name: Pci2000_QueueCommand
  373. *
  374. * Description: Process a queued command from the SCSI manager.
  375. *
  376. * Parameters: SCpnt - Pointer to SCSI command structure.
  377. * done - Pointer to done function to call.
  378. *
  379. * Returns: Status code.
  380. *
  381. ****************************************************************/
  382. int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
  383. {
  384. UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
  385. PADAPTER2000 padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
  386. int rc = -1; // command return code
  387. UCHAR bus = SCpnt->device->channel;
  388. UCHAR pun = SCpnt->device->id;
  389. UCHAR lun = SCpnt->device->lun;
  390. UCHAR cmd;
  391. PDEV2000 pdev = &padapter->dev[bus][pun];
  392. if ( !done )
  393. {
  394. printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
  395. return 0;
  396. }
  397. SCpnt->scsi_done = done;
  398. SCpnt->SCp.have_data_in = 0;
  399. pdev->SCpnt = SCpnt; // Save this command data
  400. if ( WaitReady (padapter) )
  401. {
  402. rc = DID_ERROR;
  403. goto finished;
  404. }
  405. outw_p (pun | (lun << 8), padapter->mb0);
  406. if ( bus )
  407. {
  408. DEB (if(*cdb) printk ("\nCDB: %X- %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
  409. DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d", SCpnt->timeout_per_command,
  410. SCpnt->timeout_total, SCpnt->timeout));
  411. outl (SCpnt->timeout_per_command, padapter->mb1);
  412. outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
  413. if ( WaitReady (padapter) )
  414. {
  415. rc = DID_ERROR;
  416. goto finished;
  417. }
  418. outw_p (pun | (lun << 8), padapter->mb0);
  419. outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
  420. memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
  421. outl (pdev->cdbDma, padapter->mb1);
  422. if ( BuildSgList (SCpnt, padapter, pdev) )
  423. cmd = CMD_SCSI_THRU;
  424. else
  425. cmd = CMD_SCSI_THRU_SG;
  426. if ( (pdev->tag = Command (padapter, cmd)) == 0 )
  427. rc = DID_TIME_OUT;
  428. goto finished;
  429. }
  430. else
  431. {
  432. if ( lun )
  433. {
  434. rc = DID_BAD_TARGET;
  435. goto finished;
  436. }
  437. }
  438. switch ( *cdb )
  439. {
  440. case SCSIOP_INQUIRY: // inquiry CDB
  441. if ( cdb[2] == SC_MY_RAID )
  442. {
  443. switch ( cdb[3] )
  444. {
  445. case MY_SCSI_REBUILD:
  446. OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
  447. return 0;
  448. case MY_SCSI_ALARMMUTE:
  449. OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
  450. return 0;
  451. case MY_SCSI_DEMOFAIL:
  452. OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
  453. return 0;
  454. default:
  455. if ( SCpnt->use_sg )
  456. {
  457. rc = DID_ERROR;
  458. goto finished;
  459. }
  460. else
  461. {
  462. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
  463. SCpnt->sc_data_direction);
  464. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  465. }
  466. outl (cdb[5], padapter->mb0);
  467. outl (cdb[3], padapter->mb3);
  468. cmd = CMD_DASD_RAID_RQ;
  469. break;
  470. }
  471. break;
  472. }
  473. if ( SCpnt->use_sg )
  474. {
  475. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
  476. ((struct scatterlist *)SCpnt->request_buffer)->address,
  477. SCpnt->request_bufflen,
  478. SCpnt->sc_data_direction);
  479. }
  480. else
  481. {
  482. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
  483. SCpnt->request_bufflen,
  484. SCpnt->sc_data_direction);
  485. }
  486. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  487. outl (SCpnt->request_bufflen, padapter->mb3);
  488. cmd = CMD_DASD_SCSI_INQ;
  489. break;
  490. case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
  491. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
  492. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  493. outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
  494. cmd = CMD_TEST_READY;
  495. break;
  496. case SCSIOP_READ_CAPACITY: // read capacity CDB
  497. if ( SCpnt->use_sg )
  498. {
  499. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
  500. 8, PCI_DMA_FROMDEVICE);
  501. }
  502. else
  503. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
  504. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  505. outl (8, padapter->mb3);
  506. cmd = CMD_DASD_CAP;
  507. break;
  508. case SCSIOP_VERIFY: // verify CDB
  509. outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
  510. outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
  511. cmd = CMD_READ_SG;
  512. break;
  513. case SCSIOP_READ: // read10 CDB
  514. outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
  515. outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
  516. if ( BuildSgList (SCpnt, padapter, pdev) )
  517. cmd = CMD_READ;
  518. else
  519. cmd = CMD_READ_SG;
  520. break;
  521. case SCSIOP_READ6: // read6 CDB
  522. outw_p (cdb[4], padapter->mb0 + 2);
  523. outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
  524. if ( BuildSgList (SCpnt, padapter, pdev) )
  525. cmd = CMD_READ;
  526. else
  527. cmd = CMD_READ_SG;
  528. break;
  529. case SCSIOP_WRITE: // write10 CDB
  530. outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
  531. outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
  532. if ( BuildSgList (SCpnt, padapter, pdev) )
  533. cmd = CMD_WRITE;
  534. else
  535. cmd = CMD_WRITE_SG;
  536. break;
  537. case SCSIOP_WRITE6: // write6 CDB
  538. outw_p (cdb[4], padapter->mb0 + 2);
  539. outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
  540. if ( BuildSgList (SCpnt, padapter, pdev) )
  541. cmd = CMD_WRITE;
  542. else
  543. cmd = CMD_WRITE_SG;
  544. break;
  545. case SCSIOP_START_STOP_UNIT:
  546. cmd = CMD_EJECT_MEDIA;
  547. break;
  548. case SCSIOP_MEDIUM_REMOVAL:
  549. switch ( cdb[4] )
  550. {
  551. case 0:
  552. cmd = CMD_UNLOCK_DOOR;
  553. break;
  554. case 1:
  555. cmd = CMD_LOCK_DOOR;
  556. break;
  557. default:
  558. cmd = 0;
  559. break;
  560. }
  561. if ( cmd )
  562. break;
  563. default:
  564. DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
  565. OpDone (SCpnt, DID_ERROR << 16);
  566. return 0;
  567. }
  568. if ( (pdev->tag = Command (padapter, cmd)) == 0 )
  569. rc = DID_TIME_OUT;
  570. finished:;
  571. if ( rc != -1 )
  572. OpDone (SCpnt, rc << 16);
  573. return 0;
  574. }
  575. /****************************************************************
  576. * Name: Pci2000_Detect
  577. *
  578. * Description: Detect and initialize our boards.
  579. *
  580. * Parameters: tpnt - Pointer to SCSI host template structure.
  581. *
  582. * Returns: Number of adapters installed.
  583. *
  584. ****************************************************************/
  585. int Pci2000_Detect (Scsi_Host_Template *tpnt)
  586. {
  587. int found = 0;
  588. int installed = 0;
  589. struct Scsi_Host *pshost;
  590. PADAPTER2000 padapter;
  591. int z, zz;
  592. int setirq;
  593. struct pci_dev *pdev = NULL;
  594. UCHAR *consistent;
  595. dma_addr_t consistentDma;
  596. while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
  597. {
  598. if (pci_enable_device(pdev))
  599. continue;
  600. pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
  601. if(pshost == NULL)
  602. continue;
  603. padapter = HOSTDATA(pshost);
  604. padapter->basePort = pci_resource_start (pdev, 1);
  605. DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
  606. padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
  607. padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
  608. padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
  609. padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
  610. padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
  611. padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
  612. padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
  613. padapter->pdev = pdev;
  614. if ( WaitReady (padapter) )
  615. goto unregister;
  616. outb_p (0x84, padapter->mb0);
  617. outb_p (CMD_SPECIFY, padapter->cmd);
  618. if ( WaitReady (padapter) )
  619. goto unregister;
  620. consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
  621. if ( !consistent )
  622. {
  623. printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
  624. goto unregister;
  625. }
  626. scsi_set_device(pshost, &pdev->dev);
  627. pshost->irq = pdev->irq;
  628. setirq = 1;
  629. padapter->irqOwned = 0;
  630. for ( z = 0; z < installed; z++ ) // scan for shared interrupts
  631. {
  632. if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
  633. setirq = 0;
  634. }
  635. if ( setirq ) // if not shared, posses
  636. {
  637. if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
  638. {
  639. if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
  640. {
  641. printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
  642. pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
  643. goto unregister;
  644. }
  645. }
  646. padapter->irqOwned = pshost->irq; // set IRQ as owned
  647. }
  648. PsiHost[installed] = pshost; // save SCSI_HOST pointer
  649. pshost->io_port = padapter->basePort;
  650. pshost->n_io_port = 0xFF;
  651. pshost->unique_id = padapter->basePort;
  652. pshost->max_id = 16;
  653. pshost->max_channel = 1;
  654. for ( zz = 0; zz < MAX_BUS; zz++ )
  655. for ( z = 0; z < MAX_UNITS; z++ )
  656. {
  657. padapter->dev[zz][z].tag = 0;
  658. padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
  659. padapter->dev[zz][z].scatGathDma = consistentDma;
  660. consistent += 16 * sizeof (SCATGATH);
  661. consistentDma += 16 * sizeof (SCATGATH);
  662. padapter->dev[zz][z].cdb = (UCHAR *)consistent;
  663. padapter->dev[zz][z].cdbDma = consistentDma;
  664. consistent += MAX_COMMAND_SIZE;
  665. consistentDma += MAX_COMMAND_SIZE;
  666. }
  667. printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX IRQ = %d\n", padapter->basePort, pshost->irq);
  668. printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
  669. found++;
  670. if ( ++installed < MAXADAPTER )
  671. continue;
  672. break;
  673. unregister:;
  674. scsi_unregister (pshost);
  675. found++;
  676. }
  677. NumAdapters = installed;
  678. return installed;
  679. }
  680. /****************************************************************
  681. * Name: Pci2000_Abort
  682. *
  683. * Description: Process the Abort command from the SCSI manager.
  684. *
  685. * Parameters: SCpnt - Pointer to SCSI command structure.
  686. *
  687. * Returns: Allways snooze.
  688. *
  689. ****************************************************************/
  690. int Pci2000_Abort (Scsi_Cmnd *SCpnt)
  691. {
  692. DEB (printk ("pci2000_abort\n"));
  693. return SCSI_ABORT_SNOOZE;
  694. }
  695. /****************************************************************
  696. * Name: Pci2000_Reset
  697. *
  698. * Description: Process the Reset command from the SCSI manager.
  699. *
  700. * Parameters: SCpnt - Pointer to SCSI command structure.
  701. * flags - Flags about the reset command
  702. *
  703. * Returns: No active command at this time, so this means
  704. * that each time we got some kind of response the
  705. * last time through. Tell the mid-level code to
  706. * request sense information in order to decide what
  707. * to do next.
  708. *
  709. ****************************************************************/
  710. int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  711. {
  712. return SCSI_RESET_PUNT;
  713. }
  714. /****************************************************************
  715. * Name: Pci2000_Release
  716. *
  717. * Description: Release resources allocated for a single each adapter.
  718. *
  719. * Parameters: pshost - Pointer to SCSI command structure.
  720. *
  721. * Returns: zero.
  722. *
  723. ****************************************************************/
  724. int Pci2000_Release (struct Scsi_Host *pshost)
  725. {
  726. PADAPTER2000 padapter = HOSTDATA (pshost);
  727. if ( padapter->irqOwned )
  728. free_irq (pshost->irq, padapter);
  729. pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
  730. release_region (pshost->io_port, pshost->n_io_port);
  731. scsi_unregister(pshost);
  732. return 0;
  733. }
  734. /****************************************************************
  735. * Name: Pci2000_BiosParam
  736. *
  737. * Description: Process the biosparam request from the SCSI manager to
  738. * return C/H/S data.
  739. *
  740. * Parameters: disk - Pointer to SCSI disk structure.
  741. * dev - Major/minor number from kernel.
  742. * geom - Pointer to integer array to place geometry data.
  743. *
  744. * Returns: zero.
  745. *
  746. ****************************************************************/
  747. int Pci2000_BiosParam (struct scsi_device *sdev, struct block_device *dev,
  748. sector_t capacity, int geom[])
  749. {
  750. PADAPTER2000 padapter;
  751. padapter = HOSTDATA(sdev->host);
  752. if ( WaitReady (padapter) )
  753. return 0;
  754. outb_p (sdev->id, padapter->mb0);
  755. outb_p (CMD_GET_PARMS, padapter->cmd);
  756. if ( WaitReady (padapter) )
  757. return 0;
  758. geom[0] = inb_p (padapter->mb2 + 3);
  759. geom[1] = inb_p (padapter->mb2 + 2);
  760. geom[2] = inw_p (padapter->mb2);
  761. return 0;
  762. }
  763. MODULE_LICENSE("Dual BSD/GPL");
  764. static Scsi_Host_Template driver_template = {
  765. .proc_name = "pci2000",
  766. .name = "PCI-2000 SCSI Intelligent Disk Controller",
  767. .detect = Pci2000_Detect,
  768. .release = Pci2000_Release,
  769. .queuecommand = Pci2000_QueueCommand,
  770. .abort = Pci2000_Abort,
  771. .reset = Pci2000_Reset,
  772. .bios_param = Pci2000_BiosParam,
  773. .can_queue = 16,
  774. .this_id = -1,
  775. .sg_tablesize = 16,
  776. .cmd_per_lun = 1,
  777. .use_clustering = DISABLE_CLUSTERING,
  778. };
  779. #include "scsi_module.c"