Deleted Added
sdiff udiff text old ( 192066 ) new ( 241591 )
full compact
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}