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 226947 2011-10-30 21:17:42Z 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 |
126devclass_t esp_devclass; 127 |
128MODULE_DEPEND(esp, cam, 1, 1, 1); 129 130#ifdef NCR53C9X_DEBUG 131int ncr53c9x_debug = 132 NCR_SHOWMISC /* | NCR_SHOWPHASE | NCR_SHOWTRAC | NCR_SHOWCMDS */; 133#endif 134 135static void ncr53c9x_abort(struct ncr53c9x_softc *sc, --- 40 unchanged lines hidden (view full) --- 176 int period); 177 178#define NCR_RDFIFO_START 0 179#define NCR_RDFIFO_CONTINUE 1 180 181#define NCR_SET_COUNT(sc, size) do { \ 182 NCR_WRITE_REG((sc), NCR_TCL, (size)); \ 183 NCR_WRITE_REG((sc), NCR_TCM, (size) >> 8); \ |
184 if ((sc->sc_features & NCR_F_LARGEXFER) != 0) \ |
185 NCR_WRITE_REG((sc), NCR_TCH, (size) >> 16); \ 186 if (sc->sc_rev == NCR_VARIANT_FAS366) \ 187 NCR_WRITE_REG(sc, NCR_RCH, 0); \ 188} while (/* CONSTCOND */0) 189 190#ifndef mstohz 191#define mstohz(ms) \ 192 (((ms) < 0x20000) ? \ --- 194 unchanged lines hidden (view full) --- 387 device_printf(sc->sc_dev, "cannot allocate ECB array\n"); 388 error = ENOMEM; 389 goto fail_async; 390 } 391 for (i = 0; i < NCR_TAG_DEPTH; i++) { 392 ecb = &sc->ecb_array[i]; 393 ecb->sc = sc; 394 ecb->tag_id = i; |
395 callout_init_mtx(&ecb->ch, &sc->sc_lock, 0); |
396 TAILQ_INSERT_HEAD(&sc->free_list, ecb, free_links); 397 } 398 399 callout_reset(&sc->sc_watchdog, 60 * hz, ncr53c9x_watch, sc); 400 401 NCR_UNLOCK(sc); 402 403 return (0); --- 42 unchanged lines hidden (view full) --- 446 free(li, M_DEVBUF); 447 } 448 } 449 } 450 451 xpt_register_async(0, ncr53c9x_async, sc->sc_sim, sc->sc_path); 452 xpt_free_path(sc->sc_path); 453 xpt_bus_deregister(cam_sim_path(sc->sc_sim)); |
454 cam_sim_free(sc->sc_sim, TRUE); |
455 456 NCR_UNLOCK(sc); 457 |
458 free(sc->ecb_array, M_DEVBUF); 459 free(sc->sc_tinfo, M_DEVBUF); 460 if (sc->sc_imess_self) 461 free(sc->sc_imess, M_DEVBUF); 462 if (sc->sc_omess_self) 463 free(sc->sc_omess, M_DEVBUF); 464 465 return (0); --- 35 unchanged lines hidden (view full) --- 501 case NCR_VARIANT_NCR53C94: 502 case NCR_VARIANT_NCR53C96: 503 case NCR_VARIANT_ESP200: 504 sc->sc_features |= NCR_F_HASCFG3; 505 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 506 /* FALLTHROUGH */ 507 case NCR_VARIANT_ESP100A: 508 sc->sc_features |= NCR_F_SELATN3; |
509 if ((sc->sc_cfg2 & NCRCFG2_FE) != 0) 510 sc->sc_features |= NCR_F_LARGEXFER; |
511 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 512 /* FALLTHROUGH */ 513 case NCR_VARIANT_ESP100: 514 NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1); 515 NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf); 516 NCR_WRITE_REG(sc, NCR_SYNCOFF, 0); 517 NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout); 518 break; 519 520 case NCR_VARIANT_FAS366: |
521 sc->sc_features |= NCR_F_HASCFG3 | NCR_F_FASTSCSI | 522 NCR_F_SELATN3 | NCR_F_LARGEXFER; |
523 sc->sc_cfg3 = NCRFASCFG3_FASTCLK | NCRFASCFG3_OBAUTO; 524 if (sc->sc_id > 7) 525 sc->sc_cfg3 |= NCRFASCFG3_IDBIT3; 526 sc->sc_cfg3_fscsi = NCRFASCFG3_FASTSCSI; 527 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 528 sc->sc_cfg2 = NCRCFG2_HMEFE | NCRCFG2_HME32; 529 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 530 NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1); --- 179 unchanged lines hidden (view full) --- 710 /* Only the step bits are of interest. */ 711 sc->sc_espstep = NCR_READ_REG(sc, NCR_STEP) & NCRSTEP_MASK; 712 713 if (sc->sc_rev == NCR_VARIANT_FAS366) 714 sc->sc_espstat2 = NCR_READ_REG(sc, NCR_STAT2); 715 716 sc->sc_espintr = NCR_READ_REG(sc, NCR_INTR); 717 |
718 /* 719 * Determine the SCSI bus phase, return either a real SCSI bus phase 720 * or some pseudo phase we use to detect certain exceptions. 721 */ 722 sc->sc_phase = (sc->sc_espintr & NCRINTR_DIS) ? 723 BUSFREE_PHASE : sc->sc_espstat & NCRSTAT_PHASE; 724 725 NCR_INTS(("regs[intr=%02x,stat=%02x,step=%02x,stat2=%02x] ", --- 76 unchanged lines hidden (view full) --- 802 * by DMA instead of programmed I/O soon. 803 */ 804static void 805ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb) 806{ 807 struct ncr53c9x_tinfo *ti; 808 uint8_t *cmd; 809 size_t dmasize; |
810 int clen, error, selatn3, selatns; |
811 int lun = ecb->ccb->ccb_h.target_lun; 812 int target = ecb->ccb->ccb_h.target_id; 813 814 NCR_LOCK_ASSERT(sc, MA_OWNED); 815 816 NCR_TRACE(("[%s(t%d,l%d,cmd:%x,tag:%x,%x)] ", __func__, target, lun, 817 ecb->cmd.cmd.opcode, ecb->tag[0], ecb->tag[1])); 818 --- 64 unchanged lines hidden (view full) --- 883 cmd[0] = MSG_IDENTIFY(lun, (ti->flags & T_RSELECTOFF) == 0); 884 } 885 886 if ((sc->sc_features & NCR_F_DMASELECT) && !selatns) { 887 /* Setup DMA transfer for command. */ 888 dmasize = clen; 889 sc->sc_cmdlen = clen; 890 sc->sc_cmdp = cmd; |
891 error = NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, 892 &dmasize); 893 if (error != 0) { 894 sc->sc_cmdlen = 0; 895 sc->sc_cmdp = NULL; 896 goto cmd; 897 } 898 |
899 /* Program the SCSI counter. */ 900 NCR_SET_COUNT(sc, dmasize); 901 902 /* Load the count in. */ |
903 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); |
904 905 /* And get the target's attention. */ 906 if (selatn3) { 907 sc->sc_msgout = SEND_TAG; 908 sc->sc_flags |= NCR_ATN; 909 NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA); 910 } else 911 NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA); 912 NCRDMA_GO(sc); 913 return; 914 } 915 |
916cmd: |
917 /* 918 * Who am I? This is where we tell the target that we are 919 * happy for it to disconnect etc. 920 */ 921 922 /* Now get the command into the FIFO. */ 923 ncr53c9x_wrfifo(sc, cmd, clen); 924 --- 67 unchanged lines hidden (view full) --- 992 NCR_LOCK_ASSERT(sc, MA_OWNED); 993 994 NCR_TRACE(("[%s %d]", __func__, ccb->ccb_h.func_code)); 995 996 switch (ccb->ccb_h.func_code) { 997 case XPT_RESET_BUS: 998 ncr53c9x_init(sc, 1); 999 ccb->ccb_h.status = CAM_REQ_CMP; |
1000 break; |
1001 1002 case XPT_CALC_GEOMETRY: 1003 cam_calc_geometry(&ccb->ccg, sc->sc_extended_geom); |
1004 break; |
1005 1006 case XPT_PATH_INQ: 1007 cpi = &ccb->cpi; 1008 cpi->version_num = 1; 1009 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 1010 cpi->hba_inquiry |= 1011 (sc->sc_rev == NCR_VARIANT_FAS366) ? PI_WIDE_16 : 0; 1012 cpi->target_sprt = 0; 1013 cpi->hba_misc = 0; 1014 cpi->hba_eng_cnt = 0; 1015 cpi->max_target = sc->sc_ntarg - 1; 1016 cpi->max_lun = 7; 1017 cpi->initiator_id = sc->sc_id; |
1018 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); |
1019 strncpy(cpi->hba_vid, "NCR", HBA_IDLEN); |
1020 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1021 cpi->unit_number = cam_sim_unit(sim); |
1022 cpi->bus_id = 0; 1023 cpi->base_transfer_speed = 3300; |
1024 cpi->protocol = PROTO_SCSI; 1025 cpi->protocol_version = SCSI_REV_2; |
1026 cpi->transport = XPORT_SPI; 1027 cpi->transport_version = 2; 1028 cpi->maxio = sc->sc_maxxfer; |
1029 ccb->ccb_h.status = CAM_REQ_CMP; |
1030 break; |
1031 1032 case XPT_GET_TRAN_SETTINGS: 1033 cts = &ccb->cts; 1034 ti = &sc->sc_tinfo[ccb->ccb_h.target_id]; 1035 scsi = &cts->proto_specific.scsi; 1036 spi = &cts->xport_specific.spi; 1037 1038 cts->protocol = PROTO_SCSI; --- 26 unchanged lines hidden (view full) --- 1065 } 1066 spi->valid = 1067 CTS_SPI_VALID_BUS_WIDTH | 1068 CTS_SPI_VALID_SYNC_RATE | 1069 CTS_SPI_VALID_SYNC_OFFSET | 1070 CTS_SPI_VALID_DISC; 1071 scsi->valid = CTS_SCSI_VALID_TQ; 1072 ccb->ccb_h.status = CAM_REQ_CMP; |
1073 break; |
1074 1075 case XPT_ABORT: 1076 device_printf(sc->sc_dev, "XPT_ABORT called\n"); 1077 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; |
1078 break; |
1079 1080 case XPT_TERM_IO: 1081 device_printf(sc->sc_dev, "XPT_TERM_IO called\n"); 1082 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; |
1083 break; |
1084 1085 case XPT_RESET_DEV: 1086 case XPT_SCSI_IO: 1087 if (ccb->ccb_h.target_id < 0 || 1088 ccb->ccb_h.target_id >= sc->sc_ntarg) { 1089 ccb->ccb_h.status = CAM_PATH_INVALID; |
1090 goto done; |
1091 } 1092 /* Get an ECB to use. */ 1093 ecb = ncr53c9x_get_ecb(sc); 1094 /* 1095 * This should never happen as we track resources 1096 * in the mid-layer. 1097 */ 1098 if (ecb == NULL) { 1099 xpt_freeze_simq(sim, 1); 1100 ccb->ccb_h.status = CAM_REQUEUE_REQ; 1101 device_printf(sc->sc_dev, "unable to allocate ecb\n"); |
1102 goto done; |
1103 } 1104 1105 /* Initialize ecb. */ 1106 ecb->ccb = ccb; 1107 ecb->timeout = ccb->ccb_h.timeout; 1108 1109 if (ccb->ccb_h.func_code == XPT_RESET_DEV) { 1110 ecb->flags |= ECB_RESET; --- 12 unchanged lines hidden (view full) --- 1123 ecb->dleft = csio->dxfer_len; 1124 } 1125 ecb->stat = 0; 1126 1127 TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain); 1128 ecb->flags |= ECB_READY; 1129 if (sc->sc_state == NCR_IDLE) 1130 ncr53c9x_sched(sc); |
1131 return; |
1132 1133 case XPT_SET_TRAN_SETTINGS: 1134 cts = &ccb->cts; 1135 target = ccb->ccb_h.target_id; 1136 ti = &sc->sc_tinfo[target]; 1137 scsi = &cts->proto_specific.scsi; 1138 spi = &cts->xport_specific.spi; 1139 --- 21 unchanged lines hidden (view full) --- 1161 1162 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) { 1163 NCR_MISC(("%s: target %d: sync offset negotiation\n", 1164 device_get_nameunit(sc->sc_dev), target)); 1165 ti->goal.offset = spi->sync_offset; 1166 } 1167 1168 ccb->ccb_h.status = CAM_REQ_CMP; |
1169 break; |
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 } |
1176 1177done: 1178 xpt_done(ccb); |
1179} 1180 1181/* 1182 * Used when interrupt driven I/O is not allowed, e.g. during boot. 1183 */ 1184static void 1185ncr53c9x_poll(struct cam_sim *sim) 1186{ --- 839 unchanged lines hidden (view full) --- 2026 ncr53c9x_sched_msgout(SEND_WDTR); 2027 ti->flags &= ~T_WDTRSENT; 2028 ti->goal.width = ti->curr.width; 2029 ncr53c9x_setsync(sc, ti); 2030 break; 2031 2032 default: 2033 xpt_print_path(ecb->ccb->ccb_h.path); |
2034 printf("unrecognized MESSAGE EXTENDED 0x%x;" 2035 " sending REJECT\n", sc->sc_imess[2]); |
2036 goto reject; 2037 } 2038 break; 2039 2040 default: 2041 NCR_MSGS(("ident ")); 2042 xpt_print_path(ecb->ccb->ccb_h.path); |
2043 printf("unrecognized MESSAGE 0x%x; sending REJECT\n", 2044 sc->sc_imess[0]); |
2045 /* FALLTHROUGH */ 2046 reject: 2047 ncr53c9x_sched_msgout(SEND_REJECT); 2048 break; 2049 } 2050 break; 2051 2052 case NCR_IDENTIFIED: --- 53 unchanged lines hidden (view full) --- 2106 * Send the highest priority, scheduled message. 2107 */ 2108static void 2109ncr53c9x_msgout(struct ncr53c9x_softc *sc) 2110{ 2111 struct ncr53c9x_tinfo *ti; 2112 struct ncr53c9x_ecb *ecb; 2113 size_t size; |
2114 int error; |
2115#ifdef NCR53C9X_DEBUG 2116 int i; 2117#endif 2118 2119 NCR_LOCK_ASSERT(sc, MA_OWNED); 2120 2121 NCR_TRACE(("[%s(priq:%x, prevphase:%x)]", __func__, sc->sc_msgpriq, 2122 sc->sc_prevphase)); --- 121 unchanged lines hidden (view full) --- 2244#ifdef NCR53C9X_DEBUG 2245 if ((ncr53c9x_debug & NCR_SHOWMSGS) != 0) { 2246 NCR_MSGS(("<msgout:")); 2247 for (i = 0; i < sc->sc_omlen; i++) 2248 NCR_MSGS((" %02x", sc->sc_omess[i])); 2249 NCR_MSGS(("> ")); 2250 } 2251#endif |
2252 2253 if (sc->sc_rev != NCR_VARIANT_FAS366) { |
2254 /* (Re)send the message. */ 2255 size = ulmin(sc->sc_omlen, sc->sc_maxxfer); |
2256 error = NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size); 2257 if (error != 0) 2258 goto cmd; 2259 |
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 return; |
2268 } |
2269 2270cmd: 2271 /* 2272 * XXX FIFO size 2273 */ 2274 ncr53c9x_flushfifo(sc); 2275 ncr53c9x_wrfifo(sc, sc->sc_omp, sc->sc_omlen); 2276 NCRCMD(sc, NCRCMD_TRANS); |
2277} 2278 2279void 2280ncr53c9x_intr(void *arg) 2281{ 2282 struct ncr53c9x_softc *sc = arg; 2283 2284 if (!NCRDMA_ISINTR(sc)) --- 18 unchanged lines hidden (view full) --- 2303static void 2304ncr53c9x_intr1(struct ncr53c9x_softc *sc) 2305{ 2306 struct ncr53c9x_ecb *ecb; 2307 struct ncr53c9x_linfo *li; 2308 struct ncr53c9x_tinfo *ti; 2309 struct timeval cur, wait; 2310 size_t size; |
2311 int error, i, nfifo; |
2312 uint8_t msg; 2313 2314 NCR_LOCK_ASSERT(sc, MA_OWNED); 2315 2316 NCR_INTS(("[ncr53c9x_intr: state %d]", sc->sc_state)); 2317 2318again: 2319 /* and what do the registers say... */ --- 658 unchanged lines hidden (view full) --- 2978 NCRCMD(sc, NCRCMD_SETATN); 2979 sc->sc_flags |= NCR_ATN; 2980 } 2981 if (sc->sc_features & NCR_F_DMASELECT) { 2982 /* Setup DMA transfer for command. */ 2983 size = ecb->clen; 2984 sc->sc_cmdlen = size; 2985 sc->sc_cmdp = (void *)&ecb->cmd.cmd; |
2986 error = NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, |
2987 0, &size); |
2988 if (error != 0) { 2989 sc->sc_cmdlen = 0; 2990 sc->sc_cmdp = NULL; 2991 goto cmd; 2992 } 2993 |
2994 /* Program the SCSI counter. */ 2995 NCR_SET_COUNT(sc, size); 2996 2997 /* Load the count in. */ 2998 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); 2999 3000 /* Start the command transfer. */ 3001 NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA); 3002 NCRDMA_GO(sc); |
3003 sc->sc_prevphase = COMMAND_PHASE; 3004 break; |
3005 } |
3006cmd: 3007 ncr53c9x_wrfifo(sc, (uint8_t *)&ecb->cmd.cmd, ecb->clen); 3008 NCRCMD(sc, NCRCMD_TRANS); |
3009 sc->sc_prevphase = COMMAND_PHASE; 3010 break; 3011 3012 case DATA_OUT_PHASE: 3013 NCR_PHASE(("DATA_OUT_PHASE [%ld] ", (long)sc->sc_dleft)); |
3014 sc->sc_prevphase = DATA_OUT_PHASE; |
3015 NCRCMD(sc, NCRCMD_FLUSH); 3016 size = ulmin(sc->sc_dleft, sc->sc_maxxfer); |
3017 error = NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 0, &size); |
3018 goto setup_xfer; 3019 3020 case DATA_IN_PHASE: 3021 NCR_PHASE(("DATA_IN_PHASE ")); |
3022 sc->sc_prevphase = DATA_IN_PHASE; |
3023 if (sc->sc_rev == NCR_VARIANT_ESP100) 3024 NCRCMD(sc, NCRCMD_FLUSH); 3025 size = ulmin(sc->sc_dleft, sc->sc_maxxfer); |
3026 error = NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 1, &size); 3027setup_xfer: 3028 if (error != 0) { 3029 switch (error) { 3030 case EFBIG: 3031 ecb->ccb->ccb_h.status |= CAM_REQ_TOO_BIG; 3032 break; 3033 case EINPROGRESS: 3034 panic("%s: cannot deal with deferred DMA", 3035 __func__); 3036 case EINVAL: 3037 ecb->ccb->ccb_h.status |= CAM_REQ_INVALID; 3038 break; 3039 case ENOMEM: 3040 ecb->ccb->ccb_h.status |= CAM_REQUEUE_REQ; 3041 break; 3042 default: 3043 ecb->ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 3044 } 3045 goto finish; 3046 } 3047 |
3048 /* Target returned to data phase: wipe "done" memory */ 3049 ecb->flags &= ~ECB_TENTATIVE_DONE; 3050 3051 /* Program the SCSI counter. */ 3052 NCR_SET_COUNT(sc, size); 3053 3054 /* Load the count in. */ 3055 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); --- 182 unchanged lines hidden --- |