sym53c416.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:26k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  *  sym53c416.c
  3.  *  Low-level SCSI driver for sym53c416 chip.
  4.  *  Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com)
  5.  * 
  6.  *  Changes : 
  7.  * 
  8.  *  Marcelo Tosatti <marcelo@conectiva.com.br> : Added io_request_lock locking
  9.  *  Alan Cox <alan@redhat.com> : Cleaned up code formatting
  10.  *  Fixed an irq locking bug
  11.  *  Added ISAPnP support
  12.  * 
  13.  *  LILO command line usage: sym53c416=<PORTBASE>[,<IRQ>]
  14.  *
  15.  *  This program is free software; you can redistribute it and/or modify it
  16.  *  under the terms of the GNU General Public License as published by the
  17.  *  Free Software Foundation; either version 2, or (at your option) any
  18.  *  later version.
  19.  *
  20.  *  This program is distributed in the hope that it will be useful, but
  21.  *  WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  23.  *  General Public License for more details.
  24.  *
  25.  */
  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/sched.h>
  32. #include <linux/interrupt.h>
  33. #include <linux/delay.h>
  34. #include <linux/proc_fs.h>
  35. #include <linux/spinlock.h>
  36. #include <asm/dma.h>
  37. #include <asm/system.h>
  38. #include <asm/io.h>
  39. #include <linux/blk.h>
  40. #include <linux/version.h>
  41. #include <linux/isapnp.h>
  42. #include "scsi.h"
  43. #include "hosts.h"
  44. #include "sd.h"
  45. #include "sym53c416.h"
  46. #define VERSION_STRING        "Version 1.0.0-ac"
  47. #define TC_LOW       0x00     /* Transfer counter low        */
  48. #define TC_MID       0x01     /* Transfer counter mid        */
  49. #define SCSI_FIFO    0x02     /* SCSI FIFO register          */
  50. #define COMMAND_REG  0x03     /* Command Register            */
  51. #define STATUS_REG   0x04     /* Status Register (READ)      */
  52. #define DEST_BUS_ID  0x04     /* Destination Bus ID (WRITE)  */
  53. #define INT_REG      0x05     /* Interrupt Register (READ)   */
  54. #define TOM          0x05     /* Time out multiplier (WRITE) */
  55. #define STP          0x06     /* Synchronous Transfer period */
  56. #define SYNC_OFFSET  0x07     /* Synchronous Offset          */
  57. #define CONF_REG_1   0x08     /* Configuration register 1    */
  58. #define CONF_REG_2   0x0B     /* Configuration register 2    */
  59. #define CONF_REG_3   0x0C     /* Configuration register 3    */
  60. #define CONF_REG_4   0x0D     /* Configuration register 4    */
  61. #define TC_HIGH      0x0E     /* Transfer counter high       */
  62. #define PIO_FIFO_1   0x10     /* PIO FIFO register 1         */
  63. #define PIO_FIFO_2   0x11     /* PIO FIFO register 2         */
  64. #define PIO_FIFO_3   0x12     /* PIO FIFO register 3         */
  65. #define PIO_FIFO_4   0x13     /* PIO FIFO register 4         */
  66. #define PIO_FIFO_CNT 0x14     /* PIO FIFO count              */
  67. #define PIO_INT_REG  0x15     /* PIO interrupt register      */
  68. #define CONF_REG_5   0x16     /* Configuration register 5    */
  69. #define FEATURE_EN   0x1D     /* Feature Enable register     */
  70. /* Configuration register 1 entries: */
  71. /* Bits 2-0: SCSI ID of host adapter */
  72. #define SCM    0x80                     /* Slow Cable Mode              */
  73. #define SRID   0x40                     /* SCSI Reset Interrupt Disable */
  74. #define PTM    0x20                     /* Parity Test Mode             */
  75. #define EPC    0x10                     /* Enable Parity Checking       */
  76. #define CTME   0x08                     /* Special Test Mode            */
  77. /* Configuration register 2 entries: */
  78. #define FE     0x40                     /* Features Enable              */
  79. #define SCSI2  0x08                     /* SCSI 2 Enable                */
  80. #define TBPA   0x04                     /* Target Bad Parity Abort      */
  81. /* Configuration register 3 entries: */
  82. #define IDMRC  0x80                     /* ID Message Reserved Check    */
  83. #define QTE    0x40                     /* Queue Tag Enable             */
  84. #define CDB10  0x20                     /* Command Descriptor Block 10  */
  85. #define FSCSI  0x10                     /* FastSCSI                     */
  86. #define FCLK   0x08                     /* FastClock                    */
  87. /* Configuration register 4 entries: */
  88. #define RBS    0x08                     /* Register bank select         */
  89. #define EAN    0x04                     /* Enable Active Negotiation    */
  90. /* Configuration register 5 entries: */
  91. #define LPSR   0x80                     /* Lower Power SCSI Reset       */
  92. #define IE     0x20                     /* Interrupt Enable             */
  93. #define LPM    0x02                     /* Low Power Mode               */
  94. #define WSE0   0x01                     /* 0WS Enable                   */
  95. /* Interrupt register entries: */
  96. #define SRST   0x80                     /* SCSI Reset                   */
  97. #define ILCMD  0x40                     /* Illegal Command              */
  98. #define DIS    0x20                     /* Disconnect                   */
  99. #define BS     0x10                     /* Bus Service                  */
  100. #define FC     0x08                     /* Function Complete            */
  101. #define RESEL  0x04                     /* Reselected                   */
  102. #define SI     0x03                     /* Selection Interrupt          */
  103. /* Status Register Entries: */
  104. #define SCI    0x80                     /* SCSI Core Int                */
  105. #define GE     0x40                     /* Gross Error                  */
  106. #define PE     0x20                     /* Parity Error                 */
  107. #define TC     0x10                     /* Terminal Count               */
  108. #define VGC    0x08                     /* Valid Group Code             */
  109. #define PHBITS 0x07                     /* Phase bits                   */
  110. /* PIO Interrupt Register Entries: */
  111. #define SCI    0x80                     /* SCSI Core Int                */
  112. #define PFI    0x40                     /* PIO FIFO Interrupt           */
  113. #define FULL   0x20                     /* PIO FIFO Full                */
  114. #define EMPTY  0x10                     /* PIO FIFO Empty               */
  115. #define CE     0x08                     /* Collision Error              */
  116. #define OUE    0x04                     /* Overflow / Underflow error   */
  117. #define FIE    0x02                     /* Full Interrupt Enable        */
  118. #define EIE    0x01                     /* Empty Interrupt Enable       */
  119. /* SYM53C416 SCSI phases (lower 3 bits of SYM53C416_STATUS_REG) */
  120. #define PHASE_DATA_OUT    0x00
  121. #define PHASE_DATA_IN     0x01
  122. #define PHASE_COMMAND     0x02
  123. #define PHASE_STATUS      0x03
  124. #define PHASE_RESERVED_1  0x04
  125. #define PHASE_RESERVED_2  0x05
  126. #define PHASE_MESSAGE_OUT 0x06
  127. #define PHASE_MESSAGE_IN  0x07
  128. /* SYM53C416 core commands */
  129. #define NOOP                      0x00
  130. #define FLUSH_FIFO                0x01
  131. #define RESET_CHIP                0x02
  132. #define RESET_SCSI_BUS            0x03
  133. #define DISABLE_SEL_RESEL         0x45
  134. #define RESEL_SEQ                 0x40
  135. #define SEL_WITHOUT_ATN_SEQ       0x41
  136. #define SEL_WITH_ATN_SEQ          0x42
  137. #define SEL_WITH_ATN_AND_STOP_SEQ 0x43
  138. #define ENABLE_SEL_RESEL          0x44
  139. #define SEL_WITH_ATN3_SEQ         0x46
  140. #define RESEL3_SEQ                0x47
  141. #define SND_MSG                   0x20
  142. #define SND_STAT                  0x21
  143. #define SND_DATA                  0x22
  144. #define DISCONNECT_SEQ            0x23
  145. #define TERMINATE_SEQ             0x24
  146. #define TARGET_COMM_COMPLETE_SEQ  0x25
  147. #define DISCONN                   0x27
  148. #define RECV_MSG_SEQ              0x28
  149. #define RECV_CMD                  0x29
  150. #define RECV_DATA                 0x2A
  151. #define RECV_CMD_SEQ              0x2B
  152. #define TARGET_ABORT_PIO          0x04
  153. #define TRANSFER_INFORMATION      0x10
  154. #define INIT_COMM_COMPLETE_SEQ    0x11
  155. #define MSG_ACCEPTED              0x12
  156. #define TRANSFER_PAD              0x18
  157. #define SET_ATN                   0x1A
  158. #define RESET_ATN                 0x1B
  159. #define ILLEGAL                   0xFF
  160. #define PIO_MODE                  0x80
  161. #define IO_RANGE 0x20         /* 0x00 - 0x1F                   */
  162. #define ID       "sym53c416" /* Attention: copied to the sym53c416.h */
  163. #define PIO_SIZE 128          /* Size of PIO fifo is 128 bytes */
  164. #define READ_TIMEOUT              150
  165. #define WRITE_TIMEOUT             150
  166. #ifdef MODULE
  167. #define sym53c416_base sym53c416
  168. #define sym53c416_base_1 sym53c416_1
  169. #define sym53c416_base_2 sym53c416_2
  170. #define sym53c416_base_3 sym53c416_3
  171. static unsigned int sym53c416_base[2] = {0,0};
  172. static unsigned int sym53c416_base_1[2] = {0,0};
  173. static unsigned int sym53c416_base_2[2] = {0,0};
  174. static unsigned int sym53c416_base_3[2] = {0,0};
  175. #endif
  176. /* #define DEBUG */
  177. /* Macro for debugging purposes */
  178. #ifdef DEBUG
  179. #define DEB(x) x
  180. #else
  181. #define DEB(x)
  182. #endif
  183. #define MAXHOSTS 4
  184. enum phases
  185. {
  186. idle,
  187. data_out,
  188. data_in,
  189. command_ph,
  190. status_ph,
  191. message_out,
  192. message_in
  193. };
  194. typedef struct
  195. {
  196. int base;
  197. int irq;
  198. int scsi_id;
  199. } host;
  200. static host hosts[MAXHOSTS] = {
  201.                        {0, 0, SYM53C416_SCSI_ID},
  202.                        {0, 0, SYM53C416_SCSI_ID},
  203.                        {0, 0, SYM53C416_SCSI_ID},
  204.                        {0, 0, SYM53C416_SCSI_ID}
  205.                        };
  206. static int host_index = 0;
  207. static char info[120];
  208. static Scsi_Cmnd *current_command = NULL;
  209. static int fastpio = 1;
  210. static int probeaddrs[] = {0x200, 0x220, 0x240, 0};
  211. static void sym53c416_set_transfer_counter(int base, unsigned int len)
  212. {
  213. /* Program Transfer Counter */
  214. outb(len & 0x0000FF, base + TC_LOW);
  215. outb((len & 0x00FF00) >> 8, base + TC_MID);
  216. outb((len & 0xFF0000) >> 16, base + TC_HIGH);
  217. }
  218. /* Returns the number of bytes read */
  219. static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len)
  220. {
  221. unsigned int orig_len = len;
  222. unsigned long flags = 0;
  223. unsigned int bytes_left;
  224. int i;
  225. int timeout = READ_TIMEOUT;
  226. /* Do transfer */
  227. save_flags(flags);
  228. cli();
  229. while(len && timeout)
  230. {
  231. bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */
  232. if(fastpio && bytes_left > 3)
  233. {
  234. insl(base + PIO_FIFO_1, buffer, bytes_left >> 2);
  235. buffer += bytes_left & 0xFC;
  236. len -= bytes_left & 0xFC;
  237. }
  238. else if(bytes_left > 0)
  239. {
  240. len -= bytes_left;
  241. for(; bytes_left > 0; bytes_left--)
  242. *(buffer++) = inb(base + PIO_FIFO_1);
  243. }
  244. else
  245. {
  246. i = jiffies + timeout;
  247. restore_flags(flags);
  248. while(jiffies < i && (inb(base + PIO_INT_REG) & EMPTY) && timeout)
  249. if(inb(base + PIO_INT_REG) & SCI)
  250. timeout = 0;
  251. save_flags(flags);
  252. cli();
  253. if(inb(base + PIO_INT_REG) & EMPTY)
  254. timeout = 0;
  255. }
  256. }
  257. restore_flags(flags);
  258. return orig_len - len;
  259. }
  260. /* Returns the number of bytes written */
  261. static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len)
  262. {
  263. unsigned int orig_len = len;
  264. unsigned long flags = 0;
  265. unsigned int bufferfree;
  266. unsigned int i;
  267. unsigned int timeout = WRITE_TIMEOUT;
  268. /* Do transfer */
  269. save_flags(flags);
  270. cli();
  271. while(len && timeout)
  272. {
  273. bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT);
  274. if(bufferfree > len)
  275. bufferfree = len;
  276. if(fastpio && bufferfree > 3)
  277. {
  278. outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2);
  279. buffer += bufferfree & 0xFC;
  280. len -= bufferfree & 0xFC;
  281. }
  282. else if(bufferfree > 0)
  283. {
  284. len -= bufferfree;
  285. for(; bufferfree > 0; bufferfree--)
  286. outb(*(buffer++), base + PIO_FIFO_1);
  287. }
  288. else
  289. {
  290. i = jiffies + timeout;
  291. restore_flags(flags);
  292. while(jiffies < i && (inb(base + PIO_INT_REG) & FULL) && timeout)
  293. ;
  294. save_flags(flags);
  295. cli();
  296. if(inb(base + PIO_INT_REG) & FULL)
  297. timeout = 0;
  298. }
  299. }
  300. restore_flags(flags);
  301. return orig_len - len;
  302. }
  303. static void sym53c416_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
  304. {
  305. int base = 0;
  306. int i;
  307. unsigned long flags = 0;
  308. unsigned char status_reg, pio_int_reg, int_reg;
  309. struct scatterlist *sglist;
  310. unsigned int sgcount;
  311. unsigned int tot_trans = 0;
  312. /* We search the base address of the host adapter which caused the interrupt */
  313. /* FIXME: should pass dev_id sensibly as hosts[i] */
  314. for(i = 0; i < host_index && !base; i++)
  315. if(irq == hosts[i].irq)
  316. base = hosts[i].base;
  317. /* If no adapter found, we cannot handle the interrupt. Leave a message */
  318. /* and continue. This should never happen...                            */
  319. if(!base)
  320. {
  321. printk(KERN_ERR "sym53c416: No host adapter defined for interrupt %dn", irq);
  322. return;
  323. }
  324. /* Now we have the base address and we can start handling the interrupt */
  325. spin_lock_irqsave(&io_request_lock,flags);
  326. status_reg = inb(base + STATUS_REG);
  327. pio_int_reg = inb(base + PIO_INT_REG);
  328. int_reg = inb(base + INT_REG);
  329. spin_unlock_irqrestore(&io_request_lock, flags);
  330. /* First, we handle error conditions */
  331. if(int_reg & SCI)         /* SCSI Reset */
  332. {
  333. printk(KERN_DEBUG "sym53c416: Reset receivedn");
  334. current_command->SCp.phase = idle;
  335. current_command->result = DID_RESET << 16;
  336. spin_lock_irqsave(&io_request_lock, flags);
  337. current_command->scsi_done(current_command);
  338. spin_unlock_irqrestore(&io_request_lock, flags);
  339. return;
  340. }
  341. if(int_reg & ILCMD)       /* Illegal Command */
  342. {
  343. printk(KERN_WARNING "sym53c416: Illegal Command: 0x%02x.n", inb(base + COMMAND_REG));
  344. current_command->SCp.phase = idle;
  345. current_command->result = DID_ERROR << 16;
  346. spin_lock_irqsave(&io_request_lock, flags);
  347. current_command->scsi_done(current_command);
  348. spin_unlock_irqrestore(&io_request_lock, flags);
  349. return;
  350. }
  351. if(status_reg & GE)         /* Gross Error */
  352. {
  353. printk(KERN_WARNING "sym53c416: Controller reports gross error.n");
  354. current_command->SCp.phase = idle;
  355. current_command->result = DID_ERROR << 16;
  356. spin_lock_irqsave(&io_request_lock, flags);
  357. current_command->scsi_done(current_command);
  358. spin_unlock_irqrestore(&io_request_lock, flags);
  359. return;
  360. }
  361. if(status_reg & PE)         /* Parity Error */
  362. {
  363. printk(KERN_WARNING "sym53c416:SCSI parity error.n");
  364. current_command->SCp.phase = idle;
  365. current_command->result = DID_PARITY << 16;
  366. spin_lock_irqsave(&io_request_lock, flags);
  367. current_command->scsi_done(current_command);
  368. spin_unlock_irqrestore(&io_request_lock, flags);
  369. return;
  370. }
  371. if(pio_int_reg & (CE | OUE))
  372. {
  373. printk(KERN_WARNING "sym53c416: PIO interrupt error.n");
  374. current_command->SCp.phase = idle;
  375. current_command->result = DID_ERROR << 16;
  376. spin_lock_irqsave(&io_request_lock, flags);
  377. current_command->scsi_done(current_command);
  378. spin_unlock_irqrestore(&io_request_lock, flags);
  379. return;
  380. }
  381. if(int_reg & DIS)           /* Disconnect */
  382. {
  383. if(current_command->SCp.phase != message_in)
  384. current_command->result = DID_NO_CONNECT << 16;
  385. else
  386. current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16);
  387. current_command->SCp.phase = idle;
  388. spin_lock_irqsave(&io_request_lock, flags);
  389. current_command->scsi_done(current_command);
  390. spin_unlock_irqrestore(&io_request_lock, flags);
  391. return;
  392. }
  393. /* Now we handle SCSI phases         */
  394. switch(status_reg & PHBITS)       /* Filter SCSI phase out of status reg */
  395. {
  396. case PHASE_DATA_OUT:
  397. {
  398. if(int_reg & BS)
  399. {
  400. current_command->SCp.phase = data_out;
  401. outb(FLUSH_FIFO, base + COMMAND_REG);
  402. sym53c416_set_transfer_counter(base, current_command->request_bufflen);
  403. outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
  404. if(!current_command->use_sg)
  405. tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
  406. else
  407. {
  408. sgcount = current_command->use_sg;
  409. sglist = current_command->request_buffer;
  410. while(sgcount--)
  411. {
  412. tot_trans += sym53c416_write(base, sglist->address, sglist->length);
  413. sglist++;
  414. }
  415. }
  416. if(tot_trans < current_command->underflow)
  417. printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.n", tot_trans, current_command->underflow);
  418. }
  419. break;
  420. }
  421. case PHASE_DATA_IN:
  422. {
  423. if(int_reg & BS)
  424. {
  425. current_command->SCp.phase = data_in;
  426. outb(FLUSH_FIFO, base + COMMAND_REG);
  427. sym53c416_set_transfer_counter(base, current_command->request_bufflen);
  428. outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
  429. if(!current_command->use_sg)
  430. tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
  431. else
  432. {
  433. sgcount = current_command->use_sg;
  434. sglist = current_command->request_buffer;
  435. while(sgcount--)
  436. {
  437. tot_trans += sym53c416_read(base, sglist->address, sglist->length);
  438. sglist++;
  439. }
  440. }
  441. if(tot_trans < current_command->underflow)
  442. printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.n", tot_trans, current_command->underflow);
  443. }
  444. break;
  445. }
  446. case PHASE_COMMAND:
  447. {
  448. current_command->SCp.phase = command_ph;
  449. printk(KERN_ERR "sym53c416: Unknown interrupt in command phase.n");
  450. break;
  451. }
  452. case PHASE_STATUS:
  453. {
  454. current_command->SCp.phase = status_ph;
  455. outb(FLUSH_FIFO, base + COMMAND_REG);
  456. outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG);
  457. break;
  458. }
  459. case PHASE_RESERVED_1:
  460. case PHASE_RESERVED_2:
  461. {
  462. printk(KERN_ERR "sym53c416: Reserved phase occurred.n");
  463. break;
  464. }
  465. case PHASE_MESSAGE_OUT:
  466. {
  467. current_command->SCp.phase = message_out;
  468. outb(SET_ATN, base + COMMAND_REG);
  469. outb(MSG_ACCEPTED, base + COMMAND_REG);
  470. break;
  471. }
  472. case PHASE_MESSAGE_IN:
  473. {
  474. current_command->SCp.phase = message_in;
  475. current_command->SCp.Status = inb(base + SCSI_FIFO);
  476. current_command->SCp.Message = inb(base + SCSI_FIFO);
  477. if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT)
  478. outb(SET_ATN, base + COMMAND_REG);
  479. outb(MSG_ACCEPTED, base + COMMAND_REG);
  480. break;
  481. }
  482. }
  483. }
  484. static void sym53c416_init(int base, int scsi_id)
  485. {
  486. outb(RESET_CHIP, base + COMMAND_REG);
  487. outb(NOOP, base + COMMAND_REG);
  488. outb(0x99, base + TOM); /* Time out of 250 ms */
  489. outb(0x05, base + STP);
  490. outb(0x00, base + SYNC_OFFSET);
  491. outb(EPC | scsi_id, base + CONF_REG_1);
  492. outb(FE | SCSI2 | TBPA, base + CONF_REG_2);
  493. outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3);
  494. outb(0x83 | EAN, base + CONF_REG_4);
  495. outb(IE | WSE0, base + CONF_REG_5);
  496. outb(0, base + FEATURE_EN);
  497. }
  498. static int sym53c416_probeirq(int base, int scsi_id)
  499. {
  500. int irq, irqs, i;
  501. /* Clear interrupt register */
  502. inb(base + INT_REG);
  503. /* Start probing for irq's */
  504. irqs = probe_irq_on();
  505. /* Reinit chip */
  506. sym53c416_init(base, scsi_id);
  507. /* Cause interrupt */
  508. outb(NOOP, base + COMMAND_REG);
  509. outb(ILLEGAL, base + COMMAND_REG);
  510. outb(0x07, base + DEST_BUS_ID);
  511. outb(0x00, base + DEST_BUS_ID);
  512. /* Wait for interrupt to occur */
  513. i = jiffies + 20;
  514. while(i > jiffies && !(inb(base + STATUS_REG) & SCI))
  515. barrier();
  516. if(i <= jiffies) /* timed out */
  517. return 0;
  518. /* Get occurred irq */
  519. irq = probe_irq_off(irqs);
  520. sym53c416_init(base, scsi_id);
  521. return irq;
  522. }
  523. /* Setup: sym53c416=base,irq */
  524. void sym53c416_setup(char *str, int *ints)
  525. {
  526. int i;
  527. if(host_index >= MAXHOSTS)
  528. {
  529. printk(KERN_WARNING "sym53c416: Too many hosts definedn");
  530. return;
  531. }
  532. if(ints[0] < 1 || ints[0] > 2)
  533. {
  534. printk(KERN_ERR "sym53c416: Wrong number of parameters:n");
  535. printk(KERN_ERR "sym53c416: usage: sym53c416=<base>[,<irq>]n");
  536. return;
  537. }
  538. for(i = 0; i < host_index && i >= 0; i++)
  539.         if(hosts[i].base == ints[1])
  540.          i = -2;
  541. if(i >= 0)
  542. {
  543.          hosts[host_index].base = ints[1];
  544.          hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0;
  545.          host_index++;
  546. }
  547. }
  548. static int sym53c416_test(int base)
  549. {
  550. outb(RESET_CHIP, base + COMMAND_REG);
  551. outb(NOOP, base + COMMAND_REG);
  552. if(inb(base + COMMAND_REG) != NOOP)
  553. return 0;
  554. if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF)
  555. return 0;
  556. if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY)
  557. return 0;
  558. return 1;
  559. }
  560. static struct isapnp_device_id id_table[] = {
  561. { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
  562. ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4163), 0 },
  563. {0}
  564. };
  565. MODULE_DEVICE_TABLE(isapnp, id_table);
  566. void sym53c416_probe(void)
  567. {
  568. int *base = probeaddrs;
  569. int ints[2];
  570. ints[0] = 1;
  571. for(; *base; base++)
  572. {
  573. if(!check_region(*base, IO_RANGE) && sym53c416_test(*base))
  574. {
  575. ints[1] = *base;
  576. sym53c416_setup(NULL, ints);
  577. }
  578. }
  579. }
  580. int sym53c416_detect(Scsi_Host_Template *tpnt)
  581. {
  582. unsigned long flags;
  583. struct Scsi_Host * shpnt = NULL;
  584. int i;
  585. int count;
  586. struct pci_dev *idev = NULL;
  587. #ifdef MODULE
  588. int ints[3];
  589. ints[0] = 2;
  590. if(sym53c416_base)
  591. {
  592. ints[1] = sym53c416_base[0];
  593. ints[2] = sym53c416_base[1];
  594. sym53c416_setup(NULL, ints);
  595. }
  596. if(sym53c416_base_1)
  597. {
  598. ints[1] = sym53c416_base_1[0];
  599. ints[2] = sym53c416_base_1[1];
  600. sym53c416_setup(NULL, ints);
  601. }
  602. if(sym53c416_base_2)
  603. {
  604. ints[1] = sym53c416_base_2[0];
  605. ints[2] = sym53c416_base_2[1];
  606. sym53c416_setup(NULL, ints);
  607. }
  608. if(sym53c416_base_3)
  609. {
  610. ints[1] = sym53c416_base_3[0];
  611. ints[2] = sym53c416_base_3[1];
  612. sym53c416_setup(NULL, ints);
  613. }
  614. #endif
  615. printk(KERN_INFO "sym53c416.c: %sn", VERSION_STRING);
  616. while((idev=isapnp_find_dev(NULL, ISAPNP_VENDOR('S','L','I'), 
  617. ISAPNP_FUNCTION(0x4163), idev))!=NULL)
  618. {
  619. int i[3];
  620. if(idev->prepare(idev)<0)
  621. {
  622. printk(KERN_WARNING "sym53c416: unable to prepare PnP card.n");
  623. continue;
  624. }
  625. if(idev->activate(idev)<0)
  626. {
  627. printk(KERN_WARNING "sym53c416: unable to activate PnP card.n");
  628. continue;
  629. }
  630. i[0] = 2;
  631. i[1] = idev->resource[0].start;
  632. i[2] = idev->irq_resource[0].start;
  633. printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.n",
  634. i[1], i[2]);
  635. sym53c416_setup(NULL, i);
  636. }
  637. sym53c416_probe();
  638. /* Now we register and set up each host adapter found... */
  639. for(count = 0, i = 0; i < host_index; i++)
  640. {
  641. if(!sym53c416_test(hosts[i].base))
  642. printk(KERN_WARNING "No sym53c416 found at address 0x%03xn", hosts[i].base);
  643. else
  644. {
  645. if(hosts[i].irq == 0)
  646. /* We don't have an irq yet, so we should probe for one */
  647. if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0)
  648. printk(KERN_WARNING "IRQ autoprobing failed for sym53c416 at address 0x%03xn", hosts[i].base);
  649. if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE))
  650. {
  651. shpnt = scsi_register(tpnt, 0);
  652. if(shpnt==NULL)
  653. continue;
  654. save_flags(flags);
  655. cli();
  656. /* FIXME: Request_irq with CLI is not safe */
  657. /* Request for specified IRQ */
  658. if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL))
  659. {
  660. restore_flags(flags);
  661. printk(KERN_ERR "sym53c416: Unable to assign IRQ %dn", hosts[i].irq);
  662. scsi_unregister(shpnt);
  663. }
  664. else
  665. {
  666. /* Inform the kernel of our IO range */
  667. request_region(hosts[i].base, IO_RANGE, ID);
  668. shpnt->unique_id = hosts[i].base;
  669. shpnt->io_port = hosts[i].base;
  670. shpnt->n_io_port = IO_RANGE;
  671. shpnt->irq = hosts[i].irq;
  672. shpnt->this_id = hosts[i].scsi_id;
  673. sym53c416_init(hosts[i].base, hosts[i].scsi_id);
  674. count++;
  675. restore_flags(flags);
  676. }
  677. }
  678. }
  679. }
  680. return count;
  681. }
  682. const char *sym53c416_info(struct Scsi_Host *SChost)
  683. {
  684. int i;
  685. int base = SChost->io_port;
  686. int irq = SChost->irq;
  687. int scsi_id = 0;
  688. int rev = inb(base + TC_HIGH);
  689. for(i = 0; i < host_index; i++)
  690. if(hosts[i].base == base)
  691. scsi_id = hosts[i].scsi_id;
  692. sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow");
  693. return info;
  694. }
  695. int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
  696. {
  697. int base;
  698. unsigned long flags = 0;
  699. int i;
  700. /* Store base register as we can have more than one controller in the system */
  701. base = SCpnt->host->io_port;
  702. current_command = SCpnt;                  /* set current command                */
  703. current_command->scsi_done = done;        /* set ptr to done function           */
  704. current_command->SCp.phase = command_ph;  /* currect phase is the command phase */
  705. current_command->SCp.Status = 0;
  706. current_command->SCp.Message = 0;
  707. save_flags(flags);
  708. cli();
  709. outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target        */
  710. outb(FLUSH_FIFO, base + COMMAND_REG);    /* Flush SCSI and PIO FIFO's */
  711. /* Write SCSI command into the SCSI fifo */
  712. for(i = 0; i < SCpnt->cmd_len; i++)
  713. outb(SCpnt->cmnd[i], base + SCSI_FIFO);
  714. /* Start selection sequence */
  715. outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);
  716. /* Now an interrupt will be generated which we will catch in out interrupt routine */
  717. restore_flags(flags);
  718. return 0;
  719. }
  720. static void internal_done(Scsi_Cmnd *SCpnt)
  721. {
  722. SCpnt->SCp.Status++;
  723. }
  724. static int sym53c416_command(Scsi_Cmnd *SCpnt)
  725. {
  726. sym53c416_queuecommand(SCpnt, internal_done);
  727. SCpnt->SCp.Status = 0;
  728. while(!SCpnt->SCp.Status)
  729. barrier();
  730. return SCpnt->result;
  731. }
  732. static int sym53c416_abort(Scsi_Cmnd *SCpnt)
  733. {
  734. //printk("sym53c416_abortn");
  735. /* We don't know how to abort for the moment */
  736. return SCSI_ABORT_SNOOZE;
  737. }
  738. static int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  739. {
  740. int base;
  741. int scsi_id = -1;
  742. int i;
  743. //printk("sym53c416_resetn");
  744. base = SCpnt->host->io_port;
  745. /* search scsi_id */
  746. for(i = 0; i < host_index && scsi_id != -1; i++)
  747. if(hosts[i].base == base)
  748. scsi_id = hosts[i].scsi_id;
  749. outb(RESET_CHIP, base + COMMAND_REG);
  750. outb(NOOP | PIO_MODE, base + COMMAND_REG);
  751. outb(RESET_SCSI_BUS, base + COMMAND_REG);
  752. sym53c416_init(base, scsi_id);
  753. return SCSI_RESET_PENDING;
  754. }
  755. static int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip)
  756. {
  757. int size;
  758. size = disk->capacity;
  759. ip[0] = 64; /* heads                        */
  760. ip[1] = 32; /* sectors                      */
  761. if((ip[2] = size >> 11) > 1024) /* cylinders, test for big disk */
  762. {
  763. ip[0] = 255; /* heads                        */
  764. ip[1] = 63; /* sectors                      */
  765. ip[2] = size / (255 * 63); /* cylinders                    */
  766. }
  767. return 0;
  768. }
  769. /* Loadable module support */
  770. #ifdef MODULE
  771. MODULE_AUTHOR("Lieven Willems");
  772. MODULE_LICENSE("GPL");
  773. MODULE_PARM(sym53c416, "1-2i");
  774. MODULE_PARM(sym53c416_1, "1-2i");
  775. MODULE_PARM(sym53c416_2, "1-2i");
  776. MODULE_PARM(sym53c416_3, "1-2i");
  777. #endif
  778. static Scsi_Host_Template driver_template = SYM53C416;
  779. #include "scsi_module.c"