satafis_subr.c revision 1.8 1 1.8 jdolecek /* $NetBSD: satafis_subr.c,v 1.8 2017/10/07 16:05:32 jdolecek Exp $ */
2 1.1 jakllsch
3 1.1 jakllsch /*-
4 1.1 jakllsch * Copyright (c) 2009 Jonathan A. Kollasch.
5 1.1 jakllsch * All rights reserved.
6 1.1 jakllsch *
7 1.1 jakllsch * Redistribution and use in source and binary forms, with or without
8 1.1 jakllsch * modification, are permitted provided that the following conditions
9 1.1 jakllsch * are met:
10 1.1 jakllsch * 1. Redistributions of source code must retain the above copyright
11 1.1 jakllsch * notice, this list of conditions and the following disclaimer.
12 1.1 jakllsch * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jakllsch * notice, this list of conditions and the following disclaimer in the
14 1.1 jakllsch * documentation and/or other materials provided with the distribution.
15 1.1 jakllsch *
16 1.1 jakllsch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 jakllsch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 jakllsch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 jakllsch * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 jakllsch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 jakllsch * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 jakllsch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 jakllsch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 jakllsch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 jakllsch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 jakllsch */
27 1.1 jakllsch
28 1.1 jakllsch /*
29 1.1 jakllsch * Copyright (c) 2006 Manuel Bouyer.
30 1.1 jakllsch *
31 1.1 jakllsch * Redistribution and use in source and binary forms, with or without
32 1.1 jakllsch * modification, are permitted provided that the following conditions
33 1.1 jakllsch * are met:
34 1.1 jakllsch * 1. Redistributions of source code must retain the above copyright
35 1.1 jakllsch * notice, this list of conditions and the following disclaimer.
36 1.1 jakllsch * 2. Redistributions in binary form must reproduce the above copyright
37 1.1 jakllsch * notice, this list of conditions and the following disclaimer in the
38 1.1 jakllsch * documentation and/or other materials provided with the distribution.
39 1.1 jakllsch *
40 1.1 jakllsch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
41 1.1 jakllsch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42 1.1 jakllsch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43 1.1 jakllsch * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
44 1.1 jakllsch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 1.1 jakllsch * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
46 1.1 jakllsch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
47 1.1 jakllsch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
48 1.1 jakllsch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
49 1.1 jakllsch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 1.1 jakllsch *
51 1.1 jakllsch */
52 1.1 jakllsch
53 1.1 jakllsch #include <sys/cdefs.h>
54 1.8 jdolecek __KERNEL_RCSID(0, "$NetBSD: satafis_subr.c,v 1.8 2017/10/07 16:05:32 jdolecek Exp $");
55 1.1 jakllsch
56 1.1 jakllsch #include <sys/param.h>
57 1.2 jakllsch #include <sys/systm.h>
58 1.1 jakllsch
59 1.1 jakllsch #include <sys/disklabel.h>
60 1.1 jakllsch
61 1.1 jakllsch #include <dev/ata/atareg.h>
62 1.1 jakllsch #include <dev/ata/atavar.h>
63 1.1 jakllsch
64 1.1 jakllsch #include <dev/ata/satafisreg.h>
65 1.1 jakllsch #include <dev/ata/satafisvar.h>
66 1.1 jakllsch
67 1.1 jakllsch #include "atapibus.h"
68 1.1 jakllsch
69 1.1 jakllsch void
70 1.1 jakllsch satafis_rhd_construct_cmd(struct ata_command *ata_c, uint8_t *fis)
71 1.1 jakllsch {
72 1.6 jakllsch
73 1.2 jakllsch memset(fis, 0, RHD_FISLEN);
74 1.2 jakllsch
75 1.1 jakllsch fis[fis_type] = RHD_FISTYPE;
76 1.5 jakllsch fis[rhd_c] = RHD_C;
77 1.1 jakllsch fis[rhd_command] = ata_c->r_command;
78 1.6 jakllsch fis[rhd_features0] = (ata_c->r_features >> 0) & 0xff;
79 1.6 jakllsch
80 1.6 jakllsch fis[rhd_lba0] = (ata_c->r_lba >> 0) & 0xff;
81 1.6 jakllsch fis[rhd_lba1] = (ata_c->r_lba >> 8) & 0xff;
82 1.6 jakllsch fis[rhd_lba2] = (ata_c->r_lba >> 16) & 0xff;
83 1.6 jakllsch if ((ata_c->flags & AT_LBA48) != 0) {
84 1.7 jakllsch fis[rhd_dh] = ata_c->r_device;
85 1.6 jakllsch fis[rhd_lba3] = (ata_c->r_lba >> 24) & 0xff;
86 1.6 jakllsch fis[rhd_lba4] = (ata_c->r_lba >> 32) & 0xff;
87 1.6 jakllsch fis[rhd_lba5] = (ata_c->r_lba >> 40) & 0xff;
88 1.6 jakllsch fis[rhd_features1] = (ata_c->r_features >> 8) & 0xff;
89 1.6 jakllsch } else {
90 1.7 jakllsch fis[rhd_dh] = (ata_c->r_device & 0xf0) |
91 1.7 jakllsch ((ata_c->r_lba >> 24) & 0x0f);
92 1.6 jakllsch }
93 1.6 jakllsch
94 1.6 jakllsch fis[rhd_count0] = (ata_c->r_count >> 0) & 0xff;
95 1.6 jakllsch if ((ata_c->flags & AT_LBA48) != 0) {
96 1.6 jakllsch fis[rhd_count1] = (ata_c->r_count >> 8) & 0xff;
97 1.6 jakllsch }
98 1.1 jakllsch }
99 1.1 jakllsch
100 1.1 jakllsch void
101 1.1 jakllsch satafis_rhd_construct_bio(struct ata_xfer *xfer, uint8_t *fis)
102 1.1 jakllsch {
103 1.8 jdolecek struct ata_bio *ata_bio = &xfer->c_bio;
104 1.8 jdolecek struct ata_drive_datas *drvp = &xfer->c_chp->ch_drive[xfer->c_drive];
105 1.8 jdolecek uint16_t count, features;
106 1.8 jdolecek uint8_t device;
107 1.8 jdolecek
108 1.8 jdolecek count = xfer->c_bcount / drvp->lp->d_secsize;
109 1.8 jdolecek features = 0;
110 1.8 jdolecek device = WDSD_LBA;
111 1.1 jakllsch
112 1.2 jakllsch memset(fis, 0, RHD_FISLEN);
113 1.2 jakllsch
114 1.1 jakllsch fis[fis_type] = RHD_FISTYPE;
115 1.5 jakllsch fis[rhd_c] = RHD_C;
116 1.1 jakllsch if (ata_bio->flags & ATA_LBA48) {
117 1.1 jakllsch fis[rhd_command] = (ata_bio->flags & ATA_READ) ?
118 1.1 jakllsch WDCC_READDMA_EXT : WDCC_WRITEDMA_EXT;
119 1.8 jdolecek
120 1.8 jdolecek atacmd_toncq(xfer, &fis[rhd_command], &count, &features,
121 1.8 jdolecek &device);
122 1.1 jakllsch } else {
123 1.1 jakllsch fis[rhd_command] =
124 1.1 jakllsch (ata_bio->flags & ATA_READ) ? WDCC_READDMA : WDCC_WRITEDMA;
125 1.1 jakllsch }
126 1.8 jdolecek fis[rhd_features0] = (features >> 0) & 0xff;
127 1.6 jakllsch
128 1.6 jakllsch fis[rhd_lba0] = (ata_bio->blkno >> 0) & 0xff;
129 1.6 jakllsch fis[rhd_lba1] = (ata_bio->blkno >> 8) & 0xff;
130 1.6 jakllsch fis[rhd_lba2] = (ata_bio->blkno >> 16) & 0xff;
131 1.6 jakllsch if ((ata_bio->flags & ATA_LBA48) != 0) {
132 1.8 jdolecek fis[rhd_dh] = device;
133 1.6 jakllsch fis[rhd_lba3] = (ata_bio->blkno >> 24) & 0xff;
134 1.6 jakllsch fis[rhd_lba4] = (ata_bio->blkno >> 32) & 0xff;
135 1.6 jakllsch fis[rhd_lba5] = (ata_bio->blkno >> 40) & 0xff;
136 1.8 jdolecek fis[rhd_features1] = (features >> 8) & 0xff;
137 1.1 jakllsch } else {
138 1.6 jakllsch fis[rhd_dh] = ((ata_bio->blkno >> 24) & 0x0f) |
139 1.6 jakllsch (((ata_bio->flags & ATA_LBA) != 0) ? WDSD_LBA : 0);
140 1.6 jakllsch }
141 1.6 jakllsch
142 1.8 jdolecek fis[rhd_count0] = count & 0xff;
143 1.6 jakllsch if ((ata_bio->flags & ATA_LBA48) != 0) {
144 1.8 jdolecek fis[rhd_count1] = (count >> 8) & 0xff;
145 1.1 jakllsch }
146 1.1 jakllsch }
147 1.1 jakllsch
148 1.1 jakllsch #if NATAPIBUS > 0
149 1.1 jakllsch void
150 1.1 jakllsch satafis_rhd_construct_atapi(struct ata_xfer *xfer, uint8_t *fis)
151 1.1 jakllsch {
152 1.6 jakllsch
153 1.2 jakllsch memset(fis, 0, RHD_FISLEN);
154 1.2 jakllsch
155 1.1 jakllsch fis[fis_type] = RHD_FISTYPE;
156 1.5 jakllsch fis[rhd_c] = RHD_C;
157 1.1 jakllsch fis[rhd_command] = ATAPI_PKT_CMD;
158 1.6 jakllsch fis[rhd_features0] = (xfer->c_flags & C_DMA) ?
159 1.1 jakllsch ATAPI_PKT_CMD_FTRE_DMA : 0;
160 1.1 jakllsch }
161 1.1 jakllsch #endif /* NATAPIBUS */
162 1.1 jakllsch
163 1.8 jdolecek int
164 1.5 jakllsch satafis_rdh_parse(struct ata_channel *chp, const uint8_t *fis)
165 1.1 jakllsch {
166 1.6 jakllsch
167 1.8 jdolecek return ATACH_ERR_ST(fis[rdh_error], fis[rdh_status]);
168 1.5 jakllsch }
169 1.1 jakllsch
170 1.5 jakllsch void
171 1.5 jakllsch satafis_rdh_cmd_readreg(struct ata_command *ata_c, const uint8_t *fis)
172 1.5 jakllsch {
173 1.6 jakllsch
174 1.6 jakllsch ata_c->r_lba = (uint64_t)fis[rdh_lba0] << 0;
175 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba1] << 8;
176 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba2] << 16;
177 1.6 jakllsch if ((ata_c->flags & AT_LBA48) != 0) {
178 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba3] << 24;
179 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba4] << 32;
180 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba5] << 40;
181 1.7 jakllsch ata_c->r_device = fis[rdh_dh];
182 1.6 jakllsch } else {
183 1.6 jakllsch ata_c->r_lba |= (uint64_t)(fis[rdh_dh] & 0x0f) << 24;
184 1.7 jakllsch ata_c->r_device = fis[rdh_dh] & 0xf0;
185 1.6 jakllsch }
186 1.6 jakllsch
187 1.6 jakllsch ata_c->r_count = fis[rdh_count0] << 0;
188 1.6 jakllsch if ((ata_c->flags & AT_LBA48) != 0) {
189 1.6 jakllsch ata_c->r_count |= fis[rdh_count1] << 8;
190 1.6 jakllsch }
191 1.6 jakllsch
192 1.5 jakllsch ata_c->r_error = fis[rdh_error];
193 1.6 jakllsch ata_c->r_status = fis[rdh_status];
194 1.1 jakllsch }
195