sc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /* $OpenBSD: sc.c,v 1.3 2013/10/29 21:49:07 miod Exp $ */
  2. /* $NetBSD: sc.c,v 1.4 2013/01/22 15:48:40 tsutsui Exp $ */
  3. /*
  4. * Copyright (c) 1992 OMRON Corporation.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * OMRON Corporation.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the University of
  20. * California, Berkeley and its contributors.
  21. * 4. Neither the name of the University nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. *
  37. * @(#)sc.c 8.1 (Berkeley) 6/10/93
  38. */
  39. /*
  40. * Copyright (c) 1992, 1993
  41. * The Regents of the University of California. All rights reserved.
  42. *
  43. * This code is derived from software contributed to Berkeley by
  44. * OMRON Corporation.
  45. *
  46. * Redistribution and use in source and binary forms, with or without
  47. * modification, are permitted provided that the following conditions
  48. * are met:
  49. * 1. Redistributions of source code must retain the above copyright
  50. * notice, this list of conditions and the following disclaimer.
  51. * 2. Redistributions in binary form must reproduce the above copyright
  52. * notice, this list of conditions and the following disclaimer in the
  53. * documentation and/or other materials provided with the distribution.
  54. * 3. Neither the name of the University nor the names of its contributors
  55. * may be used to endorse or promote products derived from this software
  56. * without specific prior written permission.
  57. *
  58. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  59. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  60. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  61. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  62. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  63. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  64. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  65. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  66. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  67. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  68. * SUCH DAMAGE.
  69. *
  70. * @(#)sc.c 8.1 (Berkeley) 6/10/93
  71. */
  72. /*
  73. * sc.c -- SCSI Protocole Controller (SPC) driver
  74. * remaked by A.Fujita, MAR-11-199
  75. */
  76. #include <sys/param.h>
  77. #include <machine/board.h>
  78. #include <luna88k/stand/boot/samachdep.h>
  79. #include <luna88k/stand/boot/scsireg.h>
  80. #include <luna88k/stand/boot/scsivar.h>
  81. #define SCSI_ID 7
  82. int scintr(struct scsi_softc *);
  83. void screset(struct scsi_softc *);
  84. int issue_select(struct scsidevice *, u_char);
  85. void ixfer_start(struct scsidevice *, int, u_char, int);
  86. void ixfer_out(struct scsidevice *, int, u_char *);
  87. void ixfer_in(struct scsidevice *, int, u_char *);
  88. int scrun(struct scsi_softc *, uint, u_char *, int, u_char *, int,
  89. volatile int *);
  90. int scfinish(struct scsi_softc *);
  91. void scabort(struct scsi_softc *, struct scsidevice *);
  92. /*
  93. * Initialize SPC & Data Structure
  94. */
  95. int
  96. scinit(struct scsi_softc *hs, uint unit)
  97. {
  98. void *reg;
  99. switch (unit) {
  100. case 0:
  101. reg = (void *)SCSI_ADDR;
  102. break;
  103. case 1:
  104. reg = (void *)(SCSI_ADDR + 0x40);
  105. break;
  106. default:
  107. return 0;
  108. }
  109. if (unit != 0 && machtype != LUNA_88K2)
  110. return 0;
  111. hs->sc_sd = (struct scsidevice *)reg;
  112. hs->sc_unit = unit;
  113. hs->sc_flags = 0;
  114. hs->sc_phase = BUS_FREE_PHASE;
  115. hs->sc_target = SCSI_ID;
  116. hs->sc_cdb = NULL;
  117. hs->sc_cdblen = 0;
  118. hs->sc_buf = NULL;
  119. hs->sc_len = 0;
  120. hs->sc_lock = NULL;
  121. hs->sc_stat = 0;
  122. hs->sc_msg[0] = 0;
  123. screset(hs);
  124. return(1);
  125. }
  126. void
  127. screset(struct scsi_softc *hs)
  128. {
  129. struct scsidevice *hd = hs->sc_sd;
  130. #ifdef DEBUG
  131. printf("sc%d: ", hs->sc_unit);
  132. #endif
  133. /*
  134. * Disable interrupts then reset the FUJI chip.
  135. */
  136. hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
  137. hd->scsi_scmd = 0;
  138. hd->scsi_pctl = 0;
  139. hd->scsi_temp = 0;
  140. hd->scsi_tch = 0;
  141. hd->scsi_tcm = 0;
  142. hd->scsi_tcl = 0;
  143. hd->scsi_ints = 0;
  144. #ifdef DEBUG
  145. /* We can use Asynchronous Transfer only */
  146. printf("async");
  147. #endif
  148. /*
  149. * Configure MB89352 with its SCSI address, all
  150. * interrupts enabled & appropriate parity.
  151. */
  152. hd->scsi_bdid = SCSI_ID;
  153. hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
  154. SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
  155. SCTL_INTR_ENAB;
  156. #ifdef DEBUG
  157. printf(", parity");
  158. #endif
  159. DELAY(400);
  160. hd->scsi_sctl &= ~SCTL_DISABLE;
  161. #ifdef DEBUG
  162. printf(", scsi id %d\n", SCSI_ID);
  163. #endif
  164. }
  165. /*
  166. * SPC Arbitration/Selection routine
  167. */
  168. int
  169. issue_select(struct scsidevice *hd, u_char target)
  170. {
  171. hd->scsi_pctl = 0;
  172. hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
  173. /* select timeout is hardcoded to 250ms */
  174. hd->scsi_tch = 2;
  175. hd->scsi_tcm = 113;
  176. hd->scsi_tcl = 3;
  177. hd->scsi_scmd = SCMD_SELECT;
  178. return (1);
  179. }
  180. /*
  181. * SPC Manual Transfer routines
  182. */
  183. /* not yet */
  184. /*
  185. * SPC Program Transfer routines
  186. */
  187. void
  188. ixfer_start(struct scsidevice *hd, int len, u_char phase, int wait)
  189. {
  190. hd->scsi_tch = ((len & 0xff0000) >> 16);
  191. hd->scsi_tcm = ((len & 0x00ff00) >> 8);
  192. hd->scsi_tcl = (len & 0x0000ff);
  193. hd->scsi_pctl = phase;
  194. hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
  195. }
  196. void
  197. ixfer_out(struct scsidevice *hd, int len, u_char *buf)
  198. {
  199. for(; len > 0; len--) {
  200. while (hd->scsi_ssts & SSTS_DREG_FULL) {
  201. DELAY(5);
  202. }
  203. hd->scsi_dreg = *buf++;
  204. }
  205. }
  206. void
  207. ixfer_in(struct scsidevice *hd, int len, u_char *buf)
  208. {
  209. for (; len > 0; len--) {
  210. while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
  211. DELAY(5);
  212. }
  213. *buf++ = hd->scsi_dreg;
  214. }
  215. }
  216. /*
  217. * SPC drive routines
  218. */
  219. int
  220. scrun(struct scsi_softc *hs, uint target, u_char *cdb, int cdblen, u_char *buf,
  221. int len, volatile int *lock)
  222. {
  223. struct scsidevice *hd;
  224. hd = hs->sc_sd;
  225. if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
  226. return(0);
  227. if (target > 7)
  228. return 0;
  229. hs->sc_flags = 0;
  230. hs->sc_phase = ARB_SEL_PHASE;
  231. hs->sc_target = target >= 7 ? target : 6 - target;
  232. hs->sc_cdb = cdb;
  233. hs->sc_cdblen = cdblen;
  234. hs->sc_buf = buf;
  235. hs->sc_len = len;
  236. hs->sc_lock = lock;
  237. hs->sc_stat = 0;
  238. hs->sc_msg[0] = 0;
  239. *(hs->sc_lock) = SC_IN_PROGRESS;
  240. issue_select(hd, hs->sc_target);
  241. return(1);
  242. }
  243. int
  244. scfinish(struct scsi_softc *hs)
  245. {
  246. int status = hs->sc_stat;
  247. hs->sc_flags = 0;
  248. hs->sc_phase = BUS_FREE_PHASE;
  249. hs->sc_target = SCSI_ID;
  250. hs->sc_cdb = NULL;
  251. hs->sc_cdblen = 0;
  252. hs->sc_buf = NULL;
  253. hs->sc_len = 0;
  254. hs->sc_lock = NULL;
  255. hs->sc_stat = 0;
  256. hs->sc_msg[0] = 0;
  257. return(status);
  258. }
  259. void
  260. scabort(struct scsi_softc *hs, struct scsidevice *hd)
  261. {
  262. int len;
  263. u_char junk;
  264. printf("sc%d: abort phase=0x%x, ssts=0x%x, ints=0x%x\n",
  265. hs->sc_unit, hd->scsi_psns, hd->scsi_ssts, hd->scsi_ints);
  266. if (hd->scsi_ints != 0)
  267. hd->scsi_ints = hd->scsi_ints;
  268. if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
  269. /* no longer connected to scsi target */
  270. return;
  271. /* get the number of bytes remaining in current xfer + fudge */
  272. len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
  273. /* for that many bus cycles, try to send an abort msg */
  274. for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
  275. hd->scsi_scmd = SCMD_SET_ATN;
  276. while ((hd->scsi_psns & PSNS_REQ) == 0) {
  277. if (! (hd->scsi_ssts & SSTS_INITIATOR))
  278. goto out;
  279. DELAY(1);
  280. }
  281. if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
  282. hd->scsi_scmd = SCMD_RST_ATN;
  283. hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
  284. if (hd->scsi_psns & PHASE_IO) {
  285. /* one of the input phases - read & discard a byte */
  286. hd->scsi_scmd = SCMD_SET_ACK;
  287. while (hd->scsi_psns & PSNS_REQ)
  288. DELAY(1);
  289. junk = hd->scsi_temp;
  290. } else {
  291. /* one of the output phases - send an abort msg */
  292. hd->scsi_temp = MSG_ABORT;
  293. hd->scsi_scmd = SCMD_SET_ACK;
  294. while (hd->scsi_psns & PSNS_REQ)
  295. DELAY(1);
  296. }
  297. hd->scsi_scmd = SCMD_RST_ACK;
  298. }
  299. out:
  300. /*
  301. * Either the abort was successful & the bus is disconnected or
  302. * the device didn't listen. If the latter, announce the problem.
  303. * Either way, reset the card & the SPC.
  304. */
  305. if (len < 0 && hs)
  306. printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n",
  307. hs->sc_unit, hd->scsi_psns, hd->scsi_ssts);
  308. }
  309. /*
  310. * SCSI Command Handler
  311. */
  312. int
  313. scsi_test_unit_rdy(struct scsi_softc *sc, int target, int unit)
  314. {
  315. static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
  316. int status;
  317. volatile int lock;
  318. #ifdef DEBUG
  319. printf("scsi_test_unit_rdy(%d,%d,%d): Start\n",
  320. sc->sc_unit, target, unit);
  321. #endif
  322. cdb.lun = unit;
  323. if (!(scrun(sc, target, (void *)&cdb, 6, NULL, 0, &lock))) {
  324. #ifdef DEBUG
  325. printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
  326. #endif
  327. return(-1);
  328. }
  329. while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
  330. if (scintr(sc))
  331. DELAY(10);
  332. }
  333. status = scfinish(sc);
  334. if (lock == SC_IO_COMPLETE) {
  335. #ifdef DEBUG
  336. printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
  337. #endif
  338. return(status);
  339. } else {
  340. return(lock);
  341. }
  342. }
  343. int
  344. scsi_request_sense(struct scsi_softc *sc, int target, int unit, u_char *buf,
  345. unsigned int len)
  346. {
  347. static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
  348. int status;
  349. volatile int lock;
  350. #ifdef DEBUG
  351. printf("scsi_request_sense: Start\n");
  352. #endif
  353. cdb.lun = unit;
  354. cdb.len = len;
  355. if (!(scrun(sc, target, (void *)&cdb, 6, buf, len, &lock))) {
  356. #ifdef DEBUG
  357. printf("scsi_request_sense: Command Transfer Failed.\n");
  358. #endif
  359. return(-1);
  360. }
  361. while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
  362. if (scintr(sc))
  363. DELAY(10);
  364. }
  365. status = scfinish(sc);
  366. if (lock == SC_IO_COMPLETE) {
  367. #ifdef DEBUG
  368. printf("scsi_request_sense: Status -- 0x%x\n", status);
  369. #endif
  370. return(status);
  371. } else {
  372. return(lock);
  373. }
  374. }
  375. int
  376. scsi_immed_command(struct scsi_softc *sc, int target, int unit,
  377. struct scsi_generic_cdb *cdb, u_char *buf, unsigned int len)
  378. {
  379. int status;
  380. volatile int lock;
  381. #ifdef DEBUG
  382. printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
  383. sc->sc_unit, target, unit, cdb->len, len);
  384. #endif
  385. cdb->cdb[1] |= unit << 5;
  386. if (!(scrun(sc, target, (void *)&cdb->cdb[0], cdb->len, buf, len,
  387. &lock))) {
  388. #ifdef DEBUG
  389. printf("scsi_immed_command: Command Transfer Failed.\n");
  390. #endif
  391. return(-1);
  392. }
  393. while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
  394. if (scintr(sc))
  395. DELAY(10);
  396. }
  397. status = scfinish(sc);
  398. if (lock == SC_IO_COMPLETE) {
  399. #ifdef DEBUG
  400. printf("scsi_immed_command: Status -- 0x%x\n", status);
  401. #endif
  402. return(status);
  403. } else {
  404. return(lock);
  405. }
  406. }
  407. /*
  408. * Interrupt Routine
  409. */
  410. int
  411. scintr(struct scsi_softc *hs)
  412. {
  413. struct scsidevice *hd;
  414. u_char ints, temp;
  415. u_char *buf;
  416. int i, len;
  417. hd = hs->sc_sd;
  418. if ((ints = hd->scsi_ints) == 0)
  419. return -1;
  420. #ifdef DEBUG
  421. printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x 0x%x\n",
  422. ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns,
  423. hs->sc_phase);
  424. #endif
  425. if (ints & INTS_RESEL) {
  426. if (hs->sc_phase == BUS_FREE_PHASE) {
  427. temp = hd->scsi_temp & ~(1 << SCSI_ID);
  428. for (i = 0; temp != 1; i++) {
  429. temp >>= 1;
  430. }
  431. hs->sc_target = i;
  432. *(hs->sc_lock) = SC_IN_PROGRESS;
  433. } else
  434. goto abort;
  435. } else if (ints & INTS_DISCON) {
  436. if (hs->sc_msg[0] == MSG_CMD_COMPLETE ||
  437. hs->sc_msg[0] == MSG_DISCONNECT) {
  438. hs->sc_phase = BUS_FREE_PHASE;
  439. hs->sc_target = SCSI_ID;
  440. if (hs->sc_msg[0] == MSG_CMD_COMPLETE)
  441. /* SCSI IO complete */
  442. *(hs->sc_lock) = SC_IO_COMPLETE;
  443. else
  444. /* Cisconnected from Target */
  445. *(hs->sc_lock) = SC_DISCONNECTED;
  446. hd->scsi_ints = ints;
  447. return 0;
  448. } else
  449. goto abort;
  450. } else if (ints & INTS_CMD_DONE) {
  451. if (hs->sc_phase == BUS_FREE_PHASE)
  452. goto abort;
  453. else if (hs->sc_phase == MESG_IN_PHASE) {
  454. hd->scsi_scmd = SCMD_RST_ACK;
  455. hd->scsi_ints = ints;
  456. hs->sc_phase = hd->scsi_psns & PHASE;
  457. return 0;
  458. }
  459. if (hs->sc_flags & SC_SEL_TIMEOUT)
  460. hs->sc_flags &= ~SC_SEL_TIMEOUT;
  461. } else if (ints & INTS_SRV_REQ) {
  462. if (hs->sc_phase != MESG_IN_PHASE)
  463. goto abort;
  464. } else if (ints & INTS_TIMEOUT) {
  465. if (hs->sc_phase == ARB_SEL_PHASE) {
  466. if (hs->sc_flags & SC_SEL_TIMEOUT) {
  467. hs->sc_flags &= ~SC_SEL_TIMEOUT;
  468. hs->sc_phase = BUS_FREE_PHASE;
  469. hs->sc_target = SCSI_ID;
  470. /* Such SCSI Device is not conected. */
  471. *(hs->sc_lock) = SC_DEV_NOT_FOUND;
  472. hd->scsi_ints = ints;
  473. return 0;
  474. } else {
  475. /* wait more 250 usec */
  476. hs->sc_flags |= SC_SEL_TIMEOUT;
  477. hd->scsi_temp = 0;
  478. hd->scsi_tch = 0;
  479. hd->scsi_tcm = 0x06;
  480. hd->scsi_tcl = 0x40;
  481. hd->scsi_ints = ints;
  482. return 0;
  483. }
  484. } else
  485. goto abort;
  486. } else
  487. goto abort;
  488. hd->scsi_ints = ints;
  489. /*
  490. * Next SCSI Transfer
  491. */
  492. while ((hd->scsi_psns & PSNS_REQ) == 0) {
  493. DELAY(1);
  494. }
  495. hs->sc_phase = hd->scsi_psns & PHASE;
  496. if (hs->sc_phase == DATA_OUT_PHASE || hs->sc_phase == DATA_IN_PHASE) {
  497. len = hs->sc_len;
  498. buf = hs->sc_buf;
  499. } else if (hs->sc_phase == CMD_PHASE) {
  500. len = hs->sc_cdblen;
  501. buf = hs->sc_cdb;
  502. } else if (hs->sc_phase == STATUS_PHASE) {
  503. len = 1;
  504. buf = &hs->sc_stat;
  505. } else {
  506. len = 1;
  507. buf = hs->sc_msg;
  508. }
  509. ixfer_start(hd, len, hs->sc_phase, 0);
  510. if (hs->sc_phase & PHASE_IO)
  511. ixfer_in(hd, len, buf);
  512. else
  513. ixfer_out(hd, len, buf);
  514. return 0;
  515. /*
  516. * SCSI Abort
  517. */
  518. abort:
  519. /* SCSI IO failed */
  520. scabort(hs, hd);
  521. hd->scsi_ints = ints;
  522. *(hs->sc_lock) = SC_IO_FAILED;
  523. return -1;
  524. }