1 1.9 gson /* $NetBSD: satafis_subr.c,v 1.9 2019/08/15 09:00:23 gson 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.9 gson __KERNEL_RCSID(0, "$NetBSD: satafis_subr.c,v 1.9 2019/08/15 09:00:23 gson 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.9 gson int bcount16; 153 1.6 jakllsch 154 1.2 jakllsch memset(fis, 0, RHD_FISLEN); 155 1.2 jakllsch 156 1.1 jakllsch fis[fis_type] = RHD_FISTYPE; 157 1.5 jakllsch fis[rhd_c] = RHD_C; 158 1.1 jakllsch fis[rhd_command] = ATAPI_PKT_CMD; 159 1.9 gson bcount16 = xfer->c_bcount <= 0xffff ? xfer->c_bcount : 0xffff; 160 1.9 gson fis[rhd_lba1] = (bcount16 >> 0) & 0xff; 161 1.9 gson fis[rhd_lba2] = (bcount16 >> 8) & 0xff; 162 1.6 jakllsch fis[rhd_features0] = (xfer->c_flags & C_DMA) ? 163 1.1 jakllsch ATAPI_PKT_CMD_FTRE_DMA : 0; 164 1.1 jakllsch } 165 1.1 jakllsch #endif /* NATAPIBUS */ 166 1.1 jakllsch 167 1.8 jdolecek int 168 1.5 jakllsch satafis_rdh_parse(struct ata_channel *chp, const uint8_t *fis) 169 1.1 jakllsch { 170 1.6 jakllsch 171 1.8 jdolecek return ATACH_ERR_ST(fis[rdh_error], fis[rdh_status]); 172 1.5 jakllsch } 173 1.1 jakllsch 174 1.5 jakllsch void 175 1.5 jakllsch satafis_rdh_cmd_readreg(struct ata_command *ata_c, const uint8_t *fis) 176 1.5 jakllsch { 177 1.6 jakllsch 178 1.6 jakllsch ata_c->r_lba = (uint64_t)fis[rdh_lba0] << 0; 179 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba1] << 8; 180 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba2] << 16; 181 1.6 jakllsch if ((ata_c->flags & AT_LBA48) != 0) { 182 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba3] << 24; 183 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba4] << 32; 184 1.6 jakllsch ata_c->r_lba |= (uint64_t)fis[rdh_lba5] << 40; 185 1.7 jakllsch ata_c->r_device = fis[rdh_dh]; 186 1.6 jakllsch } else { 187 1.6 jakllsch ata_c->r_lba |= (uint64_t)(fis[rdh_dh] & 0x0f) << 24; 188 1.7 jakllsch ata_c->r_device = fis[rdh_dh] & 0xf0; 189 1.6 jakllsch } 190 1.6 jakllsch 191 1.6 jakllsch ata_c->r_count = fis[rdh_count0] << 0; 192 1.6 jakllsch if ((ata_c->flags & AT_LBA48) != 0) { 193 1.6 jakllsch ata_c->r_count |= fis[rdh_count1] << 8; 194 1.6 jakllsch } 195 1.6 jakllsch 196 1.5 jakllsch ata_c->r_error = fis[rdh_error]; 197 1.6 jakllsch ata_c->r_status = fis[rdh_status]; 198 1.1 jakllsch } 199