Pull up following revision(s) (requested by tsutsui in ticket #1557): sys/dev/ic/ahcisata_core.c: revision 1.83 sys/dev/ic/ahcisata_core.c: revision 1.102 sys/dev/ata/ata.c: revision 1.164 sys/dev/ata/ata_wdc.c: revision 1.115 sys/dev/ata/ata_recovery.c: revision 1.4 sys/dev/ic/siisata.c: revision 1.42 sys/dev/ic/wdc.c: revision 1.308 sys/dev/ic/mvsata.c: revision 1.56 sys/dev/scsipi/atapi_wdc.c: revision 1.138 sys/dev/ic/siisata.c: revision 1.49 sys/dev/ata/atavar.h: revision 1.105 sys/dev/ata/wd.c: revision 1.460 sys/dev/ata/ata.c: revision 1.155 sys/dev/ata/wd.c: revision 1.462 sys/dev/ata/atavar.h: revision 1.109 sys/dev/ata/satapmp_subr.c: revision 1.16 sys/dev/ic/wdc.c: revision 1.299 sys/dev/ic/ahcisata_core.c: revision 1.93 sys/dev/ata/ata_wdc.c: revision 1.120 sys/dev/ic/wdcvar.h: revision 1.100 sys/dev/scsipi/atapi_wdc.c: revision 1.141 sys/dev/ic/mvsata.c: revision 1.61 sys/dev/usb/umass_isdata.c (apply patch) drop wd lock in wdstart1() before calling the ata_bio hook; when called from ata thread context, that can still need to sleep for wdc attachments in wdcwait() fix use-after-free for ata xfer on bio submission found by KASAN driver ata_bio hooks read parts of the xfer after ata_exec_xfer() call in order to determine return value, change so that the hook doesn't return any value - callers do not care already, as all I/O requests are asynchronous this problem was uncovered by recent change for wd(4) to not hold wd mutex during ata_bio call, the interrupt for the xfer might thus actually fire immediately adjust also ata_exec_command driver hooks similarily - remove all completion and waiting logic from drivers, upper layer ata code using AT_WAIT/AT_POLL changed to call ata_wait_cmd() itself PR kern/55169 by Nick Hudson Function declaration formating whitespace consistency. NFCI. PR kern/56403 Fix kernel freeze for wdc(4) variants with ATAC_CAP_NOIRQ: (1) Change ata_xfer_ops:c_poll from void to int function. When it returns ATAPOLL_AGAIN, let ata_xfer_start() iterate itself again. (2) Let wdc_ata_bio_poll() return ATAPOLL_AGAIN until ATA_ITSDONE is achieved. A similar change has been made for mvsata(4) (see mvsata_bio_poll()), and no functional changes for other devices. This is how the drivers worked before jdolecek-ncq branch was merged. Note that this changes are less likely to cause infinite recursion: (1) wdc_ata_bio_intr() called from wdc_ata_bio_poll() asserts ATA_ITSDONE in its error handling paths via wdc_ata_bio_done(). (2) Return value from c_start (= wdc_ata_bio_start()) is checked in ata_xfer_start(). Therefore, errors encountered in ata_xfer_ops:c_poll and c_start routines terminate the recursion for wdc(4). The situation is similar for mvsata(4). Still, there is a possibility where ata_xfer_start() takes long time to finish a normal operation. This can result in a delayed response for lower priority interrupts. But, I've never observed such a situation, even when heavy thrashing takes place for swap partition in wd(4). "Go ahead" by jdolecek@.diff -r1.149.2.2 -r1.149.2.3 src/sys/dev/ata/ata.c
(martin)
--- src/sys/dev/ata/ata.c 2022/08/30 18:28:42 1.149.2.2
+++ src/sys/dev/ata/ata.c 2022/12/30 14:39:10 1.149.2.3
@@ -1,41 +1,41 @@ | @@ -1,41 +1,41 @@ | |||
1 | /* $NetBSD: ata.c,v 1.149.2.2 2022/08/30 18:28:42 martin Exp $ */ | 1 | /* $NetBSD: ata.c,v 1.149.2.3 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | 4 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | */ | 25 | */ | |
26 | 26 | |||
27 | #include <sys/cdefs.h> | 27 | #include <sys/cdefs.h> | |
28 | __KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.149.2.2 2022/08/30 18:28:42 martin Exp $"); | 28 | __KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.149.2.3 2022/12/30 14:39:10 martin Exp $"); | |
29 | 29 | |||
30 | #include "opt_ata.h" | 30 | #include "opt_ata.h" | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/systm.h> | 33 | #include <sys/systm.h> | |
34 | #include <sys/kernel.h> | 34 | #include <sys/kernel.h> | |
35 | #include <sys/device.h> | 35 | #include <sys/device.h> | |
36 | #include <sys/conf.h> | 36 | #include <sys/conf.h> | |
37 | #include <sys/fcntl.h> | 37 | #include <sys/fcntl.h> | |
38 | #include <sys/proc.h> | 38 | #include <sys/proc.h> | |
39 | #include <sys/kthread.h> | 39 | #include <sys/kthread.h> | |
40 | #include <sys/errno.h> | 40 | #include <sys/errno.h> | |
41 | #include <sys/ataio.h> | 41 | #include <sys/ataio.h> | |
@@ -832,33 +832,28 @@ ata_get_params(struct ata_drive_datas *d | @@ -832,33 +832,28 @@ ata_get_params(struct ata_drive_datas *d | |||
832 | xfer->c_ata_c.r_command = ATAPI_IDENTIFY_DEVICE; | 832 | xfer->c_ata_c.r_command = ATAPI_IDENTIFY_DEVICE; | |
833 | xfer->c_ata_c.r_st_bmask = 0; | 833 | xfer->c_ata_c.r_st_bmask = 0; | |
834 | xfer->c_ata_c.r_st_pmask = WDCS_DRQ; | 834 | xfer->c_ata_c.r_st_pmask = WDCS_DRQ; | |
835 | xfer->c_ata_c.timeout = 10000; /* 10s */ | 835 | xfer->c_ata_c.timeout = 10000; /* 10s */ | |
836 | } else { | 836 | } else { | |
837 | ATADEBUG_PRINT(("ata_get_parms: no disks\n"), | 837 | ATADEBUG_PRINT(("ata_get_parms: no disks\n"), | |
838 | DEBUG_FUNCS|DEBUG_PROBE); | 838 | DEBUG_FUNCS|DEBUG_PROBE); | |
839 | rv = CMD_ERR; | 839 | rv = CMD_ERR; | |
840 | goto out; | 840 | goto out; | |
841 | } | 841 | } | |
842 | xfer->c_ata_c.flags = AT_READ | flags; | 842 | xfer->c_ata_c.flags = AT_READ | flags; | |
843 | xfer->c_ata_c.data = tb; | 843 | xfer->c_ata_c.data = tb; | |
844 | xfer->c_ata_c.bcount = ATA_BSIZE; | 844 | xfer->c_ata_c.bcount = ATA_BSIZE; | |
845 | if ((*atac->atac_bustype_ata->ata_exec_command)(drvp, | 845 | (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer); | |
846 | xfer) != ATACMD_COMPLETE) { | 846 | ata_wait_cmd(chp, xfer); | |
847 | ATADEBUG_PRINT(("ata_get_parms: wdc_exec_command failed\n"), | |||
848 | DEBUG_FUNCS|DEBUG_PROBE); | |||
849 | rv = CMD_AGAIN; | |||
850 | goto out; | |||
851 | } | |||
852 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 847 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
853 | ATADEBUG_PRINT(("ata_get_parms: ata_c.flags=0x%x\n", | 848 | ATADEBUG_PRINT(("ata_get_parms: ata_c.flags=0x%x\n", | |
854 | xfer->c_ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE); | 849 | xfer->c_ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE); | |
855 | rv = CMD_ERR; | 850 | rv = CMD_ERR; | |
856 | goto out; | 851 | goto out; | |
857 | } | 852 | } | |
858 | /* if we didn't read any data something is wrong */ | 853 | /* if we didn't read any data something is wrong */ | |
859 | if ((xfer->c_ata_c.flags & AT_XFDONE) == 0) { | 854 | if ((xfer->c_ata_c.flags & AT_XFDONE) == 0) { | |
860 | rv = CMD_ERR; | 855 | rv = CMD_ERR; | |
861 | goto out; | 856 | goto out; | |
862 | } | 857 | } | |
863 | 858 | |||
864 | /* Read in parameter block. */ | 859 | /* Read in parameter block. */ | |
@@ -922,31 +917,28 @@ ata_set_mode(struct ata_drive_datas *drv | @@ -922,31 +917,28 @@ ata_set_mode(struct ata_drive_datas *drv | |||
922 | if (xfer == NULL) { | 917 | if (xfer == NULL) { | |
923 | ATADEBUG_PRINT(("%s: no xfer\n", __func__), | 918 | ATADEBUG_PRINT(("%s: no xfer\n", __func__), | |
924 | DEBUG_FUNCS|DEBUG_PROBE); | 919 | DEBUG_FUNCS|DEBUG_PROBE); | |
925 | return CMD_AGAIN; | 920 | return CMD_AGAIN; | |
926 | } | 921 | } | |
927 | 922 | |||
928 | xfer->c_ata_c.r_command = SET_FEATURES; | 923 | xfer->c_ata_c.r_command = SET_FEATURES; | |
929 | xfer->c_ata_c.r_st_bmask = 0; | 924 | xfer->c_ata_c.r_st_bmask = 0; | |
930 | xfer->c_ata_c.r_st_pmask = 0; | 925 | xfer->c_ata_c.r_st_pmask = 0; | |
931 | xfer->c_ata_c.r_features = WDSF_SET_MODE; | 926 | xfer->c_ata_c.r_features = WDSF_SET_MODE; | |
932 | xfer->c_ata_c.r_count = mode; | 927 | xfer->c_ata_c.r_count = mode; | |
933 | xfer->c_ata_c.flags = flags; | 928 | xfer->c_ata_c.flags = flags; | |
934 | xfer->c_ata_c.timeout = 1000; /* 1s */ | 929 | xfer->c_ata_c.timeout = 1000; /* 1s */ | |
935 | if ((*atac->atac_bustype_ata->ata_exec_command)(drvp, | 930 | (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer); | |
936 | xfer) != ATACMD_COMPLETE) { | 931 | ata_wait_cmd(chp, xfer); | |
937 | rv = CMD_AGAIN; | |||
938 | goto out; | |||
939 | } | |||
940 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 932 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
941 | rv = CMD_ERR; | 933 | rv = CMD_ERR; | |
942 | goto out; | 934 | goto out; | |
943 | } | 935 | } | |
944 | 936 | |||
945 | rv = CMD_OK; | 937 | rv = CMD_OK; | |
946 | 938 | |||
947 | out: | 939 | out: | |
948 | ata_free_xfer(chp, xfer); | 940 | ata_free_xfer(chp, xfer); | |
949 | return rv; | 941 | return rv; | |
950 | } | 942 | } | |
951 | 943 | |||
952 | #if NATA_DMA | 944 | #if NATA_DMA | |
@@ -1208,45 +1200,48 @@ again: | @@ -1208,45 +1200,48 @@ again: | |||
1208 | 1200 | |||
1209 | /* Queue more commands if possible, but not during recovery or dump */ | 1201 | /* Queue more commands if possible, but not during recovery or dump */ | |
1210 | if (!skipq && chq->queue_active < chq->queue_openings) | 1202 | if (!skipq && chq->queue_active < chq->queue_openings) | |
1211 | goto again; | 1203 | goto again; | |
1212 | 1204 | |||
1213 | out: | 1205 | out: | |
1214 | ata_channel_unlock(chp); | 1206 | ata_channel_unlock(chp); | |
1215 | } | 1207 | } | |
1216 | 1208 | |||
1217 | int | 1209 | int | |
1218 | ata_xfer_start(struct ata_xfer *xfer) | 1210 | ata_xfer_start(struct ata_xfer *xfer) | |
1219 | { | 1211 | { | |
1220 | struct ata_channel *chp = xfer->c_chp; | 1212 | struct ata_channel *chp = xfer->c_chp; | |
1221 | int rv; | 1213 | int rv, status; | |
1222 | 1214 | |||
1223 | KASSERT(mutex_owned(&chp->ch_lock)); | 1215 | KASSERT(mutex_owned(&chp->ch_lock)); | |
1224 | 1216 | |||
1217 | again: | |||
1225 | rv = xfer->ops->c_start(chp, xfer); | 1218 | rv = xfer->ops->c_start(chp, xfer); | |
1226 | switch (rv) { | 1219 | switch (rv) { | |
1227 | case ATASTART_STARTED: | 1220 | case ATASTART_STARTED: | |
1228 | /* nothing to do */ | 1221 | /* nothing to do */ | |
1229 | break; | 1222 | break; | |
1230 | case ATASTART_TH: | 1223 | case ATASTART_TH: | |
1231 | /* postpone xfer to thread */ | 1224 | /* postpone xfer to thread */ | |
1232 | ata_thread_wake_locked(chp); | 1225 | ata_thread_wake_locked(chp); | |
1233 | break; | 1226 | break; | |
1234 | case ATASTART_POLL: | 1227 | case ATASTART_POLL: | |
1235 | /* can happen even in thread context for some ATAPI devices */ | 1228 | /* can happen even in thread context for some ATAPI devices */ | |
1236 | ata_channel_unlock(chp); | 1229 | ata_channel_unlock(chp); | |
1237 | KASSERT(xfer->ops != NULL && xfer->ops->c_poll != NULL); | 1230 | KASSERT(xfer->ops != NULL && xfer->ops->c_poll != NULL); | |
1238 | xfer->ops->c_poll(chp, xfer); | 1231 | status = xfer->ops->c_poll(chp, xfer); | |
1239 | ata_channel_lock(chp); | 1232 | ata_channel_lock(chp); | |
1233 | if (status == ATAPOLL_AGAIN) | |||
1234 | goto again; | |||
1240 | break; | 1235 | break; | |
1241 | case ATASTART_ABORT: | 1236 | case ATASTART_ABORT: | |
1242 | ata_channel_unlock(chp); | 1237 | ata_channel_unlock(chp); | |
1243 | KASSERT(xfer->ops != NULL && xfer->ops->c_abort != NULL); | 1238 | KASSERT(xfer->ops != NULL && xfer->ops->c_abort != NULL); | |
1244 | xfer->ops->c_abort(chp, xfer); | 1239 | xfer->ops->c_abort(chp, xfer); | |
1245 | ata_channel_lock(chp); | 1240 | ata_channel_lock(chp); | |
1246 | break; | 1241 | break; | |
1247 | } | 1242 | } | |
1248 | 1243 | |||
1249 | return rv; | 1244 | return rv; | |
1250 | } | 1245 | } | |
1251 | 1246 | |||
1252 | static void | 1247 | static void |
--- src/sys/dev/ata/ata_recovery.c 2022/02/08 14:45:00 1.2.8.1
+++ src/sys/dev/ata/ata_recovery.c 2022/12/30 14:39:10 1.2.8.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ata_recovery.c,v 1.2.8.1 2022/02/08 14:45:00 martin Exp $ */ | 1 | /* $NetBSD: ata_recovery.c,v 1.2.8.2 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -17,27 +17,27 @@ | @@ -17,27 +17,27 @@ | |||
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | 26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.2.8.1 2022/02/08 14:45:00 martin Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.2.8.2 2022/12/30 14:39:10 martin Exp $"); | |
31 | 31 | |||
32 | #include "opt_ata.h" | 32 | #include "opt_ata.h" | |
33 | 33 | |||
34 | #include <sys/param.h> | 34 | #include <sys/param.h> | |
35 | #include <sys/systm.h> | 35 | #include <sys/systm.h> | |
36 | #include <sys/kernel.h> | 36 | #include <sys/kernel.h> | |
37 | #include <sys/device.h> | 37 | #include <sys/device.h> | |
38 | #include <sys/conf.h> | 38 | #include <sys/conf.h> | |
39 | #include <sys/fcntl.h> | 39 | #include <sys/fcntl.h> | |
40 | #include <sys/proc.h> | 40 | #include <sys/proc.h> | |
41 | #include <sys/kthread.h> | 41 | #include <sys/kthread.h> | |
42 | #include <sys/errno.h> | 42 | #include <sys/errno.h> | |
43 | #include <sys/ataio.h> | 43 | #include <sys/ataio.h> | |
@@ -93,31 +93,29 @@ ata_read_log_ext_ncq(struct ata_drive_da | @@ -93,31 +93,29 @@ ata_read_log_ext_ncq(struct ata_drive_da | |||
93 | */ | 93 | */ | |
94 | xfer->c_flags |= C_SKIP_QUEUE; | 94 | xfer->c_flags |= C_SKIP_QUEUE; | |
95 | xfer->c_ata_c.r_command = WDCC_READ_LOG_EXT; | 95 | xfer->c_ata_c.r_command = WDCC_READ_LOG_EXT; | |
96 | xfer->c_ata_c.r_lba = page = WDCC_LOG_PAGE_NCQ; | 96 | xfer->c_ata_c.r_lba = page = WDCC_LOG_PAGE_NCQ; | |
97 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | 97 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | |
98 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 98 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
99 | xfer->c_ata_c.r_count = 1; | 99 | xfer->c_ata_c.r_count = 1; | |
100 | xfer->c_ata_c.r_device = WDSD_LBA; | 100 | xfer->c_ata_c.r_device = WDSD_LBA; | |
101 | xfer->c_ata_c.flags = AT_READ | AT_LBA | AT_LBA48 | flags; | 101 | xfer->c_ata_c.flags = AT_READ | AT_LBA | AT_LBA48 | flags; | |
102 | xfer->c_ata_c.timeout = 1000; /* 1s */ | 102 | xfer->c_ata_c.timeout = 1000; /* 1s */ | |
103 | xfer->c_ata_c.data = tb; | 103 | xfer->c_ata_c.data = tb; | |
104 | xfer->c_ata_c.bcount = sizeof(chp->recovery_blk); | 104 | xfer->c_ata_c.bcount = sizeof(chp->recovery_blk); | |
105 | 105 | |||
106 | if ((*atac->atac_bustype_ata->ata_exec_command)(drvp, | 106 | (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer); | |
107 | xfer) != ATACMD_COMPLETE) { | 107 | ata_wait_cmd(chp, xfer); | |
108 | rv = EAGAIN; | 108 | ||
109 | goto out; | |||
110 | } | |||
111 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 109 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
112 | rv = EINVAL; | 110 | rv = EINVAL; | |
113 | goto out; | 111 | goto out; | |
114 | } | 112 | } | |
115 | 113 | |||
116 | cksum = 0; | 114 | cksum = 0; | |
117 | for (int i = 0; i < sizeof(chp->recovery_blk); i++) | 115 | for (int i = 0; i < sizeof(chp->recovery_blk); i++) | |
118 | cksum += tb[i]; | 116 | cksum += tb[i]; | |
119 | if (cksum != 0) { | 117 | if (cksum != 0) { | |
120 | device_printf(drvp->drv_softc, | 118 | device_printf(drvp->drv_softc, | |
121 | "invalid checksum %x for READ LOG EXT page %x\n", | 119 | "invalid checksum %x for READ LOG EXT page %x\n", | |
122 | cksum, page); | 120 | cksum, page); | |
123 | rv = EINVAL; | 121 | rv = EINVAL; |
--- src/sys/dev/ata/ata_wdc.c 2018/11/12 18:51:01 1.113
+++ src/sys/dev/ata/ata_wdc.c 2022/12/30 14:39:10 1.113.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ata_wdc.c,v 1.113 2018/11/12 18:51:01 jdolecek Exp $ */ | 1 | /* $NetBSD: ata_wdc.c,v 1.113.4.1 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. | 4 | * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -44,27 +44,27 @@ | @@ -44,27 +44,27 @@ | |||
44 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 44 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
45 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 45 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
46 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 46 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
47 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 47 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
49 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 49 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
51 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 51 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
52 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 52 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
53 | * POSSIBILITY OF SUCH DAMAGE. | 53 | * POSSIBILITY OF SUCH DAMAGE. | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | #include <sys/cdefs.h> | 56 | #include <sys/cdefs.h> | |
57 | __KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.113 2018/11/12 18:51:01 jdolecek Exp $"); | 57 | __KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.113.4.1 2022/12/30 14:39:10 martin Exp $"); | |
58 | 58 | |||
59 | #include "opt_ata.h" | 59 | #include "opt_ata.h" | |
60 | #include "opt_wdc.h" | 60 | #include "opt_wdc.h" | |
61 | 61 | |||
62 | #include <sys/param.h> | 62 | #include <sys/param.h> | |
63 | #include <sys/systm.h> | 63 | #include <sys/systm.h> | |
64 | #include <sys/kernel.h> | 64 | #include <sys/kernel.h> | |
65 | #include <sys/file.h> | 65 | #include <sys/file.h> | |
66 | #include <sys/stat.h> | 66 | #include <sys/stat.h> | |
67 | #include <sys/buf.h> | 67 | #include <sys/buf.h> | |
68 | #include <sys/bufq.h> | 68 | #include <sys/bufq.h> | |
69 | #include <sys/device.h> | 69 | #include <sys/device.h> | |
70 | #include <sys/disklabel.h> | 70 | #include <sys/disklabel.h> | |
@@ -92,30 +92,30 @@ __KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v | @@ -92,30 +92,30 @@ __KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v | |||
92 | #define DEBUG_FUNCS 0x08 | 92 | #define DEBUG_FUNCS 0x08 | |
93 | #define DEBUG_PROBE 0x10 | 93 | #define DEBUG_PROBE 0x10 | |
94 | #ifdef ATADEBUG | 94 | #ifdef ATADEBUG | |
95 | extern int wdcdebug_wd_mask; /* inited in wd.c */ | 95 | extern int wdcdebug_wd_mask; /* inited in wd.c */ | |
96 | #define ATADEBUG_PRINT(args, level) \ | 96 | #define ATADEBUG_PRINT(args, level) \ | |
97 | if (wdcdebug_wd_mask & (level)) \ | 97 | if (wdcdebug_wd_mask & (level)) \ | |
98 | printf args | 98 | printf args | |
99 | #else | 99 | #else | |
100 | #define ATADEBUG_PRINT(args, level) | 100 | #define ATADEBUG_PRINT(args, level) | |
101 | #endif | 101 | #endif | |
102 | 102 | |||
103 | #define ATA_DELAY 10000 /* 10s for a drive I/O */ | 103 | #define ATA_DELAY 10000 /* 10s for a drive I/O */ | |
104 | 104 | |||
105 | static int wdc_ata_bio(struct ata_drive_datas*, struct ata_xfer *); | 105 | static void wdc_ata_bio(struct ata_drive_datas*, struct ata_xfer *); | |
106 | static int wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *); | 106 | static int wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *); | |
107 | static int _wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *); | 107 | static int _wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *); | |
108 | static void wdc_ata_bio_poll(struct ata_channel *,struct ata_xfer *); | 108 | static int wdc_ata_bio_poll(struct ata_channel *,struct ata_xfer *); | |
109 | static int wdc_ata_bio_intr(struct ata_channel *, struct ata_xfer *, | 109 | static int wdc_ata_bio_intr(struct ata_channel *, struct ata_xfer *, | |
110 | int); | 110 | int); | |
111 | static void wdc_ata_bio_kill_xfer(struct ata_channel *, | 111 | static void wdc_ata_bio_kill_xfer(struct ata_channel *, | |
112 | struct ata_xfer *, int); | 112 | struct ata_xfer *, int); | |
113 | static void wdc_ata_bio_done(struct ata_channel *, struct ata_xfer *); | 113 | static void wdc_ata_bio_done(struct ata_channel *, struct ata_xfer *); | |
114 | static int wdc_ata_err(struct ata_drive_datas *, struct ata_bio *, int); | 114 | static int wdc_ata_err(struct ata_drive_datas *, struct ata_bio *, int); | |
115 | #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */ | 115 | #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */ | |
116 | #define WDC_ATA_RECOV 0x01 /* There was a recovered error */ | 116 | #define WDC_ATA_RECOV 0x01 /* There was a recovered error */ | |
117 | #define WDC_ATA_ERR 0x02 /* Drive reports an error */ | 117 | #define WDC_ATA_ERR 0x02 /* Drive reports an error */ | |
118 | static int wdc_ata_addref(struct ata_drive_datas *); | 118 | static int wdc_ata_addref(struct ata_drive_datas *); | |
119 | static void wdc_ata_delref(struct ata_drive_datas *); | 119 | static void wdc_ata_delref(struct ata_drive_datas *); | |
120 | 120 | |||
121 | const struct ata_bustype wdc_ata_bustype = { | 121 | const struct ata_bustype wdc_ata_bustype = { | |
@@ -130,30 +130,29 @@ const struct ata_bustype wdc_ata_bustype | @@ -130,30 +130,29 @@ const struct ata_bustype wdc_ata_bustype | |||
130 | ata_kill_pending, | 130 | ata_kill_pending, | |
131 | NULL, | 131 | NULL, | |
132 | }; | 132 | }; | |
133 | 133 | |||
134 | static const struct ata_xfer_ops wdc_bio_xfer_ops = { | 134 | static const struct ata_xfer_ops wdc_bio_xfer_ops = { | |
135 | .c_start = wdc_ata_bio_start, | 135 | .c_start = wdc_ata_bio_start, | |
136 | .c_poll = wdc_ata_bio_poll, | 136 | .c_poll = wdc_ata_bio_poll, | |
137 | .c_abort = wdc_ata_bio_done, | 137 | .c_abort = wdc_ata_bio_done, | |
138 | .c_intr = wdc_ata_bio_intr, | 138 | .c_intr = wdc_ata_bio_intr, | |
139 | .c_kill_xfer = wdc_ata_bio_kill_xfer | 139 | .c_kill_xfer = wdc_ata_bio_kill_xfer | |
140 | }; | 140 | }; | |
141 | 141 | |||
142 | /* | 142 | /* | |
143 | * Handle block I/O operation. Return ATACMD_COMPLETE, ATACMD_QUEUED, or | 143 | * Handle block I/O operation. | |
144 | * ATACMD_TRY_AGAIN. Must be called at splbio(). | |||
145 | */ | 144 | */ | |
146 | static int | 145 | static void | |
147 | wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 146 | wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
148 | { | 147 | { | |
149 | struct ata_channel *chp = drvp->chnl_softc; | 148 | struct ata_channel *chp = drvp->chnl_softc; | |
150 | struct atac_softc *atac = chp->ch_atac; | 149 | struct atac_softc *atac = chp->ch_atac; | |
151 | struct ata_bio *ata_bio = &xfer->c_bio; | 150 | struct ata_bio *ata_bio = &xfer->c_bio; | |
152 | 151 | |||
153 | if (atac->atac_cap & ATAC_CAP_NOIRQ) | 152 | if (atac->atac_cap & ATAC_CAP_NOIRQ) | |
154 | ata_bio->flags |= ATA_POLL; | 153 | ata_bio->flags |= ATA_POLL; | |
155 | if (ata_bio->flags & ATA_POLL) | 154 | if (ata_bio->flags & ATA_POLL) | |
156 | xfer->c_flags |= C_POLL; | 155 | xfer->c_flags |= C_POLL; | |
157 | #if NATA_DMA | 156 | #if NATA_DMA | |
158 | if ((drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && | 157 | if ((drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && | |
159 | (ata_bio->flags & ATA_SINGLE) == 0) | 158 | (ata_bio->flags & ATA_SINGLE) == 0) | |
@@ -161,27 +160,26 @@ wdc_ata_bio(struct ata_drive_datas *drvp | @@ -161,27 +160,26 @@ wdc_ata_bio(struct ata_drive_datas *drvp | |||
161 | #endif | 160 | #endif | |
162 | #if NATA_DMA && NATA_PIOBM | 161 | #if NATA_DMA && NATA_PIOBM | |
163 | else | 162 | else | |
164 | #endif | 163 | #endif | |
165 | #if NATA_PIOBM | 164 | #if NATA_PIOBM | |
166 | if (atac->atac_cap & ATAC_CAP_PIOBM) | 165 | if (atac->atac_cap & ATAC_CAP_PIOBM) | |
167 | xfer->c_flags |= C_PIOBM; | 166 | xfer->c_flags |= C_PIOBM; | |
168 | #endif | 167 | #endif | |
169 | xfer->c_drive = drvp->drive; | 168 | xfer->c_drive = drvp->drive; | |
170 | xfer->c_databuf = ata_bio->databuf; | 169 | xfer->c_databuf = ata_bio->databuf; | |
171 | xfer->c_bcount = ata_bio->bcount; | 170 | xfer->c_bcount = ata_bio->bcount; | |
172 | xfer->ops = &wdc_bio_xfer_ops; | 171 | xfer->ops = &wdc_bio_xfer_ops; | |
173 | ata_exec_xfer(chp, xfer); | 172 | ata_exec_xfer(chp, xfer); | |
174 | return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED; | |||
175 | } | 173 | } | |
176 | 174 | |||
177 | static int | 175 | static int | |
178 | wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | 176 | wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
179 | { | 177 | { | |
180 | struct atac_softc *atac = chp->ch_atac; | 178 | struct atac_softc *atac = chp->ch_atac; | |
181 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 179 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
182 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | 180 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | |
183 | struct ata_bio *ata_bio = &xfer->c_bio; | 181 | struct ata_bio *ata_bio = &xfer->c_bio; | |
184 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | 182 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | |
185 | int wait_flags, tfd; | 183 | int wait_flags, tfd; | |
186 | const char *errstring; | 184 | const char *errstring; | |
187 | #ifdef WDC_NO_IDS | 185 | #ifdef WDC_NO_IDS | |
@@ -607,38 +605,39 @@ intr: | @@ -607,38 +605,39 @@ intr: | |||
607 | } else { | 605 | } else { | |
608 | return ATASTART_POLL; | 606 | return ATASTART_POLL; | |
609 | } | 607 | } | |
610 | 608 | |||
611 | timeout: | 609 | timeout: | |
612 | printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n", | 610 | printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n", | |
613 | device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, | 611 | device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, | |
614 | ATACH_ST(tfd), ATACH_ERR(tfd)); | 612 | ATACH_ST(tfd), ATACH_ERR(tfd)); | |
615 | if (wdc_ata_err(drvp, ata_bio, tfd) != WDC_ATA_ERR) | 613 | if (wdc_ata_err(drvp, ata_bio, tfd) != WDC_ATA_ERR) | |
616 | ata_bio->error = TIMEOUT; | 614 | ata_bio->error = TIMEOUT; | |
617 | return ATASTART_ABORT; | 615 | return ATASTART_ABORT; | |
618 | } | 616 | } | |
619 | 617 | |||
620 | static void | 618 | static int | |
621 | wdc_ata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 619 | wdc_ata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
622 | { | 620 | { | |
623 | /* Wait for at last 400ns for status bit to be valid */ | 621 | /* Wait for at last 400ns for status bit to be valid */ | |
624 | delay(1); | 622 | delay(1); | |
625 | #if NATA_DMA | 623 | #if NATA_DMA | |
626 | if (chp->ch_flags & ATACH_DMA_WAIT) { | 624 | if (chp->ch_flags & ATACH_DMA_WAIT) { | |
627 | wdc_dmawait(chp, xfer, ATA_DELAY); | 625 | wdc_dmawait(chp, xfer, ATA_DELAY); | |
628 | chp->ch_flags &= ~ATACH_DMA_WAIT; | 626 | chp->ch_flags &= ~ATACH_DMA_WAIT; | |
629 | } | 627 | } | |
630 | #endif | 628 | #endif | |
631 | wdc_ata_bio_intr(chp, xfer, 0); | 629 | wdc_ata_bio_intr(chp, xfer, 0); | |
630 | return (xfer->c_bio.flags & ATA_ITSDONE) ? ATAPOLL_DONE : ATAPOLL_AGAIN; | |||
632 | } | 631 | } | |
633 | 632 | |||
634 | static int | 633 | static int | |
635 | wdc_ata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | 634 | wdc_ata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | |
636 | { | 635 | { | |
637 | struct atac_softc *atac = chp->ch_atac; | 636 | struct atac_softc *atac = chp->ch_atac; | |
638 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 637 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
639 | struct ata_bio *ata_bio = &xfer->c_bio; | 638 | struct ata_bio *ata_bio = &xfer->c_bio; | |
640 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | 639 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | |
641 | int drv_err, tfd; | 640 | int drv_err, tfd; | |
642 | 641 | |||
643 | ATADEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n", | 642 | ATADEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n", | |
644 | device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive), | 643 | device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive), | |
@@ -769,27 +768,30 @@ wdc_ata_bio_intr(struct ata_channel *chp | @@ -769,27 +768,30 @@ wdc_ata_bio_intr(struct ata_channel *chp | |||
769 | end: | 768 | end: | |
770 | #endif | 769 | #endif | |
771 | ata_bio->blkno += ata_bio->nblks; | 770 | ata_bio->blkno += ata_bio->nblks; | |
772 | ata_bio->blkdone += ata_bio->nblks; | 771 | ata_bio->blkdone += ata_bio->nblks; | |
773 | xfer->c_skip += ata_bio->nbytes; | 772 | xfer->c_skip += ata_bio->nbytes; | |
774 | xfer->c_bcount -= ata_bio->nbytes; | 773 | xfer->c_bcount -= ata_bio->nbytes; | |
775 | 774 | |||
776 | /* See if this transfer is complete. */ | 775 | /* See if this transfer is complete. */ | |
777 | if (xfer->c_bcount > 0) { | 776 | if (xfer->c_bcount > 0) { | |
778 | if ((ata_bio->flags & ATA_POLL) == 0) { | 777 | if ((ata_bio->flags & ATA_POLL) == 0) { | |
779 | /* Start the next operation */ | 778 | /* Start the next operation */ | |
780 | ata_xfer_start(xfer); | 779 | ata_xfer_start(xfer); | |
781 | } else { | 780 | } else { | |
782 | /* Let _wdc_ata_bio_start do the loop */ | 781 | /* | |
782 | * Let ata_xfer_start() do the loop; | |||
783 | * see wdc_ata_bio_poll(). | |||
784 | */ | |||
783 | } | 785 | } | |
784 | ata_channel_unlock(chp); | 786 | ata_channel_unlock(chp); | |
785 | return 1; | 787 | return 1; | |
786 | } | 788 | } | |
787 | 789 | |||
788 | /* Done with this transfer */ | 790 | /* Done with this transfer */ | |
789 | ata_bio->error = NOERROR; | 791 | ata_bio->error = NOERROR; | |
790 | err: ata_channel_unlock(chp); | 792 | err: ata_channel_unlock(chp); | |
791 | wdc_ata_bio_done(chp, xfer); | 793 | wdc_ata_bio_done(chp, xfer); | |
792 | return 1; | 794 | return 1; | |
793 | } | 795 | } | |
794 | 796 | |||
795 | static void | 797 | static void |
--- src/sys/dev/ata/atavar.h 2019/04/05 21:31:44 1.103
+++ src/sys/dev/ata/atavar.h 2022/12/30 14:39:10 1.103.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: atavar.h,v 1.103 2019/04/05 21:31:44 bouyer Exp $ */ | 1 | /* $NetBSD: atavar.h,v 1.103.4.1 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001 Manuel Bouyer. | 4 | * Copyright (c) 1998, 2001 Manuel Bouyer. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -168,27 +168,29 @@ struct ata_xfer { | @@ -168,27 +168,29 @@ struct ata_xfer { | |||
168 | /* Links for error handling */ | 168 | /* Links for error handling */ | |
169 | SLIST_ENTRY(ata_xfer) c_retrychain; | 169 | SLIST_ENTRY(ata_xfer) c_retrychain; | |
170 | 170 | |||
171 | /* Low-level protocol handlers. */ | 171 | /* Low-level protocol handlers. */ | |
172 | const struct ata_xfer_ops *ops; | 172 | const struct ata_xfer_ops *ops; | |
173 | }; | 173 | }; | |
174 | 174 | |||
175 | struct ata_xfer_ops { | 175 | struct ata_xfer_ops { | |
176 | int (*c_start)(struct ata_channel *, struct ata_xfer *); | 176 | int (*c_start)(struct ata_channel *, struct ata_xfer *); | |
177 | #define ATASTART_STARTED 0 /* xfer started, waiting for intr */ | 177 | #define ATASTART_STARTED 0 /* xfer started, waiting for intr */ | |
178 | #define ATASTART_TH 1 /* xfer needs to be run in thread */ | 178 | #define ATASTART_TH 1 /* xfer needs to be run in thread */ | |
179 | #define ATASTART_POLL 2 /* xfer needs to be polled */ | 179 | #define ATASTART_POLL 2 /* xfer needs to be polled */ | |
180 | #define ATASTART_ABORT 3 /* error occurred, abort xfer */ | 180 | #define ATASTART_ABORT 3 /* error occurred, abort xfer */ | |
181 | void (*c_poll)(struct ata_channel *, struct ata_xfer *); | 181 | int (*c_poll)(struct ata_channel *, struct ata_xfer *); | |
182 | #define ATAPOLL_DONE 0 | |||
183 | #define ATAPOLL_AGAIN 1 | |||
182 | void (*c_abort)(struct ata_channel *, struct ata_xfer *); | 184 | void (*c_abort)(struct ata_channel *, struct ata_xfer *); | |
183 | int (*c_intr)(struct ata_channel *, struct ata_xfer *, int); | 185 | int (*c_intr)(struct ata_channel *, struct ata_xfer *, int); | |
184 | void (*c_kill_xfer)(struct ata_channel *, struct ata_xfer *, int); | 186 | void (*c_kill_xfer)(struct ata_channel *, struct ata_xfer *, int); | |
185 | }; | 187 | }; | |
186 | 188 | |||
187 | /* flags in c_flags */ | 189 | /* flags in c_flags */ | |
188 | #define C_ATAPI 0x0001 /* xfer is ATAPI request */ | 190 | #define C_ATAPI 0x0001 /* xfer is ATAPI request */ | |
189 | #define C_TIMEOU 0x0002 /* xfer processing timed out */ | 191 | #define C_TIMEOU 0x0002 /* xfer processing timed out */ | |
190 | #define C_POLL 0x0004 /* command is polled */ | 192 | #define C_POLL 0x0004 /* command is polled */ | |
191 | #define C_DMA 0x0008 /* command uses DMA */ | 193 | #define C_DMA 0x0008 /* command uses DMA */ | |
192 | #define C_WAIT 0x0010 /* can use kpause */ | 194 | #define C_WAIT 0x0010 /* can use kpause */ | |
193 | #define C_WAITACT 0x0020 /* wakeup when active */ | 195 | #define C_WAITACT 0x0020 /* wakeup when active */ | |
194 | #define C_FREE 0x0040 /* call ata_free_xfer() asap */ | 196 | #define C_FREE 0x0040 /* call ata_free_xfer() asap */ | |
@@ -348,30 +350,30 @@ struct ata_drive_datas { | @@ -348,30 +350,30 @@ struct ata_drive_datas { | |||
348 | #define ATA_CONFIG_DMA_DISABLE 0x0070 | 350 | #define ATA_CONFIG_DMA_DISABLE 0x0070 | |
349 | #define ATA_CONFIG_DMA_OFF 4 | 351 | #define ATA_CONFIG_DMA_OFF 4 | |
350 | #define ATA_CONFIG_UDMA_MODES 0x0700 | 352 | #define ATA_CONFIG_UDMA_MODES 0x0700 | |
351 | #define ATA_CONFIG_UDMA_SET 0x0800 | 353 | #define ATA_CONFIG_UDMA_SET 0x0800 | |
352 | #define ATA_CONFIG_UDMA_DISABLE 0x0700 | 354 | #define ATA_CONFIG_UDMA_DISABLE 0x0700 | |
353 | #define ATA_CONFIG_UDMA_OFF 8 | 355 | #define ATA_CONFIG_UDMA_OFF 8 | |
354 | 356 | |||
355 | /* | 357 | /* | |
356 | * ata_bustype. The first field must be compatible with scsipi_bustype, | 358 | * ata_bustype. The first field must be compatible with scsipi_bustype, | |
357 | * as it's used for autoconfig by both ata and atapi drivers. | 359 | * as it's used for autoconfig by both ata and atapi drivers. | |
358 | */ | 360 | */ | |
359 | struct ata_bustype { | 361 | struct ata_bustype { | |
360 | int bustype_type; /* symbolic name of type */ | 362 | int bustype_type; /* symbolic name of type */ | |
361 | int (*ata_bio)(struct ata_drive_datas *, struct ata_xfer *); | 363 | void (*ata_bio)(struct ata_drive_datas *, struct ata_xfer *); | |
362 | void (*ata_reset_drive)(struct ata_drive_datas *, int, uint32_t *); | 364 | void (*ata_reset_drive)(struct ata_drive_datas *, int, uint32_t *); | |
363 | void (*ata_reset_channel)(struct ata_channel *, int); | 365 | void (*ata_reset_channel)(struct ata_channel *, int); | |
364 | int (*ata_exec_command)(struct ata_drive_datas *, | 366 | void (*ata_exec_command)(struct ata_drive_datas *, | |
365 | struct ata_xfer *); | 367 | struct ata_xfer *); | |
366 | 368 | |||
367 | #define ATACMD_COMPLETE 0x01 | 369 | #define ATACMD_COMPLETE 0x01 | |
368 | #define ATACMD_QUEUED 0x02 | 370 | #define ATACMD_QUEUED 0x02 | |
369 | #define ATACMD_TRY_AGAIN 0x03 | 371 | #define ATACMD_TRY_AGAIN 0x03 | |
370 | 372 | |||
371 | int (*ata_get_params)(struct ata_drive_datas *, uint8_t, | 373 | int (*ata_get_params)(struct ata_drive_datas *, uint8_t, | |
372 | struct ataparams *); | 374 | struct ataparams *); | |
373 | int (*ata_addref)(struct ata_drive_datas *); | 375 | int (*ata_addref)(struct ata_drive_datas *); | |
374 | void (*ata_delref)(struct ata_drive_datas *); | 376 | void (*ata_delref)(struct ata_drive_datas *); | |
375 | void (*ata_killpending)(struct ata_drive_datas *); | 377 | void (*ata_killpending)(struct ata_drive_datas *); | |
376 | void (*ata_recovery)(struct ata_channel *, int, uint32_t); | 378 | void (*ata_recovery)(struct ata_channel *, int, uint32_t); | |
377 | }; | 379 | }; |
--- src/sys/dev/ata/satapmp_subr.c 2018/10/22 20:13:47 1.15
+++ src/sys/dev/ata/satapmp_subr.c 2022/12/30 14:39:10 1.15.4.1
@@ -1,41 +1,41 @@ | @@ -1,41 +1,41 @@ | |||
1 | /* $NetBSD: satapmp_subr.c,v 1.15 2018/10/22 20:13:47 jdolecek Exp $ */ | 1 | /* $NetBSD: satapmp_subr.c,v 1.15.4.1 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2012 Manuel Bouyer. All rights reserved. | 4 | * Copyright (c) 2012 Manuel Bouyer. All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | */ | 25 | */ | |
26 | 26 | |||
27 | #include <sys/cdefs.h> | 27 | #include <sys/cdefs.h> | |
28 | __KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.15 2018/10/22 20:13:47 jdolecek Exp $"); | 28 | __KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.15.4.1 2022/12/30 14:39:10 martin Exp $"); | |
29 | 29 | |||
30 | #include <sys/param.h> | 30 | #include <sys/param.h> | |
31 | #include <sys/systm.h> | 31 | #include <sys/systm.h> | |
32 | #include <sys/kernel.h> | 32 | #include <sys/kernel.h> | |
33 | #include <sys/device.h> | 33 | #include <sys/device.h> | |
34 | #include <sys/conf.h> | 34 | #include <sys/conf.h> | |
35 | #include <sys/fcntl.h> | 35 | #include <sys/fcntl.h> | |
36 | #include <sys/proc.h> | 36 | #include <sys/proc.h> | |
37 | #include <sys/errno.h> | 37 | #include <sys/errno.h> | |
38 | #include <sys/kmem.h> | 38 | #include <sys/kmem.h> | |
39 | #include <sys/intr.h> | 39 | #include <sys/intr.h> | |
40 | 40 | |||
41 | #include <dev/ata/ataconf.h> | 41 | #include <dev/ata/ataconf.h> | |
@@ -62,33 +62,30 @@ satapmp_read_8(struct ata_channel *chp, | @@ -62,33 +62,30 @@ satapmp_read_8(struct ata_channel *chp, | |||
62 | KASSERT(drvp->drive == PMP_PORT_CTL); | 62 | KASSERT(drvp->drive == PMP_PORT_CTL); | |
63 | ata_channel_lock_owned(chp); | 63 | ata_channel_lock_owned(chp); | |
64 | 64 | |||
65 | memset(xfer, 0, sizeof(*xfer)); | 65 | memset(xfer, 0, sizeof(*xfer)); | |
66 | xfer->c_ata_c.r_command = PMPC_READ_PORT; | 66 | xfer->c_ata_c.r_command = PMPC_READ_PORT; | |
67 | xfer->c_ata_c.r_features = reg; | 67 | xfer->c_ata_c.r_features = reg; | |
68 | xfer->c_ata_c.r_device = port; | 68 | xfer->c_ata_c.r_device = port; | |
69 | xfer->c_ata_c.timeout = 3000; /* 3s */ | 69 | xfer->c_ata_c.timeout = 3000; /* 3s */ | |
70 | xfer->c_ata_c.r_st_bmask = 0; | 70 | xfer->c_ata_c.r_st_bmask = 0; | |
71 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 71 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
72 | xfer->c_ata_c.flags = AT_LBA48 | AT_READREG | AT_WAIT; | 72 | xfer->c_ata_c.flags = AT_LBA48 | AT_READREG | AT_WAIT; | |
73 | 73 | |||
74 | ata_channel_unlock(chp); | 74 | ata_channel_unlock(chp); | |
75 | if ((*atac->atac_bustype_ata->ata_exec_command)(drvp, | 75 | ||
76 | xfer) != ATACMD_COMPLETE) { | 76 | (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer); | |
77 | aprint_error_dev(chp->atabus, | 77 | ata_wait_cmd(chp, xfer); | |
78 | "PMP port %d register %d read failed\n", port, reg); | 78 | ||
79 | error = EIO; | |||
80 | goto out; | |||
81 | } | |||
82 | if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) { | 79 | if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) { | |
83 | aprint_error_dev(chp->atabus, | 80 | aprint_error_dev(chp->atabus, | |
84 | "PMP port %d register %d read failed, flags 0x%x\n", | 81 | "PMP port %d register %d read failed, flags 0x%x\n", | |
85 | port, reg, xfer->c_ata_c.flags); | 82 | port, reg, xfer->c_ata_c.flags); | |
86 | error = EIO; | 83 | error = EIO; | |
87 | goto out; | 84 | goto out; | |
88 | } | 85 | } | |
89 | if (xfer->c_ata_c.flags & AT_ERROR) { | 86 | if (xfer->c_ata_c.flags & AT_ERROR) { | |
90 | aprint_verbose_dev(chp->atabus, | 87 | aprint_verbose_dev(chp->atabus, | |
91 | "PMP port %d register %d read failed, error 0x%x\n", | 88 | "PMP port %d register %d read failed, error 0x%x\n", | |
92 | port, reg, xfer->c_ata_c.r_error); | 89 | port, reg, xfer->c_ata_c.r_error); | |
93 | error = EIO; | 90 | error = EIO; | |
94 | goto out; | 91 | goto out; | |
@@ -138,33 +135,30 @@ satapmp_write_8(struct ata_channel *chp, | @@ -138,33 +135,30 @@ satapmp_write_8(struct ata_channel *chp, | |||
138 | xfer->c_ata_c.r_command = PMPC_WRITE_PORT; | 135 | xfer->c_ata_c.r_command = PMPC_WRITE_PORT; | |
139 | xfer->c_ata_c.r_features = reg; | 136 | xfer->c_ata_c.r_features = reg; | |
140 | xfer->c_ata_c.r_device = port; | 137 | xfer->c_ata_c.r_device = port; | |
141 | xfer->c_ata_c.r_lba = (((value >> 40) & 0xffffff) << 24) | | 138 | xfer->c_ata_c.r_lba = (((value >> 40) & 0xffffff) << 24) | | |
142 | (((value >> 8) & 0xffffff) << 0); | 139 | (((value >> 8) & 0xffffff) << 0); | |
143 | xfer->c_ata_c.r_count = (((value >> 32) & 0xff) << 8) | | 140 | xfer->c_ata_c.r_count = (((value >> 32) & 0xff) << 8) | | |
144 | (((value >> 0) & 0xff) << 0); | 141 | (((value >> 0) & 0xff) << 0); | |
145 | xfer->c_ata_c.timeout = 3000; /* 3s */ | 142 | xfer->c_ata_c.timeout = 3000; /* 3s */ | |
146 | xfer->c_ata_c.r_st_bmask = 0; | 143 | xfer->c_ata_c.r_st_bmask = 0; | |
147 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 144 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
148 | xfer->c_ata_c.flags = AT_LBA48 | AT_WAIT; | 145 | xfer->c_ata_c.flags = AT_LBA48 | AT_WAIT; | |
149 | 146 | |||
150 | ata_channel_unlock(chp); | 147 | ata_channel_unlock(chp); | |
151 | if ((*atac->atac_bustype_ata->ata_exec_command)(drvp, | 148 | ||
152 | xfer) != ATACMD_COMPLETE) { | 149 | (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer); | |
153 | aprint_error_dev(chp->atabus, | 150 | ata_wait_cmd(chp, xfer); | |
154 | "PMP port %d register %d write failed\n", port, reg); | 151 | ||
155 | error = EIO; | |||
156 | goto out; | |||
157 | } | |||
158 | if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) { | 152 | if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) { | |
159 | aprint_error_dev(chp->atabus, | 153 | aprint_error_dev(chp->atabus, | |
160 | "PMP port %d register %d write failed, flags 0x%x\n", | 154 | "PMP port %d register %d write failed, flags 0x%x\n", | |
161 | port, reg, xfer->c_ata_c.flags); | 155 | port, reg, xfer->c_ata_c.flags); | |
162 | error = EIO; | 156 | error = EIO; | |
163 | goto out; | 157 | goto out; | |
164 | } | 158 | } | |
165 | if (xfer->c_ata_c.flags & AT_ERROR) { | 159 | if (xfer->c_ata_c.flags & AT_ERROR) { | |
166 | aprint_verbose_dev(chp->atabus, | 160 | aprint_verbose_dev(chp->atabus, | |
167 | "PMP port %d register %d write failed, error 0x%x\n", | 161 | "PMP port %d register %d write failed, error 0x%x\n", | |
168 | port, reg, xfer->c_ata_c.r_error); | 162 | port, reg, xfer->c_ata_c.r_error); | |
169 | error = EIO; | 163 | error = EIO; | |
170 | goto out; | 164 | goto out; |
--- src/sys/dev/ata/wd.c 2020/03/21 15:52:09 1.452.2.2
+++ src/sys/dev/ata/wd.c 2022/12/30 14:39:10 1.452.2.3
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: wd.c,v 1.452.2.2 2020/03/21 15:52:09 martin Exp $ */ | 1 | /* $NetBSD: wd.c,v 1.452.2.3 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | 4 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -44,27 +44,27 @@ | @@ -44,27 +44,27 @@ | |||
44 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 44 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
45 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 45 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
46 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 46 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
47 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 47 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
49 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 49 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
51 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 51 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
52 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 52 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
53 | * POSSIBILITY OF SUCH DAMAGE. | 53 | * POSSIBILITY OF SUCH DAMAGE. | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | #include <sys/cdefs.h> | 56 | #include <sys/cdefs.h> | |
57 | __KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452.2.2 2020/03/21 15:52:09 martin Exp $"); | 57 | __KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452.2.3 2022/12/30 14:39:10 martin Exp $"); | |
58 | 58 | |||
59 | #include "opt_ata.h" | 59 | #include "opt_ata.h" | |
60 | #include "opt_wd.h" | 60 | #include "opt_wd.h" | |
61 | 61 | |||
62 | #include <sys/param.h> | 62 | #include <sys/param.h> | |
63 | #include <sys/systm.h> | 63 | #include <sys/systm.h> | |
64 | #include <sys/kernel.h> | 64 | #include <sys/kernel.h> | |
65 | #include <sys/conf.h> | 65 | #include <sys/conf.h> | |
66 | #include <sys/file.h> | 66 | #include <sys/file.h> | |
67 | #include <sys/stat.h> | 67 | #include <sys/stat.h> | |
68 | #include <sys/ioctl.h> | 68 | #include <sys/ioctl.h> | |
69 | #include <sys/buf.h> | 69 | #include <sys/buf.h> | |
70 | #include <sys/bufq.h> | 70 | #include <sys/bufq.h> | |
@@ -191,27 +191,27 @@ static struct wd_ioctl *wi_find(struct b | @@ -191,27 +191,27 @@ static struct wd_ioctl *wi_find(struct b | |||
191 | static void wi_free(struct wd_ioctl *); | 191 | static void wi_free(struct wd_ioctl *); | |
192 | static struct wd_ioctl *wi_get(struct wd_softc *); | 192 | static struct wd_ioctl *wi_get(struct wd_softc *); | |
193 | static void wdioctlstrategy(struct buf *); | 193 | static void wdioctlstrategy(struct buf *); | |
194 | 194 | |||
195 | static void wdrestart(void *); | 195 | static void wdrestart(void *); | |
196 | static void wdstart1(struct wd_softc *, struct buf *, struct ata_xfer *); | 196 | static void wdstart1(struct wd_softc *, struct buf *, struct ata_xfer *); | |
197 | static int wd_diskstart(device_t, struct buf *); | 197 | static int wd_diskstart(device_t, struct buf *); | |
198 | static int wd_dumpblocks(device_t, void *, daddr_t, int); | 198 | static int wd_dumpblocks(device_t, void *, daddr_t, int); | |
199 | static void wd_iosize(device_t, int *); | 199 | static void wd_iosize(device_t, int *); | |
200 | static int wd_discard(device_t, off_t, off_t); | 200 | static int wd_discard(device_t, off_t, off_t); | |
201 | static void wdbioretry(void *); | 201 | static void wdbioretry(void *); | |
202 | static void wdbiorequeue(void *); | 202 | static void wdbiorequeue(void *); | |
203 | static void wddone(device_t, struct ata_xfer *); | 203 | static void wddone(device_t, struct ata_xfer *); | |
204 | static int wd_get_params(struct wd_softc *, uint8_t, struct ataparams *); | 204 | static int wd_get_params(struct wd_softc *, struct ataparams *); | |
205 | static void wd_set_geometry(struct wd_softc *); | 205 | static void wd_set_geometry(struct wd_softc *); | |
206 | static int wd_flushcache(struct wd_softc *, int, bool); | 206 | static int wd_flushcache(struct wd_softc *, int, bool); | |
207 | static int wd_trim(struct wd_softc *, daddr_t, long); | 207 | static int wd_trim(struct wd_softc *, daddr_t, long); | |
208 | static bool wd_shutdown(device_t, int); | 208 | static bool wd_shutdown(device_t, int); | |
209 | 209 | |||
210 | static int wd_getcache(struct wd_softc *, int *); | 210 | static int wd_getcache(struct wd_softc *, int *); | |
211 | static int wd_setcache(struct wd_softc *, int); | 211 | static int wd_setcache(struct wd_softc *, int); | |
212 | 212 | |||
213 | static void wd_sysctl_attach(struct wd_softc *); | 213 | static void wd_sysctl_attach(struct wd_softc *); | |
214 | static void wd_sysctl_detach(struct wd_softc *); | 214 | static void wd_sysctl_detach(struct wd_softc *); | |
215 | 215 | |||
216 | struct dkdriver wddkdriver = { | 216 | struct dkdriver wddkdriver = { | |
217 | .d_open = wdopen, | 217 | .d_open = wdopen, | |
@@ -329,27 +329,27 @@ wdattach(device_t parent, device_t self, | @@ -329,27 +329,27 @@ wdattach(device_t parent, device_t self, | |||
329 | wd->drvp->drv_softc = dksc->sc_dev; /* done in atabusconfig_thread() | 329 | wd->drvp->drv_softc = dksc->sc_dev; /* done in atabusconfig_thread() | |
330 | but too late */ | 330 | but too late */ | |
331 | 331 | |||
332 | SLIST_INIT(&wd->sc_retry_list); | 332 | SLIST_INIT(&wd->sc_retry_list); | |
333 | SLIST_INIT(&wd->sc_requeue_list); | 333 | SLIST_INIT(&wd->sc_requeue_list); | |
334 | callout_init(&wd->sc_retry_callout, 0); /* XXX MPSAFE */ | 334 | callout_init(&wd->sc_retry_callout, 0); /* XXX MPSAFE */ | |
335 | callout_init(&wd->sc_requeue_callout, 0); /* XXX MPSAFE */ | 335 | callout_init(&wd->sc_requeue_callout, 0); /* XXX MPSAFE */ | |
336 | callout_init(&wd->sc_restart_diskqueue, 0); /* XXX MPSAFE */ | 336 | callout_init(&wd->sc_restart_diskqueue, 0); /* XXX MPSAFE */ | |
337 | 337 | |||
338 | aprint_naive("\n"); | 338 | aprint_naive("\n"); | |
339 | aprint_normal("\n"); | 339 | aprint_normal("\n"); | |
340 | 340 | |||
341 | /* read our drive info */ | 341 | /* read our drive info */ | |
342 | if (wd_get_params(wd, AT_WAIT, &wd->sc_params) != 0) { | 342 | if (wd_get_params(wd, &wd->sc_params) != 0) { | |
343 | aprint_error_dev(self, "IDENTIFY failed\n"); | 343 | aprint_error_dev(self, "IDENTIFY failed\n"); | |
344 | goto out; | 344 | goto out; | |
345 | } | 345 | } | |
346 | 346 | |||
347 | for (blank = 0, p = wd->sc_params.atap_model, q = tbuf, i = 0; | 347 | for (blank = 0, p = wd->sc_params.atap_model, q = tbuf, i = 0; | |
348 | i < sizeof(wd->sc_params.atap_model); i++) { | 348 | i < sizeof(wd->sc_params.atap_model); i++) { | |
349 | c = *p++; | 349 | c = *p++; | |
350 | if (c == '\0') | 350 | if (c == '\0') | |
351 | break; | 351 | break; | |
352 | if (c != ' ') { | 352 | if (c != ' ') { | |
353 | if (blank) { | 353 | if (blank) { | |
354 | *q++ = ' '; | 354 | *q++ = ' '; | |
355 | blank = 0; | 355 | blank = 0; | |
@@ -659,26 +659,27 @@ wdstrategy(struct buf *bp) | @@ -659,26 +659,27 @@ wdstrategy(struct buf *bp) | |||
659 | err: | 659 | err: | |
660 | bp->b_error = EIO; | 660 | bp->b_error = EIO; | |
661 | bp->b_resid = bp->b_bcount; | 661 | bp->b_resid = bp->b_bcount; | |
662 | biodone(bp); | 662 | biodone(bp); | |
663 | } | 663 | } | |
664 | 664 | |||
665 | static void | 665 | static void | |
666 | wdstart1(struct wd_softc *wd, struct buf *bp, struct ata_xfer *xfer) | 666 | wdstart1(struct wd_softc *wd, struct buf *bp, struct ata_xfer *xfer) | |
667 | { | 667 | { | |
668 | struct dk_softc *dksc = &wd->sc_dksc; | 668 | struct dk_softc *dksc = &wd->sc_dksc; | |
669 | 669 | |||
670 | KASSERT(bp == xfer->c_bio.bp || xfer->c_bio.bp == NULL); | 670 | KASSERT(bp == xfer->c_bio.bp || xfer->c_bio.bp == NULL); | |
671 | KASSERT((xfer->c_flags & (C_WAITACT|C_FREE)) == 0); | 671 | KASSERT((xfer->c_flags & (C_WAITACT|C_FREE)) == 0); | |
672 | KASSERT(mutex_owned(&wd->sc_lock)); | |||
672 | 673 | |||
673 | /* Reset state, so that retries don't use stale info */ | 674 | /* Reset state, so that retries don't use stale info */ | |
674 | if (__predict_false(xfer->c_retries > 0)) { | 675 | if (__predict_false(xfer->c_retries > 0)) { | |
675 | xfer->c_flags = 0; | 676 | xfer->c_flags = 0; | |
676 | memset(&xfer->c_bio, 0, sizeof(xfer->c_bio)); | 677 | memset(&xfer->c_bio, 0, sizeof(xfer->c_bio)); | |
677 | } | 678 | } | |
678 | 679 | |||
679 | xfer->c_bio.blkno = bp->b_rawblkno; | 680 | xfer->c_bio.blkno = bp->b_rawblkno; | |
680 | xfer->c_bio.bcount = bp->b_bcount; | 681 | xfer->c_bio.bcount = bp->b_bcount; | |
681 | xfer->c_bio.databuf = bp->b_data; | 682 | xfer->c_bio.databuf = bp->b_data; | |
682 | xfer->c_bio.blkdone = 0; | 683 | xfer->c_bio.blkdone = 0; | |
683 | xfer->c_bio.bp = bp; | 684 | xfer->c_bio.bp = bp; | |
684 | 685 | |||
@@ -750,36 +751,32 @@ wdstart1(struct wd_softc *wd, struct buf | @@ -750,36 +751,32 @@ wdstart1(struct wd_softc *wd, struct buf | |||
750 | wd->sc_flags |= WDF_DIRTY; | 751 | wd->sc_flags |= WDF_DIRTY; | |
751 | } | 752 | } | |
752 | if (bp->b_flags & B_MEDIA_FUA) { | 753 | if (bp->b_flags & B_MEDIA_FUA) { | |
753 | /* If not using NCQ, the command WRITE DMA FUA EXT is LBA48 */ | 754 | /* If not using NCQ, the command WRITE DMA FUA EXT is LBA48 */ | |
754 | KASSERT((wd->sc_flags & WDF_LBA48) != 0); | 755 | KASSERT((wd->sc_flags & WDF_LBA48) != 0); | |
755 | if ((xfer->c_flags & C_NCQ) == 0) | 756 | if ((xfer->c_flags & C_NCQ) == 0) | |
756 | xfer->c_bio.flags |= ATA_LBA48; | 757 | xfer->c_bio.flags |= ATA_LBA48; | |
757 | 758 | |||
758 | xfer->c_bio.flags |= ATA_FUA; | 759 | xfer->c_bio.flags |= ATA_FUA; | |
759 | } | 760 | } | |
760 | 761 | |||
761 | if (xfer->c_retries == 0) | 762 | if (xfer->c_retries == 0) | |
762 | wd->inflight++; | 763 | wd->inflight++; | |
763 | switch (wd->atabus->ata_bio(wd->drvp, xfer)) { | 764 | mutex_exit(&wd->sc_lock); | |
764 | case ATACMD_TRY_AGAIN: | 765 | ||
765 | panic("wdstart1: try again"); | 766 | /* Queue the xfer */ | |
766 | break; | 767 | wd->atabus->ata_bio(wd->drvp, xfer); | |
767 | case ATACMD_QUEUED: | 768 | ||
768 | case ATACMD_COMPLETE: | 769 | mutex_enter(&wd->sc_lock); | |
769 | break; | |||
770 | default: | |||
771 | panic("wdstart1: bad return code from ata_bio()"); | |||
772 | } | |||
773 | } | 770 | } | |
774 | 771 | |||
775 | static int | 772 | static int | |
776 | wd_diskstart(device_t dev, struct buf *bp) | 773 | wd_diskstart(device_t dev, struct buf *bp) | |
777 | { | 774 | { | |
778 | struct wd_softc *wd = device_private(dev); | 775 | struct wd_softc *wd = device_private(dev); | |
779 | #ifdef ATADEBUG | 776 | #ifdef ATADEBUG | |
780 | struct dk_softc *dksc = &wd->sc_dksc; | 777 | struct dk_softc *dksc = &wd->sc_dksc; | |
781 | #endif | 778 | #endif | |
782 | struct ata_xfer *xfer; | 779 | struct ata_xfer *xfer; | |
783 | struct ata_channel *chp; | 780 | struct ata_channel *chp; | |
784 | unsigned openings; | 781 | unsigned openings; | |
785 | int ticks; | 782 | int ticks; | |
@@ -1153,27 +1150,27 @@ wd_firstopen(device_t self, dev_t dev, i | @@ -1153,27 +1150,27 @@ wd_firstopen(device_t self, dev_t dev, i | |||
1153 | { | 1150 | { | |
1154 | struct wd_softc *wd = device_private(self); | 1151 | struct wd_softc *wd = device_private(self); | |
1155 | struct dk_softc *dksc = &wd->sc_dksc; | 1152 | struct dk_softc *dksc = &wd->sc_dksc; | |
1156 | int error; | 1153 | int error; | |
1157 | 1154 | |||
1158 | error = wd->atabus->ata_addref(wd->drvp); | 1155 | error = wd->atabus->ata_addref(wd->drvp); | |
1159 | if (error) | 1156 | if (error) | |
1160 | return error; | 1157 | return error; | |
1161 | 1158 | |||
1162 | if ((wd->sc_flags & WDF_LOADED) == 0) { | 1159 | if ((wd->sc_flags & WDF_LOADED) == 0) { | |
1163 | int param_error; | 1160 | int param_error; | |
1164 | 1161 | |||
1165 | /* Load the physical device parameters. */ | 1162 | /* Load the physical device parameters. */ | |
1166 | param_error = wd_get_params(wd, AT_WAIT, &wd->sc_params); | 1163 | param_error = wd_get_params(wd, &wd->sc_params); | |
1167 | if (param_error != 0) { | 1164 | if (param_error != 0) { | |
1168 | aprint_error_dev(dksc->sc_dev, "IDENTIFY failed\n"); | 1165 | aprint_error_dev(dksc->sc_dev, "IDENTIFY failed\n"); | |
1169 | error = EIO; | 1166 | error = EIO; | |
1170 | goto bad; | 1167 | goto bad; | |
1171 | } | 1168 | } | |
1172 | wd_set_geometry(wd); | 1169 | wd_set_geometry(wd); | |
1173 | wd->sc_flags |= WDF_LOADED; | 1170 | wd->sc_flags |= WDF_LOADED; | |
1174 | } | 1171 | } | |
1175 | 1172 | |||
1176 | wd->sc_flags |= WDF_OPEN; | 1173 | wd->sc_flags |= WDF_OPEN; | |
1177 | return 0; | 1174 | return 0; | |
1178 | 1175 | |||
1179 | bad: | 1176 | bad: | |
@@ -1597,38 +1594,29 @@ wd_dumpblocks(device_t dev, void *va, da | @@ -1597,38 +1594,29 @@ wd_dumpblocks(device_t dev, void *va, da | |||
1597 | memset(xfer, 0, sizeof(*xfer)); | 1594 | memset(xfer, 0, sizeof(*xfer)); | |
1598 | xfer->c_flags |= C_PRIVATE_ALLOC | C_SKIP_QUEUE; | 1595 | xfer->c_flags |= C_PRIVATE_ALLOC | C_SKIP_QUEUE; | |
1599 | 1596 | |||
1600 | xfer->c_bio.blkno = blkno; | 1597 | xfer->c_bio.blkno = blkno; | |
1601 | xfer->c_bio.flags = ATA_POLL; | 1598 | xfer->c_bio.flags = ATA_POLL; | |
1602 | if (wd->sc_flags & WDF_LBA48 && | 1599 | if (wd->sc_flags & WDF_LBA48 && | |
1603 | (xfer->c_bio.blkno + nblk) > wd->sc_capacity28) | 1600 | (xfer->c_bio.blkno + nblk) > wd->sc_capacity28) | |
1604 | xfer->c_bio.flags |= ATA_LBA48; | 1601 | xfer->c_bio.flags |= ATA_LBA48; | |
1605 | if (wd->sc_flags & WDF_LBA) | 1602 | if (wd->sc_flags & WDF_LBA) | |
1606 | xfer->c_bio.flags |= ATA_LBA; | 1603 | xfer->c_bio.flags |= ATA_LBA; | |
1607 | xfer->c_bio.bcount = nblk * dg->dg_secsize; | 1604 | xfer->c_bio.bcount = nblk * dg->dg_secsize; | |
1608 | xfer->c_bio.databuf = va; | 1605 | xfer->c_bio.databuf = va; | |
1609 | #ifndef WD_DUMP_NOT_TRUSTED | 1606 | #ifndef WD_DUMP_NOT_TRUSTED | |
1610 | switch (err = wd->atabus->ata_bio(wd->drvp, xfer)) { | 1607 | /* This will poll until the bio is complete */ | |
1611 | case ATACMD_TRY_AGAIN: | 1608 | wd->atabus->ata_bio(wd->drvp, xfer); | |
1612 | panic("wddump: try again"); | 1609 | ||
1613 | break; | |||
1614 | case ATACMD_QUEUED: | |||
1615 | panic("wddump: polled command has been queued"); | |||
1616 | break; | |||
1617 | case ATACMD_COMPLETE: | |||
1618 | break; | |||
1619 | default: | |||
1620 | panic("wddump: unknown atacmd code %d", err); | |||
1621 | } | |||
1622 | switch(err = xfer->c_bio.error) { | 1610 | switch(err = xfer->c_bio.error) { | |
1623 | case TIMEOUT: | 1611 | case TIMEOUT: | |
1624 | printf("wddump: device timed out"); | 1612 | printf("wddump: device timed out"); | |
1625 | err = EIO; | 1613 | err = EIO; | |
1626 | break; | 1614 | break; | |
1627 | case ERR_DF: | 1615 | case ERR_DF: | |
1628 | printf("wddump: drive fault"); | 1616 | printf("wddump: drive fault"); | |
1629 | err = EIO; | 1617 | err = EIO; | |
1630 | break; | 1618 | break; | |
1631 | case ERR_DMA: | 1619 | case ERR_DMA: | |
1632 | printf("wddump: DMA error"); | 1620 | printf("wddump: DMA error"); | |
1633 | err = EIO; | 1621 | err = EIO; | |
1634 | break; | 1622 | break; | |
@@ -1695,30 +1683,31 @@ wd_set_geometry(struct wd_softc *wd) | @@ -1695,30 +1683,31 @@ wd_set_geometry(struct wd_softc *wd) | |||
1695 | memset(dg, 0, sizeof(*dg)); | 1683 | memset(dg, 0, sizeof(*dg)); | |
1696 | 1684 | |||
1697 | dg->dg_secperunit = wd->sc_capacity; | 1685 | dg->dg_secperunit = wd->sc_capacity; | |
1698 | dg->dg_secsize = wd->sc_blksize; | 1686 | dg->dg_secsize = wd->sc_blksize; | |
1699 | dg->dg_nsectors = wd->sc_params.atap_sectors; | 1687 | dg->dg_nsectors = wd->sc_params.atap_sectors; | |
1700 | dg->dg_ntracks = wd->sc_params.atap_heads; | 1688 | dg->dg_ntracks = wd->sc_params.atap_heads; | |
1701 | if ((wd->sc_flags & WDF_LBA) == 0) | 1689 | if ((wd->sc_flags & WDF_LBA) == 0) | |
1702 | dg->dg_ncylinders = wd->sc_params.atap_cylinders; | 1690 | dg->dg_ncylinders = wd->sc_params.atap_cylinders; | |
1703 | 1691 | |||
1704 | disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, wd->sc_typename); | 1692 | disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, wd->sc_typename); | |
1705 | } | 1693 | } | |
1706 | 1694 | |||
1707 | int | 1695 | int | |
1708 | wd_get_params(struct wd_softc *wd, uint8_t flags, struct ataparams *params) | 1696 | wd_get_params(struct wd_softc *wd, struct ataparams *params) | |
1709 | { | 1697 | { | |
1710 | int retry = 0; | 1698 | int retry = 0; | |
1711 | struct ata_channel *chp = wd->drvp->chnl_softc; | 1699 | struct ata_channel *chp = wd->drvp->chnl_softc; | |
1700 | const int flags = AT_WAIT; | |||
1712 | 1701 | |||
1713 | again: | 1702 | again: | |
1714 | switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) { | 1703 | switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) { | |
1715 | case CMD_AGAIN: | 1704 | case CMD_AGAIN: | |
1716 | return 1; | 1705 | return 1; | |
1717 | case CMD_ERR: | 1706 | case CMD_ERR: | |
1718 | if (retry == 0) { | 1707 | if (retry == 0) { | |
1719 | retry++; | 1708 | retry++; | |
1720 | ata_channel_lock(chp); | 1709 | ata_channel_lock(chp); | |
1721 | (*wd->atabus->ata_reset_drive)(wd->drvp, flags, NULL); | 1710 | (*wd->atabus->ata_reset_drive)(wd->drvp, flags, NULL); | |
1722 | ata_channel_unlock(chp); | 1711 | ata_channel_unlock(chp); | |
1723 | goto again; | 1712 | goto again; | |
1724 | } | 1713 | } | |
@@ -1743,27 +1732,27 @@ again: | @@ -1743,27 +1732,27 @@ again: | |||
1743 | case CMD_OK: | 1732 | case CMD_OK: | |
1744 | return 0; | 1733 | return 0; | |
1745 | default: | 1734 | default: | |
1746 | panic("wd_get_params: bad return code from ata_get_params"); | 1735 | panic("wd_get_params: bad return code from ata_get_params"); | |
1747 | /* NOTREACHED */ | 1736 | /* NOTREACHED */ | |
1748 | } | 1737 | } | |
1749 | } | 1738 | } | |
1750 | 1739 | |||
1751 | int | 1740 | int | |
1752 | wd_getcache(struct wd_softc *wd, int *bitsp) | 1741 | wd_getcache(struct wd_softc *wd, int *bitsp) | |
1753 | { | 1742 | { | |
1754 | struct ataparams params; | 1743 | struct ataparams params; | |
1755 | 1744 | |||
1756 | if (wd_get_params(wd, AT_WAIT, ¶ms) != 0) | 1745 | if (wd_get_params(wd, ¶ms) != 0) | |
1757 | return EIO; | 1746 | return EIO; | |
1758 | if (params.atap_cmd_set1 == 0x0000 || | 1747 | if (params.atap_cmd_set1 == 0x0000 || | |
1759 | params.atap_cmd_set1 == 0xffff || | 1748 | params.atap_cmd_set1 == 0xffff || | |
1760 | (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) { | 1749 | (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) { | |
1761 | *bitsp = 0; | 1750 | *bitsp = 0; | |
1762 | return 0; | 1751 | return 0; | |
1763 | } | 1752 | } | |
1764 | *bitsp = DKCACHE_WCHANGE | DKCACHE_READ; | 1753 | *bitsp = DKCACHE_WCHANGE | DKCACHE_READ; | |
1765 | if (params.atap_cmd1_en & WDC_CMD1_CACHE) | 1754 | if (params.atap_cmd1_en & WDC_CMD1_CACHE) | |
1766 | *bitsp |= DKCACHE_WRITE; | 1755 | *bitsp |= DKCACHE_WRITE; | |
1767 | 1756 | |||
1768 | if (WD_USE_NCQ(wd) || (wd->drvp->drive_flags & ATA_DRIVE_WFUA)) | 1757 | if (WD_USE_NCQ(wd) || (wd->drvp->drive_flags & ATA_DRIVE_WFUA)) | |
1769 | *bitsp |= DKCACHE_FUA; | 1758 | *bitsp |= DKCACHE_FUA; | |
@@ -1771,55 +1760,52 @@ wd_getcache(struct wd_softc *wd, int *bi | @@ -1771,55 +1760,52 @@ wd_getcache(struct wd_softc *wd, int *bi | |||
1771 | return 0; | 1760 | return 0; | |
1772 | } | 1761 | } | |
1773 | 1762 | |||
1774 | const char at_errbits[] = "\20\10ERROR\11TIMEOU\12DF"; | 1763 | const char at_errbits[] = "\20\10ERROR\11TIMEOU\12DF"; | |
1775 | 1764 | |||
1776 | int | 1765 | int | |
1777 | wd_setcache(struct wd_softc *wd, int bits) | 1766 | wd_setcache(struct wd_softc *wd, int bits) | |
1778 | { | 1767 | { | |
1779 | struct dk_softc *dksc = &wd->sc_dksc; | 1768 | struct dk_softc *dksc = &wd->sc_dksc; | |
1780 | struct ataparams params; | 1769 | struct ataparams params; | |
1781 | struct ata_xfer *xfer; | 1770 | struct ata_xfer *xfer; | |
1782 | int error; | 1771 | int error; | |
1783 | 1772 | |||
1784 | if (wd_get_params(wd, AT_WAIT, ¶ms) != 0) | 1773 | if (wd_get_params(wd, ¶ms) != 0) | |
1785 | return EIO; | 1774 | return EIO; | |
1786 | 1775 | |||
1787 | if (params.atap_cmd_set1 == 0x0000 || | 1776 | if (params.atap_cmd_set1 == 0x0000 || | |
1788 | params.atap_cmd_set1 == 0xffff || | 1777 | params.atap_cmd_set1 == 0xffff || | |
1789 | (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) | 1778 | (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) | |
1790 | return EOPNOTSUPP; | 1779 | return EOPNOTSUPP; | |
1791 | 1780 | |||
1792 | if ((bits & DKCACHE_READ) == 0 || | 1781 | if ((bits & DKCACHE_READ) == 0 || | |
1793 | (bits & DKCACHE_SAVE) != 0) | 1782 | (bits & DKCACHE_SAVE) != 0) | |
1794 | return EOPNOTSUPP; | 1783 | return EOPNOTSUPP; | |
1795 | 1784 | |||
1796 | xfer = ata_get_xfer(wd->drvp->chnl_softc, true); | 1785 | xfer = ata_get_xfer(wd->drvp->chnl_softc, true); | |
1797 | 1786 | |||
1798 | xfer->c_ata_c.r_command = SET_FEATURES; | 1787 | xfer->c_ata_c.r_command = SET_FEATURES; | |
1799 | xfer->c_ata_c.r_st_bmask = 0; | 1788 | xfer->c_ata_c.r_st_bmask = 0; | |
1800 | xfer->c_ata_c.r_st_pmask = 0; | 1789 | xfer->c_ata_c.r_st_pmask = 0; | |
1801 | xfer->c_ata_c.timeout = 30000; /* 30s timeout */ | 1790 | xfer->c_ata_c.timeout = 30000; /* 30s timeout */ | |
1802 | xfer->c_ata_c.flags = AT_WAIT; | 1791 | xfer->c_ata_c.flags = AT_WAIT; | |
1803 | if (bits & DKCACHE_WRITE) | 1792 | if (bits & DKCACHE_WRITE) | |
1804 | xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_EN; | 1793 | xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_EN; | |
1805 | else | 1794 | else | |
1806 | xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_DS; | 1795 | xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_DS; | |
1807 | if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) { | 1796 | ||
1808 | aprint_error_dev(dksc->sc_dev, | 1797 | wd->atabus->ata_exec_command(wd->drvp, xfer); | |
1809 | "wd_setcache command not complete\n"); | 1798 | ata_wait_cmd(wd->drvp->chnl_softc, xfer); | |
1810 | error = EIO; | |||
1811 | goto out; | |||
1812 | } | |||
1813 | 1799 | |||
1814 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 1800 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
1815 | char sbuf[sizeof(at_errbits) + 64]; | 1801 | char sbuf[sizeof(at_errbits) + 64]; | |
1816 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | 1802 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | |
1817 | aprint_error_dev(dksc->sc_dev, "wd_setcache: status=%s\n", sbuf); | 1803 | aprint_error_dev(dksc->sc_dev, "wd_setcache: status=%s\n", sbuf); | |
1818 | error = EIO; | 1804 | error = EIO; | |
1819 | goto out; | 1805 | goto out; | |
1820 | } | 1806 | } | |
1821 | 1807 | |||
1822 | error = 0; | 1808 | error = 0; | |
1823 | 1809 | |||
1824 | out: | 1810 | out: | |
1825 | ata_free_xfer(wd->drvp->chnl_softc, xfer); | 1811 | ata_free_xfer(wd->drvp->chnl_softc, xfer); | |
@@ -1831,32 +1817,30 @@ wd_standby(struct wd_softc *wd, int flag | @@ -1831,32 +1817,30 @@ wd_standby(struct wd_softc *wd, int flag | |||
1831 | { | 1817 | { | |
1832 | struct dk_softc *dksc = &wd->sc_dksc; | 1818 | struct dk_softc *dksc = &wd->sc_dksc; | |
1833 | struct ata_xfer *xfer; | 1819 | struct ata_xfer *xfer; | |
1834 | int error; | 1820 | int error; | |
1835 | 1821 | |||
1836 | aprint_debug_dev(dksc->sc_dev, "standby immediate\n"); | 1822 | aprint_debug_dev(dksc->sc_dev, "standby immediate\n"); | |
1837 | xfer = ata_get_xfer(wd->drvp->chnl_softc, true); | 1823 | xfer = ata_get_xfer(wd->drvp->chnl_softc, true); | |
1838 | 1824 | |||
1839 | xfer->c_ata_c.r_command = WDCC_STANDBY_IMMED; | 1825 | xfer->c_ata_c.r_command = WDCC_STANDBY_IMMED; | |
1840 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | 1826 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | |
1841 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 1827 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
1842 | xfer->c_ata_c.flags = flags; | 1828 | xfer->c_ata_c.flags = flags; | |
1843 | xfer->c_ata_c.timeout = 30000; /* 30s timeout */ | 1829 | xfer->c_ata_c.timeout = 30000; /* 30s timeout */ | |
1844 | if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) { | 1830 | ||
1845 | aprint_error_dev(dksc->sc_dev, | 1831 | wd->atabus->ata_exec_command(wd->drvp, xfer); | |
1846 | "standby immediate command didn't complete\n"); | 1832 | ata_wait_cmd(wd->drvp->chnl_softc, xfer); | |
1847 | error = EIO; | 1833 | ||
1848 | goto out; | |||
1849 | } | |||
1850 | if (xfer->c_ata_c.flags & AT_ERROR) { | 1834 | if (xfer->c_ata_c.flags & AT_ERROR) { | |
1851 | if (xfer->c_ata_c.r_error == WDCE_ABRT) { | 1835 | if (xfer->c_ata_c.r_error == WDCE_ABRT) { | |
1852 | /* command not supported */ | 1836 | /* command not supported */ | |
1853 | aprint_debug_dev(dksc->sc_dev, | 1837 | aprint_debug_dev(dksc->sc_dev, | |
1854 | "standby immediate not supported\n"); | 1838 | "standby immediate not supported\n"); | |
1855 | error = ENODEV; | 1839 | error = ENODEV; | |
1856 | goto out; | 1840 | goto out; | |
1857 | } | 1841 | } | |
1858 | } | 1842 | } | |
1859 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 1843 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
1860 | char sbuf[sizeof(at_errbits) + 64]; | 1844 | char sbuf[sizeof(at_errbits) + 64]; | |
1861 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | 1845 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | |
1862 | aprint_error_dev(dksc->sc_dev, "wd_standby: status=%s\n", sbuf); | 1846 | aprint_error_dev(dksc->sc_dev, "wd_standby: status=%s\n", sbuf); | |
@@ -1888,32 +1872,30 @@ wd_flushcache(struct wd_softc *wd, int f | @@ -1888,32 +1872,30 @@ wd_flushcache(struct wd_softc *wd, int f | |||
1888 | 1872 | |||
1889 | xfer = ata_get_xfer(wd->drvp->chnl_softc, true); | 1873 | xfer = ata_get_xfer(wd->drvp->chnl_softc, true); | |
1890 | 1874 | |||
1891 | if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0 && | 1875 | if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0 && | |
1892 | (wd->sc_params.atap_cmd2_en & ATA_CMD2_FCE) != 0) { | 1876 | (wd->sc_params.atap_cmd2_en & ATA_CMD2_FCE) != 0) { | |
1893 | xfer->c_ata_c.r_command = WDCC_FLUSHCACHE_EXT; | 1877 | xfer->c_ata_c.r_command = WDCC_FLUSHCACHE_EXT; | |
1894 | flags |= AT_LBA48; | 1878 | flags |= AT_LBA48; | |
1895 | } else | 1879 | } else | |
1896 | xfer->c_ata_c.r_command = WDCC_FLUSHCACHE; | 1880 | xfer->c_ata_c.r_command = WDCC_FLUSHCACHE; | |
1897 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | 1881 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | |
1898 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 1882 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
1899 | xfer->c_ata_c.flags = flags | AT_READREG; | 1883 | xfer->c_ata_c.flags = flags | AT_READREG; | |
1900 | xfer->c_ata_c.timeout = 300000; /* 5m timeout */ | 1884 | xfer->c_ata_c.timeout = 300000; /* 5m timeout */ | |
1901 | if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) { | 1885 | ||
1902 | aprint_error_dev(dksc->sc_dev, | 1886 | wd->atabus->ata_exec_command(wd->drvp, xfer); | |
1903 | "flush cache command didn't complete\n"); | 1887 | ata_wait_cmd(wd->drvp->chnl_softc, xfer); | |
1904 | error = EIO; | 1888 | ||
1905 | goto out_xfer; | |||
1906 | } | |||
1907 | if (xfer->c_ata_c.flags & AT_ERROR) { | 1889 | if (xfer->c_ata_c.flags & AT_ERROR) { | |
1908 | if (xfer->c_ata_c.r_error == WDCE_ABRT) { | 1890 | if (xfer->c_ata_c.r_error == WDCE_ABRT) { | |
1909 | /* command not supported */ | 1891 | /* command not supported */ | |
1910 | error = ENODEV; | 1892 | error = ENODEV; | |
1911 | goto out_xfer; | 1893 | goto out_xfer; | |
1912 | } | 1894 | } | |
1913 | } | 1895 | } | |
1914 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 1896 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
1915 | char sbuf[sizeof(at_errbits) + 64]; | 1897 | char sbuf[sizeof(at_errbits) + 64]; | |
1916 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | 1898 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | |
1917 | aprint_error_dev(dksc->sc_dev, "wd_flushcache: status=%s\n", | 1899 | aprint_error_dev(dksc->sc_dev, "wd_flushcache: status=%s\n", | |
1918 | sbuf); | 1900 | sbuf); | |
1919 | error = EIO; | 1901 | error = EIO; | |
@@ -1957,33 +1939,30 @@ wd_trim(struct wd_softc *wd, daddr_t bno | @@ -1957,33 +1939,30 @@ wd_trim(struct wd_softc *wd, daddr_t bno | |||
1957 | * atastart() et.al would need to be adjusted to allow and support | 1939 | * atastart() et.al would need to be adjusted to allow and support | |
1958 | * running several non-I/O ATA commands in parallel. | 1940 | * running several non-I/O ATA commands in parallel. | |
1959 | */ | 1941 | */ | |
1960 | 1942 | |||
1961 | xfer->c_ata_c.r_command = ATA_DATA_SET_MANAGEMENT; | 1943 | xfer->c_ata_c.r_command = ATA_DATA_SET_MANAGEMENT; | |
1962 | xfer->c_ata_c.r_count = 1; | 1944 | xfer->c_ata_c.r_count = 1; | |
1963 | xfer->c_ata_c.r_features = ATA_SUPPORT_DSM_TRIM; | 1945 | xfer->c_ata_c.r_features = ATA_SUPPORT_DSM_TRIM; | |
1964 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | 1946 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | |
1965 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 1947 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
1966 | xfer->c_ata_c.timeout = 30000; /* 30s timeout */ | 1948 | xfer->c_ata_c.timeout = 30000; /* 30s timeout */ | |
1967 | xfer->c_ata_c.data = req; | 1949 | xfer->c_ata_c.data = req; | |
1968 | xfer->c_ata_c.bcount = 512; | 1950 | xfer->c_ata_c.bcount = 512; | |
1969 | xfer->c_ata_c.flags |= AT_WRITE | AT_WAIT; | 1951 | xfer->c_ata_c.flags |= AT_WRITE | AT_WAIT; | |
1970 | if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) { | 1952 | ||
1971 | aprint_error_dev(dksc->sc_dev, | 1953 | wd->atabus->ata_exec_command(wd->drvp, xfer); | |
1972 | "trim command didn't complete\n"); | 1954 | ata_wait_cmd(wd->drvp->chnl_softc, xfer); | |
1973 | kmem_free(req, 512); | 1955 | ||
1974 | error = EIO; | |||
1975 | goto out; | |||
1976 | } | |||
1977 | kmem_free(req, 512); | 1956 | kmem_free(req, 512); | |
1978 | if (xfer->c_ata_c.flags & AT_ERROR) { | 1957 | if (xfer->c_ata_c.flags & AT_ERROR) { | |
1979 | if (xfer->c_ata_c.r_error == WDCE_ABRT) { | 1958 | if (xfer->c_ata_c.r_error == WDCE_ABRT) { | |
1980 | /* command not supported */ | 1959 | /* command not supported */ | |
1981 | error = ENODEV; | 1960 | error = ENODEV; | |
1982 | goto out; | 1961 | goto out; | |
1983 | } | 1962 | } | |
1984 | } | 1963 | } | |
1985 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 1964 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
1986 | char sbuf[sizeof(at_errbits) + 64]; | 1965 | char sbuf[sizeof(at_errbits) + 64]; | |
1987 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | 1966 | snprintb(sbuf, sizeof(sbuf), at_errbits, xfer->c_ata_c.flags); | |
1988 | aprint_error_dev(dksc->sc_dev, "wd_trim: status=%s\n", | 1967 | aprint_error_dev(dksc->sc_dev, "wd_trim: status=%s\n", | |
1989 | sbuf); | 1968 | sbuf); | |
@@ -2158,32 +2137,28 @@ wdioctlstrategy(struct buf *bp) | @@ -2158,32 +2137,28 @@ wdioctlstrategy(struct buf *bp) | |||
2158 | 2137 | |||
2159 | xfer->c_ata_c.timeout = wi->wi_atareq.timeout; | 2138 | xfer->c_ata_c.timeout = wi->wi_atareq.timeout; | |
2160 | xfer->c_ata_c.r_command = wi->wi_atareq.command; | 2139 | xfer->c_ata_c.r_command = wi->wi_atareq.command; | |
2161 | xfer->c_ata_c.r_lba = ((wi->wi_atareq.head & 0x0f) << 24) | | 2140 | xfer->c_ata_c.r_lba = ((wi->wi_atareq.head & 0x0f) << 24) | | |
2162 | (wi->wi_atareq.cylinder << 8) | | 2141 | (wi->wi_atareq.cylinder << 8) | | |
2163 | wi->wi_atareq.sec_num; | 2142 | wi->wi_atareq.sec_num; | |
2164 | xfer->c_ata_c.r_count = wi->wi_atareq.sec_count; | 2143 | xfer->c_ata_c.r_count = wi->wi_atareq.sec_count; | |
2165 | xfer->c_ata_c.r_features = wi->wi_atareq.features; | 2144 | xfer->c_ata_c.r_features = wi->wi_atareq.features; | |
2166 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | 2145 | xfer->c_ata_c.r_st_bmask = WDCS_DRDY; | |
2167 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | 2146 | xfer->c_ata_c.r_st_pmask = WDCS_DRDY; | |
2168 | xfer->c_ata_c.data = wi->wi_bp.b_data; | 2147 | xfer->c_ata_c.data = wi->wi_bp.b_data; | |
2169 | xfer->c_ata_c.bcount = wi->wi_bp.b_bcount; | 2148 | xfer->c_ata_c.bcount = wi->wi_bp.b_bcount; | |
2170 | 2149 | |||
2171 | if (wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, xfer) | 2150 | wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, xfer); | |
2172 | != ATACMD_COMPLETE) { | 2151 | ata_wait_cmd(wi->wi_softc->drvp->chnl_softc, xfer); | |
2173 | wi->wi_atareq.retsts = ATACMD_ERROR; | |||
2174 | error = EIO; | |||
2175 | goto out; | |||
2176 | } | |||
2177 | 2152 | |||
2178 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 2153 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
2179 | if (xfer->c_ata_c.flags & AT_ERROR) { | 2154 | if (xfer->c_ata_c.flags & AT_ERROR) { | |
2180 | wi->wi_atareq.retsts = ATACMD_ERROR; | 2155 | wi->wi_atareq.retsts = ATACMD_ERROR; | |
2181 | wi->wi_atareq.error = xfer->c_ata_c.r_error; | 2156 | wi->wi_atareq.error = xfer->c_ata_c.r_error; | |
2182 | } else if (xfer->c_ata_c.flags & AT_DF) | 2157 | } else if (xfer->c_ata_c.flags & AT_DF) | |
2183 | wi->wi_atareq.retsts = ATACMD_DF; | 2158 | wi->wi_atareq.retsts = ATACMD_DF; | |
2184 | else | 2159 | else | |
2185 | wi->wi_atareq.retsts = ATACMD_TIMEOUT; | 2160 | wi->wi_atareq.retsts = ATACMD_TIMEOUT; | |
2186 | } else { | 2161 | } else { | |
2187 | wi->wi_atareq.retsts = ATACMD_OK; | 2162 | wi->wi_atareq.retsts = ATACMD_OK; | |
2188 | if (wi->wi_atareq.flags & ATACMD_READREG) { | 2163 | if (wi->wi_atareq.flags & ATACMD_READREG) { | |
2189 | wi->wi_atareq.command = xfer->c_ata_c.r_status; | 2164 | wi->wi_atareq.command = xfer->c_ata_c.r_status; |
--- src/sys/dev/ic/ahcisata_core.c 2020/12/30 15:12:38 1.75.4.4
+++ src/sys/dev/ic/ahcisata_core.c 2022/12/30 14:39:09 1.75.4.5
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ahcisata_core.c,v 1.75.4.4 2020/12/30 15:12:38 martin Exp $ */ | 1 | /* $NetBSD: ahcisata_core.c,v 1.75.4.5 2022/12/30 14:39:09 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2006 Manuel Bouyer. | 4 | * Copyright (c) 2006 Manuel Bouyer. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -16,27 +16,27 @@ | @@ -16,27 +16,27 @@ | |||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | * | 25 | * | |
26 | */ | 26 | */ | |
27 | 27 | |||
28 | #include <sys/cdefs.h> | 28 | #include <sys/cdefs.h> | |
29 | __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.75.4.4 2020/12/30 15:12:38 martin Exp $"); | 29 | __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.75.4.5 2022/12/30 14:39:09 martin Exp $"); | |
30 | 30 | |||
31 | #include <sys/types.h> | 31 | #include <sys/types.h> | |
32 | #include <sys/malloc.h> | 32 | #include <sys/malloc.h> | |
33 | #include <sys/param.h> | 33 | #include <sys/param.h> | |
34 | #include <sys/kernel.h> | 34 | #include <sys/kernel.h> | |
35 | #include <sys/systm.h> | 35 | #include <sys/systm.h> | |
36 | #include <sys/disklabel.h> | 36 | #include <sys/disklabel.h> | |
37 | #include <sys/proc.h> | 37 | #include <sys/proc.h> | |
38 | #include <sys/buf.h> | 38 | #include <sys/buf.h> | |
39 | 39 | |||
40 | #include <dev/ata/atareg.h> | 40 | #include <dev/ata/atareg.h> | |
41 | #include <dev/ata/satavar.h> | 41 | #include <dev/ata/satavar.h> | |
42 | #include <dev/ata/satareg.h> | 42 | #include <dev/ata/satareg.h> | |
@@ -47,63 +47,63 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_cor | @@ -47,63 +47,63 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_cor | |||
47 | #include <dev/ic/wdcreg.h> | 47 | #include <dev/ic/wdcreg.h> | |
48 | 48 | |||
49 | #include <dev/scsipi/scsi_all.h> /* for SCSI status */ | 49 | #include <dev/scsipi/scsi_all.h> /* for SCSI status */ | |
50 | 50 | |||
51 | #include "atapibus.h" | 51 | #include "atapibus.h" | |
52 | 52 | |||
53 | #ifdef AHCI_DEBUG | 53 | #ifdef AHCI_DEBUG | |
54 | int ahcidebug_mask = 0; | 54 | int ahcidebug_mask = 0; | |
55 | #endif | 55 | #endif | |
56 | 56 | |||
57 | static void ahci_probe_drive(struct ata_channel *); | 57 | static void ahci_probe_drive(struct ata_channel *); | |
58 | static void ahci_setup_channel(struct ata_channel *); | 58 | static void ahci_setup_channel(struct ata_channel *); | |
59 | 59 | |||
60 | static int ahci_ata_bio(struct ata_drive_datas *, struct ata_xfer *); | 60 | static void ahci_ata_bio(struct ata_drive_datas *, struct ata_xfer *); | |
61 | static int ahci_do_reset_drive(struct ata_channel *, int, int, uint32_t *, | 61 | static int ahci_do_reset_drive(struct ata_channel *, int, int, uint32_t *, | |
62 | uint8_t); | 62 | uint8_t); | |
63 | static void ahci_reset_drive(struct ata_drive_datas *, int, uint32_t *); | 63 | static void ahci_reset_drive(struct ata_drive_datas *, int, uint32_t *); | |
64 | static void ahci_reset_channel(struct ata_channel *, int); | 64 | static void ahci_reset_channel(struct ata_channel *, int); | |
65 | static int ahci_exec_command(struct ata_drive_datas *, struct ata_xfer *); | 65 | static void ahci_exec_command(struct ata_drive_datas *, struct ata_xfer *); | |
66 | static int ahci_ata_addref(struct ata_drive_datas *); | 66 | static int ahci_ata_addref(struct ata_drive_datas *); | |
67 | static void ahci_ata_delref(struct ata_drive_datas *); | 67 | static void ahci_ata_delref(struct ata_drive_datas *); | |
68 | static void ahci_killpending(struct ata_drive_datas *); | 68 | static void ahci_killpending(struct ata_drive_datas *); | |
69 | 69 | |||
70 | static int ahci_cmd_start(struct ata_channel *, struct ata_xfer *); | 70 | static int ahci_cmd_start(struct ata_channel *, struct ata_xfer *); | |
71 | static int ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int); | 71 | static int ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int); | |
72 | static void ahci_cmd_poll(struct ata_channel *, struct ata_xfer *); | 72 | static int ahci_cmd_poll(struct ata_channel *, struct ata_xfer *); | |
73 | static void ahci_cmd_abort(struct ata_channel *, struct ata_xfer *); | 73 | static void ahci_cmd_abort(struct ata_channel *, struct ata_xfer *); | |
74 | static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *); | 74 | static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *); | |
75 | static void ahci_cmd_done_end(struct ata_channel *, struct ata_xfer *); | 75 | static void ahci_cmd_done_end(struct ata_channel *, struct ata_xfer *); | |
76 | static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | 76 | static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | |
77 | static int ahci_bio_start(struct ata_channel *, struct ata_xfer *); | 77 | static int ahci_bio_start(struct ata_channel *, struct ata_xfer *); | |
78 | static void ahci_bio_poll(struct ata_channel *, struct ata_xfer *); | 78 | static int ahci_bio_poll(struct ata_channel *, struct ata_xfer *); | |
79 | static void ahci_bio_abort(struct ata_channel *, struct ata_xfer *); | 79 | static void ahci_bio_abort(struct ata_channel *, struct ata_xfer *); | |
80 | static int ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int); | 80 | static int ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int); | |
81 | static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ; | 81 | static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ; | |
82 | static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int); | 82 | static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int); | |
83 | static void ahci_channel_start(struct ahci_softc *, struct ata_channel *, | 83 | static void ahci_channel_start(struct ahci_softc *, struct ata_channel *, | |
84 | int, int); | 84 | int, int); | |
85 | static void ahci_channel_recover(struct ata_channel *, int, uint32_t); | 85 | static void ahci_channel_recover(struct ata_channel *, int, uint32_t); | |
86 | static int ahci_dma_setup(struct ata_channel *, int, void *, size_t, int); | 86 | static int ahci_dma_setup(struct ata_channel *, int, void *, size_t, int); | |
87 | static int ahci_intr_port_common(struct ata_channel *); | 87 | static int ahci_intr_port_common(struct ata_channel *); | |
88 | 88 | |||
89 | #if NATAPIBUS > 0 | 89 | #if NATAPIBUS > 0 | |
90 | static void ahci_atapibus_attach(struct atabus_softc *); | 90 | static void ahci_atapibus_attach(struct atabus_softc *); | |
91 | static void ahci_atapi_kill_pending(struct scsipi_periph *); | 91 | static void ahci_atapi_kill_pending(struct scsipi_periph *); | |
92 | static void ahci_atapi_minphys(struct buf *); | 92 | static void ahci_atapi_minphys(struct buf *); | |
93 | static void ahci_atapi_scsipi_request(struct scsipi_channel *, | 93 | static void ahci_atapi_scsipi_request(struct scsipi_channel *, | |
94 | scsipi_adapter_req_t, void *); | 94 | scsipi_adapter_req_t, void *); | |
95 | static int ahci_atapi_start(struct ata_channel *, struct ata_xfer *); | 95 | static int ahci_atapi_start(struct ata_channel *, struct ata_xfer *); | |
96 | static void ahci_atapi_poll(struct ata_channel *, struct ata_xfer *); | 96 | static int ahci_atapi_poll(struct ata_channel *, struct ata_xfer *); | |
97 | static void ahci_atapi_abort(struct ata_channel *, struct ata_xfer *); | 97 | static void ahci_atapi_abort(struct ata_channel *, struct ata_xfer *); | |
98 | static int ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int); | 98 | static int ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int); | |
99 | static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | 99 | static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | |
100 | static void ahci_atapi_probe_device(struct atapibus_softc *, int); | 100 | static void ahci_atapi_probe_device(struct atapibus_softc *, int); | |
101 | 101 | |||
102 | static const struct scsipi_bustype ahci_atapi_bustype = { | 102 | static const struct scsipi_bustype ahci_atapi_bustype = { | |
103 | SCSIPI_BUSTYPE_ATAPI, | 103 | SCSIPI_BUSTYPE_ATAPI, | |
104 | atapi_scsipi_cmd, | 104 | atapi_scsipi_cmd, | |
105 | atapi_interpret_sense, | 105 | atapi_interpret_sense, | |
106 | atapi_print_addr, | 106 | atapi_print_addr, | |
107 | ahci_atapi_kill_pending, | 107 | ahci_atapi_kill_pending, | |
108 | NULL, | 108 | NULL, | |
109 | }; | 109 | }; | |
@@ -1118,65 +1118,46 @@ static void | @@ -1118,65 +1118,46 @@ static void | |||
1118 | ahci_setup_channel(struct ata_channel *chp) | 1118 | ahci_setup_channel(struct ata_channel *chp) | |
1119 | { | 1119 | { | |
1120 | return; | 1120 | return; | |
1121 | } | 1121 | } | |
1122 | 1122 | |||
1123 | static const struct ata_xfer_ops ahci_cmd_xfer_ops = { | 1123 | static const struct ata_xfer_ops ahci_cmd_xfer_ops = { | |
1124 | .c_start = ahci_cmd_start, | 1124 | .c_start = ahci_cmd_start, | |
1125 | .c_poll = ahci_cmd_poll, | 1125 | .c_poll = ahci_cmd_poll, | |
1126 | .c_abort = ahci_cmd_abort, | 1126 | .c_abort = ahci_cmd_abort, | |
1127 | .c_intr = ahci_cmd_complete, | 1127 | .c_intr = ahci_cmd_complete, | |
1128 | .c_kill_xfer = ahci_cmd_kill_xfer, | 1128 | .c_kill_xfer = ahci_cmd_kill_xfer, | |
1129 | }; | 1129 | }; | |
1130 | 1130 | |||
1131 | static int | 1131 | static void | |
1132 | ahci_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 1132 | ahci_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
1133 | { | 1133 | { | |
1134 | struct ata_channel *chp = drvp->chnl_softc; | 1134 | struct ata_channel *chp = drvp->chnl_softc; | |
1135 | struct ata_command *ata_c = &xfer->c_ata_c; | 1135 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1136 | int ret; | |||
1137 | int s; | |||
1138 | 1136 | |||
1139 | AHCIDEBUG_PRINT(("ahci_exec_command port %d CI 0x%x\n", | 1137 | AHCIDEBUG_PRINT(("ahci_exec_command port %d CI 0x%x\n", | |
1140 | chp->ch_channel, | 1138 | chp->ch_channel, | |
1141 | AHCI_READ(AHCI_CH2SC(chp), AHCI_P_CI(chp->ch_channel))), | 1139 | AHCI_READ(AHCI_CH2SC(chp), AHCI_P_CI(chp->ch_channel))), | |
1142 | DEBUG_XFERS); | 1140 | DEBUG_XFERS); | |
1143 | if (ata_c->flags & AT_POLL) | 1141 | if (ata_c->flags & AT_POLL) | |
1144 | xfer->c_flags |= C_POLL; | 1142 | xfer->c_flags |= C_POLL; | |
1145 | if (ata_c->flags & AT_WAIT) | 1143 | if (ata_c->flags & AT_WAIT) | |
1146 | xfer->c_flags |= C_WAIT; | 1144 | xfer->c_flags |= C_WAIT; | |
1147 | xfer->c_drive = drvp->drive; | 1145 | xfer->c_drive = drvp->drive; | |
1148 | xfer->c_databuf = ata_c->data; | 1146 | xfer->c_databuf = ata_c->data; | |
1149 | xfer->c_bcount = ata_c->bcount; | 1147 | xfer->c_bcount = ata_c->bcount; | |
1150 | xfer->ops = &ahci_cmd_xfer_ops; | 1148 | xfer->ops = &ahci_cmd_xfer_ops; | |
1151 | s = splbio(); | 1149 | ||
1152 | ata_exec_xfer(chp, xfer); | 1150 | ata_exec_xfer(chp, xfer); | |
1153 | #ifdef DIAGNOSTIC | |||
1154 | if ((ata_c->flags & AT_POLL) != 0 && | |||
1155 | (ata_c->flags & AT_DONE) == 0) | |||
1156 | panic("ahci_exec_command: polled command not done"); | |||
1157 | #endif | |||
1158 | if (ata_c->flags & AT_DONE) { | |||
1159 | ret = ATACMD_COMPLETE; | |||
1160 | } else { | |||
1161 | if (ata_c->flags & AT_WAIT) { | |||
1162 | ata_wait_cmd(chp, xfer); | |||
1163 | ret = ATACMD_COMPLETE; | |||
1164 | } else { | |||
1165 | ret = ATACMD_QUEUED; | |||
1166 | } | |||
1167 | } | |||
1168 | splx(s); | |||
1169 | return ret; | |||
1170 | } | 1151 | } | |
1171 | 1152 | |||
1172 | static int | 1153 | static int | |
1173 | ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer) | 1154 | ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
1174 | { | 1155 | { | |
1175 | struct ahci_softc *sc = AHCI_CH2SC(chp); | 1156 | struct ahci_softc *sc = AHCI_CH2SC(chp); | |
1176 | struct ahci_channel *achp = (struct ahci_channel *)chp; | 1157 | struct ahci_channel *achp = (struct ahci_channel *)chp; | |
1177 | struct ata_command *ata_c = &xfer->c_ata_c; | 1158 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1178 | int slot = xfer->c_slot; | 1159 | int slot = xfer->c_slot; | |
1179 | struct ahci_cmd_tbl *cmd_tbl; | 1160 | struct ahci_cmd_tbl *cmd_tbl; | |
1180 | struct ahci_cmd_header *cmd_h; | 1161 | struct ahci_cmd_header *cmd_h; | |
1181 | 1162 | |||
1182 | AHCIDEBUG_PRINT(("ahci_cmd_start CI 0x%x timo %d\n slot %d", | 1163 | AHCIDEBUG_PRINT(("ahci_cmd_start CI 0x%x timo %d\n slot %d", | |
@@ -1217,27 +1198,27 @@ ahci_cmd_start(struct ata_channel *chp, | @@ -1217,27 +1198,27 @@ ahci_cmd_start(struct ata_channel *chp, | |||
1217 | AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE); | 1198 | AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE); | |
1218 | } | 1199 | } | |
1219 | /* start command */ | 1200 | /* start command */ | |
1220 | AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1U << slot); | 1201 | AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1U << slot); | |
1221 | 1202 | |||
1222 | if ((ata_c->flags & AT_POLL) == 0) { | 1203 | if ((ata_c->flags & AT_POLL) == 0) { | |
1223 | callout_reset(&chp->c_timo_callout, mstohz(ata_c->timeout), | 1204 | callout_reset(&chp->c_timo_callout, mstohz(ata_c->timeout), | |
1224 | ata_timeout, chp); | 1205 | ata_timeout, chp); | |
1225 | return ATASTART_STARTED; | 1206 | return ATASTART_STARTED; | |
1226 | } else | 1207 | } else | |
1227 | return ATASTART_POLL; | 1208 | return ATASTART_POLL; | |
1228 | } | 1209 | } | |
1229 | 1210 | |||
1230 | static void | 1211 | static int | |
1231 | ahci_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1212 | ahci_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1232 | { | 1213 | { | |
1233 | struct ahci_softc *sc = AHCI_CH2SC(chp); | 1214 | struct ahci_softc *sc = AHCI_CH2SC(chp); | |
1234 | struct ahci_channel *achp = (struct ahci_channel *)chp; | 1215 | struct ahci_channel *achp = (struct ahci_channel *)chp; | |
1235 | 1216 | |||
1236 | ata_channel_lock(chp); | 1217 | ata_channel_lock(chp); | |
1237 | 1218 | |||
1238 | /* | 1219 | /* | |
1239 | * Polled command. | 1220 | * Polled command. | |
1240 | */ | 1221 | */ | |
1241 | for (int i = 0; i < xfer->c_ata_c.timeout / 10; i++) { | 1222 | for (int i = 0; i < xfer->c_ata_c.timeout / 10; i++) { | |
1242 | if (xfer->c_ata_c.flags & AT_DONE) | 1223 | if (xfer->c_ata_c.flags & AT_DONE) | |
1243 | break; | 1224 | break; | |
@@ -1254,26 +1235,28 @@ ahci_cmd_poll(struct ata_channel *chp, s | @@ -1254,26 +1235,28 @@ ahci_cmd_poll(struct ata_channel *chp, s | |||
1254 | AHCI_READ(sc, AHCI_P_FB(chp->ch_channel)), | 1235 | AHCI_READ(sc, AHCI_P_FB(chp->ch_channel)), | |
1255 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)), | 1236 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)), | |
1256 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), | 1237 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), | |
1257 | DEBUG_XFERS); | 1238 | DEBUG_XFERS); | |
1258 | 1239 | |||
1259 | ata_channel_unlock(chp); | 1240 | ata_channel_unlock(chp); | |
1260 | 1241 | |||
1261 | if ((xfer->c_ata_c.flags & AT_DONE) == 0) { | 1242 | if ((xfer->c_ata_c.flags & AT_DONE) == 0) { | |
1262 | xfer->c_ata_c.flags |= AT_TIMEOU; | 1243 | xfer->c_ata_c.flags |= AT_TIMEOU; | |
1263 | xfer->ops->c_intr(chp, xfer, 0); | 1244 | xfer->ops->c_intr(chp, xfer, 0); | |
1264 | } | 1245 | } | |
1265 | /* reenable interrupts */ | 1246 | /* reenable interrupts */ | |
1266 | AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); | 1247 | AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); | |
1248 | ||||
1249 | return ATAPOLL_DONE; | |||
1267 | } | 1250 | } | |
1268 | 1251 | |||
1269 | static void | 1252 | static void | |
1270 | ahci_cmd_abort(struct ata_channel *chp, struct ata_xfer *xfer) | 1253 | ahci_cmd_abort(struct ata_channel *chp, struct ata_xfer *xfer) | |
1271 | { | 1254 | { | |
1272 | ahci_cmd_complete(chp, xfer, 0); | 1255 | ahci_cmd_complete(chp, xfer, 0); | |
1273 | } | 1256 | } | |
1274 | 1257 | |||
1275 | static void | 1258 | static void | |
1276 | ahci_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason) | 1259 | ahci_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason) | |
1277 | { | 1260 | { | |
1278 | struct ata_command *ata_c = &xfer->c_ata_c; | 1261 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1279 | bool deactivate = true; | 1262 | bool deactivate = true; | |
@@ -1388,44 +1371,43 @@ ahci_cmd_done_end(struct ata_channel *ch | @@ -1388,44 +1371,43 @@ ahci_cmd_done_end(struct ata_channel *ch | |||
1388 | struct ata_command *ata_c = &xfer->c_ata_c; | 1371 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1389 | 1372 | |||
1390 | ata_c->flags |= AT_DONE; | 1373 | ata_c->flags |= AT_DONE; | |
1391 | } | 1374 | } | |
1392 | 1375 | |||
1393 | static const struct ata_xfer_ops ahci_bio_xfer_ops = { | 1376 | static const struct ata_xfer_ops ahci_bio_xfer_ops = { | |
1394 | .c_start = ahci_bio_start, | 1377 | .c_start = ahci_bio_start, | |
1395 | .c_poll = ahci_bio_poll, | 1378 | .c_poll = ahci_bio_poll, | |
1396 | .c_abort = ahci_bio_abort, | 1379 | .c_abort = ahci_bio_abort, | |
1397 | .c_intr = ahci_bio_complete, | 1380 | .c_intr = ahci_bio_complete, | |
1398 | .c_kill_xfer = ahci_bio_kill_xfer, | 1381 | .c_kill_xfer = ahci_bio_kill_xfer, | |
1399 | }; | 1382 | }; | |
1400 | 1383 | |||
1401 | static int | 1384 | static void | |
1402 | ahci_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 1385 | ahci_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
1403 | { | 1386 | { | |
1404 | struct ata_channel *chp = drvp->chnl_softc; | 1387 | struct ata_channel *chp = drvp->chnl_softc; | |
1405 | struct ata_bio *ata_bio = &xfer->c_bio; | 1388 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1406 | 1389 | |||
1407 | AHCIDEBUG_PRINT(("ahci_ata_bio port %d CI 0x%x\n", | 1390 | AHCIDEBUG_PRINT(("ahci_ata_bio port %d CI 0x%x\n", | |
1408 | chp->ch_channel, | 1391 | chp->ch_channel, | |
1409 | AHCI_READ(AHCI_CH2SC(chp), AHCI_P_CI(chp->ch_channel))), | 1392 | AHCI_READ(AHCI_CH2SC(chp), AHCI_P_CI(chp->ch_channel))), | |
1410 | DEBUG_XFERS); | 1393 | DEBUG_XFERS); | |
1411 | if (ata_bio->flags & ATA_POLL) | 1394 | if (ata_bio->flags & ATA_POLL) | |
1412 | xfer->c_flags |= C_POLL; | 1395 | xfer->c_flags |= C_POLL; | |
1413 | xfer->c_drive = drvp->drive; | 1396 | xfer->c_drive = drvp->drive; | |
1414 | xfer->c_databuf = ata_bio->databuf; | 1397 | xfer->c_databuf = ata_bio->databuf; | |
1415 | xfer->c_bcount = ata_bio->bcount; | 1398 | xfer->c_bcount = ata_bio->bcount; | |
1416 | xfer->ops = &ahci_bio_xfer_ops; | 1399 | xfer->ops = &ahci_bio_xfer_ops; | |
1417 | ata_exec_xfer(chp, xfer); | 1400 | ata_exec_xfer(chp, xfer); | |
1418 | return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED; | |||
1419 | } | 1401 | } | |
1420 | 1402 | |||
1421 | static int | 1403 | static int | |
1422 | ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | 1404 | ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
1423 | { | 1405 | { | |
1424 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | 1406 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | |
1425 | struct ahci_channel *achp = (struct ahci_channel *)chp; | 1407 | struct ahci_channel *achp = (struct ahci_channel *)chp; | |
1426 | struct ata_bio *ata_bio = &xfer->c_bio; | 1408 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1427 | struct ahci_cmd_tbl *cmd_tbl; | 1409 | struct ahci_cmd_tbl *cmd_tbl; | |
1428 | struct ahci_cmd_header *cmd_h; | 1410 | struct ahci_cmd_header *cmd_h; | |
1429 | 1411 | |||
1430 | AHCIDEBUG_PRINT(("ahci_bio_start CI 0x%x\n", | 1412 | AHCIDEBUG_PRINT(("ahci_bio_start CI 0x%x\n", | |
1431 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), DEBUG_XFERS); | 1413 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), DEBUG_XFERS); | |
@@ -1463,27 +1445,27 @@ ahci_bio_start(struct ata_channel *chp, | @@ -1463,27 +1445,27 @@ ahci_bio_start(struct ata_channel *chp, | |||
1463 | if (xfer->c_flags & C_NCQ) | 1445 | if (xfer->c_flags & C_NCQ) | |
1464 | AHCI_WRITE(sc, AHCI_P_SACT(chp->ch_channel), 1U << xfer->c_slot); | 1446 | AHCI_WRITE(sc, AHCI_P_SACT(chp->ch_channel), 1U << xfer->c_slot); | |
1465 | /* start command */ | 1447 | /* start command */ | |
1466 | AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1U << xfer->c_slot); | 1448 | AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1U << xfer->c_slot); | |
1467 | 1449 | |||
1468 | if ((xfer->c_flags & C_POLL) == 0) { | 1450 | if ((xfer->c_flags & C_POLL) == 0) { | |
1469 | callout_reset(&chp->c_timo_callout, mstohz(ATA_DELAY), | 1451 | callout_reset(&chp->c_timo_callout, mstohz(ATA_DELAY), | |
1470 | ata_timeout, chp); | 1452 | ata_timeout, chp); | |
1471 | return ATASTART_STARTED; | 1453 | return ATASTART_STARTED; | |
1472 | } else | 1454 | } else | |
1473 | return ATASTART_POLL; | 1455 | return ATASTART_POLL; | |
1474 | } | 1456 | } | |
1475 | 1457 | |||
1476 | static void | 1458 | static int | |
1477 | ahci_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1459 | ahci_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1478 | { | 1460 | { | |
1479 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | 1461 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | |
1480 | struct ahci_channel *achp = (struct ahci_channel *)chp; | 1462 | struct ahci_channel *achp = (struct ahci_channel *)chp; | |
1481 | 1463 | |||
1482 | /* | 1464 | /* | |
1483 | * Polled command. | 1465 | * Polled command. | |
1484 | */ | 1466 | */ | |
1485 | for (int i = 0; i < ATA_DELAY * 10; i++) { | 1467 | for (int i = 0; i < ATA_DELAY * 10; i++) { | |
1486 | if (xfer->c_bio.flags & ATA_ITSDONE) | 1468 | if (xfer->c_bio.flags & ATA_ITSDONE) | |
1487 | break; | 1469 | break; | |
1488 | ahci_intr_port(achp); | 1470 | ahci_intr_port(achp); | |
1489 | delay(100); | 1471 | delay(100); | |
@@ -1493,26 +1475,27 @@ ahci_bio_poll(struct ata_channel *chp, s | @@ -1493,26 +1475,27 @@ ahci_bio_poll(struct ata_channel *chp, s | |||
1493 | AHCI_READ(sc, AHCI_P_CLBU(chp->ch_channel)), | 1475 | AHCI_READ(sc, AHCI_P_CLBU(chp->ch_channel)), | |
1494 | AHCI_READ(sc, AHCI_P_CLB(chp->ch_channel)), | 1476 | AHCI_READ(sc, AHCI_P_CLB(chp->ch_channel)), | |
1495 | AHCI_READ(sc, AHCI_P_FBU(chp->ch_channel)), | 1477 | AHCI_READ(sc, AHCI_P_FBU(chp->ch_channel)), | |
1496 | AHCI_READ(sc, AHCI_P_FB(chp->ch_channel)), | 1478 | AHCI_READ(sc, AHCI_P_FB(chp->ch_channel)), | |
1497 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)), | 1479 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)), | |
1498 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), | 1480 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), | |
1499 | DEBUG_XFERS); | 1481 | DEBUG_XFERS); | |
1500 | if ((xfer->c_bio.flags & ATA_ITSDONE) == 0) { | 1482 | if ((xfer->c_bio.flags & ATA_ITSDONE) == 0) { | |
1501 | xfer->c_bio.error = TIMEOUT; | 1483 | xfer->c_bio.error = TIMEOUT; | |
1502 | xfer->ops->c_intr(chp, xfer, 0); | 1484 | xfer->ops->c_intr(chp, xfer, 0); | |
1503 | } | 1485 | } | |
1504 | /* reenable interrupts */ | 1486 | /* reenable interrupts */ | |
1505 | AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); | 1487 | AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); | |
1488 | return ATAPOLL_DONE; | |||
1506 | } | 1489 | } | |
1507 | 1490 | |||
1508 | static void | 1491 | static void | |
1509 | ahci_bio_abort(struct ata_channel *chp, struct ata_xfer *xfer) | 1492 | ahci_bio_abort(struct ata_channel *chp, struct ata_xfer *xfer) | |
1510 | { | 1493 | { | |
1511 | ahci_bio_complete(chp, xfer, 0); | 1494 | ahci_bio_complete(chp, xfer, 0); | |
1512 | } | 1495 | } | |
1513 | 1496 | |||
1514 | static void | 1497 | static void | |
1515 | ahci_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason) | 1498 | ahci_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason) | |
1516 | { | 1499 | { | |
1517 | int drive = xfer->c_drive; | 1500 | int drive = xfer->c_drive; | |
1518 | struct ata_bio *ata_bio = &xfer->c_bio; | 1501 | struct ata_bio *ata_bio = &xfer->c_bio; | |
@@ -1960,27 +1943,27 @@ ahci_atapi_start(struct ata_channel *chp | @@ -1960,27 +1943,27 @@ ahci_atapi_start(struct ata_channel *chp | |||
1960 | AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE); | 1943 | AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE); | |
1961 | } | 1944 | } | |
1962 | /* start command */ | 1945 | /* start command */ | |
1963 | AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1U << xfer->c_slot); | 1946 | AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1U << xfer->c_slot); | |
1964 | 1947 | |||
1965 | if ((xfer->c_flags & C_POLL) == 0) { | 1948 | if ((xfer->c_flags & C_POLL) == 0) { | |
1966 | callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), | 1949 | callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), | |
1967 | ata_timeout, chp); | 1950 | ata_timeout, chp); | |
1968 | return ATASTART_STARTED; | 1951 | return ATASTART_STARTED; | |
1969 | } else | 1952 | } else | |
1970 | return ATASTART_POLL; | 1953 | return ATASTART_POLL; | |
1971 | } | 1954 | } | |
1972 | 1955 | |||
1973 | static void | 1956 | static int | |
1974 | ahci_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1957 | ahci_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1975 | { | 1958 | { | |
1976 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | 1959 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | |
1977 | struct ahci_channel *achp = (struct ahci_channel *)chp; | 1960 | struct ahci_channel *achp = (struct ahci_channel *)chp; | |
1978 | 1961 | |||
1979 | /* | 1962 | /* | |
1980 | * Polled command. | 1963 | * Polled command. | |
1981 | */ | 1964 | */ | |
1982 | for (int i = 0; i < ATA_DELAY / 10; i++) { | 1965 | for (int i = 0; i < ATA_DELAY / 10; i++) { | |
1983 | if (xfer->c_scsipi->xs_status & XS_STS_DONE) | 1966 | if (xfer->c_scsipi->xs_status & XS_STS_DONE) | |
1984 | break; | 1967 | break; | |
1985 | ahci_intr_port(achp); | 1968 | ahci_intr_port(achp); | |
1986 | delay(10000); | 1969 | delay(10000); | |
@@ -1990,26 +1973,27 @@ ahci_atapi_poll(struct ata_channel *chp, | @@ -1990,26 +1973,27 @@ ahci_atapi_poll(struct ata_channel *chp, | |||
1990 | AHCI_READ(sc, AHCI_P_CLBU(chp->ch_channel)), | 1973 | AHCI_READ(sc, AHCI_P_CLBU(chp->ch_channel)), | |
1991 | AHCI_READ(sc, AHCI_P_CLB(chp->ch_channel)), | 1974 | AHCI_READ(sc, AHCI_P_CLB(chp->ch_channel)), | |
1992 | AHCI_READ(sc, AHCI_P_FBU(chp->ch_channel)), | 1975 | AHCI_READ(sc, AHCI_P_FBU(chp->ch_channel)), | |
1993 | AHCI_READ(sc, AHCI_P_FB(chp->ch_channel)), | 1976 | AHCI_READ(sc, AHCI_P_FB(chp->ch_channel)), | |
1994 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)), | 1977 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)), | |
1995 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), | 1978 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))), | |
1996 | DEBUG_XFERS); | 1979 | DEBUG_XFERS); | |
1997 | if ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | 1980 | if ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | |
1998 | xfer->c_scsipi->error = XS_TIMEOUT; | 1981 | xfer->c_scsipi->error = XS_TIMEOUT; | |
1999 | xfer->ops->c_intr(chp, xfer, 0); | 1982 | xfer->ops->c_intr(chp, xfer, 0); | |
2000 | } | 1983 | } | |
2001 | /* reenable interrupts */ | 1984 | /* reenable interrupts */ | |
2002 | AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); | 1985 | AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); | |
1986 | return ATAPOLL_DONE; | |||
2003 | } | 1987 | } | |
2004 | 1988 | |||
2005 | static void | 1989 | static void | |
2006 | ahci_atapi_abort(struct ata_channel *chp, struct ata_xfer *xfer) | 1990 | ahci_atapi_abort(struct ata_channel *chp, struct ata_xfer *xfer) | |
2007 | { | 1991 | { | |
2008 | ahci_atapi_complete(chp, xfer, 0); | 1992 | ahci_atapi_complete(chp, xfer, 0); | |
2009 | } | 1993 | } | |
2010 | 1994 | |||
2011 | static int | 1995 | static int | |
2012 | ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int tfd) | 1996 | ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int tfd) | |
2013 | { | 1997 | { | |
2014 | struct scsipi_xfer *sc_xfer = xfer->c_scsipi; | 1998 | struct scsipi_xfer *sc_xfer = xfer->c_scsipi; | |
2015 | struct ahci_channel *achp = (struct ahci_channel *)chp; | 1999 | struct ahci_channel *achp = (struct ahci_channel *)chp; |
--- src/sys/dev/ic/mvsata.c 2019/06/23 06:33:17 1.48
+++ src/sys/dev/ic/mvsata.c 2022/12/30 14:39:09 1.48.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: mvsata.c,v 1.48 2019/06/23 06:33:17 tsutsui Exp $ */ | 1 | /* $NetBSD: mvsata.c,v 1.48.2.1 2022/12/30 14:39:09 martin Exp $ */ | |
2 | /* | 2 | /* | |
3 | * Copyright (c) 2008 KIYOHARA Takashi | 3 | * Copyright (c) 2008 KIYOHARA Takashi | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -16,27 +16,27 @@ | @@ -16,27 +16,27 @@ | |||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | 18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | |
19 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 19 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | 23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
24 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
25 | * POSSIBILITY OF SUCH DAMAGE. | 25 | * POSSIBILITY OF SUCH DAMAGE. | |
26 | */ | 26 | */ | |
27 | 27 | |||
28 | #include <sys/cdefs.h> | 28 | #include <sys/cdefs.h> | |
29 | __KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.48 2019/06/23 06:33:17 tsutsui Exp $"); | 29 | __KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.48.2.1 2022/12/30 14:39:09 martin Exp $"); | |
30 | 30 | |||
31 | #include "opt_mvsata.h" | 31 | #include "opt_mvsata.h" | |
32 | 32 | |||
33 | #include <sys/param.h> | 33 | #include <sys/param.h> | |
34 | #include <sys/buf.h> | 34 | #include <sys/buf.h> | |
35 | #include <sys/bus.h> | 35 | #include <sys/bus.h> | |
36 | #include <sys/cpu.h> | 36 | #include <sys/cpu.h> | |
37 | #include <sys/device.h> | 37 | #include <sys/device.h> | |
38 | #include <sys/disklabel.h> | 38 | #include <sys/disklabel.h> | |
39 | #include <sys/errno.h> | 39 | #include <sys/errno.h> | |
40 | #include <sys/kernel.h> | 40 | #include <sys/kernel.h> | |
41 | #include <sys/malloc.h> | 41 | #include <sys/malloc.h> | |
42 | #include <sys/proc.h> | 42 | #include <sys/proc.h> | |
@@ -111,64 +111,64 @@ int mvsata_debug = 0; | @@ -111,64 +111,64 @@ int mvsata_debug = 0; | |||
111 | #define ATA_DELAY 10000 /* 10s for a drive I/O */ | 111 | #define ATA_DELAY 10000 /* 10s for a drive I/O */ | |
112 | #define ATAPI_DELAY 10 /* 10 ms, this is used only before | 112 | #define ATAPI_DELAY 10 /* 10 ms, this is used only before | |
113 | sending a cmd */ | 113 | sending a cmd */ | |
114 | #define ATAPI_MODE_DELAY 1000 /* 1s, timeout for SET_FEATURE cmds */ | 114 | #define ATAPI_MODE_DELAY 1000 /* 1s, timeout for SET_FEATURE cmds */ | |
115 | 115 | |||
116 | #define MVSATA_MAX_SEGS (MAXPHYS / PAGE_SIZE + 1) | 116 | #define MVSATA_MAX_SEGS (MAXPHYS / PAGE_SIZE + 1) | |
117 | #define MVSATA_EPRD_MAX_SIZE (sizeof(struct eprd) * MVSATA_MAX_SEGS) | 117 | #define MVSATA_EPRD_MAX_SIZE (sizeof(struct eprd) * MVSATA_MAX_SEGS) | |
118 | 118 | |||
119 | 119 | |||
120 | static void mvsata_probe_drive(struct ata_channel *); | 120 | static void mvsata_probe_drive(struct ata_channel *); | |
121 | 121 | |||
122 | #ifndef MVSATA_WITHOUTDMA | 122 | #ifndef MVSATA_WITHOUTDMA | |
123 | static void mvsata_reset_channel(struct ata_channel *, int); | 123 | static void mvsata_reset_channel(struct ata_channel *, int); | |
124 | static int mvsata_bio(struct ata_drive_datas *, struct ata_xfer *); | 124 | static void mvsata_bio(struct ata_drive_datas *, struct ata_xfer *); | |
125 | static void mvsata_reset_drive(struct ata_drive_datas *, int, uint32_t *); | 125 | static void mvsata_reset_drive(struct ata_drive_datas *, int, uint32_t *); | |
126 | static int mvsata_exec_command(struct ata_drive_datas *, struct ata_xfer *); | 126 | static void mvsata_exec_command(struct ata_drive_datas *, struct ata_xfer *); | |
127 | static int mvsata_addref(struct ata_drive_datas *); | 127 | static int mvsata_addref(struct ata_drive_datas *); | |
128 | static void mvsata_delref(struct ata_drive_datas *); | 128 | static void mvsata_delref(struct ata_drive_datas *); | |
129 | static void mvsata_killpending(struct ata_drive_datas *); | 129 | static void mvsata_killpending(struct ata_drive_datas *); | |
130 | 130 | |||
131 | #if NATAPIBUS > 0 | 131 | #if NATAPIBUS > 0 | |
132 | static void mvsata_atapibus_attach(struct atabus_softc *); | 132 | static void mvsata_atapibus_attach(struct atabus_softc *); | |
133 | static void mvsata_atapi_scsipi_request(struct scsipi_channel *, | 133 | static void mvsata_atapi_scsipi_request(struct scsipi_channel *, | |
134 | scsipi_adapter_req_t, void *); | 134 | scsipi_adapter_req_t, void *); | |
135 | static void mvsata_atapi_minphys(struct buf *); | 135 | static void mvsata_atapi_minphys(struct buf *); | |
136 | static void mvsata_atapi_probe_device(struct atapibus_softc *, int); | 136 | static void mvsata_atapi_probe_device(struct atapibus_softc *, int); | |
137 | static void mvsata_atapi_kill_pending(struct scsipi_periph *); | 137 | static void mvsata_atapi_kill_pending(struct scsipi_periph *); | |
138 | #endif | 138 | #endif | |
139 | #endif | 139 | #endif | |
140 | 140 | |||
141 | static void mvsata_setup_channel(struct ata_channel *); | 141 | static void mvsata_setup_channel(struct ata_channel *); | |
142 | 142 | |||
143 | #ifndef MVSATA_WITHOUTDMA | 143 | #ifndef MVSATA_WITHOUTDMA | |
144 | static int mvsata_bio_start(struct ata_channel *, struct ata_xfer *); | 144 | static int mvsata_bio_start(struct ata_channel *, struct ata_xfer *); | |
145 | static int mvsata_bio_intr(struct ata_channel *, struct ata_xfer *, int); | 145 | static int mvsata_bio_intr(struct ata_channel *, struct ata_xfer *, int); | |
146 | static void mvsata_bio_poll(struct ata_channel *, struct ata_xfer *); | 146 | static int mvsata_bio_poll(struct ata_channel *, struct ata_xfer *); | |
147 | static void mvsata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | 147 | static void mvsata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | |
148 | static void mvsata_bio_done(struct ata_channel *, struct ata_xfer *); | 148 | static void mvsata_bio_done(struct ata_channel *, struct ata_xfer *); | |
149 | static int mvsata_bio_ready(struct mvsata_port *, struct ata_bio *, int, | 149 | static int mvsata_bio_ready(struct mvsata_port *, struct ata_bio *, int, | |
150 | int); | 150 | int); | |
151 | static int mvsata_wdc_cmd_start(struct ata_channel *, struct ata_xfer *); | 151 | static int mvsata_wdc_cmd_start(struct ata_channel *, struct ata_xfer *); | |
152 | static int mvsata_wdc_cmd_intr(struct ata_channel *, struct ata_xfer *, int); | 152 | static int mvsata_wdc_cmd_intr(struct ata_channel *, struct ata_xfer *, int); | |
153 | static void mvsata_wdc_cmd_poll(struct ata_channel *, struct ata_xfer *); | 153 | static int mvsata_wdc_cmd_poll(struct ata_channel *, struct ata_xfer *); | |
154 | static void mvsata_wdc_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, | 154 | static void mvsata_wdc_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, | |
155 | int); | 155 | int); | |
156 | static void mvsata_wdc_cmd_done(struct ata_channel *, struct ata_xfer *); | 156 | static void mvsata_wdc_cmd_done(struct ata_channel *, struct ata_xfer *); | |
157 | static void mvsata_wdc_cmd_done_end(struct ata_channel *, struct ata_xfer *); | 157 | static void mvsata_wdc_cmd_done_end(struct ata_channel *, struct ata_xfer *); | |
158 | #if NATAPIBUS > 0 | 158 | #if NATAPIBUS > 0 | |
159 | static int mvsata_atapi_start(struct ata_channel *, struct ata_xfer *); | 159 | static int mvsata_atapi_start(struct ata_channel *, struct ata_xfer *); | |
160 | static int mvsata_atapi_intr(struct ata_channel *, struct ata_xfer *, int); | 160 | static int mvsata_atapi_intr(struct ata_channel *, struct ata_xfer *, int); | |
161 | static void mvsata_atapi_poll(struct ata_channel *, struct ata_xfer *); | 161 | static int mvsata_atapi_poll(struct ata_channel *, struct ata_xfer *); | |
162 | static void mvsata_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, | 162 | static void mvsata_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, | |
163 | int); | 163 | int); | |
164 | static void mvsata_atapi_reset(struct ata_channel *, struct ata_xfer *); | 164 | static void mvsata_atapi_reset(struct ata_channel *, struct ata_xfer *); | |
165 | static void mvsata_atapi_phase_complete(struct ata_xfer *, int); | 165 | static void mvsata_atapi_phase_complete(struct ata_xfer *, int); | |
166 | static void mvsata_atapi_done(struct ata_channel *, struct ata_xfer *); | 166 | static void mvsata_atapi_done(struct ata_channel *, struct ata_xfer *); | |
167 | static void mvsata_atapi_polldsc(void *); | 167 | static void mvsata_atapi_polldsc(void *); | |
168 | #endif | 168 | #endif | |
169 | 169 | |||
170 | static int mvsata_edma_enqueue(struct mvsata_port *, struct ata_xfer *); | 170 | static int mvsata_edma_enqueue(struct mvsata_port *, struct ata_xfer *); | |
171 | static int mvsata_edma_handle(struct mvsata_port *, struct ata_xfer *); | 171 | static int mvsata_edma_handle(struct mvsata_port *, struct ata_xfer *); | |
172 | static int mvsata_edma_wait(struct mvsata_port *, struct ata_xfer *, int); | 172 | static int mvsata_edma_wait(struct mvsata_port *, struct ata_xfer *, int); | |
173 | static void mvsata_edma_rqq_remove(struct mvsata_port *, struct ata_xfer *); | 173 | static void mvsata_edma_rqq_remove(struct mvsata_port *, struct ata_xfer *); | |
174 | #if NATAPIBUS > 0 | 174 | #if NATAPIBUS > 0 | |
@@ -986,51 +986,50 @@ no_edma: | @@ -986,51 +986,50 @@ no_edma: | |||
986 | mvsata_edma_enable(mvport); | 986 | mvsata_edma_enable(mvport); | |
987 | #endif | 987 | #endif | |
988 | } | 988 | } | |
989 | 989 | |||
990 | #ifndef MVSATA_WITHOUTDMA | 990 | #ifndef MVSATA_WITHOUTDMA | |
991 | static const struct ata_xfer_ops mvsata_bio_xfer_ops = { | 991 | static const struct ata_xfer_ops mvsata_bio_xfer_ops = { | |
992 | .c_start = mvsata_bio_start, | 992 | .c_start = mvsata_bio_start, | |
993 | .c_intr = mvsata_bio_intr, | 993 | .c_intr = mvsata_bio_intr, | |
994 | .c_poll = mvsata_bio_poll, | 994 | .c_poll = mvsata_bio_poll, | |
995 | .c_abort = mvsata_bio_done, | 995 | .c_abort = mvsata_bio_done, | |
996 | .c_kill_xfer = mvsata_bio_kill_xfer, | 996 | .c_kill_xfer = mvsata_bio_kill_xfer, | |
997 | }; | 997 | }; | |
998 | 998 | |||
999 | static int | 999 | static void | |
1000 | mvsata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 1000 | mvsata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
1001 | { | 1001 | { | |
1002 | struct ata_channel *chp = drvp->chnl_softc; | 1002 | struct ata_channel *chp = drvp->chnl_softc; | |
1003 | struct atac_softc *atac = chp->ch_atac; | 1003 | struct atac_softc *atac = chp->ch_atac; | |
1004 | struct ata_bio *ata_bio = &xfer->c_bio; | 1004 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1005 | 1005 | |||
1006 | DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, | 1006 | DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, | |
1007 | ("%s:%d: mvsata_bio: drive=%d, blkno=%" PRId64 | 1007 | ("%s:%d: mvsata_bio: drive=%d, blkno=%" PRId64 | |
1008 | ", bcount=%ld\n", device_xname(atac->atac_dev), chp->ch_channel, | 1008 | ", bcount=%ld\n", device_xname(atac->atac_dev), chp->ch_channel, | |
1009 | drvp->drive, ata_bio->blkno, ata_bio->bcount)); | 1009 | drvp->drive, ata_bio->blkno, ata_bio->bcount)); | |
1010 | 1010 | |||
1011 | if (atac->atac_cap & ATAC_CAP_NOIRQ) | 1011 | if (atac->atac_cap & ATAC_CAP_NOIRQ) | |
1012 | ata_bio->flags |= ATA_POLL; | 1012 | ata_bio->flags |= ATA_POLL; | |
1013 | if (ata_bio->flags & ATA_POLL) | 1013 | if (ata_bio->flags & ATA_POLL) | |
1014 | xfer->c_flags |= C_POLL; | 1014 | xfer->c_flags |= C_POLL; | |
1015 | if ((drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && | 1015 | if ((drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && | |
1016 | (ata_bio->flags & ATA_SINGLE) == 0) | 1016 | (ata_bio->flags & ATA_SINGLE) == 0) | |
1017 | xfer->c_flags |= C_DMA; | 1017 | xfer->c_flags |= C_DMA; | |
1018 | xfer->c_drive = drvp->drive; | 1018 | xfer->c_drive = drvp->drive; | |
1019 | xfer->c_databuf = ata_bio->databuf; | 1019 | xfer->c_databuf = ata_bio->databuf; | |
1020 | xfer->c_bcount = ata_bio->bcount; | 1020 | xfer->c_bcount = ata_bio->bcount; | |
1021 | xfer->ops = &mvsata_bio_xfer_ops; | 1021 | xfer->ops = &mvsata_bio_xfer_ops; | |
1022 | ata_exec_xfer(chp, xfer); | 1022 | ata_exec_xfer(chp, xfer); | |
1023 | return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED; | |||
1024 | } | 1023 | } | |
1025 | 1024 | |||
1026 | static int | 1025 | static int | |
1027 | mvsata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | 1026 | mvsata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
1028 | { | 1027 | { | |
1029 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | 1028 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | |
1030 | struct mvsata_softc *sc = device_private(MVSATA_DEV2(mvport)); | 1029 | struct mvsata_softc *sc = device_private(MVSATA_DEV2(mvport)); | |
1031 | struct atac_softc *atac = chp->ch_atac; | 1030 | struct atac_softc *atac = chp->ch_atac; | |
1032 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 1031 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
1033 | struct ata_bio *ata_bio = &xfer->c_bio; | 1032 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1034 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | 1033 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | |
1035 | int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; | 1034 | int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; | |
1036 | u_int16_t cyl; | 1035 | u_int16_t cyl; | |
@@ -1253,44 +1252,43 @@ intr: | @@ -1253,44 +1252,43 @@ intr: | |||
1253 | if ((ata_bio->flags & ATA_POLL) != 0) | 1252 | if ((ata_bio->flags & ATA_POLL) != 0) | |
1254 | return ATASTART_POLL; | 1253 | return ATASTART_POLL; | |
1255 | else | 1254 | else | |
1256 | return ATASTART_STARTED; | 1255 | return ATASTART_STARTED; | |
1257 | 1256 | |||
1258 | timeout: | 1257 | timeout: | |
1259 | aprint_error_dev(atac->atac_dev, | 1258 | aprint_error_dev(atac->atac_dev, | |
1260 | "channel %d: drive %d not ready, st=0x%02x, err=0x%02x\n", | 1259 | "channel %d: drive %d not ready, st=0x%02x, err=0x%02x\n", | |
1261 | chp->ch_channel, xfer->c_drive, ATACH_ST(tfd), ATACH_ERR(tfd)); | 1260 | chp->ch_channel, xfer->c_drive, ATACH_ST(tfd), ATACH_ERR(tfd)); | |
1262 | ata_bio->error = TIMEOUT; | 1261 | ata_bio->error = TIMEOUT; | |
1263 | return ATASTART_ABORT; | 1262 | return ATASTART_ABORT; | |
1264 | } | 1263 | } | |
1265 | 1264 | |||
1266 | static void | 1265 | static int | |
1267 | mvsata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1266 | mvsata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1268 | { | 1267 | { | |
1269 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | 1268 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | |
1270 | struct mvsata_softc *sc = device_private(MVSATA_DEV2(mvport)); | 1269 | struct mvsata_softc *sc = device_private(MVSATA_DEV2(mvport)); | |
1271 | 1270 | |||
1272 | /* Wait for at last 400ns for status bit to be valid */ | 1271 | /* Wait for at last 400ns for status bit to be valid */ | |
1273 | delay(1); | 1272 | delay(1); | |
1274 | if (chp->ch_flags & ATACH_DMA_WAIT) { | 1273 | if (chp->ch_flags & ATACH_DMA_WAIT) { | |
1275 | mvsata_edma_wait(mvport, xfer, ATA_DELAY); | 1274 | mvsata_edma_wait(mvport, xfer, ATA_DELAY); | |
1276 | sc->sc_enable_intr(mvport, 1 /*on*/); | 1275 | sc->sc_enable_intr(mvport, 1 /*on*/); | |
1277 | chp->ch_flags &= ~ATACH_DMA_WAIT; | 1276 | chp->ch_flags &= ~ATACH_DMA_WAIT; | |
1278 | } | 1277 | } | |
1279 | 1278 | |||
1280 | if ((xfer->c_bio.flags & ATA_ITSDONE) == 0) { | 1279 | mvsata_bio_intr(chp, xfer, 0); | |
1281 | KASSERT(xfer->c_flags & C_TIMEOU); | 1280 | ||
1282 | mvsata_bio_intr(chp, xfer, 0); | 1281 | return (xfer->c_bio.flags & ATA_ITSDONE) ? ATAPOLL_DONE : ATAPOLL_AGAIN; | |
1283 | } | |||
1284 | } | 1282 | } | |
1285 | 1283 | |||
1286 | static int | 1284 | static int | |
1287 | mvsata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int intr_arg) | 1285 | mvsata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int intr_arg) | |
1288 | { | 1286 | { | |
1289 | struct atac_softc *atac = chp->ch_atac; | 1287 | struct atac_softc *atac = chp->ch_atac; | |
1290 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 1288 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
1291 | struct ata_bio *ata_bio = &xfer->c_bio; | 1289 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1292 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | 1290 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | |
1293 | int irq = ISSET(xfer->c_flags, (C_POLL|C_TIMEOU)) ? 0 : 1; | 1291 | int irq = ISSET(xfer->c_flags, (C_POLL|C_TIMEOU)) ? 0 : 1; | |
1294 | int tfd = 0; | 1292 | int tfd = 0; | |
1295 | 1293 | |||
1296 | if (ISSET(xfer->c_flags, C_DMA|C_RECOVERED) && irq) { | 1294 | if (ISSET(xfer->c_flags, C_DMA|C_RECOVERED) && irq) { | |
@@ -1393,27 +1391,30 @@ err: | @@ -1393,27 +1391,30 @@ err: | |||
1393 | 1391 | |||
1394 | end: | 1392 | end: | |
1395 | ata_bio->blkno += ata_bio->nblks; | 1393 | ata_bio->blkno += ata_bio->nblks; | |
1396 | ata_bio->blkdone += ata_bio->nblks; | 1394 | ata_bio->blkdone += ata_bio->nblks; | |
1397 | xfer->c_skip += ata_bio->nbytes; | 1395 | xfer->c_skip += ata_bio->nbytes; | |
1398 | xfer->c_bcount -= ata_bio->nbytes; | 1396 | xfer->c_bcount -= ata_bio->nbytes; | |
1399 | 1397 | |||
1400 | /* See if this transfer is complete. */ | 1398 | /* See if this transfer is complete. */ | |
1401 | if (xfer->c_bcount > 0) { | 1399 | if (xfer->c_bcount > 0) { | |
1402 | if ((ata_bio->flags & ATA_POLL) == 0) { | 1400 | if ((ata_bio->flags & ATA_POLL) == 0) { | |
1403 | /* Start the next operation */ | 1401 | /* Start the next operation */ | |
1404 | ata_xfer_start(xfer); | 1402 | ata_xfer_start(xfer); | |
1405 | } else { | 1403 | } else { | |
1406 | /* Let mvsata_bio_start do the loop */ | 1404 | /* | |
1405 | * Let ata_xfer_start() do the loop; | |||
1406 | * see mvsata_bio_poll(). | |||
1407 | */ | |||
1407 | } | 1408 | } | |
1408 | ata_channel_unlock(chp); | 1409 | ata_channel_unlock(chp); | |
1409 | } else { /* Done with this transfer */ | 1410 | } else { /* Done with this transfer */ | |
1410 | ata_bio->error = NOERROR; | 1411 | ata_bio->error = NOERROR; | |
1411 | ata_channel_unlock(chp); | 1412 | ata_channel_unlock(chp); | |
1412 | mvsata_bio_done(chp, xfer); | 1413 | mvsata_bio_done(chp, xfer); | |
1413 | } | 1414 | } | |
1414 | return 1; | 1415 | return 1; | |
1415 | } | 1416 | } | |
1416 | 1417 | |||
1417 | static void | 1418 | static void | |
1418 | mvsata_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason) | 1419 | mvsata_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason) | |
1419 | { | 1420 | { | |
@@ -1602,68 +1603,51 @@ ctrldone: | @@ -1602,68 +1603,51 @@ ctrldone: | |||
1602 | drvp->state = 0; | 1603 | drvp->state = 0; | |
1603 | MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT); | 1604 | MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT); | |
1604 | return -1; | 1605 | return -1; | |
1605 | } | 1606 | } | |
1606 | 1607 | |||
1607 | static const struct ata_xfer_ops mvsata_wdc_cmd_xfer_ops = { | 1608 | static const struct ata_xfer_ops mvsata_wdc_cmd_xfer_ops = { | |
1608 | .c_start = mvsata_wdc_cmd_start, | 1609 | .c_start = mvsata_wdc_cmd_start, | |
1609 | .c_intr = mvsata_wdc_cmd_intr, | 1610 | .c_intr = mvsata_wdc_cmd_intr, | |
1610 | .c_poll = mvsata_wdc_cmd_poll, | 1611 | .c_poll = mvsata_wdc_cmd_poll, | |
1611 | .c_abort = mvsata_wdc_cmd_done, | 1612 | .c_abort = mvsata_wdc_cmd_done, | |
1612 | .c_kill_xfer = mvsata_wdc_cmd_kill_xfer, | 1613 | .c_kill_xfer = mvsata_wdc_cmd_kill_xfer, | |
1613 | }; | 1614 | }; | |
1614 | 1615 | |||
1615 | static int | 1616 | static void | |
1616 | mvsata_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 1617 | mvsata_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
1617 | { | 1618 | { | |
1618 | struct ata_channel *chp = drvp->chnl_softc; | 1619 | struct ata_channel *chp = drvp->chnl_softc; | |
1619 | struct ata_command *ata_c = &xfer->c_ata_c; | 1620 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1620 | int rv, s; | |||
1621 | 1621 | |||
1622 | DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, | 1622 | DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, | |
1623 | ("%s:%d: mvsata_exec_command: drive=%d, bcount=%d," | 1623 | ("%s:%d: mvsata_exec_command: drive=%d, bcount=%d," | |
1624 | " r_lba=0x%012"PRIx64", r_count=0x%04x, r_features=0x%04x," | 1624 | " r_lba=0x%012"PRIx64", r_count=0x%04x, r_features=0x%04x," | |
1625 | " r_device=0x%02x, r_command=0x%02x\n", | 1625 | " r_device=0x%02x, r_command=0x%02x\n", | |
1626 | device_xname(MVSATA_DEV2((struct mvsata_port *)chp)), | 1626 | device_xname(MVSATA_DEV2((struct mvsata_port *)chp)), | |
1627 | chp->ch_channel, | 1627 | chp->ch_channel, | |
1628 | drvp->drive, ata_c->bcount, ata_c->r_lba, ata_c->r_count, | 1628 | drvp->drive, ata_c->bcount, ata_c->r_lba, ata_c->r_count, | |
1629 | ata_c->r_features, ata_c->r_device, ata_c->r_command)); | 1629 | ata_c->r_features, ata_c->r_device, ata_c->r_command)); | |
1630 | 1630 | |||
1631 | if (ata_c->flags & AT_POLL) | 1631 | if (ata_c->flags & AT_POLL) | |
1632 | xfer->c_flags |= C_POLL; | 1632 | xfer->c_flags |= C_POLL; | |
1633 | if (ata_c->flags & AT_WAIT) | 1633 | if (ata_c->flags & AT_WAIT) | |
1634 | xfer->c_flags |= C_WAIT; | 1634 | xfer->c_flags |= C_WAIT; | |
1635 | xfer->c_drive = drvp->drive; | 1635 | xfer->c_drive = drvp->drive; | |
1636 | xfer->c_databuf = ata_c->data; | 1636 | xfer->c_databuf = ata_c->data; | |
1637 | xfer->c_bcount = ata_c->bcount; | 1637 | xfer->c_bcount = ata_c->bcount; | |
1638 | xfer->ops = &mvsata_wdc_cmd_xfer_ops; | 1638 | xfer->ops = &mvsata_wdc_cmd_xfer_ops; | |
1639 | s = splbio(); | 1639 | ||
1640 | ata_exec_xfer(chp, xfer); | 1640 | ata_exec_xfer(chp, xfer); | |
1641 | #ifdef DIAGNOSTIC | |||
1642 | if ((ata_c->flags & AT_POLL) != 0 && | |||
1643 | (ata_c->flags & AT_DONE) == 0) | |||
1644 | panic("mvsata_exec_command: polled command not done"); | |||
1645 | #endif | |||
1646 | if (ata_c->flags & AT_DONE) | |||
1647 | rv = ATACMD_COMPLETE; | |||
1648 | else { | |||
1649 | if (ata_c->flags & AT_WAIT) { | |||
1650 | ata_wait_cmd(chp, xfer); | |||
1651 | rv = ATACMD_COMPLETE; | |||
1652 | } else | |||
1653 | rv = ATACMD_QUEUED; | |||
1654 | } | |||
1655 | splx(s); | |||
1656 | return rv; | |||
1657 | } | 1641 | } | |
1658 | 1642 | |||
1659 | static int | 1643 | static int | |
1660 | mvsata_wdc_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer) | 1644 | mvsata_wdc_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
1661 | { | 1645 | { | |
1662 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | 1646 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | |
1663 | int drive = xfer->c_drive; | 1647 | int drive = xfer->c_drive; | |
1664 | int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; | 1648 | int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; | |
1665 | struct ata_command *ata_c = &xfer->c_ata_c; | 1649 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1666 | int tfd; | 1650 | int tfd; | |
1667 | 1651 | |||
1668 | DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, | 1652 | DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, | |
1669 | ("%s:%d: mvsata_cmd_start: drive=%d\n", | 1653 | ("%s:%d: mvsata_cmd_start: drive=%d\n", | |
@@ -1705,35 +1689,36 @@ mvsata_wdc_cmd_start(struct ata_channel | @@ -1705,35 +1689,36 @@ mvsata_wdc_cmd_start(struct ata_channel | |||
1705 | ata_c->r_count & 0xff, | 1689 | ata_c->r_count & 0xff, | |
1706 | ata_c->r_features & 0xff); | 1690 | ata_c->r_features & 0xff); | |
1707 | } | 1691 | } | |
1708 | 1692 | |||
1709 | if ((ata_c->flags & AT_POLL) == 0) { | 1693 | if ((ata_c->flags & AT_POLL) == 0) { | |
1710 | callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz, | 1694 | callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz, | |
1711 | wdctimeout, chp); | 1695 | wdctimeout, chp); | |
1712 | return ATASTART_STARTED; | 1696 | return ATASTART_STARTED; | |
1713 | } | 1697 | } | |
1714 | 1698 | |||
1715 | return ATASTART_POLL; | 1699 | return ATASTART_POLL; | |
1716 | } | 1700 | } | |
1717 | 1701 | |||
1718 | static void | 1702 | static int | |
1719 | mvsata_wdc_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1703 | mvsata_wdc_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1720 | { | 1704 | { | |
1721 | /* | 1705 | /* | |
1722 | * Polled command. Wait for drive ready or drq. Done in intr(). | 1706 | * Polled command. Wait for drive ready or drq. Done in intr(). | |
1723 | * Wait for at last 400ns for status bit to be valid. | 1707 | * Wait for at last 400ns for status bit to be valid. | |
1724 | */ | 1708 | */ | |
1725 | delay(10); /* 400ns delay */ | 1709 | delay(10); /* 400ns delay */ | |
1726 | mvsata_wdc_cmd_intr(chp, xfer, 0); | 1710 | mvsata_wdc_cmd_intr(chp, xfer, 0); | |
1711 | return ATAPOLL_DONE; | |||
1727 | } | 1712 | } | |
1728 | 1713 | |||
1729 | static int | 1714 | static int | |
1730 | mvsata_wdc_cmd_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | 1715 | mvsata_wdc_cmd_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | |
1731 | { | 1716 | { | |
1732 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | 1717 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | |
1733 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 1718 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
1734 | struct ata_command *ata_c = &xfer->c_ata_c; | 1719 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1735 | int bcount = ata_c->bcount; | 1720 | int bcount = ata_c->bcount; | |
1736 | char *data = ata_c->data; | 1721 | char *data = ata_c->data; | |
1737 | int wflags; | 1722 | int wflags; | |
1738 | int drive_flags; | 1723 | int drive_flags; | |
1739 | int tfd; | 1724 | int tfd; | |
@@ -2190,53 +2175,55 @@ timeout: | @@ -2190,53 +2175,55 @@ timeout: | |||
2190 | return ATASTART_ABORT; | 2175 | return ATASTART_ABORT; | |
2191 | 2176 | |||
2192 | error: | 2177 | error: | |
2193 | aprint_error_dev(atac->atac_dev, | 2178 | aprint_error_dev(atac->atac_dev, | |
2194 | "channel %d drive %d: %s error (0x%x)\n", | 2179 | "channel %d drive %d: %s error (0x%x)\n", | |
2195 | chp->ch_channel, xfer->c_drive, errstring, ATACH_ERR(tfd)); | 2180 | chp->ch_channel, xfer->c_drive, errstring, ATACH_ERR(tfd)); | |
2196 | sc_xfer->error = XS_SHORTSENSE; | 2181 | sc_xfer->error = XS_SHORTSENSE; | |
2197 | sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); | 2182 | sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); | |
2198 | MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT); | 2183 | MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT); | |
2199 | delay(10); /* some drives need a little delay here */ | 2184 | delay(10); /* some drives need a little delay here */ | |
2200 | return ATASTART_ABORT; | 2185 | return ATASTART_ABORT; | |
2201 | } | 2186 | } | |
2202 | 2187 | |||
2203 | static void | 2188 | static int | |
2204 | mvsata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 2189 | mvsata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
2205 | { | 2190 | { | |
2206 | /* | 2191 | /* | |
2207 | * If there is no interrupt for CMD input, busy-wait for it (done in | 2192 | * If there is no interrupt for CMD input, busy-wait for it (done in | |
2208 | * the interrupt routine. If it is a polled command, call the interrupt | 2193 | * the interrupt routine. If it is a polled command, call the interrupt | |
2209 | * routine until command is done. | 2194 | * routine until command is done. | |
2210 | */ | 2195 | */ | |
2211 | const bool poll = ((xfer->c_scsipi->xs_control & XS_CTL_POLL) != 0); | 2196 | const bool poll = ((xfer->c_scsipi->xs_control & XS_CTL_POLL) != 0); | |
2212 | 2197 | |||
2213 | /* Wait for at last 400ns for status bit to be valid */ | 2198 | /* Wait for at last 400ns for status bit to be valid */ | |
2214 | DELAY(1); | 2199 | DELAY(1); | |
2215 | mvsata_atapi_intr(chp, xfer, 0); | 2200 | mvsata_atapi_intr(chp, xfer, 0); | |
2216 | 2201 | |||
2217 | if (!poll) | 2202 | if (!poll) | |
2218 | return; | 2203 | return ATAPOLL_DONE; | |
2219 | 2204 | |||
2220 | if (chp->ch_flags & ATACH_DMA_WAIT) { | 2205 | if (chp->ch_flags & ATACH_DMA_WAIT) { | |
2221 | wdc_dmawait(chp, xfer, xfer->c_scsipi->timeout); | 2206 | wdc_dmawait(chp, xfer, xfer->c_scsipi->timeout); | |
2222 | chp->ch_flags &= ~ATACH_DMA_WAIT; | 2207 | chp->ch_flags &= ~ATACH_DMA_WAIT; | |
2223 | } | 2208 | } | |
2224 | 2209 | |||
2225 | while ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | 2210 | while ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | |
2226 | /* Wait for at last 400ns for status bit to be valid */ | 2211 | /* Wait for at last 400ns for status bit to be valid */ | |
2227 | DELAY(1); | 2212 | DELAY(1); | |
2228 | mvsata_atapi_intr(chp, xfer, 0); | 2213 | mvsata_atapi_intr(chp, xfer, 0); | |
2229 | } | 2214 | } | |
2215 | ||||
2216 | return ATAPOLL_DONE; | |||
2230 | } | 2217 | } | |
2231 | 2218 | |||
2232 | static int | 2219 | static int | |
2233 | mvsata_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | 2220 | mvsata_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | |
2234 | { | 2221 | { | |
2235 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | 2222 | struct mvsata_port *mvport = (struct mvsata_port *)chp; | |
2236 | struct atac_softc *atac = chp->ch_atac; | 2223 | struct atac_softc *atac = chp->ch_atac; | |
2237 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 2224 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
2238 | struct scsipi_xfer *sc_xfer = xfer->c_scsipi; | 2225 | struct scsipi_xfer *sc_xfer = xfer->c_scsipi; | |
2239 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | 2226 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | |
2240 | int len, phase, ire, error, retries=0, i; | 2227 | int len, phase, ire, error, retries=0, i; | |
2241 | int tfd; | 2228 | int tfd; | |
2242 | void *cmd; | 2229 | void *cmd; |
--- src/sys/dev/ic/siisata.c 2018/11/19 19:52:08 1.39
+++ src/sys/dev/ic/siisata.c 2022/12/30 14:39:09 1.39.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: siisata.c,v 1.39 2018/11/19 19:52:08 jdolecek Exp $ */ | 1 | /* $NetBSD: siisata.c,v 1.39.4.1 2022/12/30 14:39:09 martin Exp $ */ | |
2 | 2 | |||
3 | /* from ahcisata_core.c */ | 3 | /* from ahcisata_core.c */ | |
4 | 4 | |||
5 | /* | 5 | /* | |
6 | * Copyright (c) 2006 Manuel Bouyer. | 6 | * Copyright (c) 2006 Manuel Bouyer. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
@@ -69,27 +69,27 @@ | @@ -69,27 +69,27 @@ | |||
69 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 69 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
70 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 70 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
71 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 71 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
72 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 72 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
73 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 73 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
74 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 74 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
75 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 75 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
76 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 76 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
77 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 77 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
78 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 78 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
79 | */ | 79 | */ | |
80 | 80 | |||
81 | #include <sys/cdefs.h> | 81 | #include <sys/cdefs.h> | |
82 | __KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.39 2018/11/19 19:52:08 jdolecek Exp $"); | 82 | __KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.39.4.1 2022/12/30 14:39:09 martin Exp $"); | |
83 | 83 | |||
84 | #include <sys/types.h> | 84 | #include <sys/types.h> | |
85 | #include <sys/param.h> | 85 | #include <sys/param.h> | |
86 | #include <sys/kernel.h> | 86 | #include <sys/kernel.h> | |
87 | #include <sys/malloc.h> | 87 | #include <sys/malloc.h> | |
88 | #include <sys/systm.h> | 88 | #include <sys/systm.h> | |
89 | #include <sys/syslog.h> | 89 | #include <sys/syslog.h> | |
90 | #include <sys/disklabel.h> | 90 | #include <sys/disklabel.h> | |
91 | #include <sys/buf.h> | 91 | #include <sys/buf.h> | |
92 | #include <sys/proc.h> | 92 | #include <sys/proc.h> | |
93 | 93 | |||
94 | #include <dev/ata/atareg.h> | 94 | #include <dev/ata/atareg.h> | |
95 | #include <dev/ata/satavar.h> | 95 | #include <dev/ata/satavar.h> | |
@@ -130,62 +130,62 @@ bus_space_read_region_stream_4(bus_space | @@ -130,62 +130,62 @@ bus_space_read_region_stream_4(bus_space | |||
130 | for (bus_size_t i = 0; i < c; i++) { | 130 | for (bus_size_t i = 0; i < c; i++) { | |
131 | p[i] = htole32(p[i]); | 131 | p[i] = htole32(p[i]); | |
132 | } | 132 | } | |
133 | } | 133 | } | |
134 | #endif | 134 | #endif | |
135 | #endif | 135 | #endif | |
136 | 136 | |||
137 | static void siisata_attach_port(struct siisata_softc *, int); | 137 | static void siisata_attach_port(struct siisata_softc *, int); | |
138 | static void siisata_intr_port(struct siisata_channel *); | 138 | static void siisata_intr_port(struct siisata_channel *); | |
139 | 139 | |||
140 | void siisata_probe_drive(struct ata_channel *); | 140 | void siisata_probe_drive(struct ata_channel *); | |
141 | void siisata_setup_channel(struct ata_channel *); | 141 | void siisata_setup_channel(struct ata_channel *); | |
142 | 142 | |||
143 | int siisata_ata_bio(struct ata_drive_datas *, struct ata_xfer *); | 143 | void siisata_ata_bio(struct ata_drive_datas *, struct ata_xfer *); | |
144 | void siisata_reset_drive(struct ata_drive_datas *, int, uint32_t *); | 144 | void siisata_reset_drive(struct ata_drive_datas *, int, uint32_t *); | |
145 | void siisata_reset_channel(struct ata_channel *, int); | 145 | void siisata_reset_channel(struct ata_channel *, int); | |
146 | int siisata_ata_addref(struct ata_drive_datas *); | 146 | int siisata_ata_addref(struct ata_drive_datas *); | |
147 | void siisata_ata_delref(struct ata_drive_datas *); | 147 | void siisata_ata_delref(struct ata_drive_datas *); | |
148 | void siisata_killpending(struct ata_drive_datas *); | 148 | void siisata_killpending(struct ata_drive_datas *); | |
149 | 149 | |||
150 | int siisata_cmd_start(struct ata_channel *, struct ata_xfer *); | 150 | int siisata_cmd_start(struct ata_channel *, struct ata_xfer *); | |
151 | int siisata_cmd_complete(struct ata_channel *, struct ata_xfer *, int); | 151 | int siisata_cmd_complete(struct ata_channel *, struct ata_xfer *, int); | |
152 | void siisata_cmd_poll(struct ata_channel *, struct ata_xfer *); | 152 | int siisata_cmd_poll(struct ata_channel *, struct ata_xfer *); | |
153 | void siisata_cmd_abort(struct ata_channel *, struct ata_xfer *); | 153 | void siisata_cmd_abort(struct ata_channel *, struct ata_xfer *); | |
154 | void siisata_cmd_done(struct ata_channel *, struct ata_xfer *, int); | 154 | void siisata_cmd_done(struct ata_channel *, struct ata_xfer *, int); | |
155 | static void siisata_cmd_done_end(struct ata_channel *, struct ata_xfer *); | 155 | static void siisata_cmd_done_end(struct ata_channel *, struct ata_xfer *); | |
156 | void siisata_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | 156 | void siisata_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | |
157 | 157 | |||
158 | int siisata_bio_start(struct ata_channel *, struct ata_xfer *); | 158 | int siisata_bio_start(struct ata_channel *, struct ata_xfer *); | |
159 | int siisata_bio_complete(struct ata_channel *, struct ata_xfer *, int); | 159 | int siisata_bio_complete(struct ata_channel *, struct ata_xfer *, int); | |
160 | void siisata_bio_poll(struct ata_channel *, struct ata_xfer *); | 160 | int siisata_bio_poll(struct ata_channel *, struct ata_xfer *); | |
161 | void siisata_bio_abort(struct ata_channel *, struct ata_xfer *); | 161 | void siisata_bio_abort(struct ata_channel *, struct ata_xfer *); | |
162 | void siisata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | 162 | void siisata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | |
163 | int siisata_exec_command(struct ata_drive_datas *, struct ata_xfer *); | 163 | void siisata_exec_command(struct ata_drive_datas *, struct ata_xfer *); | |
164 | 164 | |||
165 | static int siisata_reinit_port(struct ata_channel *, int); | 165 | static int siisata_reinit_port(struct ata_channel *, int); | |
166 | static void siisata_device_reset(struct ata_channel *); | 166 | static void siisata_device_reset(struct ata_channel *); | |
167 | static void siisata_activate_prb(struct siisata_channel *, int); | 167 | static void siisata_activate_prb(struct siisata_channel *, int); | |
168 | static void siisata_deactivate_prb(struct siisata_channel *, int); | 168 | static void siisata_deactivate_prb(struct siisata_channel *, int); | |
169 | static int siisata_dma_setup(struct ata_channel *, int, void *, size_t, int); | 169 | static int siisata_dma_setup(struct ata_channel *, int, void *, size_t, int); | |
170 | static void siisata_channel_recover(struct ata_channel *, int, uint32_t); | 170 | static void siisata_channel_recover(struct ata_channel *, int, uint32_t); | |
171 | 171 | |||
172 | #if NATAPIBUS > 0 | 172 | #if NATAPIBUS > 0 | |
173 | void siisata_atapibus_attach(struct atabus_softc *); | 173 | void siisata_atapibus_attach(struct atabus_softc *); | |
174 | void siisata_atapi_probe_device(struct atapibus_softc *, int); | 174 | void siisata_atapi_probe_device(struct atapibus_softc *, int); | |
175 | void siisata_atapi_minphys(struct buf *); | 175 | void siisata_atapi_minphys(struct buf *); | |
176 | int siisata_atapi_start(struct ata_channel *,struct ata_xfer *); | 176 | int siisata_atapi_start(struct ata_channel *,struct ata_xfer *); | |
177 | int siisata_atapi_complete(struct ata_channel *, struct ata_xfer *, int); | 177 | int siisata_atapi_complete(struct ata_channel *, struct ata_xfer *, int); | |
178 | void siisata_atapi_poll(struct ata_channel *, struct ata_xfer *); | 178 | int siisata_atapi_poll(struct ata_channel *, struct ata_xfer *); | |
179 | void siisata_atapi_abort(struct ata_channel *, struct ata_xfer *); | 179 | void siisata_atapi_abort(struct ata_channel *, struct ata_xfer *); | |
180 | void siisata_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | 180 | void siisata_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | |
181 | void siisata_atapi_scsipi_request(struct scsipi_channel *, | 181 | void siisata_atapi_scsipi_request(struct scsipi_channel *, | |
182 | scsipi_adapter_req_t, void *); | 182 | scsipi_adapter_req_t, void *); | |
183 | void siisata_atapi_kill_pending(struct scsipi_periph *); | 183 | void siisata_atapi_kill_pending(struct scsipi_periph *); | |
184 | #endif /* NATAPIBUS */ | 184 | #endif /* NATAPIBUS */ | |
185 | 185 | |||
186 | const struct ata_bustype siisata_ata_bustype = { | 186 | const struct ata_bustype siisata_ata_bustype = { | |
187 | SCSIPI_BUSTYPE_ATA, | 187 | SCSIPI_BUSTYPE_ATA, | |
188 | siisata_ata_bio, | 188 | siisata_ata_bio, | |
189 | siisata_reset_drive, | 189 | siisata_reset_drive, | |
190 | siisata_reset_channel, | 190 | siisata_reset_channel, | |
191 | siisata_exec_command, | 191 | siisata_exec_command, | |
@@ -920,68 +920,50 @@ void | @@ -920,68 +920,50 @@ void | |||
920 | siisata_setup_channel(struct ata_channel *chp) | 920 | siisata_setup_channel(struct ata_channel *chp) | |
921 | { | 921 | { | |
922 | return; | 922 | return; | |
923 | } | 923 | } | |
924 | 924 | |||
925 | static const struct ata_xfer_ops siisata_cmd_xfer_ops = { | 925 | static const struct ata_xfer_ops siisata_cmd_xfer_ops = { | |
926 | .c_start = siisata_cmd_start, | 926 | .c_start = siisata_cmd_start, | |
927 | .c_intr = siisata_cmd_complete, | 927 | .c_intr = siisata_cmd_complete, | |
928 | .c_poll = siisata_cmd_poll, | 928 | .c_poll = siisata_cmd_poll, | |
929 | .c_abort = siisata_cmd_abort, | 929 | .c_abort = siisata_cmd_abort, | |
930 | .c_kill_xfer = siisata_cmd_kill_xfer, | 930 | .c_kill_xfer = siisata_cmd_kill_xfer, | |
931 | }; | 931 | }; | |
932 | 932 | |||
933 | int | 933 | void | |
934 | siisata_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 934 | siisata_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
935 | { | 935 | { | |
936 | struct ata_channel *chp = drvp->chnl_softc; | 936 | struct ata_channel *chp = drvp->chnl_softc; | |
937 | struct ata_command *ata_c = &xfer->c_ata_c; | 937 | struct ata_command *ata_c = &xfer->c_ata_c; | |
938 | int ret; | |||
939 | int s; | |||
940 | 938 | |||
941 | SIISATA_DEBUG_PRINT(("%s: %s begins\n", | 939 | SIISATA_DEBUG_PRINT(("%s: %s begins\n", | |
942 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | 940 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | |
943 | DEBUG_FUNCS); | 941 | DEBUG_FUNCS); | |
944 | 942 | |||
945 | if (ata_c->flags & AT_POLL) | 943 | if (ata_c->flags & AT_POLL) | |
946 | xfer->c_flags |= C_POLL; | 944 | xfer->c_flags |= C_POLL; | |
947 | if (ata_c->flags & AT_WAIT) | 945 | if (ata_c->flags & AT_WAIT) | |
948 | xfer->c_flags |= C_WAIT; | 946 | xfer->c_flags |= C_WAIT; | |
949 | xfer->c_drive = drvp->drive; | 947 | xfer->c_drive = drvp->drive; | |
950 | xfer->c_databuf = ata_c->data; | 948 | xfer->c_databuf = ata_c->data; | |
951 | xfer->c_bcount = ata_c->bcount; | 949 | xfer->c_bcount = ata_c->bcount; | |
952 | xfer->ops = &siisata_cmd_xfer_ops; | 950 | xfer->ops = &siisata_cmd_xfer_ops; | |
953 | s = splbio(); | 951 | ||
954 | ata_exec_xfer(chp, xfer); | 952 | ata_exec_xfer(chp, xfer); | |
955 | #ifdef DIAGNOSTIC | 953 | ||
956 | if ((ata_c->flags & AT_POLL) != 0 && | |||
957 | (ata_c->flags & AT_DONE) == 0) | |||
958 | panic("%s: polled command not done", __func__); | |||
959 | #endif | |||
960 | if (ata_c->flags & AT_DONE) { | |||
961 | ret = ATACMD_COMPLETE; | |||
962 | } else { | |||
963 | if (ata_c->flags & AT_WAIT) { | |||
964 | ata_wait_cmd(chp, xfer); | |||
965 | ret = ATACMD_COMPLETE; | |||
966 | } else { | |||
967 | ret = ATACMD_QUEUED; | |||
968 | } | |||
969 | } | |||
970 | splx(s); | |||
971 | SIISATA_DEBUG_PRINT( ("%s: %s ends\n", | 954 | SIISATA_DEBUG_PRINT( ("%s: %s ends\n", | |
972 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | 955 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | |
973 | DEBUG_FUNCS); | 956 | DEBUG_FUNCS); | |
974 | return ret; | |||
975 | } | 957 | } | |
976 | 958 | |||
977 | int | 959 | int | |
978 | siisata_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer) | 960 | siisata_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
979 | { | 961 | { | |
980 | struct siisata_channel *schp = (struct siisata_channel *)chp; | 962 | struct siisata_channel *schp = (struct siisata_channel *)chp; | |
981 | struct ata_command *ata_c = &xfer->c_ata_c; | 963 | struct ata_command *ata_c = &xfer->c_ata_c; | |
982 | struct siisata_prb *prb; | 964 | struct siisata_prb *prb; | |
983 | 965 | |||
984 | SIISATA_DEBUG_PRINT(("%s: %s port %d drive %d command 0x%x, slot %d\n", | 966 | SIISATA_DEBUG_PRINT(("%s: %s port %d drive %d command 0x%x, slot %d\n", | |
985 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__, | 967 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__, | |
986 | chp->ch_channel, xfer->c_drive, ata_c->r_command, xfer->c_slot), | 968 | chp->ch_channel, xfer->c_drive, ata_c->r_command, xfer->c_slot), | |
987 | DEBUG_FUNCS|DEBUG_XFERS); | 969 | DEBUG_FUNCS|DEBUG_XFERS); | |
@@ -1015,51 +997,53 @@ siisata_cmd_start(struct ata_channel *ch | @@ -1015,51 +997,53 @@ siisata_cmd_start(struct ata_channel *ch | |||
1015 | } | 997 | } | |
1016 | 998 | |||
1017 | /* go for it */ | 999 | /* go for it */ | |
1018 | siisata_activate_prb(schp, xfer->c_slot); | 1000 | siisata_activate_prb(schp, xfer->c_slot); | |
1019 | 1001 | |||
1020 | if ((ata_c->flags & AT_POLL) == 0) { | 1002 | if ((ata_c->flags & AT_POLL) == 0) { | |
1021 | callout_reset(&chp->c_timo_callout, mstohz(ata_c->timeout), | 1003 | callout_reset(&chp->c_timo_callout, mstohz(ata_c->timeout), | |
1022 | ata_timeout, chp); | 1004 | ata_timeout, chp); | |
1023 | return ATASTART_STARTED; | 1005 | return ATASTART_STARTED; | |
1024 | } else | 1006 | } else | |
1025 | return ATASTART_POLL; | 1007 | return ATASTART_POLL; | |
1026 | } | 1008 | } | |
1027 | 1009 | |||
1028 | void | 1010 | int | |
1029 | siisata_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1011 | siisata_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1030 | { | 1012 | { | |
1031 | struct siisata_channel *schp = (struct siisata_channel *)chp; | 1013 | struct siisata_channel *schp = (struct siisata_channel *)chp; | |
1032 | 1014 | |||
1033 | /* | 1015 | /* | |
1034 | * polled command | 1016 | * polled command | |
1035 | */ | 1017 | */ | |
1036 | for (int i = 0; i < xfer->c_ata_c.timeout * 10; i++) { | 1018 | for (int i = 0; i < xfer->c_ata_c.timeout * 10; i++) { | |
1037 | if (xfer->c_ata_c.flags & AT_DONE) | 1019 | if (xfer->c_ata_c.flags & AT_DONE) | |
1038 | break; | 1020 | break; | |
1039 | siisata_intr_port(schp); | 1021 | siisata_intr_port(schp); | |
1040 | DELAY(100); | 1022 | DELAY(100); | |
1041 | } | 1023 | } | |
1042 | 1024 | |||
1043 | if ((xfer->c_ata_c.flags & AT_DONE) == 0) { | 1025 | if ((xfer->c_ata_c.flags & AT_DONE) == 0) { | |
1044 | ata_timeout(xfer); | 1026 | ata_timeout(xfer); | |
1045 | } | 1027 | } | |
1046 | 1028 | |||
1047 | /* reenable interrupts */ | 1029 | /* reenable interrupts */ | |
1048 | siisata_enable_port_interrupt(chp); | 1030 | siisata_enable_port_interrupt(chp); | |
1049 | 1031 | |||
1050 | SIISATA_DEBUG_PRINT(("%s: %s: done\n", | 1032 | SIISATA_DEBUG_PRINT(("%s: %s: done\n", | |
1051 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | 1033 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | |
1052 | DEBUG_FUNCS); | 1034 | DEBUG_FUNCS); | |
1035 | ||||
1036 | return ATAPOLL_DONE; | |||
1053 | } | 1037 | } | |
1054 | 1038 | |||
1055 | void | 1039 | void | |
1056 | siisata_cmd_abort(struct ata_channel *chp, struct ata_xfer *xfer) | 1040 | siisata_cmd_abort(struct ata_channel *chp, struct ata_xfer *xfer) | |
1057 | { | 1041 | { | |
1058 | siisata_cmd_complete(chp, xfer, 0); | 1042 | siisata_cmd_complete(chp, xfer, 0); | |
1059 | } | 1043 | } | |
1060 | 1044 | |||
1061 | void | 1045 | void | |
1062 | siisata_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, | 1046 | siisata_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, | |
1063 | int reason) | 1047 | int reason) | |
1064 | { | 1048 | { | |
1065 | struct ata_command *ata_c = &xfer->c_ata_c; | 1049 | struct ata_command *ata_c = &xfer->c_ata_c; | |
@@ -1180,47 +1164,43 @@ siisata_cmd_done_end(struct ata_channel | @@ -1180,47 +1164,43 @@ siisata_cmd_done_end(struct ata_channel | |||
1180 | struct ata_command *ata_c = &xfer->c_ata_c; | 1164 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1181 | 1165 | |||
1182 | ata_c->flags |= AT_DONE; | 1166 | ata_c->flags |= AT_DONE; | |
1183 | } | 1167 | } | |
1184 | 1168 | |||
1185 | static const struct ata_xfer_ops siisata_bio_xfer_ops = { | 1169 | static const struct ata_xfer_ops siisata_bio_xfer_ops = { | |
1186 | .c_start = siisata_bio_start, | 1170 | .c_start = siisata_bio_start, | |
1187 | .c_intr = siisata_bio_complete, | 1171 | .c_intr = siisata_bio_complete, | |
1188 | .c_poll = siisata_bio_poll, | 1172 | .c_poll = siisata_bio_poll, | |
1189 | .c_abort = siisata_bio_abort, | 1173 | .c_abort = siisata_bio_abort, | |
1190 | .c_kill_xfer = siisata_bio_kill_xfer, | 1174 | .c_kill_xfer = siisata_bio_kill_xfer, | |
1191 | }; | 1175 | }; | |
1192 | 1176 | |||
1193 | int | 1177 | void | |
1194 | siisata_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 1178 | siisata_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
1195 | { | 1179 | { | |
1196 | struct ata_channel *chp = drvp->chnl_softc; | 1180 | struct ata_channel *chp = drvp->chnl_softc; | |
1197 | struct ata_bio *ata_bio = &xfer->c_bio; | 1181 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1198 | 1182 | |||
1199 | SIISATA_DEBUG_PRINT(("%s: %s.\n", | 1183 | SIISATA_DEBUG_PRINT(("%s: %s.\n", | |
1200 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | 1184 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | |
1201 | DEBUG_FUNCS); | 1185 | DEBUG_FUNCS); | |
1202 | 1186 | |||
1203 | if (xfer == NULL) | |||
1204 | return ATACMD_TRY_AGAIN; | |||
1205 | if (ata_bio->flags & ATA_POLL) | 1187 | if (ata_bio->flags & ATA_POLL) | |
1206 | xfer->c_flags |= C_POLL; | 1188 | xfer->c_flags |= C_POLL; | |
1207 | xfer->c_drive = drvp->drive; | 1189 | xfer->c_drive = drvp->drive; | |
1208 | xfer->c_databuf = ata_bio->databuf; | 1190 | xfer->c_databuf = ata_bio->databuf; | |
1209 | xfer->c_bcount = ata_bio->bcount; | 1191 | xfer->c_bcount = ata_bio->bcount; | |
1210 | xfer->ops = &siisata_bio_xfer_ops; | 1192 | xfer->ops = &siisata_bio_xfer_ops; | |
1211 | ata_exec_xfer(chp, xfer); | 1193 | ata_exec_xfer(chp, xfer); | |
1212 | return (ata_bio->flags & ATA_ITSDONE) ? | |||
1213 | ATACMD_COMPLETE : ATACMD_QUEUED; | |||
1214 | } | 1194 | } | |
1215 | 1195 | |||
1216 | int | 1196 | int | |
1217 | siisata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | 1197 | siisata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
1218 | { | 1198 | { | |
1219 | struct siisata_channel *schp = (struct siisata_channel *)chp; | 1199 | struct siisata_channel *schp = (struct siisata_channel *)chp; | |
1220 | struct siisata_prb *prb; | 1200 | struct siisata_prb *prb; | |
1221 | struct ata_bio *ata_bio = &xfer->c_bio; | 1201 | struct ata_bio *ata_bio = &xfer->c_bio; | |
1222 | 1202 | |||
1223 | SIISATA_DEBUG_PRINT(("%s: %s port %d slot %d drive %d\n", | 1203 | SIISATA_DEBUG_PRINT(("%s: %s port %d slot %d drive %d\n", | |
1224 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__, | 1204 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__, | |
1225 | chp->ch_channel, xfer->c_slot, xfer->c_drive), DEBUG_FUNCS); | 1205 | chp->ch_channel, xfer->c_slot, xfer->c_drive), DEBUG_FUNCS); | |
1226 | 1206 | |||
@@ -1246,50 +1226,52 @@ siisata_bio_start(struct ata_channel *ch | @@ -1246,50 +1226,52 @@ siisata_bio_start(struct ata_channel *ch | |||
1246 | siisata_disable_port_interrupt(chp); | 1226 | siisata_disable_port_interrupt(chp); | |
1247 | } | 1227 | } | |
1248 | 1228 | |||
1249 | siisata_activate_prb(schp, xfer->c_slot); | 1229 | siisata_activate_prb(schp, xfer->c_slot); | |
1250 | 1230 | |||
1251 | if ((ata_bio->flags & ATA_POLL) == 0) { | 1231 | if ((ata_bio->flags & ATA_POLL) == 0) { | |
1252 | callout_reset(&chp->c_timo_callout, mstohz(ATA_DELAY), | 1232 | callout_reset(&chp->c_timo_callout, mstohz(ATA_DELAY), | |
1253 | ata_timeout, chp); | 1233 | ata_timeout, chp); | |
1254 | return ATASTART_STARTED; | 1234 | return ATASTART_STARTED; | |
1255 | } else | 1235 | } else | |
1256 | return ATASTART_POLL; | 1236 | return ATASTART_POLL; | |
1257 | } | 1237 | } | |
1258 | 1238 | |||
1259 | void | 1239 | int | |
1260 | siisata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1240 | siisata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1261 | { | 1241 | { | |
1262 | struct siisata_channel *schp = (struct siisata_channel *)chp; | 1242 | struct siisata_channel *schp = (struct siisata_channel *)chp; | |
1263 | 1243 | |||
1264 | /* | 1244 | /* | |
1265 | * polled command | 1245 | * polled command | |
1266 | */ | 1246 | */ | |
1267 | for (int i = 0; i < ATA_DELAY * 10; i++) { | 1247 | for (int i = 0; i < ATA_DELAY * 10; i++) { | |
1268 | if (xfer->c_bio.flags & ATA_ITSDONE) | 1248 | if (xfer->c_bio.flags & ATA_ITSDONE) | |
1269 | break; | 1249 | break; | |
1270 | siisata_intr_port(schp); | 1250 | siisata_intr_port(schp); | |
1271 | DELAY(100); | 1251 | DELAY(100); | |
1272 | } | 1252 | } | |
1273 | 1253 | |||
1274 | if ((xfer->c_bio.flags & ATA_ITSDONE) == 0) { | 1254 | if ((xfer->c_bio.flags & ATA_ITSDONE) == 0) { | |
1275 | ata_timeout(xfer); | 1255 | ata_timeout(xfer); | |
1276 | } | 1256 | } | |
1277 | 1257 | |||
1278 | siisata_enable_port_interrupt(chp); | 1258 | siisata_enable_port_interrupt(chp); | |
1279 | 1259 | |||
1280 | SIISATA_DEBUG_PRINT(("%s: %s: done\n", | 1260 | SIISATA_DEBUG_PRINT(("%s: %s: done\n", | |
1281 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | 1261 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | |
1282 | DEBUG_FUNCS); | 1262 | DEBUG_FUNCS); | |
1263 | ||||
1264 | return ATAPOLL_DONE; | |||
1283 | } | 1265 | } | |
1284 | 1266 | |||
1285 | void | 1267 | void | |
1286 | siisata_bio_abort(struct ata_channel *chp, struct ata_xfer *xfer) | 1268 | siisata_bio_abort(struct ata_channel *chp, struct ata_xfer *xfer) | |
1287 | { | 1269 | { | |
1288 | siisata_cmd_complete(chp, xfer, 0); | 1270 | siisata_cmd_complete(chp, xfer, 0); | |
1289 | } | 1271 | } | |
1290 | 1272 | |||
1291 | void | 1273 | void | |
1292 | siisata_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, | 1274 | siisata_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, | |
1293 | int reason) | 1275 | int reason) | |
1294 | { | 1276 | { | |
1295 | struct siisata_channel *schp = (struct siisata_channel *)chp; | 1277 | struct siisata_channel *schp = (struct siisata_channel *)chp; | |
@@ -1855,49 +1837,51 @@ siisata_atapi_start(struct ata_channel * | @@ -1855,49 +1837,51 @@ siisata_atapi_start(struct ata_channel * | |||
1855 | siisata_disable_port_interrupt(chp); | 1837 | siisata_disable_port_interrupt(chp); | |
1856 | } | 1838 | } | |
1857 | 1839 | |||
1858 | siisata_activate_prb(schp, xfer->c_slot); | 1840 | siisata_activate_prb(schp, xfer->c_slot); | |
1859 | 1841 | |||
1860 | if ((xfer->c_flags & C_POLL) == 0) { | 1842 | if ((xfer->c_flags & C_POLL) == 0) { | |
1861 | callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), | 1843 | callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), | |
1862 | ata_timeout, chp); | 1844 | ata_timeout, chp); | |
1863 | return ATASTART_STARTED; | 1845 | return ATASTART_STARTED; | |
1864 | } else | 1846 | } else | |
1865 | return ATASTART_POLL; | 1847 | return ATASTART_POLL; | |
1866 | } | 1848 | } | |
1867 | 1849 | |||
1868 | void | 1850 | int | |
1869 | siisata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1851 | siisata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1870 | { | 1852 | { | |
1871 | struct siisata_channel *schp = (struct siisata_channel *)chp; | 1853 | struct siisata_channel *schp = (struct siisata_channel *)chp; | |
1872 | 1854 | |||
1873 | /* | 1855 | /* | |
1874 | * polled command | 1856 | * polled command | |
1875 | */ | 1857 | */ | |
1876 | for (int i = 0; i < ATA_DELAY * 10; i++) { | 1858 | for (int i = 0; i < ATA_DELAY * 10; i++) { | |
1877 | if (xfer->c_scsipi->xs_status & XS_STS_DONE) | 1859 | if (xfer->c_scsipi->xs_status & XS_STS_DONE) | |
1878 | break; | 1860 | break; | |
1879 | siisata_intr_port(schp); | 1861 | siisata_intr_port(schp); | |
1880 | DELAY(100); | 1862 | DELAY(100); | |
1881 | } | 1863 | } | |
1882 | if ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | 1864 | if ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | |
1883 | ata_timeout(xfer); | 1865 | ata_timeout(xfer); | |
1884 | } | 1866 | } | |
1885 | /* reenable interrupts */ | 1867 | /* reenable interrupts */ | |
1886 | siisata_enable_port_interrupt(chp); | 1868 | siisata_enable_port_interrupt(chp); | |
1887 | 1869 | |||
1888 | SIISATA_DEBUG_PRINT(("%s: %s: done\n", | 1870 | SIISATA_DEBUG_PRINT(("%s: %s: done\n", | |
1889 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | 1871 | SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), | |
1890 | DEBUG_FUNCS); | 1872 | DEBUG_FUNCS); | |
1873 | ||||
1874 | return ATAPOLL_DONE; | |||
1891 | } | 1875 | } | |
1892 | 1876 | |||
1893 | void | 1877 | void | |
1894 | siisata_atapi_abort(struct ata_channel *chp, struct ata_xfer *xfer) | 1878 | siisata_atapi_abort(struct ata_channel *chp, struct ata_xfer *xfer) | |
1895 | { | 1879 | { | |
1896 | siisata_atapi_complete(chp, xfer, 0); | 1880 | siisata_atapi_complete(chp, xfer, 0); | |
1897 | } | 1881 | } | |
1898 | 1882 | |||
1899 | int | 1883 | int | |
1900 | siisata_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, | 1884 | siisata_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, | |
1901 | int tfd) | 1885 | int tfd) | |
1902 | { | 1886 | { | |
1903 | struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac; | 1887 | struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac; |
--- src/sys/dev/ic/wdc.c 2019/09/23 07:09:47 1.291.4.1
+++ src/sys/dev/ic/wdc.c 2022/12/30 14:39:09 1.291.4.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: wdc.c,v 1.291.4.1 2019/09/23 07:09:47 martin Exp $ */ | 1 | /* $NetBSD: wdc.c,v 1.291.4.2 2022/12/30 14:39:09 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved. | 4 | * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -48,27 +48,27 @@ | @@ -48,27 +48,27 @@ | |||
48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
49 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 49 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
51 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 51 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
52 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 52 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
53 | * POSSIBILITY OF SUCH DAMAGE. | 53 | * POSSIBILITY OF SUCH DAMAGE. | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | /* | 56 | /* | |
57 | * CODE UNTESTED IN THE CURRENT REVISION: | 57 | * CODE UNTESTED IN THE CURRENT REVISION: | |
58 | */ | 58 | */ | |
59 | 59 | |||
60 | #include <sys/cdefs.h> | 60 | #include <sys/cdefs.h> | |
61 | __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.291.4.1 2019/09/23 07:09:47 martin Exp $"); | 61 | __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.291.4.2 2022/12/30 14:39:09 martin Exp $"); | |
62 | 62 | |||
63 | #include "opt_ata.h" | 63 | #include "opt_ata.h" | |
64 | #include "opt_wdc.h" | 64 | #include "opt_wdc.h" | |
65 | 65 | |||
66 | #include <sys/param.h> | 66 | #include <sys/param.h> | |
67 | #include <sys/systm.h> | 67 | #include <sys/systm.h> | |
68 | #include <sys/kernel.h> | 68 | #include <sys/kernel.h> | |
69 | #include <sys/conf.h> | 69 | #include <sys/conf.h> | |
70 | #include <sys/buf.h> | 70 | #include <sys/buf.h> | |
71 | #include <sys/device.h> | 71 | #include <sys/device.h> | |
72 | #include <sys/malloc.h> | 72 | #include <sys/malloc.h> | |
73 | #include <sys/syslog.h> | 73 | #include <sys/syslog.h> | |
74 | #include <sys/proc.h> | 74 | #include <sys/proc.h> | |
@@ -138,27 +138,27 @@ const struct ata_bustype wdc_ata_bustype | @@ -138,27 +138,27 @@ const struct ata_bustype wdc_ata_bustype | |||
138 | .ata_recovery = NULL, | 138 | .ata_recovery = NULL, | |
139 | }; | 139 | }; | |
140 | #endif | 140 | #endif | |
141 | 141 | |||
142 | /* Flags to wdcreset(). */ | 142 | /* Flags to wdcreset(). */ | |
143 | #define RESET_POLL 1 | 143 | #define RESET_POLL 1 | |
144 | #define RESET_SLEEP 0 /* wdcreset() will use kpause() */ | 144 | #define RESET_SLEEP 0 /* wdcreset() will use kpause() */ | |
145 | 145 | |||
146 | static int wdcprobe1(struct ata_channel *, int); | 146 | static int wdcprobe1(struct ata_channel *, int); | |
147 | static int wdcreset(struct ata_channel *, int); | 147 | static int wdcreset(struct ata_channel *, int); | |
148 | static void __wdcerror(struct ata_channel *, const char *); | 148 | static void __wdcerror(struct ata_channel *, const char *); | |
149 | static int __wdcwait_reset(struct ata_channel *, int, int); | 149 | static int __wdcwait_reset(struct ata_channel *, int, int); | |
150 | static void __wdccommand_done(struct ata_channel *, struct ata_xfer *); | 150 | static void __wdccommand_done(struct ata_channel *, struct ata_xfer *); | |
151 | static void __wdccommand_poll(struct ata_channel *, struct ata_xfer *); | 151 | static int __wdccommand_poll(struct ata_channel *, struct ata_xfer *); | |
152 | static void __wdccommand_done_end(struct ata_channel *, struct ata_xfer *); | 152 | static void __wdccommand_done_end(struct ata_channel *, struct ata_xfer *); | |
153 | static void __wdccommand_kill_xfer(struct ata_channel *, | 153 | static void __wdccommand_kill_xfer(struct ata_channel *, | |
154 | struct ata_xfer *, int); | 154 | struct ata_xfer *, int); | |
155 | static int __wdccommand_start(struct ata_channel *, struct ata_xfer *); | 155 | static int __wdccommand_start(struct ata_channel *, struct ata_xfer *); | |
156 | static int __wdccommand_intr(struct ata_channel *, struct ata_xfer *, int); | 156 | static int __wdccommand_intr(struct ata_channel *, struct ata_xfer *, int); | |
157 | static int __wdcwait(struct ata_channel *, int, int, int, int *); | 157 | static int __wdcwait(struct ata_channel *, int, int, int, int *); | |
158 | 158 | |||
159 | static void wdc_datain_pio(struct ata_channel *, int, void *, size_t); | 159 | static void wdc_datain_pio(struct ata_channel *, int, void *, size_t); | |
160 | static void wdc_dataout_pio(struct ata_channel *, int, void *, size_t); | 160 | static void wdc_dataout_pio(struct ata_channel *, int, void *, size_t); | |
161 | #define DEBUG_INTR 0x01 | 161 | #define DEBUG_INTR 0x01 | |
162 | #define DEBUG_XFERS 0x02 | 162 | #define DEBUG_XFERS 0x02 | |
163 | #define DEBUG_STATUS 0x04 | 163 | #define DEBUG_STATUS 0x04 | |
164 | #define DEBUG_FUNCS 0x08 | 164 | #define DEBUG_FUNCS 0x08 | |
@@ -1380,68 +1380,49 @@ wdctimeout(void *arg) | @@ -1380,68 +1380,49 @@ wdctimeout(void *arg) | |||
1380 | 1380 | |||
1381 | out: | 1381 | out: | |
1382 | splx(s); | 1382 | splx(s); | |
1383 | } | 1383 | } | |
1384 | 1384 | |||
1385 | static const struct ata_xfer_ops wdc_cmd_xfer_ops = { | 1385 | static const struct ata_xfer_ops wdc_cmd_xfer_ops = { | |
1386 | .c_start = __wdccommand_start, | 1386 | .c_start = __wdccommand_start, | |
1387 | .c_poll = __wdccommand_poll, | 1387 | .c_poll = __wdccommand_poll, | |
1388 | .c_abort = __wdccommand_done, | 1388 | .c_abort = __wdccommand_done, | |
1389 | .c_intr = __wdccommand_intr, | 1389 | .c_intr = __wdccommand_intr, | |
1390 | .c_kill_xfer = __wdccommand_kill_xfer, | 1390 | .c_kill_xfer = __wdccommand_kill_xfer, | |
1391 | }; | 1391 | }; | |
1392 | 1392 | |||
1393 | int | 1393 | void | |
1394 | wdc_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | 1394 | wdc_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer) | |
1395 | { | 1395 | { | |
1396 | struct ata_channel *chp = drvp->chnl_softc; | 1396 | struct ata_channel *chp = drvp->chnl_softc; | |
1397 | struct ata_command *ata_c = &xfer->c_ata_c; | 1397 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1398 | int s, ret; | |||
1399 | 1398 | |||
1400 | ATADEBUG_PRINT(("wdc_exec_command %s:%d:%d\n", | 1399 | ATADEBUG_PRINT(("wdc_exec_command %s:%d:%d\n", | |
1401 | device_xname(chp->ch_atac->atac_dev), chp->ch_channel, | 1400 | device_xname(chp->ch_atac->atac_dev), chp->ch_channel, | |
1402 | drvp->drive), DEBUG_FUNCS); | 1401 | drvp->drive), DEBUG_FUNCS); | |
1403 | 1402 | |||
1404 | /* set up an xfer and queue. Wait for completion */ | 1403 | /* set up an xfer and queue. Wait for completion */ | |
1405 | if (chp->ch_atac->atac_cap & ATAC_CAP_NOIRQ) | 1404 | if (chp->ch_atac->atac_cap & ATAC_CAP_NOIRQ) | |
1406 | ata_c->flags |= AT_POLL; | 1405 | ata_c->flags |= AT_POLL; | |
1407 | if (ata_c->flags & AT_POLL) | 1406 | if (ata_c->flags & AT_POLL) | |
1408 | xfer->c_flags |= C_POLL; | 1407 | xfer->c_flags |= C_POLL; | |
1409 | if (ata_c->flags & AT_WAIT) | 1408 | if (ata_c->flags & AT_WAIT) | |
1410 | xfer->c_flags |= C_WAIT; | 1409 | xfer->c_flags |= C_WAIT; | |
1411 | xfer->c_drive = drvp->drive; | 1410 | xfer->c_drive = drvp->drive; | |
1412 | xfer->c_databuf = ata_c->data; | 1411 | xfer->c_databuf = ata_c->data; | |
1413 | xfer->c_bcount = ata_c->bcount; | 1412 | xfer->c_bcount = ata_c->bcount; | |
1414 | xfer->ops = &wdc_cmd_xfer_ops; | 1413 | xfer->ops = &wdc_cmd_xfer_ops; | |
1415 | 1414 | |||
1416 | s = splbio(); | |||
1417 | ata_exec_xfer(chp, xfer); | 1415 | ata_exec_xfer(chp, xfer); | |
1418 | #ifdef DIAGNOSTIC | |||
1419 | if ((ata_c->flags & AT_POLL) != 0 && | |||
1420 | (ata_c->flags & AT_DONE) == 0) | |||
1421 | panic("wdc_exec_command: polled command not done"); | |||
1422 | #endif | |||
1423 | if (ata_c->flags & AT_DONE) { | |||
1424 | ret = ATACMD_COMPLETE; | |||
1425 | } else { | |||
1426 | if (ata_c->flags & AT_WAIT) { | |||
1427 | ata_wait_cmd(chp, xfer); | |||
1428 | ret = ATACMD_COMPLETE; | |||
1429 | } else { | |||
1430 | ret = ATACMD_QUEUED; | |||
1431 | } | |||
1432 | } | |||
1433 | splx(s); | |||
1434 | return ret; | |||
1435 | } | 1416 | } | |
1436 | 1417 | |||
1437 | static int | 1418 | static int | |
1438 | __wdccommand_start(struct ata_channel *chp, struct ata_xfer *xfer) | 1419 | __wdccommand_start(struct ata_channel *chp, struct ata_xfer *xfer) | |
1439 | { | 1420 | { | |
1440 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 1421 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
1441 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | 1422 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | |
1442 | int drive = xfer->c_drive; | 1423 | int drive = xfer->c_drive; | |
1443 | int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; | 1424 | int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; | |
1444 | struct ata_command *ata_c = &xfer->c_ata_c; | 1425 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1445 | int tfd; | 1426 | int tfd; | |
1446 | 1427 | |||
1447 | ATADEBUG_PRINT(("__wdccommand_start %s:%d:%d\n", | 1428 | ATADEBUG_PRINT(("__wdccommand_start %s:%d:%d\n", | |
@@ -1488,30 +1469,31 @@ __wdccommand_start(struct ata_channel *c | @@ -1488,30 +1469,31 @@ __wdccommand_start(struct ata_channel *c | |||
1488 | callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz, | 1469 | callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz, | |
1489 | wdctimeout, chp); | 1470 | wdctimeout, chp); | |
1490 | return ATASTART_STARTED; | 1471 | return ATASTART_STARTED; | |
1491 | } | 1472 | } | |
1492 | 1473 | |||
1493 | /* | 1474 | /* | |
1494 | * Polled command. Wait for drive ready or drq. Done in intr(). | 1475 | * Polled command. Wait for drive ready or drq. Done in intr(). | |
1495 | * Wait for at last 400ns for status bit to be valid. | 1476 | * Wait for at last 400ns for status bit to be valid. | |
1496 | */ | 1477 | */ | |
1497 | delay(10); /* 400ns delay */ | 1478 | delay(10); /* 400ns delay */ | |
1498 | return ATASTART_POLL; | 1479 | return ATASTART_POLL; | |
1499 | } | 1480 | } | |
1500 | 1481 | |||
1501 | static void | 1482 | static int | |
1502 | __wdccommand_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 1483 | __wdccommand_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
1503 | { | 1484 | { | |
1504 | __wdccommand_intr(chp, xfer, 0); | 1485 | __wdccommand_intr(chp, xfer, 0); | |
1486 | return ATAPOLL_DONE; | |||
1505 | } | 1487 | } | |
1506 | 1488 | |||
1507 | static int | 1489 | static int | |
1508 | __wdccommand_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | 1490 | __wdccommand_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | |
1509 | { | 1491 | { | |
1510 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 1492 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
1511 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | 1493 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | |
1512 | struct ata_command *ata_c = &xfer->c_ata_c; | 1494 | struct ata_command *ata_c = &xfer->c_ata_c; | |
1513 | int bcount = ata_c->bcount; | 1495 | int bcount = ata_c->bcount; | |
1514 | char *data = ata_c->data; | 1496 | char *data = ata_c->data; | |
1515 | int wflags, tfd; | 1497 | int wflags, tfd; | |
1516 | int drive_flags; | 1498 | int drive_flags; | |
1517 | 1499 |
--- src/sys/dev/ic/wdcvar.h 2019/09/23 07:09:47 1.98.10.1
+++ src/sys/dev/ic/wdcvar.h 2022/12/30 14:39:10 1.98.10.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: wdcvar.h,v 1.98.10.1 2019/09/23 07:09:47 martin Exp $ */ | 1 | /* $NetBSD: wdcvar.h,v 1.98.10.2 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2003, 2004 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, by Onno van der Linden and by Manuel Bouyer. | 8 | * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer. | |
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. | |
@@ -165,27 +165,27 @@ int wdcwait(struct ata_channel *, int, i | @@ -165,27 +165,27 @@ int wdcwait(struct ata_channel *, int, i | |||
165 | void wdcbit_bucket(struct ata_channel *, int); | 165 | void wdcbit_bucket(struct ata_channel *, int); | |
166 | 166 | |||
167 | int wdc_dmawait(struct ata_channel *, struct ata_xfer *, int); | 167 | int wdc_dmawait(struct ata_channel *, struct ata_xfer *, int); | |
168 | void wdccommand(struct ata_channel *, u_int8_t, u_int8_t, u_int16_t, | 168 | void wdccommand(struct ata_channel *, u_int8_t, u_int8_t, u_int16_t, | |
169 | u_int8_t, u_int8_t, u_int8_t, u_int8_t); | 169 | u_int8_t, u_int8_t, u_int8_t, u_int8_t); | |
170 | void wdccommandext(struct ata_channel *, u_int8_t, u_int8_t, u_int64_t, | 170 | void wdccommandext(struct ata_channel *, u_int8_t, u_int8_t, u_int64_t, | |
171 | u_int16_t, u_int16_t, u_int8_t); | 171 | u_int16_t, u_int16_t, u_int8_t); | |
172 | void wdccommandshort(struct ata_channel *, int, int); | 172 | void wdccommandshort(struct ata_channel *, int, int); | |
173 | void wdctimeout(void *arg); | 173 | void wdctimeout(void *arg); | |
174 | void wdc_reset_drive(struct ata_drive_datas *, int, uint32_t *); | 174 | void wdc_reset_drive(struct ata_drive_datas *, int, uint32_t *); | |
175 | void wdc_reset_channel(struct ata_channel *, int); | 175 | void wdc_reset_channel(struct ata_channel *, int); | |
176 | void wdc_do_reset(struct ata_channel *, int); | 176 | void wdc_do_reset(struct ata_channel *, int); | |
177 | 177 | |||
178 | int wdc_exec_command(struct ata_drive_datas *, struct ata_xfer *); | 178 | void wdc_exec_command(struct ata_drive_datas *, struct ata_xfer *); | |
179 | 179 | |||
180 | /* | 180 | /* | |
181 | * ST506 spec says that if READY or SEEKCMPLT go off, then the read or write | 181 | * ST506 spec says that if READY or SEEKCMPLT go off, then the read or write | |
182 | * command is aborted. | 182 | * command is aborted. | |
183 | */ | 183 | */ | |
184 | #define wdc_wait_for_drq(chp, timeout, flags, tfd) \ | 184 | #define wdc_wait_for_drq(chp, timeout, flags, tfd) \ | |
185 | wdcwait((chp), WDCS_DRQ, WDCS_DRQ, (timeout), (flags), (tfd)) | 185 | wdcwait((chp), WDCS_DRQ, WDCS_DRQ, (timeout), (flags), (tfd)) | |
186 | #define wdc_wait_for_unbusy(chp, timeout, flags, tfd) \ | 186 | #define wdc_wait_for_unbusy(chp, timeout, flags, tfd) \ | |
187 | wdcwait((chp), 0, 0, (timeout), (flags), (tfd)) | 187 | wdcwait((chp), 0, 0, (timeout), (flags), (tfd)) | |
188 | #define wdc_wait_for_ready(chp, timeout, flags, tfd) \ | 188 | #define wdc_wait_for_ready(chp, timeout, flags, tfd) \ | |
189 | wdcwait((chp), WDCS_DRDY, WDCS_DRDY, (timeout), (flags), (tfd)) | 189 | wdcwait((chp), WDCS_DRDY, WDCS_DRDY, (timeout), (flags), (tfd)) | |
190 | 190 | |||
191 | /* ATA/ATAPI specs says a device can take 31s to reset */ | 191 | /* ATA/ATAPI specs says a device can take 31s to reset */ |
--- src/sys/dev/scsipi/atapi_wdc.c 2018/11/12 20:54:03 1.133
+++ src/sys/dev/scsipi/atapi_wdc.c 2022/12/30 14:39:10 1.133.4.1
@@ -1,41 +1,41 @@ | @@ -1,41 +1,41 @@ | |||
1 | /* $NetBSD: atapi_wdc.c,v 1.133 2018/11/12 20:54:03 jdolecek Exp $ */ | 1 | /* $NetBSD: atapi_wdc.c,v 1.133.4.1 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001 Manuel Bouyer. | 4 | * Copyright (c) 1998, 2001 Manuel Bouyer. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | */ | 25 | */ | |
26 | 26 | |||
27 | #include <sys/cdefs.h> | 27 | #include <sys/cdefs.h> | |
28 | __KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.133 2018/11/12 20:54:03 jdolecek Exp $"); | 28 | __KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.133.4.1 2022/12/30 14:39:10 martin Exp $"); | |
29 | 29 | |||
30 | #ifndef ATADEBUG | 30 | #ifndef ATADEBUG | |
31 | #define ATADEBUG | 31 | #define ATADEBUG | |
32 | #endif /* ATADEBUG */ | 32 | #endif /* ATADEBUG */ | |
33 | 33 | |||
34 | #include <sys/param.h> | 34 | #include <sys/param.h> | |
35 | #include <sys/systm.h> | 35 | #include <sys/systm.h> | |
36 | #include <sys/kernel.h> | 36 | #include <sys/kernel.h> | |
37 | #include <sys/file.h> | 37 | #include <sys/file.h> | |
38 | #include <sys/stat.h> | 38 | #include <sys/stat.h> | |
39 | #include <sys/buf.h> | 39 | #include <sys/buf.h> | |
40 | #include <sys/malloc.h> | 40 | #include <sys/malloc.h> | |
41 | #include <sys/device.h> | 41 | #include <sys/device.h> | |
@@ -80,27 +80,27 @@ int wdcdebug_atapi_mask = ATADEBUG_ATAPI | @@ -80,27 +80,27 @@ int wdcdebug_atapi_mask = ATADEBUG_ATAPI | |||
80 | 80 | |||
81 | #define ATAPI_DELAY 10 /* 10 ms, this is used only before sending a cmd */ | 81 | #define ATAPI_DELAY 10 /* 10 ms, this is used only before sending a cmd */ | |
82 | #define ATAPI_MODE_DELAY 1000 /* 1s, timeout for SET_FEATYRE cmds */ | 82 | #define ATAPI_MODE_DELAY 1000 /* 1s, timeout for SET_FEATYRE cmds */ | |
83 | 83 | |||
84 | static int wdc_atapi_get_params(struct scsipi_channel *, int, | 84 | static int wdc_atapi_get_params(struct scsipi_channel *, int, | |
85 | struct ataparams *); | 85 | struct ataparams *); | |
86 | static void wdc_atapi_probe_device(struct atapibus_softc *, int); | 86 | static void wdc_atapi_probe_device(struct atapibus_softc *, int); | |
87 | static void wdc_atapi_minphys (struct buf *bp); | 87 | static void wdc_atapi_minphys (struct buf *bp); | |
88 | static int wdc_atapi_start(struct ata_channel *,struct ata_xfer *); | 88 | static int wdc_atapi_start(struct ata_channel *,struct ata_xfer *); | |
89 | static int wdc_atapi_intr(struct ata_channel *, struct ata_xfer *, int); | 89 | static int wdc_atapi_intr(struct ata_channel *, struct ata_xfer *, int); | |
90 | static void wdc_atapi_kill_xfer(struct ata_channel *, | 90 | static void wdc_atapi_kill_xfer(struct ata_channel *, | |
91 | struct ata_xfer *, int); | 91 | struct ata_xfer *, int); | |
92 | static void wdc_atapi_phase_complete(struct ata_xfer *, int); | 92 | static void wdc_atapi_phase_complete(struct ata_xfer *, int); | |
93 | static void wdc_atapi_poll(struct ata_channel *, struct ata_xfer *); | 93 | static int wdc_atapi_poll(struct ata_channel *, struct ata_xfer *); | |
94 | static void wdc_atapi_done(struct ata_channel *, struct ata_xfer *); | 94 | static void wdc_atapi_done(struct ata_channel *, struct ata_xfer *); | |
95 | static void wdc_atapi_reset(struct ata_channel *, struct ata_xfer *); | 95 | static void wdc_atapi_reset(struct ata_channel *, struct ata_xfer *); | |
96 | static void wdc_atapi_scsipi_request(struct scsipi_channel *, | 96 | static void wdc_atapi_scsipi_request(struct scsipi_channel *, | |
97 | scsipi_adapter_req_t, void *); | 97 | scsipi_adapter_req_t, void *); | |
98 | static void wdc_atapi_kill_pending(struct scsipi_periph *); | 98 | static void wdc_atapi_kill_pending(struct scsipi_periph *); | |
99 | static void wdc_atapi_polldsc(void *arg); | 99 | static void wdc_atapi_polldsc(void *arg); | |
100 | 100 | |||
101 | #define MAX_SIZE MAXPHYS | 101 | #define MAX_SIZE MAXPHYS | |
102 | 102 | |||
103 | static const struct scsipi_bustype wdc_atapi_bustype = { | 103 | static const struct scsipi_bustype wdc_atapi_bustype = { | |
104 | SCSIPI_BUSTYPE_ATAPI, | 104 | SCSIPI_BUSTYPE_ATAPI, | |
105 | atapi_scsipi_cmd, | 105 | atapi_scsipi_cmd, | |
106 | atapi_interpret_sense, | 106 | atapi_interpret_sense, | |
@@ -212,32 +212,30 @@ wdc_atapi_get_params(struct scsipi_chann | @@ -212,32 +212,30 @@ wdc_atapi_get_params(struct scsipi_chann | |||
212 | int rv; | 212 | int rv; | |
213 | 213 | |||
214 | xfer = ata_get_xfer(chp, false); | 214 | xfer = ata_get_xfer(chp, false); | |
215 | if (xfer == NULL) { | 215 | if (xfer == NULL) { | |
216 | printf("wdc_atapi_get_params: no xfer\n"); | 216 | printf("wdc_atapi_get_params: no xfer\n"); | |
217 | return EBUSY; | 217 | return EBUSY; | |
218 | } | 218 | } | |
219 | 219 | |||
220 | xfer->c_ata_c.r_command = ATAPI_SOFT_RESET; | 220 | xfer->c_ata_c.r_command = ATAPI_SOFT_RESET; | |
221 | xfer->c_ata_c.r_st_bmask = 0; | 221 | xfer->c_ata_c.r_st_bmask = 0; | |
222 | xfer->c_ata_c.r_st_pmask = 0; | 222 | xfer->c_ata_c.r_st_pmask = 0; | |
223 | xfer->c_ata_c.flags = AT_WAIT | AT_POLL; | 223 | xfer->c_ata_c.flags = AT_WAIT | AT_POLL; | |
224 | xfer->c_ata_c.timeout = WDC_RESET_WAIT; | 224 | xfer->c_ata_c.timeout = WDC_RESET_WAIT; | |
225 | if (wdc_exec_command(&chp->ch_drive[drive], xfer) != ATACMD_COMPLETE) { | 225 | ||
226 | printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for" | 226 | wdc_exec_command(&chp->ch_drive[drive], xfer); | |
227 | " drive %s:%d:%d: driver failed\n", | 227 | ata_wait_cmd(chp, xfer); | |
228 | device_xname(atac->atac_dev), chp->ch_channel, drive); | 228 | ||
229 | panic("wdc_atapi_get_params"); | |||
230 | } | |||
231 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 229 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
232 | ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET " | 230 | ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET " | |
233 | "failed for drive %s:%d:%d: error 0x%x\n", | 231 | "failed for drive %s:%d:%d: error 0x%x\n", | |
234 | device_xname(atac->atac_dev), chp->ch_channel, drive, | 232 | device_xname(atac->atac_dev), chp->ch_channel, drive, | |
235 | xfer->c_ata_c.r_error), DEBUG_PROBE); | 233 | xfer->c_ata_c.r_error), DEBUG_PROBE); | |
236 | rv = -1; | 234 | rv = -1; | |
237 | goto out_xfer; | 235 | goto out_xfer; | |
238 | } | 236 | } | |
239 | chp->ch_drive[drive].state = 0; | 237 | chp->ch_drive[drive].state = 0; | |
240 | 238 | |||
241 | ata_free_xfer(chp, xfer); | 239 | ata_free_xfer(chp, xfer); | |
242 | 240 | |||
243 | (void)bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_status], 0); | 241 | (void)bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_status], 0); | |
@@ -695,54 +693,56 @@ timeout: | @@ -695,54 +693,56 @@ timeout: | |||
695 | 693 | |||
696 | error: | 694 | error: | |
697 | printf("%s:%d:%d: %s ", | 695 | printf("%s:%d:%d: %s ", | |
698 | device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, | 696 | device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, | |
699 | errstring); | 697 | errstring); | |
700 | printf("error (0x%x)\n", ATACH_ERR(tfd)); | 698 | printf("error (0x%x)\n", ATACH_ERR(tfd)); | |
701 | sc_xfer->error = XS_SHORTSENSE; | 699 | sc_xfer->error = XS_SHORTSENSE; | |
702 | sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); | 700 | sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); | |
703 | bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT); | 701 | bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT); | |
704 | delay(10); /* some drives need a little delay here */ | 702 | delay(10); /* some drives need a little delay here */ | |
705 | return ATASTART_ABORT; | 703 | return ATASTART_ABORT; | |
706 | } | 704 | } | |
707 | 705 | |||
708 | static void | 706 | static int | |
709 | wdc_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | 707 | wdc_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer) | |
710 | { | 708 | { | |
711 | /* | 709 | /* | |
712 | * If there is no interrupt for CMD input, busy-wait for it (done in | 710 | * If there is no interrupt for CMD input, busy-wait for it (done in | |
713 | * the interrupt routine. If it is a polled command, call the interrupt | 711 | * the interrupt routine. If it is a polled command, call the interrupt | |
714 | * routine until command is done. | 712 | * routine until command is done. | |
715 | */ | 713 | */ | |
716 | const bool poll = ((xfer->c_scsipi->xs_control & XS_CTL_POLL) != 0); | 714 | const bool poll = ((xfer->c_scsipi->xs_control & XS_CTL_POLL) != 0); | |
717 | 715 | |||
718 | /* Wait for at last 400ns for status bit to be valid */ | 716 | /* Wait for at last 400ns for status bit to be valid */ | |
719 | DELAY(1); | 717 | DELAY(1); | |
720 | wdc_atapi_intr(chp, xfer, 0); | 718 | wdc_atapi_intr(chp, xfer, 0); | |
721 | 719 | |||
722 | if (!poll) | 720 | if (!poll) | |
723 | return; | 721 | return ATAPOLL_DONE; | |
724 | 722 | |||
725 | #if NATA_DMA | 723 | #if NATA_DMA | |
726 | if (chp->ch_flags & ATACH_DMA_WAIT) { | 724 | if (chp->ch_flags & ATACH_DMA_WAIT) { | |
727 | wdc_dmawait(chp, xfer, xfer->c_scsipi->timeout); | 725 | wdc_dmawait(chp, xfer, xfer->c_scsipi->timeout); | |
728 | chp->ch_flags &= ~ATACH_DMA_WAIT; | 726 | chp->ch_flags &= ~ATACH_DMA_WAIT; | |
729 | } | 727 | } | |
730 | #endif | 728 | #endif | |
731 | while ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | 729 | while ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) { | |
732 | /* Wait for at last 400ns for status bit to be valid */ | 730 | /* Wait for at last 400ns for status bit to be valid */ | |
733 | DELAY(1); | 731 | DELAY(1); | |
734 | wdc_atapi_intr(chp, xfer, 0); | 732 | wdc_atapi_intr(chp, xfer, 0); | |
735 | } | 733 | } | |
734 | ||||
735 | return ATAPOLL_DONE; | |||
736 | } | 736 | } | |
737 | 737 | |||
738 | static int | 738 | static int | |
739 | wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | 739 | wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq) | |
740 | { | 740 | { | |
741 | struct atac_softc *atac = chp->ch_atac; | 741 | struct atac_softc *atac = chp->ch_atac; | |
742 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | 742 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | |
743 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | 743 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | |
744 | struct scsipi_xfer *sc_xfer = xfer->c_scsipi; | 744 | struct scsipi_xfer *sc_xfer = xfer->c_scsipi; | |
745 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | 745 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; | |
746 | int len, phase, i, retries=0; | 746 | int len, phase, i, retries=0; | |
747 | int ire, tfd; | 747 | int ire, tfd; | |
748 | #if NATA_DMA | 748 | #if NATA_DMA |
--- src/sys/dev/usb/Attic/umass_isdata.c 2019/02/10 19:23:55 1.42
+++ src/sys/dev/usb/Attic/umass_isdata.c 2022/12/30 14:39:10 1.42.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: umass_isdata.c,v 1.42 2019/02/10 19:23:55 jdolecek Exp $ */ | 1 | /* $NetBSD: umass_isdata.c,v 1.42.4.1 2022/12/30 14:39:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * TODO: | 4 | * TODO: | |
5 | * get ATA registers on any kind of error | 5 | * get ATA registers on any kind of error | |
6 | * implement more commands (what is needed) | 6 | * implement more commands (what is needed) | |
7 | */ | 7 | */ | |
8 | 8 | |||
9 | /* | 9 | /* | |
10 | * Copyright (c) 2001 The NetBSD Foundation, Inc. | 10 | * Copyright (c) 2001 The NetBSD Foundation, Inc. | |
11 | * All rights reserved. | 11 | * All rights reserved. | |
12 | * | 12 | * | |
13 | * This code is derived from software contributed to The NetBSD Foundation | 13 | * This code is derived from software contributed to The NetBSD Foundation | |
14 | * by Lennart Augustsson (lennart@augustsson.net) at | 14 | * by Lennart Augustsson (lennart@augustsson.net) at | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
36 | * POSSIBILITY OF SUCH DAMAGE. | 36 | * POSSIBILITY OF SUCH DAMAGE. | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | #include <sys/cdefs.h> | 39 | #include <sys/cdefs.h> | |
40 | __KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.42 2019/02/10 19:23:55 jdolecek Exp $"); | 40 | __KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.42.4.1 2022/12/30 14:39:10 martin Exp $"); | |
41 | 41 | |||
42 | #ifdef _KERNEL_OPT | 42 | #ifdef _KERNEL_OPT | |
43 | #include "opt_usb.h" | 43 | #include "opt_usb.h" | |
44 | #endif | 44 | #endif | |
45 | 45 | |||
46 | #include <sys/param.h> | 46 | #include <sys/param.h> | |
47 | #include <sys/buf.h> | 47 | #include <sys/buf.h> | |
48 | #include <sys/conf.h> | 48 | #include <sys/conf.h> | |
49 | #include <sys/device.h> | 49 | #include <sys/device.h> | |
50 | #include <sys/disklabel.h> | 50 | #include <sys/disklabel.h> | |
51 | #include <sys/kernel.h> | 51 | #include <sys/kernel.h> | |
52 | #include <sys/kmem.h> | 52 | #include <sys/kmem.h> | |
53 | #include <sys/proc.h> | 53 | #include <sys/proc.h> | |
@@ -105,31 +105,31 @@ struct uisdata_softc { | @@ -105,31 +105,31 @@ struct uisdata_softc { | |||
105 | #define CH2SELF(chnl_softc) ((void *)chnl_softc->atabus) | 105 | #define CH2SELF(chnl_softc) ((void *)chnl_softc->atabus) | |
106 | 106 | |||
107 | #undef DPRINTF | 107 | #undef DPRINTF | |
108 | #undef DPRINTFN | 108 | #undef DPRINTFN | |
109 | #ifdef UISDATA_DEBUG | 109 | #ifdef UISDATA_DEBUG | |
110 | #define DPRINTF(x) if (uisdatadebug) printf x | 110 | #define DPRINTF(x) if (uisdatadebug) printf x | |
111 | #define DPRINTFN(n,x) if (uisdatadebug>(n)) printf x | 111 | #define DPRINTFN(n,x) if (uisdatadebug>(n)) printf x | |
112 | int uisdatadebug = 0; | 112 | int uisdatadebug = 0; | |
113 | #else | 113 | #else | |
114 | #define DPRINTF(x) | 114 | #define DPRINTF(x) | |
115 | #define DPRINTFN(n,x) | 115 | #define DPRINTFN(n,x) | |
116 | #endif | 116 | #endif | |
117 | 117 | |||
118 | int uisdata_bio(struct ata_drive_datas *, struct ata_xfer *); | 118 | void uisdata_bio(struct ata_drive_datas *, struct ata_xfer *); | |
119 | int uisdata_bio1(struct ata_drive_datas *, struct ata_xfer *); | 119 | void uisdata_bio1(struct ata_drive_datas *, struct ata_xfer *); | |
120 | void uisdata_reset_drive(struct ata_drive_datas *, int, uint32_t *); | 120 | void uisdata_reset_drive(struct ata_drive_datas *, int, uint32_t *); | |
121 | void uisdata_reset_channel(struct ata_channel *, int); | 121 | void uisdata_reset_channel(struct ata_channel *, int); | |
122 | int uisdata_exec_command(struct ata_drive_datas *, struct ata_xfer *); | 122 | void uisdata_exec_command(struct ata_drive_datas *, struct ata_xfer *); | |
123 | int uisdata_get_params(struct ata_drive_datas *, uint8_t, struct ataparams *); | 123 | int uisdata_get_params(struct ata_drive_datas *, uint8_t, struct ataparams *); | |
124 | int uisdata_addref(struct ata_drive_datas *); | 124 | int uisdata_addref(struct ata_drive_datas *); | |
125 | void uisdata_delref(struct ata_drive_datas *); | 125 | void uisdata_delref(struct ata_drive_datas *); | |
126 | void uisdata_kill_pending(struct ata_drive_datas *); | 126 | void uisdata_kill_pending(struct ata_drive_datas *); | |
127 | 127 | |||
128 | void uisdata_bio_cb(struct umass_softc *, void *, int, int); | 128 | void uisdata_bio_cb(struct umass_softc *, void *, int, int); | |
129 | void uisdata_exec_cb(struct umass_softc *, void *, int, int); | 129 | void uisdata_exec_cb(struct umass_softc *, void *, int, int); | |
130 | int uwdprint(void *, const char *); | 130 | int uwdprint(void *, const char *); | |
131 | 131 | |||
132 | const struct ata_bustype uisdata_bustype = { | 132 | const struct ata_bustype uisdata_bustype = { | |
133 | SCSIPI_BUSTYPE_ATA, | 133 | SCSIPI_BUSTYPE_ATA, | |
134 | uisdata_bio, | 134 | uisdata_bio, | |
135 | uisdata_reset_drive, | 135 | uisdata_reset_drive, | |
@@ -264,73 +264,72 @@ uisdata_bio_cb(struct umass_softc *sc, v | @@ -264,73 +264,72 @@ uisdata_bio_cb(struct umass_softc *sc, v | |||
264 | ata_bio->error = ERR_DF; /* ??? */ | 264 | ata_bio->error = ERR_DF; /* ??? */ | |
265 | else | 265 | else | |
266 | ata_bio->error = NOERROR; | 266 | ata_bio->error = NOERROR; | |
267 | ata_bio->flags |= ATA_ITSDONE; | 267 | ata_bio->flags |= ATA_ITSDONE; | |
268 | 268 | |||
269 | ata_bio->blkdone += ata_bio->nblks; | 269 | ata_bio->blkdone += ata_bio->nblks; | |
270 | ata_bio->blkno += ata_bio->nblks; | 270 | ata_bio->blkno += ata_bio->nblks; | |
271 | ata_bio->bcount -= ata_bio->nbytes; | 271 | ata_bio->bcount -= ata_bio->nbytes; | |
272 | scbus->sc_skip += ata_bio->nbytes; | 272 | scbus->sc_skip += ata_bio->nbytes; | |
273 | if (residue != 0) { | 273 | if (residue != 0) { | |
274 | ata_bio->bcount += residue; | 274 | ata_bio->bcount += residue; | |
275 | } else if (ata_bio->bcount > 0) { | 275 | } else if (ata_bio->bcount > 0) { | |
276 | DPRINTF(("%s: continue\n", __func__)); | 276 | DPRINTF(("%s: continue\n", __func__)); | |
277 | (void)uisdata_bio1(&scbus->sc_drv_data, xfer); /*XXX save drv*/ | 277 | uisdata_bio1(&scbus->sc_drv_data, xfer); /*XXX save drv*/ | |
278 | splx(s); | 278 | splx(s); | |
279 | return; | 279 | return; | |
280 | } | 280 | } | |
281 | 281 | |||
282 | if (ata_bio->flags & ATA_POLL) { | 282 | if (ata_bio->flags & ATA_POLL) { | |
283 | DPRINTF(("%s: wakeup %p\n", __func__, ata_bio)); | 283 | DPRINTF(("%s: wakeup %p\n", __func__, ata_bio)); | |
284 | wakeup(ata_bio); | 284 | wakeup(ata_bio); | |
285 | } else { | 285 | } else { | |
286 | (*scbus->sc_drv_data.drv_done)(scbus->sc_drv_data.drv_softc, | 286 | (*scbus->sc_drv_data.drv_done)(scbus->sc_drv_data.drv_softc, | |
287 | xfer); | 287 | xfer); | |
288 | } | 288 | } | |
289 | splx(s); | 289 | splx(s); | |
290 | } | 290 | } | |
291 | 291 | |||
292 | int | 292 | void | |
293 | uisdata_bio(struct ata_drive_datas *drv, struct ata_xfer *xfer) | 293 | uisdata_bio(struct ata_drive_datas *drv, struct ata_xfer *xfer) | |
294 | { | 294 | { | |
295 | struct umass_softc *sc = CH2SELF(drv->chnl_softc); | 295 | struct umass_softc *sc = CH2SELF(drv->chnl_softc); | |
296 | struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; | 296 | struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; | |
297 | 297 | |||
298 | scbus->sc_skip = 0; | 298 | scbus->sc_skip = 0; | |
299 | return uisdata_bio1(drv, xfer); | 299 | uisdata_bio1(drv, xfer); | |
300 | } | 300 | } | |
301 | 301 | |||
302 | int | 302 | void | |
303 | uisdata_bio1(struct ata_drive_datas *drv, struct ata_xfer *xfer) | 303 | uisdata_bio1(struct ata_drive_datas *drv, struct ata_xfer *xfer) | |
304 | { | 304 | { | |
305 | struct umass_softc *sc = CH2SELF(drv->chnl_softc); | 305 | struct umass_softc *sc = CH2SELF(drv->chnl_softc); | |
306 | struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; | 306 | struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; | |
307 | struct isd200_config *cf = &scbus->sc_isd_config; | 307 | struct isd200_config *cf = &scbus->sc_isd_config; | |
308 | struct ata_bio *ata_bio = &xfer->c_bio; | 308 | struct ata_bio *ata_bio = &xfer->c_bio; | |
309 | struct ata_cmd ata; | 309 | struct ata_cmd ata; | |
310 | uint16_t cyl; | 310 | uint16_t cyl; | |
311 | uint8_t head, sect; | 311 | uint8_t head, sect; | |
312 | int dir; | 312 | int dir; | |
313 | long nbytes; | 313 | long nbytes; | |
314 | u_int nblks; | 314 | u_int nblks; | |
315 | 315 | |||
316 | DPRINTF(("%s\n", __func__)); | 316 | DPRINTF(("%s\n", __func__)); | |
317 | /* XXX */ | 317 | /* XXX */ | |
318 | 318 | |||
319 | if (ata_bio->flags & ATA_POLL) { | 319 | if (ata_bio->flags & ATA_POLL) { | |
320 | printf("%s: ATA_POLL not supported\n", __func__); | 320 | printf("%s: ATA_POLL not supported\n", __func__); | |
321 | ata_bio->error = TIMEOUT; | 321 | ata_bio->error = TIMEOUT; | |
322 | ata_bio->flags |= ATA_ITSDONE; | 322 | ata_bio->flags |= ATA_ITSDONE; | |
323 | return ATACMD_COMPLETE; | |||
324 | } | 323 | } | |
325 | 324 | |||
326 | if (ata_bio->flags & ATA_LBA) { | 325 | if (ata_bio->flags & ATA_LBA) { | |
327 | sect = (ata_bio->blkno >> 0) & 0xff; | 326 | sect = (ata_bio->blkno >> 0) & 0xff; | |
328 | cyl = (ata_bio->blkno >> 8) & 0xffff; | 327 | cyl = (ata_bio->blkno >> 8) & 0xffff; | |
329 | head = (ata_bio->blkno >> 24) & 0x0f; | 328 | head = (ata_bio->blkno >> 24) & 0x0f; | |
330 | head |= WDSD_LBA; | 329 | head |= WDSD_LBA; | |
331 | } else { | 330 | } else { | |
332 | int blkno = ata_bio->blkno; | 331 | int blkno = ata_bio->blkno; | |
333 | sect = blkno % drv->lp->d_nsectors; | 332 | sect = blkno % drv->lp->d_nsectors; | |
334 | sect++; /* Sectors begin with 1, not 0. */ | 333 | sect++; /* Sectors begin with 1, not 0. */ | |
335 | blkno /= drv->lp->d_nsectors; | 334 | blkno /= drv->lp->d_nsectors; | |
336 | head = blkno % drv->lp->d_ntracks; | 335 | head = blkno % drv->lp->d_ntracks; | |
@@ -380,31 +379,28 @@ uisdata_bio1(struct ata_drive_datas *drv | @@ -380,31 +379,28 @@ uisdata_bio1(struct ata_drive_datas *drv | |||
380 | (ata_bio->flags & ATA_LBA) != 0, cyl, head, sect, | 379 | (ata_bio->flags & ATA_LBA) != 0, cyl, head, sect, | |
381 | ata.ac_sector_count, drv->multi)); | 380 | ata.ac_sector_count, drv->multi)); | |
382 | DPRINTF((" data=%p bcount=%ld, drive=%d\n", ata_bio->databuf, | 381 | DPRINTF((" data=%p bcount=%ld, drive=%d\n", ata_bio->databuf, | |
383 | ata_bio->bcount, drv->drive)); | 382 | ata_bio->bcount, drv->drive)); | |
384 | sc->sc_methods->wire_xfer(sc, drv->drive, &ata, sizeof(ata), | 383 | sc->sc_methods->wire_xfer(sc, drv->drive, &ata, sizeof(ata), | |
385 | ata_bio->databuf + scbus->sc_skip, nbytes, | 384 | ata_bio->databuf + scbus->sc_skip, nbytes, | |
386 | dir, ATA_DELAY, 0, uisdata_bio_cb, xfer); | 385 | dir, ATA_DELAY, 0, uisdata_bio_cb, xfer); | |
387 | 386 | |||
388 | while (ata_bio->flags & ATA_POLL) { | 387 | while (ata_bio->flags & ATA_POLL) { | |
389 | DPRINTF(("%s: tsleep %p\n", __func__, ata_bio)); | 388 | DPRINTF(("%s: tsleep %p\n", __func__, ata_bio)); | |
390 | if (tsleep(ata_bio, PZERO, "uisdatabl", 0)) { | 389 | if (tsleep(ata_bio, PZERO, "uisdatabl", 0)) { | |
391 | ata_bio->error = TIMEOUT; | 390 | ata_bio->error = TIMEOUT; | |
392 | ata_bio->flags |= ATA_ITSDONE; | 391 | ata_bio->flags |= ATA_ITSDONE; | |
393 | return ATACMD_COMPLETE; | |||
394 | } | 392 | } | |
395 | } | 393 | } | |
396 | ||||
397 | return ata_bio->flags & ATA_ITSDONE ? ATACMD_COMPLETE : ATACMD_QUEUED; | |||
398 | } | 394 | } | |
399 | 395 | |||
400 | void | 396 | void | |
401 | uisdata_reset_drive(struct ata_drive_datas *drv, int flags, uint32_t *sigp) | 397 | uisdata_reset_drive(struct ata_drive_datas *drv, int flags, uint32_t *sigp) | |
402 | { | 398 | { | |
403 | DPRINTFN(-1,("%s\n", __func__)); | 399 | DPRINTFN(-1,("%s\n", __func__)); | |
404 | KASSERT(sigp == NULL); | 400 | KASSERT(sigp == NULL); | |
405 | /* XXX what? */ | 401 | /* XXX what? */ | |
406 | } | 402 | } | |
407 | 403 | |||
408 | void | 404 | void | |
409 | uisdata_reset_channel(struct ata_channel *chp, int flags) | 405 | uisdata_reset_channel(struct ata_channel *chp, int flags) | |
410 | { | 406 | { | |
@@ -420,90 +416,87 @@ uisdata_exec_cb(struct umass_softc *sc, | @@ -420,90 +416,87 @@ uisdata_exec_cb(struct umass_softc *sc, | |||
420 | 416 | |||
421 | DPRINTF(("%s: status=%d\n", __func__, status)); | 417 | DPRINTF(("%s: status=%d\n", __func__, status)); | |
422 | if (status != STATUS_CMD_OK) | 418 | if (status != STATUS_CMD_OK) | |
423 | cmd->flags |= AT_DF; /* XXX */ | 419 | cmd->flags |= AT_DF; /* XXX */ | |
424 | cmd->flags |= AT_DONE; | 420 | cmd->flags |= AT_DONE; | |
425 | if (cmd->flags & (AT_READ | AT_WRITE)) | 421 | if (cmd->flags & (AT_READ | AT_WRITE)) | |
426 | cmd->flags |= AT_XFDONE; | 422 | cmd->flags |= AT_XFDONE; | |
427 | if (cmd->flags & (AT_POLL | AT_WAIT)) { | 423 | if (cmd->flags & (AT_POLL | AT_WAIT)) { | |
428 | DPRINTF(("%s: wakeup %p\n", __func__, cmd)); | 424 | DPRINTF(("%s: wakeup %p\n", __func__, cmd)); | |
429 | wakeup(cmd); | 425 | wakeup(cmd); | |
430 | } | 426 | } | |
431 | } | 427 | } | |
432 | 428 | |||
433 | int | 429 | void | |
434 | uisdata_exec_command(struct ata_drive_datas *drv, struct ata_xfer *xfer) | 430 | uisdata_exec_command(struct ata_drive_datas *drv, struct ata_xfer *xfer) | |
435 | { | 431 | { | |
436 | struct umass_softc *sc = CH2SELF(drv->chnl_softc); | 432 | struct umass_softc *sc = CH2SELF(drv->chnl_softc); | |
437 | struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; | 433 | struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; | |
438 | struct isd200_config *cf = &scbus->sc_isd_config; | 434 | struct isd200_config *cf = &scbus->sc_isd_config; | |
439 | int dir; | 435 | int dir; | |
440 | struct ata_command *cmd = &xfer->c_ata_c; | 436 | struct ata_command *cmd = &xfer->c_ata_c; | |
441 | struct ata_cmd ata; | 437 | struct ata_cmd ata; | |
442 | 438 | |||
443 | DPRINTF(("%s\n", __func__)); | 439 | DPRINTF(("%s\n", __func__)); | |
444 | DPRINTF((" r_command=0x%02x timeout=%d flags=0x%x bcount=%d\n", | 440 | DPRINTF((" r_command=0x%02x timeout=%d flags=0x%x bcount=%d\n", | |
445 | cmd->r_command, cmd->timeout, cmd->flags, cmd->bcount)); | 441 | cmd->r_command, cmd->timeout, cmd->flags, cmd->bcount)); | |
446 | 442 | |||
447 | dir = DIR_NONE; | 443 | dir = DIR_NONE; | |
448 | if (cmd->bcount != 0) { | 444 | if (cmd->bcount != 0) { | |
449 | if (cmd->flags & AT_READ) | 445 | if (cmd->flags & AT_READ) | |
450 | dir = DIR_IN; | 446 | dir = DIR_IN; | |
451 | else | 447 | else | |
452 | dir = DIR_OUT; | 448 | dir = DIR_OUT; | |
453 | } | 449 | } | |
454 | 450 | |||
455 | if (cmd->bcount > UMASS_MAX_TRANSFER_SIZE) { | 451 | if (cmd->bcount > UMASS_MAX_TRANSFER_SIZE) { | |
456 | printf("uisdata_exec_command: large datalen %d\n", cmd->bcount); | 452 | printf("uisdata_exec_command: large datalen %d\n", cmd->bcount); | |
457 | cmd->flags |= AT_ERROR; | 453 | cmd->flags |= AT_ERROR; | |
458 | goto done; | 454 | return; | |
459 | } | 455 | } | |
460 | 456 | |||
461 | memset(&ata, 0, sizeof(ata)); | 457 | memset(&ata, 0, sizeof(ata)); | |
462 | ata.ac_signature0 = cf->ATAMajorCommand; | 458 | ata.ac_signature0 = cf->ATAMajorCommand; | |
463 | ata.ac_signature1 = cf->ATAMinorCommand; | 459 | ata.ac_signature1 = cf->ATAMinorCommand; | |
464 | ata.ac_transfer_blocksize = 1; | 460 | ata.ac_transfer_blocksize = 1; | |
465 | 461 | |||
466 | switch (cmd->r_command) { | 462 | switch (cmd->r_command) { | |
467 | case WDCC_IDENTIFY: | 463 | case WDCC_IDENTIFY: | |
468 | ata.ac_register_select |= AC_SelectCommand; | 464 | ata.ac_register_select |= AC_SelectCommand; | |
469 | ata.ac_command = WDCC_IDENTIFY; | 465 | ata.ac_command = WDCC_IDENTIFY; | |
470 | break; | 466 | break; | |
471 | default: | 467 | default: | |
472 | printf("uisdata_exec_command: bad command 0x%02x\n", | 468 | printf("uisdata_exec_command: bad command 0x%02x\n", | |
473 | cmd->r_command); | 469 | cmd->r_command); | |
474 | cmd->flags |= AT_ERROR; | 470 | cmd->flags |= AT_ERROR; | |
475 | goto done; | 471 | return; | |
476 | } | 472 | } | |
477 | 473 | |||
478 | DPRINTF(("%s: execute ATA command 0x%02x, drive=%d\n", __func__, | 474 | DPRINTF(("%s: execute ATA command 0x%02x, drive=%d\n", __func__, | |
479 | ata.ac_command, drv->drive)); | 475 | ata.ac_command, drv->drive)); | |
480 | sc->sc_methods->wire_xfer(sc, drv->drive, &ata, | 476 | sc->sc_methods->wire_xfer(sc, drv->drive, &ata, | |
481 | sizeof(ata), cmd->data, cmd->bcount, dir, | 477 | sizeof(ata), cmd->data, cmd->bcount, dir, | |
482 | cmd->timeout, 0, uisdata_exec_cb, cmd); | 478 | cmd->timeout, 0, uisdata_exec_cb, cmd); | |
483 | if (cmd->flags & (AT_POLL | AT_WAIT)) { | 479 | if (cmd->flags & (AT_POLL | AT_WAIT)) { | |
484 | #if 0 | 480 | #if 0 | |
485 | if (cmd->flags & AT_POLL) | 481 | if (cmd->flags & AT_POLL) | |
486 | printf("%s: AT_POLL not supported\n", __func__); | 482 | printf("%s: AT_POLL not supported\n", __func__); | |
487 | #endif | 483 | #endif | |
488 | DPRINTF(("%s: tsleep %p\n", __func__, cmd)); | 484 | DPRINTF(("%s: tsleep %p\n", __func__, cmd)); | |
489 | if (tsleep(cmd, PZERO, "uisdataex", 0)) { | 485 | if (tsleep(cmd, PZERO, "uisdataex", 0)) { | |
490 | cmd->flags |= AT_ERROR; | 486 | cmd->flags |= AT_ERROR; | |
491 | goto done; | 487 | return; | |
492 | } | 488 | } | |
493 | } | 489 | } | |
494 | ||||
495 | done: | |||
496 | return ATACMD_COMPLETE; | |||
497 | } | 490 | } | |
498 | 491 | |||
499 | int | 492 | int | |
500 | uisdata_addref(struct ata_drive_datas *drv) | 493 | uisdata_addref(struct ata_drive_datas *drv) | |
501 | { | 494 | { | |
502 | DPRINTF(("%s\n", __func__)); | 495 | DPRINTF(("%s\n", __func__)); | |
503 | /* Nothing to do */ | 496 | /* Nothing to do */ | |
504 | return 0; | 497 | return 0; | |
505 | } | 498 | } | |
506 | 499 | |||
507 | void | 500 | void | |
508 | uisdata_delref(struct ata_drive_datas *drv) | 501 | uisdata_delref(struct ata_drive_datas *drv) | |
509 | { | 502 | { | |
@@ -550,31 +543,28 @@ uisdata_get_params(struct ata_drive_data | @@ -550,31 +543,28 @@ uisdata_get_params(struct ata_drive_data | |||
550 | memset(prms, 0, sizeof(struct ataparams)); | 543 | memset(prms, 0, sizeof(struct ataparams)); | |
551 | 544 | |||
552 | xfer = ata_get_xfer(drvp->chnl_softc, false); | 545 | xfer = ata_get_xfer(drvp->chnl_softc, false); | |
553 | if (!xfer) { | 546 | if (!xfer) { | |
554 | rv = CMD_AGAIN; | 547 | rv = CMD_AGAIN; | |
555 | goto out; | 548 | goto out; | |
556 | } | 549 | } | |
557 | 550 | |||
558 | xfer->c_ata_c.r_command = WDCC_IDENTIFY; | 551 | xfer->c_ata_c.r_command = WDCC_IDENTIFY; | |
559 | xfer->c_ata_c.timeout = 1000; /* 1s */ | 552 | xfer->c_ata_c.timeout = 1000; /* 1s */ | |
560 | xfer->c_ata_c.flags = AT_READ | flags; | 553 | xfer->c_ata_c.flags = AT_READ | flags; | |
561 | xfer->c_ata_c.data = tb; | 554 | xfer->c_ata_c.data = tb; | |
562 | xfer->c_ata_c.bcount = DEV_BSIZE; | 555 | xfer->c_ata_c.bcount = DEV_BSIZE; | |
563 | if (uisdata_exec_command(drvp, xfer) != ATACMD_COMPLETE) { | 556 | uisdata_exec_command(drvp, xfer); | |
564 | DPRINTF(("uisdata_get_parms: uisdata_exec_command failed\n")); | 557 | ata_wait_cmd(drvp->chnl_softc, xfer); | |
565 | rv = CMD_AGAIN; | |||
566 | goto out; | |||
567 | } | |||
568 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | 558 | if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { | |
569 | DPRINTF(("uisdata_get_parms: ata_c.flags=0x%x\n", | 559 | DPRINTF(("uisdata_get_parms: ata_c.flags=0x%x\n", | |
570 | xfer->c_ata_c.flags)); | 560 | xfer->c_ata_c.flags)); | |
571 | rv = CMD_ERR; | 561 | rv = CMD_ERR; | |
572 | goto out; | 562 | goto out; | |
573 | } | 563 | } | |
574 | 564 | |||
575 | /* Read in parameter block. */ | 565 | /* Read in parameter block. */ | |
576 | memcpy(prms, tb, sizeof(struct ataparams)); | 566 | memcpy(prms, tb, sizeof(struct ataparams)); | |
577 | #if BYTE_ORDER == LITTLE_ENDIAN | 567 | #if BYTE_ORDER == LITTLE_ENDIAN | |
578 | /* XXX copied from ata.c */ | 568 | /* XXX copied from ata.c */ | |
579 | /* | 569 | /* | |
580 | * Shuffle string byte order. | 570 | * Shuffle string byte order. |