Deleted Added
sdiff udiff text old ( 226381 ) new ( 226947 )
full compact
1/*-
2 * Copyright (c) 2004 Scott Long
3 * Copyright (c) 2005, 2008 Marius Strobl <marius@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 84 unchanged lines hidden (view full) ---

93 * Based on aic6360 by Jarle Greipsland
94 *
95 * Acknowledgements: Many of the algorithms used in this driver are
96 * inspired by the work of Julian Elischer (julian@FreeBSD.org) and
97 * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
98 */
99
100#include <sys/cdefs.h>
101__FBSDID("$FreeBSD: head/sys/dev/esp/ncr53c9x.c 226381 2011-10-15 09:29:43Z marius $");
102
103#include <sys/param.h>
104#include <sys/systm.h>
105#include <sys/bus.h>
106#include <sys/kernel.h>
107#include <sys/malloc.h>
108#include <sys/lock.h>
109#include <sys/module.h>

--- 8 unchanged lines hidden (view full) ---

118#include <cam/cam_sim.h>
119#include <cam/cam_xpt_sim.h>
120#include <cam/scsi/scsi_all.h>
121#include <cam/scsi/scsi_message.h>
122
123#include <dev/esp/ncr53c9xreg.h>
124#include <dev/esp/ncr53c9xvar.h>
125
126MODULE_DEPEND(esp, cam, 1, 1, 1);
127
128#ifdef NCR53C9X_DEBUG
129int ncr53c9x_debug =
130 NCR_SHOWMISC /* | NCR_SHOWPHASE | NCR_SHOWTRAC | NCR_SHOWCMDS */;
131#endif
132
133static void ncr53c9x_abort(struct ncr53c9x_softc *sc,

--- 40 unchanged lines hidden (view full) ---

174 int period);
175
176#define NCR_RDFIFO_START 0
177#define NCR_RDFIFO_CONTINUE 1
178
179#define NCR_SET_COUNT(sc, size) do { \
180 NCR_WRITE_REG((sc), NCR_TCL, (size)); \
181 NCR_WRITE_REG((sc), NCR_TCM, (size) >> 8); \
182 if ((sc->sc_cfg2 & NCRCFG2_FE) || \
183 (sc->sc_rev == NCR_VARIANT_FAS366)) \
184 NCR_WRITE_REG((sc), NCR_TCH, (size) >> 16); \
185 if (sc->sc_rev == NCR_VARIANT_FAS366) \
186 NCR_WRITE_REG(sc, NCR_RCH, 0); \
187} while (/* CONSTCOND */0)
188
189#ifndef mstohz
190#define mstohz(ms) \
191 (((ms) < 0x20000) ? \

--- 194 unchanged lines hidden (view full) ---

386 device_printf(sc->sc_dev, "cannot allocate ECB array\n");
387 error = ENOMEM;
388 goto fail_async;
389 }
390 for (i = 0; i < NCR_TAG_DEPTH; i++) {
391 ecb = &sc->ecb_array[i];
392 ecb->sc = sc;
393 ecb->tag_id = i;
394 TAILQ_INSERT_HEAD(&sc->free_list, ecb, free_links);
395 }
396
397 callout_reset(&sc->sc_watchdog, 60 * hz, ncr53c9x_watch, sc);
398
399 NCR_UNLOCK(sc);
400
401 return (0);

--- 42 unchanged lines hidden (view full) ---

444 free(li, M_DEVBUF);
445 }
446 }
447 }
448
449 xpt_register_async(0, ncr53c9x_async, sc->sc_sim, sc->sc_path);
450 xpt_free_path(sc->sc_path);
451 xpt_bus_deregister(cam_sim_path(sc->sc_sim));
452
453 NCR_UNLOCK(sc);
454
455 cam_sim_free(sc->sc_sim, TRUE);
456 free(sc->ecb_array, M_DEVBUF);
457 free(sc->sc_tinfo, M_DEVBUF);
458 if (sc->sc_imess_self)
459 free(sc->sc_imess, M_DEVBUF);
460 if (sc->sc_omess_self)
461 free(sc->sc_omess, M_DEVBUF);
462
463 return (0);

