pci2000.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  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, scsi_to_pci_dma_dir (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, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
  212. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  213. outl (SCpnt->request_bufflen, padapter->mb3);
  214. return TRUE;
  215. }
  216. /*********************************************************************
  217. * Name: PsiRaidCmd
  218. *
  219. * Description: Execute a simple command.
  220. *
  221. * Parameters: padapter - Pointer to adapter control structure.
  222. * cmd - Roy command byte.
  223. *
  224. * Returns: Return error status.
  225. *
  226. ********************************************************************/
  227. static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
  228. {
  229. if ( WaitReady (padapter) ) // test for command register ready
  230. return DID_TIME_OUT;
  231. outb_p (cmd, padapter->cmd); // issue command
  232. if ( WaitReadyLong (padapter) ) // wait for adapter ready
  233. return DID_TIME_OUT;
  234. return DID_OK;
  235. }
  236. /****************************************************************
  237. * Name: Irq_Handler :LOCAL
  238. *
  239. * Description: Interrupt handler.
  240. *
  241. * Parameters: irq - Hardware IRQ number.
  242. * dev_id -
  243. * regs -
  244. *
  245. * Returns: TRUE if drive is not ready in time.
  246. *
  247. ****************************************************************/
  248. static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
  249. {
  250. struct Scsi_Host *shost = NULL; // Pointer to host data block
  251. PADAPTER2000 padapter; // Pointer to adapter control structure
  252. PDEV2000 pdev;
  253. Scsi_Cmnd *SCpnt;
  254. UCHAR tag = 0;
  255. UCHAR tag0;
  256. ULONG error;
  257. int pun;
  258. int bus;
  259. int z;
  260. unsigned long flags;
  261. int handled = 0;
  262. DEB(printk ("\npci2000 received interrupt "));
  263. for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
  264. {
  265. if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
  266. {
  267. tag = inb_p (HOSTDATA(PsiHost[z])->tag);
  268. if ( tag )
  269. {
  270. shost = PsiHost[z];
  271. break;
  272. }
  273. }
  274. }
  275. if ( !shost )
  276. {
  277. DEB (printk ("\npci2000: not my interrupt"));
  278. goto out;
  279. }
  280. handled = 1;
  281. spin_lock_irqsave(shost->host_lock, flags);
  282. padapter = HOSTDATA(shost);
  283. tag0 = tag & 0x7F; // mask off the error bit
  284. for ( bus = 0; bus < MAX_BUS; bus++ ) // scan the busses
  285. {
  286. for ( pun = 0; pun < MAX_UNITS; pun++ ) // scan the targets
  287. {
  288. pdev = &padapter->dev[bus][pun];
  289. if ( !pdev->tag )
  290. continue;
  291. if ( pdev->tag == tag0 ) // is this it?
  292. {
  293. pdev->tag = 0;
  294. SCpnt = pdev->SCpnt;
  295. goto unmapProceed;
  296. }
  297. }
  298. }
  299. outb_p (0xFF, padapter->tag); // clear the op interrupt
  300. outb_p (CMD_DONE, padapter->cmd); // complete the op
  301. goto irq_return; // done, but, with what?
  302. unmapProceed:;
  303. if ( !bus )
  304. {
  305. switch ( SCpnt->cmnd[0] )
  306. {
  307. case SCSIOP_TEST_UNIT_READY:
  308. pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
  309. goto irqProceed;
  310. case SCSIOP_READ_CAPACITY:
  311. pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
  312. goto irqProceed;
  313. case SCSIOP_VERIFY:
  314. case SCSIOP_START_STOP_UNIT:
  315. case SCSIOP_MEDIUM_REMOVAL:
  316. goto irqProceed;
  317. }
  318. }
  319. if ( SCpnt->SCp.have_data_in )
  320. pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  321. else
  322. {
  323. if ( SCpnt->use_sg )
  324. pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  325. }
  326. irqProceed:;
  327. if ( tag & ERR08_TAGGED ) // is there an error here?
  328. {
  329. if ( WaitReady (padapter) )
  330. {
  331. OpDone (SCpnt, DID_TIME_OUT << 16);
  332. goto irq_return;
  333. }
  334. outb_p (tag0, padapter->mb0); // get real error code
  335. outb_p (CMD_ERROR, padapter->cmd);
  336. if ( WaitReady (padapter) ) // wait for controller to suck up the op
  337. {
  338. OpDone (SCpnt, DID_TIME_OUT << 16);
  339. goto irq_return;
  340. }
  341. error = inl (padapter->mb0); // get error data
  342. outb_p (0xFF, padapter->tag); // clear the op interrupt
  343. outb_p (CMD_DONE, padapter->cmd); // complete the op
  344. DEB (printk ("status: %lX ", error));
  345. if ( error == 0x00020002 ) // is this error a check condition?
  346. {
  347. if ( bus ) // are we doint SCSI commands?
  348. {
  349. OpDone (SCpnt, (DID_OK << 16) | 2);
  350. goto irq_return;
  351. }
  352. if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
  353. OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2); // test caller we have sense data too
  354. else
  355. OpDone (SCpnt, DID_ERROR << 16);
  356. goto irq_return;
  357. }
  358. OpDone (SCpnt, DID_ERROR << 16);
  359. goto irq_return;
  360. }
  361. outb_p (0xFF, padapter->tag); // clear the op interrupt
  362. outb_p (CMD_DONE, padapter->cmd); // complete the op
  363. OpDone (SCpnt, DID_OK << 16);
  364. irq_return:
  365. spin_unlock_irqrestore(shost->host_lock, flags);
  366. out:
  367. return IRQ_RETVAL(handled);
  368. }
  369. /****************************************************************
  370. * Name: Pci2000_QueueCommand
  371. *
  372. * Description: Process a queued command from the SCSI manager.
  373. *
  374. * Parameters: SCpnt - Pointer to SCSI command structure.
  375. * done - Pointer to done function to call.
  376. *
  377. * Returns: Status code.
  378. *
  379. ****************************************************************/
  380. int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
  381. {
  382. UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
  383. PADAPTER2000 padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
  384. int rc = -1; // command return code
  385. UCHAR bus = SCpnt->device->channel;
  386. UCHAR pun = SCpnt->device->id;
  387. UCHAR lun = SCpnt->device->lun;
  388. UCHAR cmd;
  389. PDEV2000 pdev = &padapter->dev[bus][pun];
  390. if ( !done )
  391. {
  392. printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
  393. return 0;
  394. }
  395. SCpnt->scsi_done = done;
  396. SCpnt->SCp.have_data_in = 0;
  397. pdev->SCpnt = SCpnt; // Save this command data
  398. if ( WaitReady (padapter) )
  399. {
  400. rc = DID_ERROR;
  401. goto finished;
  402. }
  403. outw_p (pun | (lun << 8), padapter->mb0);
  404. if ( bus )
  405. {
  406. 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]));
  407. DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d", SCpnt->timeout_per_command,
  408. SCpnt->timeout_total, SCpnt->timeout));
  409. outl (SCpnt->timeout_per_command, padapter->mb1);
  410. outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
  411. if ( WaitReady (padapter) )
  412. {
  413. rc = DID_ERROR;
  414. goto finished;
  415. }
  416. outw_p (pun | (lun << 8), padapter->mb0);
  417. outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
  418. memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
  419. outl (pdev->cdbDma, padapter->mb1);
  420. if ( BuildSgList (SCpnt, padapter, pdev) )
  421. cmd = CMD_SCSI_THRU;
  422. else
  423. cmd = CMD_SCSI_THRU_SG;
  424. if ( (pdev->tag = Command (padapter, cmd)) == 0 )
  425. rc = DID_TIME_OUT;
  426. goto finished;
  427. }
  428. else
  429. {
  430. if ( lun )
  431. {
  432. rc = DID_BAD_TARGET;
  433. goto finished;
  434. }
  435. }
  436. switch ( *cdb )
  437. {
  438. case SCSIOP_INQUIRY: // inquiry CDB
  439. if ( cdb[2] == SC_MY_RAID )
  440. {
  441. switch ( cdb[3] )
  442. {
  443. case MY_SCSI_REBUILD:
  444. OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
  445. return 0;
  446. case MY_SCSI_ALARMMUTE:
  447. OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
  448. return 0;
  449. case MY_SCSI_DEMOFAIL:
  450. OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
  451. return 0;
  452. default:
  453. if ( SCpnt->use_sg )
  454. {
  455. rc = DID_ERROR;
  456. goto finished;
  457. }
  458. else
  459. {
  460. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
  461. scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  462. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  463. }
  464. outl (cdb[5], padapter->mb0);
  465. outl (cdb[3], padapter->mb3);
  466. cmd = CMD_DASD_RAID_RQ;
  467. break;
  468. }
  469. break;
  470. }
  471. if ( SCpnt->use_sg )
  472. {
  473. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
  474. ((struct scatterlist *)SCpnt->request_buffer)->address,
  475. SCpnt->request_bufflen,
  476. scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
  477. }
  478. else
  479. {
  480. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
  481. SCpnt->request_bufflen,
  482. scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
  483. }
  484. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  485. outl (SCpnt->request_bufflen, padapter->mb3);
  486. cmd = CMD_DASD_SCSI_INQ;
  487. break;
  488. case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
  489. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
  490. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  491. outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
  492. cmd = CMD_TEST_READY;
  493. break;
  494. case SCSIOP_READ_CAPACITY: // read capacity CDB
  495. if ( SCpnt->use_sg )
  496. {
  497. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
  498. 8, PCI_DMA_FROMDEVICE);
  499. }
  500. else
  501. SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
  502. outl (SCpnt->SCp.have_data_in, padapter->mb2);
  503. outl (8, padapter->mb3);
  504. cmd = CMD_DASD_CAP;
  505. break;
  506. case SCSIOP_VERIFY: // verify CDB
  507. outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
  508. outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
  509. cmd = CMD_READ_SG;
  510. break;
  511. case SCSIOP_READ: // read10 CDB
  512. outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
  513. outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
  514. if ( BuildSgList (SCpnt, padapter, pdev) )
  515. cmd = CMD_READ;
  516. else
  517. cmd = CMD_READ_SG;
  518. break;
  519. case SCSIOP_READ6: // read6 CDB
  520. outw_p (cdb[4], padapter->mb0 + 2);
  521. outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
  522. if ( BuildSgList (SCpnt, padapter, pdev) )
  523. cmd = CMD_READ;
  524. else
  525. cmd = CMD_READ_SG;
  526. break;
  527. case SCSIOP_WRITE: // write10 CDB
  528. outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
  529. outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
  530. if ( BuildSgList (SCpnt, padapter, pdev) )
  531. cmd = CMD_WRITE;
  532. else
  533. cmd = CMD_WRITE_SG;
  534. break;
  535. case SCSIOP_WRITE6: // write6 CDB
  536. outw_p (cdb[4], padapter->mb0 + 2);
  537. outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
  538. if ( BuildSgList (SCpnt, padapter, pdev) )
  539. cmd = CMD_WRITE;
  540. else
  541. cmd = CMD_WRITE_SG;
  542. break;
  543. case SCSIOP_START_STOP_UNIT:
  544. cmd = CMD_EJECT_MEDIA;
  545. break;
  546. case SCSIOP_MEDIUM_REMOVAL:
  547. switch ( cdb[4] )
  548. {
  549. case 0:
  550. cmd = CMD_UNLOCK_DOOR;
  551. break;
  552. case 1:
  553. cmd = CMD_LOCK_DOOR;
  554. break;
  555. default:
  556. cmd = 0;
  557. break;
  558. }
  559. if ( cmd )
  560. break;
  561. default:
  562. DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
  563. OpDone (SCpnt, DID_ERROR << 16);
  564. return 0;
  565. }
  566. if ( (pdev->tag = Command (padapter, cmd)) == 0 )
  567. rc = DID_TIME_OUT;
  568. finished:;
  569. if ( rc != -1 )
  570. OpDone (SCpnt, rc << 16);
  571. return 0;
  572. }
  573. /****************************************************************
  574. * Name: Pci2000_Detect
  575. *
  576. * Description: Detect and initialize our boards.
  577. *
  578. * Parameters: tpnt - Pointer to SCSI host template structure.
  579. *
  580. * Returns: Number of adapters installed.
  581. *
  582. ****************************************************************/
  583. int Pci2000_Detect (Scsi_Host_Template *tpnt)
  584. {
  585. int found = 0;
  586. int installed = 0;
  587. struct Scsi_Host *pshost;
  588. PADAPTER2000 padapter;
  589. int z, zz;
  590. int setirq;
  591. struct pci_dev *pdev = NULL;
  592. UCHAR *consistent;
  593. dma_addr_t consistentDma;
  594. while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
  595. {
  596. if (pci_enable_device(pdev))
  597. continue;
  598. pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
  599. if(pshost == NULL)
  600. continue;
  601. padapter = HOSTDATA(pshost);
  602. padapter->basePort = pci_resource_start (pdev, 1);
  603. DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
  604. padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
  605. padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
  606. padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
  607. padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
  608. padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
  609. padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
  610. padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
  611. padapter->pdev = pdev;
  612. if ( WaitReady (padapter) )
  613. goto unregister;
  614. outb_p (0x84, padapter->mb0);
  615. outb_p (CMD_SPECIFY, padapter->cmd);
  616. if ( WaitReady (padapter) )
  617. goto unregister;
  618. consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
  619. if ( !consistent )
  620. {
  621. printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
  622. goto unregister;
  623. }
  624. scsi_set_device(pshost, &pdev->dev);
  625. pshost->irq = pdev->irq;
  626. setirq = 1;
  627. padapter->irqOwned = 0;
  628. for ( z = 0; z < installed; z++ ) // scan for shared interrupts
  629. {
  630. if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
  631. setirq = 0;
  632. }
  633. if ( setirq ) // if not shared, posses
  634. {
  635. if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
  636. {
  637. if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
  638. {
  639. printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
  640. pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
  641. goto unregister;
  642. }
  643. }
  644. padapter->irqOwned = pshost->irq; // set IRQ as owned
  645. }
  646. PsiHost[installed] = pshost; // save SCSI_HOST pointer
  647. pshost->io_port = padapter->basePort;
  648. pshost->n_io_port = 0xFF;
  649. pshost->unique_id = padapter->basePort;
  650. pshost->max_id = 16;
  651. pshost->max_channel = 1;
  652. for ( zz = 0; zz < MAX_BUS; zz++ )
  653. for ( z = 0; z < MAX_UNITS; z++ )
  654. {
  655. padapter->dev[zz][z].tag = 0;
  656. padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
  657. padapter->dev[zz][z].scatGathDma = consistentDma;
  658. consistent += 16 * sizeof (SCATGATH);
  659. consistentDma += 16 * sizeof (SCATGATH);
  660. padapter->dev[zz][z].cdb = (UCHAR *)consistent;
  661. padapter->dev[zz][z].cdbDma = consistentDma;
  662. consistent += MAX_COMMAND_SIZE;
  663. consistentDma += MAX_COMMAND_SIZE;
  664. }
  665. printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX IRQ = %d\n", padapter->basePort, pshost->irq);
  666. printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
  667. found++;
  668. if ( ++installed < MAXADAPTER )
  669. continue;
  670. break;
  671. unregister:;
  672. scsi_unregister (pshost);
  673. found++;
  674. }
  675. NumAdapters = installed;
  676. return installed;
  677. }
  678. /****************************************************************
  679. * Name: Pci2000_Abort
  680. *
  681. * Description: Process the Abort command from the SCSI manager.
  682. *
  683. * Parameters: SCpnt - Pointer to SCSI command structure.
  684. *
  685. * Returns: Allways snooze.
  686. *
  687. ****************************************************************/
  688. int Pci2000_Abort (Scsi_Cmnd *SCpnt)
  689. {
  690. DEB (printk ("pci2000_abort\n"));
  691. return SCSI_ABORT_SNOOZE;
  692. }
  693. /****************************************************************
  694. * Name: Pci2000_Reset
  695. *
  696. * Description: Process the Reset command from the SCSI manager.
  697. *
  698. * Parameters: SCpnt - Pointer to SCSI command structure.
  699. * flags - Flags about the reset command
  700. *
  701. * Returns: No active command at this time, so this means
  702. * that each time we got some kind of response the
  703. * last time through. Tell the mid-level code to
  704. * request sense information in order to decide what
  705. * to do next.
  706. *
  707. ****************************************************************/
  708. int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  709. {
  710. return SCSI_RESET_PUNT;
  711. }
  712. /****************************************************************
  713. * Name: Pci2000_Release
  714. *
  715. * Description: Release resources allocated for a single each adapter.
  716. *
  717. * Parameters: pshost - Pointer to SCSI command structure.
  718. *
  719. * Returns: zero.
  720. *
  721. ****************************************************************/
  722. int Pci2000_Release (struct Scsi_Host *pshost)
  723. {
  724. PADAPTER2000 padapter = HOSTDATA (pshost);
  725. if ( padapter->irqOwned )
  726. free_irq (pshost->irq, padapter);
  727. pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
  728. release_region (pshost->io_port, pshost->n_io_port);
  729. scsi_unregister(pshost);
  730. return 0;
  731. }
  732. /****************************************************************
  733. * Name: Pci2000_BiosParam
  734. *
  735. * Description: Process the biosparam request from the SCSI manager to
  736. * return C/H/S data.
  737. *
  738. * Parameters: disk - Pointer to SCSI disk structure.
  739. * dev - Major/minor number from kernel.
  740. * geom - Pointer to integer array to place geometry data.
  741. *
  742. * Returns: zero.
  743. *
  744. ****************************************************************/
  745. int Pci2000_BiosParam (struct scsi_device *sdev, struct block_device *dev,
  746. sector_t capacity, int geom[])
  747. {
  748. PADAPTER2000 padapter;
  749. padapter = HOSTDATA(sdev->host);
  750. if ( WaitReady (padapter) )
  751. return 0;
  752. outb_p (sdev->id, padapter->mb0);
  753. outb_p (CMD_GET_PARMS, padapter->cmd);
  754. if ( WaitReady (padapter) )
  755. return 0;
  756. geom[0] = inb_p (padapter->mb2 + 3);
  757. geom[1] = inb_p (padapter->mb2 + 2);
  758. geom[2] = inw_p (padapter->mb2);
  759. return 0;
  760. }
  761. MODULE_LICENSE("Dual BSD/GPL");
  762. static Scsi_Host_Template driver_template = {
  763. .proc_name = "pci2000",
  764. .name = "PCI-2000 SCSI Intelligent Disk Controller",
  765. .detect = Pci2000_Detect,
  766. .release = Pci2000_Release,
  767. .queuecommand = Pci2000_QueueCommand,
  768. .abort = Pci2000_Abort,
  769. .reset = Pci2000_Reset,
  770. .bios_param = Pci2000_BiosParam,
  771. .can_queue = 16,
  772. .this_id = -1,
  773. .sg_tablesize = 16,
  774. .cmd_per_lun = 1,
  775. .use_clustering = DISABLE_CLUSTERING,
  776. };
  777. #include "scsi_module.c"