1/* 2 * Copyright (c) 2011 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <errors/errno.h> 12#include "sata_fis.h" 13 14void sata_h2d_fis_new(struct sata_fis_reg_h2d* fis, uint8_t command, uint64_t lba, uint16_t sectors) 15{ 16 sata_h2d_fis_init(fis); 17 sata_h2d_set_command(fis, command); 18 sata_h2d_set_lba48(fis, lba); 19 sata_h2d_set_count(fis, sectors); 20} 21 22void sata_h2d_fis_init(struct sata_fis_reg_h2d* fis) 23{ 24 fis->type = SATA_FIS_TYPE_H2D; 25 26 /* Device Shadow Register layout (see: [1]) 27 * [ 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 ] 28 * [ - | L | - | DEV | HS3 | HS2 | HS1 | HS0 ] 29 * 30 * L is the address mode, cleared implies CHS addressing, set, LBA addressing 31 * DEV device select, cleared and set imply Device 0 and 1 resp. 32 * for SATA this should always be cleared (see: [2]) 33 * HS3-HS0 are bits 28-25 of the LBA 28 (not used for LBA 48, see [3]) 34 * 35 * [1] Serial ATA NSSD Rev. 1.0 (Sept 2008), section 6.3.1 36 * [2] Serial ATA Rev. 2.6 (15-February-2007), section 13.1, paragraph 2 37 * [3] ATA8-ACS Rev. 3f (December 11, 2006), section 7.1.5.2 38 */ 39 fis->device |= (1 << 6); 40} 41 42void sata_h2d_set_command(struct sata_fis_reg_h2d* fis, uint8_t command) 43{ 44 fis->command = command; 45 /* set bit to indicate update of command register (see [1]) 46 * 47 * [1]: SATA Rev. 2.6 (15-February-2007), section 10.3.4 48 */ 49 fis->specialstuff |= (1 << 7); 50} 51 52void sata_h2d_set_feature(struct sata_fis_reg_h2d* fis, uint8_t feature) 53{ 54 fis->feature = feature; 55} 56 57void sata_h2d_set_lba28(struct sata_fis_reg_h2d* fis, uint32_t lba) 58{ 59 fis->lba0 = lba & 0xFF; 60 fis->lba1 = (lba >> 8) & 0xFF; 61 fis->lba2 = (lba >> 16) & 0xFF; 62 fis->device = (fis->device & ~0x0F) | ((lba >> 24) & 0x0F); 63} 64 65void sata_h2d_set_lba48(struct sata_fis_reg_h2d* fis, uint64_t lba) 66{ 67 fis->lba0 = lba & 0xFF; 68 fis->lba1 = (lba >> 8) & 0xFF; 69 fis->lba2 = (lba >> 16) & 0xFF; 70 fis->device &= 0xF0; // clear bits otherwise used by lba28 71 72 fis->lba3 = (lba >> 24) & 0xFF; 73 fis->lba4 = (lba >> 32) & 0xFF; 74 fis->lba5 = (lba >> 40) & 0xFF; 75} 76 77void sata_h2d_set_count(struct sata_fis_reg_h2d* fis, uint16_t count) 78{ 79 fis->countl = count & 0xFF; 80 fis->counth = (count >> 8) & 0xFF; 81} 82