--- 35 unchanged lines hidden (view full) ---

499 case NCR_VARIANT_NCR53C94:
500 case NCR_VARIANT_NCR53C96:
501 case NCR_VARIANT_ESP200:
502 sc->sc_features |= NCR_F_HASCFG3;
503 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
504 /* FALLTHROUGH */
505 case NCR_VARIANT_ESP100A:
506 sc->sc_features |= NCR_F_SELATN3;
507 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
508 /* FALLTHROUGH */
509 case NCR_VARIANT_ESP100:
510 NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
511 NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
512 NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
513 NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
514 break;
515
516 case NCR_VARIANT_FAS366:
517 sc->sc_features |=
518 NCR_F_HASCFG3 | NCR_F_FASTSCSI | NCR_F_SELATN3;
519 sc->sc_cfg3 = NCRFASCFG3_FASTCLK | NCRFASCFG3_OBAUTO;
520 if (sc->sc_id > 7)
521 sc->sc_cfg3 |= NCRFASCFG3_IDBIT3;
522 sc->sc_cfg3_fscsi = NCRFASCFG3_FASTSCSI;
523 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
524 sc->sc_cfg2 = NCRCFG2_HMEFE | NCRCFG2_HME32;
525 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
526 NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);

--- 179 unchanged lines hidden (view full) ---

