1/*- 2 * Copyright (c) 1999 Luoqi Chen. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/dev/aic/aic.c 241591 2012-10-15 16:09:59Z jhb $"); |
29 30#include <sys/param.h> |
31#include <sys/conf.h> |
32#include <sys/systm.h> 33#include <sys/kernel.h> 34#include <sys/lock.h> 35#include <sys/mutex.h> 36#include <sys/malloc.h> 37#include <sys/bus.h> 38 39#include <machine/bus.h> |
40#include <sys/rman.h> |
41 42#include <cam/cam.h> 43#include <cam/cam_ccb.h> 44#include <cam/cam_sim.h> 45#include <cam/cam_xpt_sim.h> 46#include <cam/cam_debug.h> 47 48#include <cam/scsi/scsi_message.h> 49 50#include <dev/aic/aic6360reg.h> 51#include <dev/aic/aicvar.h> 52 53static void aic_action(struct cam_sim *sim, union ccb *ccb); 54static void aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, 55 int nseg, int error); |
56static void aic_intr_locked(struct aic_softc *aic); |
57static void aic_start(struct aic_softc *aic); 58static void aic_select(struct aic_softc *aic); 59static void aic_selected(struct aic_softc *aic); 60static void aic_reselected(struct aic_softc *aic); 61static void aic_reconnect(struct aic_softc *aic, int tag); 62static void aic_cmd(struct aic_softc *aic); 63static void aic_msgin(struct aic_softc *aic); 64static void aic_handle_msgin(struct aic_softc *aic); --- 4 unchanged lines hidden (view full) --- 69static void aic_poll(struct cam_sim *sim); 70static void aic_timeout(void *arg); 71static void aic_scsi_reset(struct aic_softc *aic); 72static void aic_chip_reset(struct aic_softc *aic); 73static void aic_reset(struct aic_softc *aic, int initiate_reset); 74 75devclass_t aic_devclass; 76 |
77static struct aic_scb * 78aic_get_scb(struct aic_softc *aic) 79{ 80 struct aic_scb *scb; |
81 82 if (!dumping) 83 mtx_assert(&aic->lock, MA_OWNED); 84 if ((scb = SLIST_FIRST(&aic->free_scbs)) != NULL) 85 SLIST_REMOVE_HEAD(&aic->free_scbs, link); |
86 return (scb); 87} 88 89static void 90aic_free_scb(struct aic_softc *aic, struct aic_scb *scb) 91{ |
92 93 if (!dumping) 94 mtx_assert(&aic->lock, MA_OWNED); |
95 if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0 && 96 (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 97 scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 98 aic->flags &= ~AIC_RESOURCE_SHORTAGE; 99 } 100 scb->flags = 0; |
101 SLIST_INSERT_HEAD(&aic->free_scbs, scb, link); |
102} 103 104static void 105aic_action(struct cam_sim *sim, union ccb *ccb) 106{ 107 struct aic_softc *aic; |
108 109 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aic_action\n")); 110 111 aic = (struct aic_softc *)cam_sim_softc(sim); |
112 mtx_assert(&aic->lock, MA_OWNED); |
113 114 switch (ccb->ccb_h.func_code) { 115 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 116 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 117 { 118 struct aic_scb *scb; 119 120 if ((scb = aic_get_scb(aic)) == NULL) { |
121 aic->flags |= AIC_RESOURCE_SHORTAGE; |
122 xpt_freeze_simq(aic->sim, /*count*/1); 123 ccb->ccb_h.status = CAM_REQUEUE_REQ; 124 xpt_done(ccb); 125 return; 126 } 127 128 scb->ccb = ccb; 129 ccb->ccb_h.ccb_scb_ptr = scb; --- 40 unchanged lines hidden (view full) --- 170 { 171 struct ccb_trans_settings *cts = &ccb->cts; 172 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id]; 173 struct ccb_trans_settings_scsi *scsi = 174 &cts->proto_specific.scsi; 175 struct ccb_trans_settings_spi *spi = 176 &cts->xport_specific.spi; 177 |
178 if ((spi->valid & CTS_SPI_VALID_DISC) != 0 && 179 (aic->flags & AIC_DISC_ENABLE) != 0) { 180 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 181 ti->flags |= TINFO_DISC_ENB; 182 else 183 ti->flags &= ~TINFO_DISC_ENB; 184 } 185 --- 21 unchanged lines hidden (view full) --- 207 else if (ti->goal.offset > AIC_SYNC_OFFSET) 208 ti->goal.offset = AIC_SYNC_OFFSET; 209 } 210 211 if ((ti->goal.period != ti->current.period) 212 || (ti->goal.offset != ti->current.offset)) 213 ti->flags |= TINFO_SDTR_NEGO; 214 |
215 ccb->ccb_h.status = CAM_REQ_CMP; 216 xpt_done(ccb); 217 break; 218 } 219 case XPT_GET_TRAN_SETTINGS: 220 { 221 struct ccb_trans_settings *cts = &ccb->cts; 222 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id]; --- 4 unchanged lines hidden (view full) --- 227 228 cts->protocol = PROTO_SCSI; 229 cts->protocol_version = SCSI_REV_2; 230 cts->transport = XPORT_SPI; 231 cts->transport_version = 2; 232 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 233 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 234 |
235 if ((ti->flags & TINFO_DISC_ENB) != 0) 236 spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 237 if ((ti->flags & TINFO_TAG_ENB) != 0) 238 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 239 240 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 241 spi->sync_period = ti->current.period; 242 spi->sync_offset = ti->current.offset; 243 } else { 244 spi->sync_period = ti->user.period; 245 spi->sync_offset = ti->user.offset; 246 } |
247 248 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 249 spi->valid = CTS_SPI_VALID_SYNC_RATE 250 | CTS_SPI_VALID_SYNC_OFFSET 251 | CTS_SPI_VALID_BUS_WIDTH 252 | CTS_SPI_VALID_DISC; 253 scsi->valid = CTS_SCSI_VALID_TQ; 254 --- 46 unchanged lines hidden (view full) --- 301} 302 303static void 304aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 305{ 306 struct aic_scb *scb = (struct aic_scb *)arg; 307 union ccb *ccb = scb->ccb; 308 struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr; |
309 |
310 if (!dumping) 311 mtx_assert(&aic->lock, MA_OWNED); |
312 if (ccb->ccb_h.status != CAM_REQ_INPROG) { |
313 aic_free_scb(aic, scb); 314 xpt_done(ccb); 315 return; 316 } 317 318 scb->flags |= SCB_ACTIVE; 319 ccb->ccb_h.status |= CAM_SIM_QUEUED; 320 TAILQ_INSERT_TAIL(&aic->pending_ccbs, &ccb->ccb_h, sim_links.tqe); 321 |
322 callout_reset(&scb->timer, (ccb->ccb_h.timeout * hz) / 1000, 323 aic_timeout, scb); |
324 325 aic_start(aic); |
326} 327 328/* 329 * Start another command if the controller is not busy. 330 */ 331static void 332aic_start(struct aic_softc *aic) 333{ --- 706 unchanged lines hidden (view full) --- 1040aic_done(struct aic_softc *aic, struct aic_scb *scb) 1041{ 1042 union ccb *ccb = scb->ccb; 1043 1044 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 1045 ("aic_done - ccb %p status %x resid %d\n", 1046 ccb, ccb->ccb_h.status, ccb->csio.resid)); 1047 |
1048 callout_stop(&scb->timer); |
1049 1050 if ((scb->flags & SCB_DEVICE_RESET) != 0 && 1051 ccb->ccb_h.func_code != XPT_RESET_DEV) { 1052 struct cam_path *path; 1053 struct ccb_hdr *ccb_h; 1054 cam_status error; 1055 1056 error = xpt_create_path(&path, /*periph*/NULL, --- 13 unchanged lines hidden (view full) --- 1070 pending_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr; 1071 if (ccb_h->target_id == scb->target) { 1072 ccb_h->status |= CAM_BDR_SENT; 1073 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe); 1074 TAILQ_REMOVE(&aic->pending_ccbs, 1075 &pending_scb->ccb->ccb_h, sim_links.tqe); 1076 aic_done(aic, pending_scb); 1077 } else { |
1078 callout_reset(&pending_scb->timer, 1079 (ccb_h->timeout * hz) / 1000, aic_timeout, 1080 pending_scb); |
1081 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe); 1082 } 1083 } 1084 1085 ccb_h = TAILQ_FIRST(&aic->nexus_ccbs); 1086 while (ccb_h != NULL) { 1087 struct aic_scb *nexus_scb; 1088 1089 nexus_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr; 1090 if (ccb_h->target_id == scb->target) { 1091 ccb_h->status |= CAM_BDR_SENT; 1092 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe); 1093 TAILQ_REMOVE(&aic->nexus_ccbs, 1094 &nexus_scb->ccb->ccb_h, sim_links.tqe); 1095 aic_done(aic, nexus_scb); 1096 } else { |
1097 callout_reset(&nexus_scb->timer, 1098 (ccb_h->timeout * hz) / 1000, aic_timeout, 1099 nexus_scb); |
1100 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe); 1101 } 1102 } 1103 } 1104 1105 if (aic->nexus == scb || scb->flags & SCB_DISCONNECTED) 1106 aic->tinfo[scb->target].lubusy &= ~(1 << scb->lun); 1107 1108 if (aic->nexus == scb) { 1109 aic->nexus = NULL; 1110 } 1111 aic_free_scb(aic, scb); 1112 xpt_done(ccb); 1113} 1114 1115static void 1116aic_poll(struct cam_sim *sim) 1117{ |
1118 aic_intr_locked(cam_sim_softc(sim)); |
1119} 1120 1121static void 1122aic_timeout(void *arg) 1123{ 1124 struct aic_scb *scb = (struct aic_scb *)arg; 1125 union ccb *ccb = scb->ccb; 1126 struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr; |
1127 |
1128 mtx_assert(&aic->lock, MA_OWNED); |
1129 xpt_print_path(ccb->ccb_h.path); 1130 printf("ccb %p - timed out", ccb); 1131 if (aic->nexus && aic->nexus != scb) 1132 printf(", nexus %p", aic->nexus->ccb); 1133 printf(", phase 0x%x, state %d\n", aic_inb(aic, SCSISIGI), aic->state); 1134 |
1135 if ((scb->flags & SCB_ACTIVE) == 0) { |
1136 xpt_print_path(ccb->ccb_h.path); 1137 printf("ccb %p - timed out already completed\n", ccb); 1138 return; 1139 } 1140 1141 if ((scb->flags & SCB_DEVICE_RESET) == 0 && aic->nexus == scb) { 1142 struct ccb_hdr *ccb_h = &scb->ccb->ccb_h; |
1143 struct aic_scb *pending_scb; |
1144 1145 if ((ccb_h->status & CAM_RELEASE_SIMQ) == 0) { 1146 xpt_freeze_simq(aic->sim, /*count*/1); 1147 ccb_h->status |= CAM_RELEASE_SIMQ; 1148 } 1149 1150 TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) { |
1151 pending_scb = ccb_h->ccb_scb_ptr; 1152 callout_stop(&pending_scb->timer); |
1153 } 1154 1155 TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) { |
1156 pending_scb = ccb_h->ccb_scb_ptr; 1157 callout_stop(&pending_scb->timer); |
1158 } 1159 1160 scb->flags |= SCB_DEVICE_RESET; |
1161 callout_reset(&scb->timer, 5 * hz, aic_timeout, scb); |
1162 aic_sched_msgout(aic, MSG_BUS_DEV_RESET); 1163 } else { 1164 if (aic->nexus == scb) { 1165 ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 1166 aic_done(aic, scb); 1167 } 1168 aic_reset(aic, /*initiate_reset*/TRUE); 1169 } |
1170} 1171 1172void 1173aic_intr(void *arg) 1174{ 1175 struct aic_softc *aic = (struct aic_softc *)arg; |
1176 1177 mtx_lock(&aic->lock); 1178 aic_intr_locked(aic); 1179 mtx_unlock(&aic->lock); 1180} 1181 1182void 1183aic_intr_locked(struct aic_softc *aic) 1184{ |
1185 u_int8_t sstat0, sstat1; 1186 union ccb *ccb; 1187 struct aic_scb *scb; 1188 1189 if (!(aic_inb(aic, DMASTAT) & INTSTAT)) 1190 return; 1191 1192 aic_outb(aic, DMACNTRL0, 0); --- 232 unchanged lines hidden (view full) --- 1425 struct aic_scb *scb; 1426 struct aic_tinfo *ti; 1427 u_int8_t porta, portb; 1428 char chip_id[33]; 1429 int i; 1430 1431 TAILQ_INIT(&aic->pending_ccbs); 1432 TAILQ_INIT(&aic->nexus_ccbs); |
1433 SLIST_INIT(&aic->free_scbs); |
1434 aic->nexus = NULL; 1435 aic->state = AIC_IDLE; 1436 aic->prev_phase = -1; 1437 aic->flags = 0; 1438 1439 aic_chip_reset(aic); 1440 aic_scsi_reset(aic); 1441 --- 31 unchanged lines hidden (view full) --- 1473 } 1474 1475 if (aic->flags & AIC_FAST_ENABLE) 1476 aic->max_period = AIC_FAST_SYNC_PERIOD; 1477 else 1478 aic->max_period = AIC_SYNC_PERIOD; 1479 aic->min_period = AIC_MIN_SYNC_PERIOD; 1480 |
1481 for (i = 255; i >= 0; i--) { 1482 scb = &aic->scbs[i]; 1483 scb->tag = i; |
1484 callout_init_mtx(&scb->timer, &aic->lock, 0); |
1485 aic_free_scb(aic, scb); 1486 } 1487 1488 for (i = 0; i < 8; i++) { 1489 if (i == aic->initiator) 1490 continue; 1491 ti = &aic->tinfo[i]; 1492 bzero(ti, sizeof(*ti)); --- 42 unchanged lines hidden (view full) --- 1535 devq = cam_simq_alloc(256); 1536 if (devq == NULL) 1537 return (ENOMEM); 1538 1539 /* 1540 * Construct our SIM entry 1541 */ 1542 aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic, |
1543 device_get_unit(aic->dev), &aic->lock, 2, 256, devq); |
1544 if (aic->sim == NULL) { 1545 cam_simq_free(devq); 1546 return (ENOMEM); 1547 } 1548 |
1549 mtx_lock(&aic->lock); |
1550 if (xpt_bus_register(aic->sim, aic->dev, 0) != CAM_SUCCESS) { 1551 cam_sim_free(aic->sim, /*free_devq*/TRUE); |
1552 mtx_unlock(&aic->lock); |
1553 return (ENXIO); 1554 } 1555 1556 if (xpt_create_path(&aic->path, /*periph*/NULL, 1557 cam_sim_path(aic->sim), CAM_TARGET_WILDCARD, 1558 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1559 xpt_bus_deregister(cam_sim_path(aic->sim)); 1560 cam_sim_free(aic->sim, /*free_devq*/TRUE); |
1561 mtx_unlock(&aic->lock); |
1562 return (ENXIO); 1563 } 1564 1565 aic_init(aic); 1566 |
1567 device_printf(aic->dev, "%s", aic_chip_names[aic->chip_type]); |
1568 if (aic->flags & AIC_DMA_ENABLE) 1569 printf(", dma"); 1570 if (aic->flags & AIC_DISC_ENABLE) 1571 printf(", disconnection"); 1572 if (aic->flags & AIC_PARITY_ENABLE) 1573 printf(", parity check"); 1574 if (aic->flags & AIC_FAST_ENABLE) 1575 printf(", fast SCSI"); 1576 printf("\n"); |
1577 mtx_unlock(&aic->lock); |
1578 return (0); 1579} 1580 1581int 1582aic_detach(struct aic_softc *aic) 1583{ |
1584 struct aic_scb *scb; 1585 int i; 1586 1587 mtx_lock(&aic->lock); |
1588 xpt_async(AC_LOST_DEVICE, aic->path, NULL); 1589 xpt_free_path(aic->path); 1590 xpt_bus_deregister(cam_sim_path(aic->sim)); 1591 cam_sim_free(aic->sim, /*free_devq*/TRUE); |
1592 mtx_unlock(&aic->lock); 1593 for (i = 255; i >= 0; i--) { 1594 scb = &aic->scbs[i]; 1595 callout_drain(&scb->timer); 1596 } |
1597 return (0); 1598} |