1/* 2 * Copyright (c) 2014, University of Washington. 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <barrelfish/barrelfish.h> 11#include <barrelfish/waitset.h> 12#include <if/ata_rw28_defs.h> 13#include <if/ata_rw28_ahci_defs.h> 14#include <if/ata_rw28_defs.h> 15#include <storage/vsic.h> 16 17struct ahci_vsic { 18 struct ahci_ata_rw28_binding ahci_ata_rw28_binding; 19 struct ata_rw28_binding ata_rw28_rpc; 20 struct ata_rw28_binding *ata_rw28_binding; 21 struct ahci_binding *ahci_binding; 22 errval_t bind_err; 23}; 24 25static errval_t vsic_write(struct storage_vsic *vsic, struct storage_vsa *vsa, 26 off_t offset, size_t size, void *buffer) 27{ 28 assert(vsic != NULL); 29 assert(vsa != NULL); 30 assert(buffer != NULL); 31 struct ahci_vsic *mydata = vsic->data; 32 errval_t status; 33 34 errval_t err = mydata->ata_rw28_rpc->rpc_tx_vtbl. 35 write_dma(&mydata->ata_rw28_rpc, buffer, STORAGE_VSIC_ROUND(vsic, size), 36 offset, &status); 37 if (err_is_fail(err)) { 38 USER_PANIC_ERR(err, "write_dma rpc"); 39 } 40 if (err_is_fail(status)) { 41 USER_PANIC_ERR(status, "write_dma status"); 42 } 43 44 return SYS_ERR_OK; 45} 46 47static errval_t vsic_read(struct storage_vsic *vsic, struct storage_vsa *vsa, 48 off_t offset, size_t size, void *buffer) 49{ 50 assert(vsic != NULL); 51 assert(vsa != NULL); 52 assert(buffer != NULL); 53 struct ahci_vsic *mydata = vsic->data; 54 uint8_t *buf = NULL; 55 size_t bytes_read, toread = STORAGE_VSIC_ROUND(vsic, size); 56 57 errval_t err = mydata->ata_rw28_rpc->rpc_tx_vtbl. 58 read_dma(&mydata->ata_rw28_rpc, toread, offset, &buf, &bytes_read); 59 if (err_is_fail(err)) 60 USER_PANIC_ERR(err, "read_dma rpc"); 61 if (!buf) 62 USER_PANIC("read_dma -> !buf"); 63 if (bytes_read != toread) 64 USER_PANIC("read_dma -> read_size != size"); 65 66 // XXX: Copy from DMA buffer to user buffer 67 memcpy(buffer, buf, size); 68 free(buf); 69 70 return SYS_ERR_OK; 71} 72 73static errval_t vsic_flush(struct storage_vsic *vsic, struct storage_vsa *vsa) 74{ 75 assert(vsic != NULL); 76 assert(vsa != NULL); 77 struct ahci_vsic *mydata = vsic->data; 78 errval_t outerr; 79 80 errval_t err = mydata->ata_rw28_rpc->rpc_tx_vtbl. 81 flush_cache(&mydata->ata_rw28_rpc, &outerr); 82 assert(err_is_ok(err)); 83 84 return outerr; 85} 86 87static errval_t vsic_wait(struct storage_vsic *vsic) 88{ 89 // XXX: Interface currently synchronous 90 return SYS_ERR_OK; 91} 92 93static struct storage_vsic_ops ahci_vsic_ops = { 94 .write = vsic_write, 95 .read = vsic_read, 96 .flush = vsic_flush, 97 .wait = vsic_wait, 98}; 99 100static void ahci_bind_cb(void *st, errval_t err, struct ahci_binding *_binding) 101{ 102 assert(err_is_ok(err)); 103 struct ahci_vsic *mydata = st; 104 mydata->ahci_binding = _binding; 105} 106 107// XXX: This could be made public and controlled by the programmer instead of 108// the commandline 109static errval_t ahci_vsic_alloc(struct storage_vsic *vsic, uint8_t port) 110{ 111 assert(vsic != NULL); 112 errval_t err; 113 struct ahci_vsic *mydata = malloc(sizeof(struct ahci_vsic)); 114 assert(mydata != NULL); 115 memset(mydata, 0, sizeof(struct ahci_vsic)); 116 117 // init ahci management binding 118 err = ahci_init(port, ahci_bind_cb, mydata, get_default_waitset()); 119 assert(err_is_ok(err)); 120 121 while(!mydata->ahci_binding) { 122 event_dispatch(get_default_waitset()); 123 } 124 125 // init ata flounder binding 126 err = ahci_ata_rw28_init(&mydata->ahci_ata_rw28_binding, 127 get_default_waitset(), mydata->ahci_binding); 128 if (err_is_fail(err)) { 129 USER_PANIC_ERR(err, "ahci_ata_rw28_init"); 130 } 131 mydata->ata_rw28_binding = 132 (struct ata_rw28_binding*)&mydata->ahci_ata_rw28_binding; 133 134 // init RPC client 135 err = ata_rw28_binding_init(&mydata->ata_rw28_rpc, 136 mydata->ata_rw28_binding); 137 if (err_is_fail(err)) { 138 USER_PANIC_ERR(err, "ata_rw28_binding_init"); 139 } 140 141 // Init VSIC data structure 142 vsic->ops = ahci_vsic_ops; 143 vsic->data = mydata; 144 vsic->blocksize = 512; // XXX: Determine from drive? 145 146 return SYS_ERR_OK; 147} 148 149errval_t storage_vsic_driver_init(int argc, const char **argv, 150 struct storage_vsic *vsic) 151{ 152 // init dma pool 153 ahci_dma_pool_init(1024*1024); 154 155 // Allocate port 0 156 return ahci_vsic_alloc(vsic, 0); 157} 158