706 /* Only the step bits are of interest. */
707 sc->sc_espstep = NCR_READ_REG(sc, NCR_STEP) & NCRSTEP_MASK;
708
709 if (sc->sc_rev == NCR_VARIANT_FAS366)
710 sc->sc_espstat2 = NCR_READ_REG(sc, NCR_STAT2);
711
712 sc->sc_espintr = NCR_READ_REG(sc, NCR_INTR);
713
714 if (sc->sc_glue->gl_clear_latched_intr != NULL)
715 (*sc->sc_glue->gl_clear_latched_intr)(sc);
716
717 /*
718 * Determine the SCSI bus phase, return either a real SCSI bus phase
719 * or some pseudo phase we use to detect certain exceptions.
720 */
721 sc->sc_phase = (sc->sc_espintr & NCRINTR_DIS) ?
722 BUSFREE_PHASE : sc->sc_espstat & NCRSTAT_PHASE;
723
724 NCR_INTS(("regs[intr=%02x,stat=%02x,step=%02x,stat2=%02x] ",

--- 76 unchanged lines hidden (view full) ---

801 * by DMA instead of programmed I/O soon.
802 */
803static void
804ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
805{
806 struct ncr53c9x_tinfo *ti;
807 uint8_t *cmd;
808 size_t dmasize;
809 int clen, selatn3, selatns;
810 int lun = ecb->ccb->ccb_h.target_lun;
811 int target = ecb->ccb->ccb_h.target_id;
812
813 NCR_LOCK_ASSERT(sc, MA_OWNED);
814
815 NCR_TRACE(("[%s(t%d,l%d,cmd:%x,tag:%x,%x)] ", __func__, target, lun,
816 ecb->cmd.cmd.opcode, ecb->tag[0], ecb->tag[1]));
817

--- 64 unchanged lines hidden (view full) ---

882 cmd[0] = MSG_IDENTIFY(lun, (ti->flags & T_RSELECTOFF) == 0);
883 }
884
885 if ((sc->sc_features & NCR_F_DMASELECT) && !selatns) {
886 /* Setup DMA transfer for command. */
887 dmasize = clen;
888 sc->sc_cmdlen = clen;
889 sc->sc_cmdp = cmd;
890 NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
891 /* Program the SCSI counter. */
892 NCR_SET_COUNT(sc, dmasize);
893
894 /* Load the count in. */
895 /* if (sc->sc_rev != NCR_VARIANT_FAS366) */
896 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
897
898 /* And get the target's attention. */
899 if (selatn3) {
900 sc->sc_msgout = SEND_TAG;
901 sc->sc_flags |= NCR_ATN;
902 NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA);
903 } else
904 NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
905 NCRDMA_GO(sc);
906 return;
907 }
908
909 /*
910 * Who am I? This is where we tell the target that we are
911 * happy for it to disconnect etc.
912 */
913
914 /* Now get the command into the FIFO. */
915 ncr53c9x_wrfifo(sc, cmd, clen);
916

--- 67 unchanged lines hidden (view full) ---

984 NCR_LOCK_ASSERT(sc, MA_OWNED);
985
986 NCR_TRACE(("[%s %d]", __func__, ccb->ccb_h.func_code));
987
988 switch (ccb->ccb_h.func_code) {
989 case XPT_RESET_BUS:
990 ncr53c9x_init(sc, 1);
991 ccb->ccb_h.status = CAM_REQ_CMP;
992 xpt_done(ccb);
993 return;
994
995 case XPT_CALC_GEOMETRY:
996 cam_calc_geometry(&ccb->ccg, sc->sc_extended_geom);
997 xpt_done(ccb);
998 return;
999
1000 case XPT_PATH_INQ:
1001 cpi = &ccb->cpi;
1002 cpi->version_num = 1;
1003 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
1004 cpi->hba_inquiry |=
1005 (sc->sc_rev == NCR_VARIANT_FAS366) ? PI_WIDE_16 : 0;
1006 cpi->target_sprt = 0;
1007 cpi->hba_misc = 0;
1008 cpi->hba_eng_cnt = 0;
1009 cpi->max_target = sc->sc_ntarg - 1;
1010 cpi->max_lun = 7;
1011 cpi->initiator_id = sc->sc_id;
1012 cpi->bus_id = 0;
1013 cpi->base_transfer_speed = 3300;
1014 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1015 strncpy(cpi->hba_vid, "Sun", HBA_IDLEN);
1016 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1017 cpi->unit_number = cam_sim_unit(sim);
1018 cpi->transport = XPORT_SPI;
1019 cpi->transport_version = 2;
1020 cpi->protocol = PROTO_SCSI;
1021 cpi->protocol_version = SCSI_REV_2;
1022 ccb->ccb_h.status = CAM_REQ_CMP;
1023 xpt_done(ccb);
1024 return;
1025
1026 case XPT_GET_TRAN_SETTINGS:
1027 cts = &ccb->cts;
1028 ti = &sc->sc_tinfo[ccb->ccb_h.target_id];
1029 scsi = &cts->proto_specific.scsi;
1030 spi = &cts->xport_specific.spi;
1031
1032 cts->protocol = PROTO_SCSI;

--- 26 unchanged lines hidden (view full) ---

1059 }
1060 spi->valid =
1061 CTS_SPI_VALID_BUS_WIDTH |
1062 CTS_SPI_VALID_SYNC_RATE |
1063 CTS_SPI_VALID_SYNC_OFFSET |
1064 CTS_SPI_VALID_DISC;
1065 scsi->valid = CTS_SCSI_VALID_TQ;
1066 ccb->ccb_h.status = CAM_REQ_CMP;
1067 xpt_done(ccb);
1068 return;
1069
1070 case XPT_ABORT:
1071 device_printf(sc->sc_dev, "XPT_ABORT called\n");
1072 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1073 xpt_done(ccb);
1074 return;
1075
1076 case XPT_TERM_IO:
1077 device_printf(sc->sc_dev, "XPT_TERM_IO called\n");
1078 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1079 xpt_done(ccb);
1080 return;
1081
1082 case XPT_RESET_DEV:
1083 case XPT_SCSI_IO:
1084 if (ccb->ccb_h.target_id < 0 ||
1085 ccb->ccb_h.target_id >= sc->sc_ntarg) {
1086 ccb->ccb_h.status = CAM_PATH_INVALID;
1087 xpt_done(ccb);
1088 return;
1089 }
1090 /* Get an ECB to use. */
1091 ecb = ncr53c9x_get_ecb(sc);
1092 /*
1093 * This should never happen as we track resources
1094 * in the mid-layer.
1095 */
1096 if (ecb == NULL) {
1097 xpt_freeze_simq(sim, 1);
1098 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1099 device_printf(sc->sc_dev, "unable to allocate ecb\n");
1100 xpt_done(ccb);
1101 return;
1102 }
1103
1104 /* Initialize ecb. */
1105 ecb->ccb = ccb;
1106 ecb->timeout = ccb->ccb_h.timeout;
1107
1108 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
1109 ecb->flags |= ECB_RESET;

--- 12 unchanged lines hidden (view full) ---

1122 ecb->dleft = csio->dxfer_len;
1123 }
1124 ecb->stat = 0;
1125
1126 TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain);
1127 ecb->flags |= ECB_READY;
1128 if (sc->sc_state == NCR_IDLE)
1129 ncr53c9x_sched(sc);
1130 break;
1131
1132 case XPT_SET_TRAN_SETTINGS:
1133 cts = &ccb->cts;
1134 target = ccb->ccb_h.target_id;
1135 ti = &sc->sc_tinfo[target];
1136 scsi = &cts->proto_specific.scsi;
1137 spi = &cts->xport_specific.spi;
1138

