| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ncr53c9x.c,v 1.142 2011/07/04 16:06:17 joerg Exp $ */ | | 1 | /* $NetBSD: ncr53c9x.c,v 1.143 2011/07/31 18:39:00 jakllsch Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Charles M. Hannum. | | 8 | * by Charles M. Hannum. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -60,27 +60,27 @@ | | | @@ -60,27 +60,27 @@ |
60 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 60 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
61 | * POSSIBILITY OF SUCH DAMAGE. | | 61 | * POSSIBILITY OF SUCH DAMAGE. |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | /* | | 64 | /* |
65 | * Based on aic6360 by Jarle Greipsland | | 65 | * Based on aic6360 by Jarle Greipsland |
66 | * | | 66 | * |
67 | * Acknowledgements: Many of the algorithms used in this driver are | | 67 | * Acknowledgements: Many of the algorithms used in this driver are |
68 | * inspired by the work of Julian Elischer (julian@tfs.com) and | | 68 | * inspired by the work of Julian Elischer (julian@tfs.com) and |
69 | * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million! | | 69 | * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million! |
70 | */ | | 70 | */ |
71 | | | 71 | |
72 | #include <sys/cdefs.h> | | 72 | #include <sys/cdefs.h> |
73 | __KERNEL_RCSID(0, "$NetBSD: ncr53c9x.c,v 1.142 2011/07/04 16:06:17 joerg Exp $"); | | 73 | __KERNEL_RCSID(0, "$NetBSD: ncr53c9x.c,v 1.143 2011/07/31 18:39:00 jakllsch Exp $"); |
74 | | | 74 | |
75 | #include <sys/param.h> | | 75 | #include <sys/param.h> |
76 | #include <sys/systm.h> | | 76 | #include <sys/systm.h> |
77 | #include <sys/callout.h> | | 77 | #include <sys/callout.h> |
78 | #include <sys/kernel.h> | | 78 | #include <sys/kernel.h> |
79 | #include <sys/errno.h> | | 79 | #include <sys/errno.h> |
80 | #include <sys/ioctl.h> | | 80 | #include <sys/ioctl.h> |
81 | #include <sys/device.h> | | 81 | #include <sys/device.h> |
82 | #include <sys/buf.h> | | 82 | #include <sys/buf.h> |
83 | #include <sys/malloc.h> | | 83 | #include <sys/malloc.h> |
84 | #include <sys/proc.h> | | 84 | #include <sys/proc.h> |
85 | #include <sys/queue.h> | | 85 | #include <sys/queue.h> |
86 | #include <sys/pool.h> | | 86 | #include <sys/pool.h> |
| @@ -184,27 +184,27 @@ ncr53c9x_lunsearch(struct ncr53c9x_tinfo | | | @@ -184,27 +184,27 @@ ncr53c9x_lunsearch(struct ncr53c9x_tinfo |
184 | return li; | | 184 | return li; |
185 | return NULL; | | 185 | return NULL; |
186 | } | | 186 | } |
187 | | | 187 | |
188 | /* | | 188 | /* |
189 | * Attach this instance, and then all the sub-devices | | 189 | * Attach this instance, and then all the sub-devices |
190 | */ | | 190 | */ |
191 | void | | 191 | void |
192 | ncr53c9x_attach(struct ncr53c9x_softc *sc) | | 192 | ncr53c9x_attach(struct ncr53c9x_softc *sc) |
193 | { | | 193 | { |
194 | struct scsipi_adapter *adapt = &sc->sc_adapter; | | 194 | struct scsipi_adapter *adapt = &sc->sc_adapter; |
195 | struct scsipi_channel *chan = &sc->sc_channel; | | 195 | struct scsipi_channel *chan = &sc->sc_channel; |
196 | | | 196 | |
197 | simple_lock_init(&sc->sc_lock); | | 197 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO); |
198 | | | 198 | |
199 | callout_init(&sc->sc_watchdog, 0); | | 199 | callout_init(&sc->sc_watchdog, 0); |
200 | | | 200 | |
201 | /* | | 201 | /* |
202 | * Note, the front-end has set us up to print the chip variation. | | 202 | * Note, the front-end has set us up to print the chip variation. |
203 | */ | | 203 | */ |
204 | if (sc->sc_rev >= NCR_VARIANT_MAX) { | | 204 | if (sc->sc_rev >= NCR_VARIANT_MAX) { |
205 | aprint_error(": unknown variant %d, devices not attached\n", | | 205 | aprint_error(": unknown variant %d, devices not attached\n", |
206 | sc->sc_rev); | | 206 | sc->sc_rev); |
207 | return; | | 207 | return; |
208 | } | | 208 | } |
209 | | | 209 | |
210 | aprint_normal(": %s, %dMHz, SCSI ID %d\n", | | 210 | aprint_normal(": %s, %dMHz, SCSI ID %d\n", |
| @@ -331,26 +331,28 @@ ncr53c9x_detach(struct ncr53c9x_softc *s | | | @@ -331,26 +331,28 @@ ncr53c9x_detach(struct ncr53c9x_softc *s |
331 | } | | 331 | } |
332 | | | 332 | |
333 | if (sc->sc_child) { | | 333 | if (sc->sc_child) { |
334 | error = config_detach(sc->sc_child, flags); | | 334 | error = config_detach(sc->sc_child, flags); |
335 | if (error) | | 335 | if (error) |
336 | return error; | | 336 | return error; |
337 | } | | 337 | } |
338 | | | 338 | |
339 | if (sc->sc_imess) | | 339 | if (sc->sc_imess) |
340 | free(sc->sc_imess, M_DEVBUF); | | 340 | free(sc->sc_imess, M_DEVBUF); |
341 | if (sc->sc_omess) | | 341 | if (sc->sc_omess) |
342 | free(sc->sc_omess, M_DEVBUF); | | 342 | free(sc->sc_omess, M_DEVBUF); |
343 | | | 343 | |
| | | 344 | mutex_destroy(&sc->sc_lock); |
| | | 345 | |
344 | return 0; | | 346 | return 0; |
345 | } | | 347 | } |
346 | | | 348 | |
347 | /* | | 349 | /* |
348 | * This is the generic ncr53c9x reset function. It does not reset the SCSI bus, | | 350 | * This is the generic ncr53c9x reset function. It does not reset the SCSI bus, |
349 | * only this controller, but kills any on-going commands, and also stops | | 351 | * only this controller, but kills any on-going commands, and also stops |
350 | * and resets the DMA. | | 352 | * and resets the DMA. |
351 | * | | 353 | * |
352 | * After reset, registers are loaded with the defaults from the attach | | 354 | * After reset, registers are loaded with the defaults from the attach |
353 | * routine above. | | 355 | * routine above. |
354 | */ | | 356 | */ |
355 | void | | 357 | void |
356 | ncr53c9x_reset(struct ncr53c9x_softc *sc) | | 358 | ncr53c9x_reset(struct ncr53c9x_softc *sc) |
| @@ -847,57 +849,55 @@ ncr53c9x_get_ecb(struct ncr53c9x_softc * | | | @@ -847,57 +849,55 @@ ncr53c9x_get_ecb(struct ncr53c9x_softc * |
847 | * Start a SCSI-command | | 849 | * Start a SCSI-command |
848 | * This function is called by the higher level SCSI-driver to queue/run | | 850 | * This function is called by the higher level SCSI-driver to queue/run |
849 | * SCSI-commands. | | 851 | * SCSI-commands. |
850 | */ | | 852 | */ |
851 | | | 853 | |
852 | void | | 854 | void |
853 | ncr53c9x_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, | | 855 | ncr53c9x_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, |
854 | void *arg) | | 856 | void *arg) |
855 | { | | 857 | { |
856 | struct scsipi_xfer *xs; | | 858 | struct scsipi_xfer *xs; |
857 | struct scsipi_periph *periph; | | 859 | struct scsipi_periph *periph; |
858 | struct ncr53c9x_softc *sc; | | 860 | struct ncr53c9x_softc *sc; |
859 | struct ncr53c9x_ecb *ecb; | | 861 | struct ncr53c9x_ecb *ecb; |
860 | int s, flags; | | 862 | int flags; |
861 | | | 863 | |
862 | NCR_TRACE(("[ncr53c9x_scsipi_request] ")); | | 864 | NCR_TRACE(("[ncr53c9x_scsipi_request] ")); |
863 | | | 865 | |
864 | sc = device_private(chan->chan_adapter->adapt_dev); | | 866 | sc = device_private(chan->chan_adapter->adapt_dev); |
865 | s = splbio(); | | 867 | mutex_enter(&sc->sc_lock); |
866 | simple_lock(&sc->sc_lock); | | | |
867 | | | 868 | |
868 | switch (req) { | | 869 | switch (req) { |
869 | case ADAPTER_REQ_RUN_XFER: | | 870 | case ADAPTER_REQ_RUN_XFER: |
870 | xs = arg; | | 871 | xs = arg; |
871 | periph = xs->xs_periph; | | 872 | periph = xs->xs_periph; |
872 | flags = xs->xs_control; | | 873 | flags = xs->xs_control; |
873 | | | 874 | |
874 | NCR_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen, | | 875 | NCR_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen, |
875 | periph->periph_target)); | | 876 | periph->periph_target)); |
876 | | | 877 | |
877 | /* Get an ECB to use. */ | | 878 | /* Get an ECB to use. */ |
878 | ecb = ncr53c9x_get_ecb(sc, xs->xs_control); | | 879 | ecb = ncr53c9x_get_ecb(sc, xs->xs_control); |
879 | /* | | 880 | /* |
880 | * This should never happen as we track resources | | 881 | * This should never happen as we track resources |
881 | * in the mid-layer, but for now it can as pool_get() | | 882 | * in the mid-layer, but for now it can as pool_get() |
882 | * can fail. | | 883 | * can fail. |
883 | */ | | 884 | */ |
884 | if (ecb == NULL) { | | 885 | if (ecb == NULL) { |
885 | scsipi_printaddr(periph); | | 886 | scsipi_printaddr(periph); |
886 | printf("%s: unable to allocate ecb\n", | | 887 | printf("%s: unable to allocate ecb\n", |
887 | device_xname(sc->sc_dev)); | | 888 | device_xname(sc->sc_dev)); |
888 | xs->error = XS_RESOURCE_SHORTAGE; | | 889 | xs->error = XS_RESOURCE_SHORTAGE; |
889 | simple_unlock(&sc->sc_lock); | | 890 | mutex_exit(&sc->sc_lock); |
890 | splx(s); | | | |
891 | scsipi_done(xs); | | 891 | scsipi_done(xs); |
892 | return; | | 892 | return; |
893 | } | | 893 | } |
894 | | | 894 | |
895 | /* Initialize ecb */ | | 895 | /* Initialize ecb */ |
896 | ecb->xs = xs; | | 896 | ecb->xs = xs; |
897 | ecb->timeout = xs->timeout; | | 897 | ecb->timeout = xs->timeout; |
898 | | | 898 | |
899 | if (flags & XS_CTL_RESET) { | | 899 | if (flags & XS_CTL_RESET) { |
900 | ecb->flags |= ECB_RESET; | | 900 | ecb->flags |= ECB_RESET; |
901 | ecb->clen = 0; | | 901 | ecb->clen = 0; |
902 | ecb->dleft = 0; | | 902 | ecb->dleft = 0; |
903 | } else { | | 903 | } else { |
| @@ -962,28 +962,27 @@ ncr53c9x_scsipi_request(struct scsipi_ch | | | @@ -962,28 +962,27 @@ ncr53c9x_scsipi_request(struct scsipi_ch |
962 | ti->flags |= T_NEGOTIATE; | | 962 | ti->flags |= T_NEGOTIATE; |
963 | ti->period = sc->sc_minsync; | | 963 | ti->period = sc->sc_minsync; |
964 | } | | 964 | } |
965 | /* | | 965 | /* |
966 | * If we're not going to negotiate, send the notification | | 966 | * If we're not going to negotiate, send the notification |
967 | * now, since it won't happen later. | | 967 | * now, since it won't happen later. |
968 | */ | | 968 | */ |
969 | if ((ti->flags & T_NEGOTIATE) == 0) | | 969 | if ((ti->flags & T_NEGOTIATE) == 0) |
970 | ncr53c9x_update_xfer_mode(sc, xm->xm_target); | | 970 | ncr53c9x_update_xfer_mode(sc, xm->xm_target); |
971 | } | | 971 | } |
972 | break; | | 972 | break; |
973 | } | | 973 | } |
974 | | | 974 | |
975 | simple_unlock(&sc->sc_lock); | | 975 | mutex_exit(&sc->sc_lock); |
976 | splx(s); | | | |
977 | } | | 976 | } |
978 | | | 977 | |
979 | void | | 978 | void |
980 | ncr53c9x_update_xfer_mode(struct ncr53c9x_softc *sc, int target) | | 979 | ncr53c9x_update_xfer_mode(struct ncr53c9x_softc *sc, int target) |
981 | { | | 980 | { |
982 | struct scsipi_xfer_mode xm; | | 981 | struct scsipi_xfer_mode xm; |
983 | struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[target]; | | 982 | struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[target]; |
984 | | | 983 | |
985 | xm.xm_target = target; | | 984 | xm.xm_target = target; |
986 | xm.xm_mode = 0; | | 985 | xm.xm_mode = 0; |
987 | xm.xm_period = 0; | | 986 | xm.xm_period = 0; |
988 | xm.xm_offset = 0; | | 987 | xm.xm_offset = 0; |
989 | | | 988 | |
| @@ -1001,61 +1000,59 @@ ncr53c9x_update_xfer_mode(struct ncr53c9 | | | @@ -1001,61 +1000,59 @@ ncr53c9x_update_xfer_mode(struct ncr53c9 |
1001 | scsipi_async_event(&sc->sc_channel, ASYNC_EVENT_XFER_MODE, &xm); | | 1000 | scsipi_async_event(&sc->sc_channel, ASYNC_EVENT_XFER_MODE, &xm); |
1002 | } | | 1001 | } |
1003 | | | 1002 | |
1004 | /* | | 1003 | /* |
1005 | * Used when interrupt driven I/O isn't allowed, e.g. during boot. | | 1004 | * Used when interrupt driven I/O isn't allowed, e.g. during boot. |
1006 | */ | | 1005 | */ |
1007 | int | | 1006 | int |
1008 | ncr53c9x_poll(struct ncr53c9x_softc *sc, struct scsipi_xfer *xs, int count) | | 1007 | ncr53c9x_poll(struct ncr53c9x_softc *sc, struct scsipi_xfer *xs, int count) |
1009 | { | | 1008 | { |
1010 | | | 1009 | |
1011 | NCR_TRACE(("[ncr53c9x_poll] ")); | | 1010 | NCR_TRACE(("[ncr53c9x_poll] ")); |
1012 | while (count) { | | 1011 | while (count) { |
1013 | if (NCRDMA_ISINTR(sc)) { | | 1012 | if (NCRDMA_ISINTR(sc)) { |
1014 | simple_unlock(&sc->sc_lock); | | 1013 | mutex_exit(&sc->sc_lock); |
1015 | ncr53c9x_intr(sc); | | 1014 | ncr53c9x_intr(sc); |
1016 | simple_lock(&sc->sc_lock); | | 1015 | mutex_enter(&sc->sc_lock); |
1017 | } | | 1016 | } |
1018 | #if alternatively | | 1017 | #if alternatively |
1019 | if (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT) | | 1018 | if (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT) |
1020 | ncr53c9x_intr(sc); | | 1019 | ncr53c9x_intr(sc); |
1021 | #endif | | 1020 | #endif |
1022 | if ((xs->xs_status & XS_STS_DONE) != 0) | | 1021 | if ((xs->xs_status & XS_STS_DONE) != 0) |
1023 | return 0; | | 1022 | return 0; |
1024 | if (sc->sc_state == NCR_IDLE) { | | 1023 | if (sc->sc_state == NCR_IDLE) { |
1025 | NCR_TRACE(("[ncr53c9x_poll: rescheduling] ")); | | 1024 | NCR_TRACE(("[ncr53c9x_poll: rescheduling] ")); |
1026 | ncr53c9x_sched(sc); | | 1025 | ncr53c9x_sched(sc); |
1027 | } | | 1026 | } |
1028 | DELAY(1000); | | 1027 | DELAY(1000); |
1029 | count--; | | 1028 | count--; |
1030 | } | | 1029 | } |
1031 | return 1; | | 1030 | return 1; |
1032 | } | | 1031 | } |
1033 | | | 1032 | |
1034 | int | | 1033 | int |
1035 | ncr53c9x_ioctl(struct scsipi_channel *chan, u_long cmd, void *arg, | | 1034 | ncr53c9x_ioctl(struct scsipi_channel *chan, u_long cmd, void *arg, |
1036 | int flag, struct proc *p) | | 1035 | int flag, struct proc *p) |
1037 | { | | 1036 | { |
1038 | struct ncr53c9x_softc *sc; | | 1037 | struct ncr53c9x_softc *sc; |
1039 | int s, error = 0; | | 1038 | int error = 0; |
1040 | | | 1039 | |
1041 | sc = device_private(chan->chan_adapter->adapt_dev); | | 1040 | sc = device_private(chan->chan_adapter->adapt_dev); |
1042 | switch (cmd) { | | 1041 | switch (cmd) { |
1043 | case SCBUSIORESET: | | 1042 | case SCBUSIORESET: |
1044 | s = splbio(); | | 1043 | mutex_enter(&sc->sc_lock); |
1045 | simple_lock(&sc->sc_lock); | | | |
1046 | ncr53c9x_init(sc, 1); | | 1044 | ncr53c9x_init(sc, 1); |
1047 | simple_unlock(&sc->sc_lock); | | 1045 | mutex_exit(&sc->sc_lock); |
1048 | splx(s); | | | |
1049 | break; | | 1046 | break; |
1050 | default: | | 1047 | default: |
1051 | error = ENOTTY; | | 1048 | error = ENOTTY; |
1052 | break; | | 1049 | break; |
1053 | } | | 1050 | } |
1054 | return error; | | 1051 | return error; |
1055 | } | | 1052 | } |
1056 | | | 1053 | |
1057 | | | 1054 | |
1058 | /* | | 1055 | /* |
1059 | * LOW LEVEL SCSI UTILITIES | | 1056 | * LOW LEVEL SCSI UTILITIES |
1060 | */ | | 1057 | */ |
1061 | | | 1058 | |
| @@ -1269,29 +1266,29 @@ ncr53c9x_done(struct ncr53c9x_softc *sc, | | | @@ -1269,29 +1266,29 @@ ncr53c9x_done(struct ncr53c9x_softc *sc, |
1269 | | | 1266 | |
1270 | if (xs->error == XS_SELTIMEOUT) { | | 1267 | if (xs->error == XS_SELTIMEOUT) { |
1271 | /* Selection timeout -- discard this LUN if empty */ | | 1268 | /* Selection timeout -- discard this LUN if empty */ |
1272 | if (li->untagged == NULL && li->used == 0) { | | 1269 | if (li->untagged == NULL && li->used == 0) { |
1273 | if (lun < NCR_NLUN) | | 1270 | if (lun < NCR_NLUN) |
1274 | ti->lun[lun] = NULL; | | 1271 | ti->lun[lun] = NULL; |
1275 | LIST_REMOVE(li, link); | | 1272 | LIST_REMOVE(li, link); |
1276 | free(li, M_DEVBUF); | | 1273 | free(li, M_DEVBUF); |
1277 | } | | 1274 | } |
1278 | } | | 1275 | } |
1279 | | | 1276 | |
1280 | ncr53c9x_free_ecb(sc, ecb); | | 1277 | ncr53c9x_free_ecb(sc, ecb); |
1281 | ti->cmds++; | | 1278 | ti->cmds++; |
1282 | simple_unlock(&sc->sc_lock); | | 1279 | mutex_exit(&sc->sc_lock); |
1283 | scsipi_done(xs); | | 1280 | scsipi_done(xs); |
1284 | simple_lock(&sc->sc_lock); | | 1281 | mutex_enter(&sc->sc_lock); |
1285 | } | | 1282 | } |
1286 | | | 1283 | |
1287 | void | | 1284 | void |
1288 | ncr53c9x_dequeue(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb) | | 1285 | ncr53c9x_dequeue(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb) |
1289 | { | | 1286 | { |
1290 | struct ncr53c9x_tinfo *ti = | | 1287 | struct ncr53c9x_tinfo *ti = |
1291 | &sc->sc_tinfo[ecb->xs->xs_periph->periph_target]; | | 1288 | &sc->sc_tinfo[ecb->xs->xs_periph->periph_target]; |
1292 | struct ncr53c9x_linfo *li; | | 1289 | struct ncr53c9x_linfo *li; |
1293 | int64_t lun = ecb->xs->xs_periph->periph_lun; | | 1290 | int64_t lun = ecb->xs->xs_periph->periph_lun; |
1294 | | | 1291 | |
1295 | li = TINFO_LUN(ti, lun); | | 1292 | li = TINFO_LUN(ti, lun); |
1296 | #ifdef DIAGNOSTIC | | 1293 | #ifdef DIAGNOSTIC |
1297 | if (li == NULL || li->lun != lun) | | 1294 | if (li == NULL || li->lun != lun) |
| @@ -2080,27 +2077,27 @@ ncr53c9x_intr(void *arg) | | | @@ -2080,27 +2077,27 @@ ncr53c9x_intr(void *arg) |
2080 | { | | 2077 | { |
2081 | struct ncr53c9x_softc *sc = arg; | | 2078 | struct ncr53c9x_softc *sc = arg; |
2082 | struct ncr53c9x_ecb *ecb; | | 2079 | struct ncr53c9x_ecb *ecb; |
2083 | struct scsipi_periph *periph; | | 2080 | struct scsipi_periph *periph; |
2084 | struct ncr53c9x_tinfo *ti; | | 2081 | struct ncr53c9x_tinfo *ti; |
2085 | size_t size; | | 2082 | size_t size; |
2086 | int nfifo; | | 2083 | int nfifo; |
2087 | | | 2084 | |
2088 | NCR_INTS(("[ncr53c9x_intr: state %d]", sc->sc_state)); | | 2085 | NCR_INTS(("[ncr53c9x_intr: state %d]", sc->sc_state)); |
2089 | | | 2086 | |
2090 | if (!NCRDMA_ISINTR(sc)) | | 2087 | if (!NCRDMA_ISINTR(sc)) |
2091 | return 0; | | 2088 | return 0; |
2092 | | | 2089 | |
2093 | simple_lock(&sc->sc_lock); | | 2090 | mutex_enter(&sc->sc_lock); |
2094 | again: | | 2091 | again: |
2095 | /* and what do the registers say... */ | | 2092 | /* and what do the registers say... */ |
2096 | ncr53c9x_readregs(sc); | | 2093 | ncr53c9x_readregs(sc); |
2097 | | | 2094 | |
2098 | sc->sc_intrcnt.ev_count++; | | 2095 | sc->sc_intrcnt.ev_count++; |
2099 | | | 2096 | |
2100 | /* | | 2097 | /* |
2101 | * At the moment, only a SCSI Bus Reset or Illegal | | 2098 | * At the moment, only a SCSI Bus Reset or Illegal |
2102 | * Command are classed as errors. A disconnect is a | | 2099 | * Command are classed as errors. A disconnect is a |
2103 | * valid condition, and we let the code check is the | | 2100 | * valid condition, and we let the code check is the |
2104 | * "NCR_BUSFREE_OK" flag was set before declaring it | | 2101 | * "NCR_BUSFREE_OK" flag was set before declaring it |
2105 | * and error. | | 2102 | * and error. |
2106 | * | | 2103 | * |
| @@ -2614,27 +2611,27 @@ again: | | | @@ -2614,27 +2611,27 @@ again: |
2614 | } else { | | 2611 | } else { |
2615 | | | 2612 | |
2616 | printf("%s: unexpected status after select" | | 2613 | printf("%s: unexpected status after select" |
2617 | ": [intr %x, stat %x, step %x]\n", | | 2614 | ": [intr %x, stat %x, step %x]\n", |
2618 | device_xname(sc->sc_dev), | | 2615 | device_xname(sc->sc_dev), |
2619 | sc->sc_espintr, sc->sc_espstat, sc->sc_espstep); | | 2616 | sc->sc_espintr, sc->sc_espstat, sc->sc_espstep); |
2620 | NCRCMD(sc, NCRCMD_FLUSH); | | 2617 | NCRCMD(sc, NCRCMD_FLUSH); |
2621 | DELAY(1); | | 2618 | DELAY(1); |
2622 | goto reset; | | 2619 | goto reset; |
2623 | } | | 2620 | } |
2624 | if (sc->sc_state == NCR_IDLE) { | | 2621 | if (sc->sc_state == NCR_IDLE) { |
2625 | printf("%s: stray interrupt\n", | | 2622 | printf("%s: stray interrupt\n", |
2626 | device_xname(sc->sc_dev)); | | 2623 | device_xname(sc->sc_dev)); |
2627 | simple_unlock(&sc->sc_lock); | | 2624 | mutex_exit(&sc->sc_lock); |
2628 | return 0; | | 2625 | return 0; |
2629 | } | | 2626 | } |
2630 | break; | | 2627 | break; |
2631 | | | 2628 | |
2632 | case NCR_CONNECTED: | | 2629 | case NCR_CONNECTED: |
2633 | if ((sc->sc_flags & NCR_ICCS) != 0) { | | 2630 | if ((sc->sc_flags & NCR_ICCS) != 0) { |
2634 | /* "Initiate Command Complete Steps" in progress */ | | 2631 | /* "Initiate Command Complete Steps" in progress */ |
2635 | uint8_t msg; | | 2632 | uint8_t msg; |
2636 | | | 2633 | |
2637 | sc->sc_flags &= ~NCR_ICCS; | | 2634 | sc->sc_flags &= ~NCR_ICCS; |
2638 | | | 2635 | |
2639 | if ((sc->sc_espintr & NCRINTR_DONE) == 0) { | | 2636 | if ((sc->sc_espintr & NCRINTR_DONE) == 0) { |
2640 | printf("%s: ICCS: " | | 2637 | printf("%s: ICCS: " |
| @@ -2805,27 +2802,27 @@ msgin: | | | @@ -2805,27 +2802,27 @@ msgin: |
2805 | sc->sc_prevphase = STATUS_PHASE; | | 2802 | sc->sc_prevphase = STATUS_PHASE; |
2806 | goto shortcut; /* i.e. expect status results soon */ | | 2803 | goto shortcut; /* i.e. expect status results soon */ |
2807 | | | 2804 | |
2808 | case INVALID_PHASE: | | 2805 | case INVALID_PHASE: |
2809 | break; | | 2806 | break; |
2810 | | | 2807 | |
2811 | default: | | 2808 | default: |
2812 | printf("%s: unexpected bus phase; resetting\n", | | 2809 | printf("%s: unexpected bus phase; resetting\n", |
2813 | device_xname(sc->sc_dev)); | | 2810 | device_xname(sc->sc_dev)); |
2814 | goto reset; | | 2811 | goto reset; |
2815 | } | | 2812 | } |
2816 | | | 2813 | |
2817 | out: | | 2814 | out: |
2818 | simple_unlock(&sc->sc_lock); | | 2815 | mutex_exit(&sc->sc_lock); |
2819 | return 1; | | 2816 | return 1; |
2820 | | | 2817 | |
2821 | reset: | | 2818 | reset: |
2822 | ncr53c9x_init(sc, 1); | | 2819 | ncr53c9x_init(sc, 1); |
2823 | goto out; | | 2820 | goto out; |
2824 | | | 2821 | |
2825 | finish: | | 2822 | finish: |
2826 | ncr53c9x_done(sc, ecb); | | 2823 | ncr53c9x_done(sc, ecb); |
2827 | goto out; | | 2824 | goto out; |
2828 | | | 2825 | |
2829 | sched: | | 2826 | sched: |
2830 | sc->sc_state = NCR_IDLE; | | 2827 | sc->sc_state = NCR_IDLE; |
2831 | ncr53c9x_sched(sc); | | 2828 | ncr53c9x_sched(sc); |
| @@ -2889,98 +2886,93 @@ ncr53c9x_abort(struct ncr53c9x_softc *sc | | | @@ -2889,98 +2886,93 @@ ncr53c9x_abort(struct ncr53c9x_softc *sc |
2889 | if (sc->sc_state == NCR_IDLE) | | 2886 | if (sc->sc_state == NCR_IDLE) |
2890 | ncr53c9x_sched(sc); | | 2887 | ncr53c9x_sched(sc); |
2891 | } | | 2888 | } |
2892 | } | | 2889 | } |
2893 | | | 2890 | |
2894 | void | | 2891 | void |
2895 | ncr53c9x_timeout(void *arg) | | 2892 | ncr53c9x_timeout(void *arg) |
2896 | { | | 2893 | { |
2897 | struct ncr53c9x_ecb *ecb = arg; | | 2894 | struct ncr53c9x_ecb *ecb = arg; |
2898 | struct scsipi_xfer *xs = ecb->xs; | | 2895 | struct scsipi_xfer *xs = ecb->xs; |
2899 | struct scsipi_periph *periph = xs->xs_periph; | | 2896 | struct scsipi_periph *periph = xs->xs_periph; |
2900 | struct ncr53c9x_softc *sc; | | 2897 | struct ncr53c9x_softc *sc; |
2901 | struct ncr53c9x_tinfo *ti; | | 2898 | struct ncr53c9x_tinfo *ti; |
2902 | int s; | | | |
2903 | | | 2899 | |
2904 | sc = device_private(periph->periph_channel->chan_adapter->adapt_dev); | | 2900 | sc = device_private(periph->periph_channel->chan_adapter->adapt_dev); |
2905 | ti = &sc->sc_tinfo[periph->periph_target]; | | 2901 | ti = &sc->sc_tinfo[periph->periph_target]; |
2906 | | | 2902 | |
2907 | scsipi_printaddr(periph); | | 2903 | scsipi_printaddr(periph); |
2908 | printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], " | | 2904 | printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], " |
2909 | "<state %d, nexus %p, phase(l %x, c %x, p %x), resid %lx, " | | 2905 | "<state %d, nexus %p, phase(l %x, c %x, p %x), resid %lx, " |
2910 | "msg(q %x,o %x) %s>", | | 2906 | "msg(q %x,o %x) %s>", |
2911 | device_xname(sc->sc_dev), | | 2907 | device_xname(sc->sc_dev), |
2912 | ecb, ecb->flags, ecb->dleft, ecb->stat, | | 2908 | ecb, ecb->flags, ecb->dleft, ecb->stat, |
2913 | sc->sc_state, sc->sc_nexus, | | 2909 | sc->sc_state, sc->sc_nexus, |
2914 | NCR_READ_REG(sc, NCR_STAT), | | 2910 | NCR_READ_REG(sc, NCR_STAT), |
2915 | sc->sc_phase, sc->sc_prevphase, | | 2911 | sc->sc_phase, sc->sc_prevphase, |
2916 | (long)sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout, | | 2912 | (long)sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout, |
2917 | NCRDMA_ISACTIVE(sc) ? "DMA active" : ""); | | 2913 | NCRDMA_ISACTIVE(sc) ? "DMA active" : ""); |
2918 | #if NCR53C9X_DEBUG > 1 | | 2914 | #if NCR53C9X_DEBUG > 1 |
2919 | printf("TRACE: %s.", ecb->trace); | | 2915 | printf("TRACE: %s.", ecb->trace); |
2920 | #endif | | 2916 | #endif |
2921 | | | 2917 | |
2922 | s = splbio(); | | 2918 | mutex_enter(&sc->sc_lock); |
2923 | simple_lock(&sc->sc_lock); | | | |
2924 | | | 2919 | |
2925 | if (ecb->flags & ECB_ABORT) { | | 2920 | if (ecb->flags & ECB_ABORT) { |
2926 | /* abort timed out */ | | 2921 | /* abort timed out */ |
2927 | printf(" AGAIN\n"); | | 2922 | printf(" AGAIN\n"); |
2928 | | | 2923 | |
2929 | ncr53c9x_init(sc, 1); | | 2924 | ncr53c9x_init(sc, 1); |
2930 | } else { | | 2925 | } else { |
2931 | /* abort the operation that has timed out */ | | 2926 | /* abort the operation that has timed out */ |
2932 | printf("\n"); | | 2927 | printf("\n"); |
2933 | xs->error = XS_TIMEOUT; | | 2928 | xs->error = XS_TIMEOUT; |
2934 | ncr53c9x_abort(sc, ecb); | | 2929 | ncr53c9x_abort(sc, ecb); |
2935 | | | 2930 | |
2936 | /* Disable sync mode if stuck in a data phase */ | | 2931 | /* Disable sync mode if stuck in a data phase */ |
2937 | if (ecb == sc->sc_nexus && | | 2932 | if (ecb == sc->sc_nexus && |
2938 | (ti->flags & T_SYNCMODE) != 0 && | | 2933 | (ti->flags & T_SYNCMODE) != 0 && |
2939 | (sc->sc_phase & (MSGI | CDI)) == 0) { | | 2934 | (sc->sc_phase & (MSGI | CDI)) == 0) { |
2940 | /* XXX ASYNC CALLBACK! */ | | 2935 | /* XXX ASYNC CALLBACK! */ |
2941 | scsipi_printaddr(periph); | | 2936 | scsipi_printaddr(periph); |
2942 | printf("sync negotiation disabled\n"); | | 2937 | printf("sync negotiation disabled\n"); |
2943 | sc->sc_cfflags |= | | 2938 | sc->sc_cfflags |= |
2944 | (1 << ((periph->periph_target & 7) + 8)); | | 2939 | (1 << ((periph->periph_target & 7) + 8)); |
2945 | ncr53c9x_update_xfer_mode(sc, periph->periph_target); | | 2940 | ncr53c9x_update_xfer_mode(sc, periph->periph_target); |
2946 | } | | 2941 | } |
2947 | } | | 2942 | } |
2948 | | | 2943 | |
2949 | simple_unlock(&sc->sc_lock); | | 2944 | mutex_exit(&sc->sc_lock); |
2950 | splx(s); | | | |
2951 | } | | 2945 | } |
2952 | | | 2946 | |
2953 | void | | 2947 | void |
2954 | ncr53c9x_watch(void *arg) | | 2948 | ncr53c9x_watch(void *arg) |
2955 | { | | 2949 | { |
2956 | struct ncr53c9x_softc *sc = arg; | | 2950 | struct ncr53c9x_softc *sc = arg; |
2957 | struct ncr53c9x_tinfo *ti; | | 2951 | struct ncr53c9x_tinfo *ti; |
2958 | struct ncr53c9x_linfo *li; | | 2952 | struct ncr53c9x_linfo *li; |
2959 | int t, s; | | 2953 | int t; |
2960 | /* Delete any structures that have not been used in 10min. */ | | 2954 | /* Delete any structures that have not been used in 10min. */ |
2961 | time_t old = time_second - (10 * 60); | | 2955 | time_t old = time_second - (10 * 60); |
2962 | | | 2956 | |
2963 | s = splbio(); | | 2957 | mutex_enter(&sc->sc_lock); |
2964 | simple_lock(&sc->sc_lock); | | | |
2965 | for (t = 0; t < sc->sc_ntarg; t++) { | | 2958 | for (t = 0; t < sc->sc_ntarg; t++) { |
2966 | ti = &sc->sc_tinfo[t]; | | 2959 | ti = &sc->sc_tinfo[t]; |
2967 | li = LIST_FIRST(&ti->luns); | | 2960 | li = LIST_FIRST(&ti->luns); |
2968 | while (li) { | | 2961 | while (li) { |
2969 | if (li->last_used < old && | | 2962 | if (li->last_used < old && |
2970 | li->untagged == NULL && | | 2963 | li->untagged == NULL && |
2971 | li->used == 0) { | | 2964 | li->used == 0) { |
2972 | if (li->lun < NCR_NLUN) | | 2965 | if (li->lun < NCR_NLUN) |
2973 | ti->lun[li->lun] = NULL; | | 2966 | ti->lun[li->lun] = NULL; |
2974 | LIST_REMOVE(li, link); | | 2967 | LIST_REMOVE(li, link); |
2975 | free(li, M_DEVBUF); | | 2968 | free(li, M_DEVBUF); |
2976 | /* Restart the search at the beginning */ | | 2969 | /* Restart the search at the beginning */ |
2977 | li = LIST_FIRST(&ti->luns); | | 2970 | li = LIST_FIRST(&ti->luns); |
2978 | continue; | | 2971 | continue; |
2979 | } | | 2972 | } |
2980 | li = LIST_NEXT(li, link); | | 2973 | li = LIST_NEXT(li, link); |
2981 | } | | 2974 | } |
2982 | } | | 2975 | } |
2983 | simple_unlock(&sc->sc_lock); | | 2976 | mutex_exit(&sc->sc_lock); |
2984 | splx(s); | | | |
2985 | callout_reset(&sc->sc_watchdog, 60 * hz, ncr53c9x_watch, sc); | | 2977 | callout_reset(&sc->sc_watchdog, 60 * hz, ncr53c9x_watch, sc); |
2986 | } | | 2978 | } |