--- 21 unchanged lines hidden (view full) ---

1160
1161 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
1162 NCR_MISC(("%s: target %d: sync offset negotiation\n",
1163 device_get_nameunit(sc->sc_dev), target));
1164 ti->goal.offset = spi->sync_offset;
1165 }
1166
1167 ccb->ccb_h.status = CAM_REQ_CMP;
1168 xpt_done(ccb);
1169 return;
1170
1171 default:
1172 device_printf(sc->sc_dev, "Unhandled function code %d\n",
1173 ccb->ccb_h.func_code);
1174 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1175 xpt_done(ccb);
1176 return;
1177 }
1178}
1179
1180/*
1181 * Used when interrupt driven I/O is not allowed, e.g. during boot.
1182 */
1183static void
1184ncr53c9x_poll(struct cam_sim *sim)
1185{

--- 839 unchanged lines hidden (view full) ---

2025 ncr53c9x_sched_msgout(SEND_WDTR);
2026 ti->flags &= ~T_WDTRSENT;
2027 ti->goal.width = ti->curr.width;
2028 ncr53c9x_setsync(sc, ti);
2029 break;
2030
2031 default:
2032 xpt_print_path(ecb->ccb->ccb_h.path);
2033 printf("unrecognized MESSAGE EXTENDED;"
2034 " sending REJECT\n");
2035 goto reject;
2036 }
2037 break;
2038
2039 default:
2040 NCR_MSGS(("ident "));
2041 xpt_print_path(ecb->ccb->ccb_h.path);
2042 printf("unrecognized MESSAGE; sending REJECT\n");
2043 /* FALLTHROUGH */
2044 reject:
2045 ncr53c9x_sched_msgout(SEND_REJECT);
2046 break;
2047 }
2048 break;
2049
2050 case NCR_IDENTIFIED:

--- 53 unchanged lines hidden (view full) ---

2104 * Send the highest priority, scheduled message.
2105 */
2106static void
2107ncr53c9x_msgout(struct ncr53c9x_softc *sc)
2108{
2109 struct ncr53c9x_tinfo *ti;
2110 struct ncr53c9x_ecb *ecb;
2111 size_t size;
2112#ifdef NCR53C9X_DEBUG
2113 int i;
2114#endif
2115
2116 NCR_LOCK_ASSERT(sc, MA_OWNED);
2117
2118 NCR_TRACE(("[%s(priq:%x, prevphase:%x)]", __func__, sc->sc_msgpriq,
2119 sc->sc_prevphase));

--- 121 unchanged lines hidden (view full) ---

2241#ifdef NCR53C9X_DEBUG
2242 if ((ncr53c9x_debug & NCR_SHOWMSGS) != 0) {
2243 NCR_MSGS(("<msgout:"));
2244 for (i = 0; i < sc->sc_omlen; i++)
2245 NCR_MSGS((" %02x", sc->sc_omess[i]));
2246 NCR_MSGS(("> "));
2247 }
2248#endif
2249 if (sc->sc_rev == NCR_VARIANT_FAS366) {
2250 /*
2251 * XXX FIFO size
2252 */
2253 ncr53c9x_flushfifo(sc);
2254 ncr53c9x_wrfifo(sc, sc->sc_omp, sc->sc_omlen);
2255 NCRCMD(sc, NCRCMD_TRANS);
2256 } else {
2257 /* (Re)send the message. */
2258 size = ulmin(sc->sc_omlen, sc->sc_maxxfer);
2259 NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
2260 /* Program the SCSI counter. */
2261 NCR_SET_COUNT(sc, size);
2262
2263 /* Load the count in and start the message-out transfer. */
2264 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
2265 NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
2266 NCRDMA_GO(sc);
2267 }
2268}
2269
2270void
2271ncr53c9x_intr(void *arg)
2272{
2273 struct ncr53c9x_softc *sc = arg;
2274
2275 if (!NCRDMA_ISINTR(sc))

--- 18 unchanged lines hidden (view full) ---

2294static void
2295ncr53c9x_intr1(struct ncr53c9x_softc *sc)
2296{
2297 struct ncr53c9x_ecb *ecb;
2298 struct ncr53c9x_linfo *li;
2299 struct ncr53c9x_tinfo *ti;
2300 struct timeval cur, wait;
2301 size_t size;
2302 int i, nfifo;
2303 uint8_t msg;
2304
2305 NCR_LOCK_ASSERT(sc, MA_OWNED);
2306
2307 NCR_INTS(("[ncr53c9x_intr: state %d]", sc->sc_state));
2308
2309again:
2310 /* and what do the registers say... */

--- 658 unchanged lines hidden (view full) ---

2969 NCRCMD(sc, NCRCMD_SETATN);
2970 sc->sc_flags |= NCR_ATN;
2971 }
2972 if (sc->sc_features & NCR_F_DMASELECT) {
2973 /* Setup DMA transfer for command. */
2974 size = ecb->clen;
2975 sc->sc_cmdlen = size;
2976 sc->sc_cmdp = (void *)&ecb->cmd.cmd;
2977 NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen,
2978 0, &size);
2979 /* Program the SCSI counter. */
2980 NCR_SET_COUNT(sc, size);
2981
2982 /* Load the count in. */
2983 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
2984
2985 /* Start the command transfer. */
2986 NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
2987 NCRDMA_GO(sc);
2988 } else {
2989 ncr53c9x_wrfifo(sc, (uint8_t *)&ecb->cmd.cmd,
2990 ecb->clen);
2991 NCRCMD(sc, NCRCMD_TRANS);
2992 }
2993 sc->sc_prevphase = COMMAND_PHASE;
2994 break;
2995
2996 case DATA_OUT_PHASE:
2997 NCR_PHASE(("DATA_OUT_PHASE [%ld] ", (long)sc->sc_dleft));
2998 NCRCMD(sc, NCRCMD_FLUSH);
2999 size = ulmin(sc->sc_dleft, sc->sc_maxxfer);
3000 NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 0, &size);
3001 sc->sc_prevphase = DATA_OUT_PHASE;
3002 goto setup_xfer;
3003
3004 case DATA_IN_PHASE:
3005 NCR_PHASE(("DATA_IN_PHASE "));
3006 if (sc->sc_rev == NCR_VARIANT_ESP100)
3007 NCRCMD(sc, NCRCMD_FLUSH);
3008 size = ulmin(sc->sc_dleft, sc->sc_maxxfer);
3009 NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 1, &size);
3010 sc->sc_prevphase = DATA_IN_PHASE;
3011 setup_xfer:
3012 /* Target returned to data phase: wipe "done" memory */
3013 ecb->flags &= ~ECB_TENTATIVE_DONE;
3014
3015 /* Program the SCSI counter. */
3016 NCR_SET_COUNT(sc, size);
3017
3018 /* Load the count in. */
3019 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);

--- 182 unchanged lines hidden ---