1/*- 2 * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru) 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28#include <stand.h> 29 30#include "bootstrap.h" 31#include "lv1call.h" 32#include "ps3bus.h" 33#include "ps3repo.h" 34#include "ps3stor.h" 35 36int ps3stor_setup(struct ps3_stordev *sd, int type) 37{ 38 unsigned int i; 39 int err; 40 41 sd->sd_type = type; 42 43 err = ps3repo_find_bus_by_type(PS3_BUS_TYPE_STOR, &sd->sd_busidx); 44 if (err) 45 goto out; 46 47 err = ps3repo_read_bus_id(sd->sd_busidx, &sd->sd_busid); 48 if (err) 49 goto out; 50 51 err = ps3repo_find_bus_dev_by_type(sd->sd_busidx, type, &sd->sd_devidx); 52 if (err) 53 goto out; 54 55 err = ps3repo_read_bus_dev_id(sd->sd_busidx, sd->sd_devidx, 56 &sd->sd_devid); 57 if (err) 58 goto out; 59 60 err = ps3repo_read_bus_dev_blk_size(sd->sd_busidx, sd->sd_devidx, 61 &sd->sd_blksize); 62 if (err) 63 goto out; 64 65 err = ps3repo_read_bus_dev_nblocks(sd->sd_busidx, sd->sd_devidx, 66 &sd->sd_nblocks); 67 if (err) 68 goto out; 69 70 err = ps3repo_read_bus_dev_nregs(sd->sd_busidx, sd->sd_devidx, 71 &sd->sd_nregs); 72 if (err) 73 goto out; 74 75 for (i = 0; i < sd->sd_nregs; i++) { 76 err = ps3repo_read_bus_dev_reg_id(sd->sd_busidx, sd->sd_devidx, 77 i, &sd->sd_regs[i].sr_id); 78 if (err) 79 goto out; 80 81 err = ps3repo_read_bus_dev_reg_start(sd->sd_busidx, 82 sd->sd_devidx, i, &sd->sd_regs[i].sr_start); 83 if (err) 84 goto out; 85 86 err = ps3repo_read_bus_dev_reg_size(sd->sd_busidx, 87 sd->sd_devidx, i, &sd->sd_regs[i].sr_size); 88 if (err) 89 goto out; 90 } 91 92 if (!sd->sd_nregs) { 93 err = ENODEV; 94 goto out; 95 } 96 97 err = lv1_open_device(sd->sd_busid, sd->sd_devid, 0); 98 if (err) 99 goto out; 100 101 err = lv1_setup_dma(sd->sd_busid, sd->sd_devid, &sd->sd_dmabase); 102 if (err) 103 goto close_dev; 104 105 return 0; 106 107close_dev: 108 109 lv1_close_device(sd->sd_busid, sd->sd_devid); 110 111out: 112 113 return err; 114} 115 116static char dma_buf[2048] __aligned(2048); 117 118int ps3stor_read_sectors(struct ps3_stordev *sd, int regidx, 119 uint64_t start_sector, uint64_t sector_count, uint64_t flags, char *buf) 120{ 121#define MIN(a, b) ((a) <= (b) ? (a) : (b)) 122#define BOUNCE_SECTORS (sizeof(dma_buf) / sd->sd_blksize) 123#define ASYNC_STATUS_POLL_PERIOD 100 /* microseconds */ 124 125 struct ps3_storreg *reg = &sd->sd_regs[regidx]; 126 uint64_t nleft, nread, nsectors; 127 uint64_t tag, status; 128 unsigned int timeout; 129 int err = 0; 130 131 nleft = sector_count; 132 nread = 0; 133 134 while (nleft) { 135 nsectors = MIN(nleft, BOUNCE_SECTORS); 136 137 err = lv1_storage_read(sd->sd_devid, reg->sr_id, 138 start_sector + nread, nsectors, flags, (uint32_t)dma_buf, 139 &tag); 140 if (err) 141 return err; 142 143 timeout = 5000000; /* microseconds */ 144 145 while (1) { 146 if (timeout < ASYNC_STATUS_POLL_PERIOD) 147 return ETIMEDOUT; 148 149 err = lv1_storage_check_async_status(sd->sd_devid, tag, 150 &status); 151 if (!err && !status) 152 break; 153 154 delay(ASYNC_STATUS_POLL_PERIOD); 155 timeout -= ASYNC_STATUS_POLL_PERIOD; 156 } 157 158 if (status != 0) 159 return EIO; 160 161 memcpy(buf + nread * sd->sd_blksize, (u_char *)dma_buf, 162 nsectors * sd->sd_blksize); 163 nread += nsectors; 164 nleft -= nsectors; 165 } 166 167 return err; 168 169#undef MIN 170#undef BOUNCE_SECTORS 171#undef ASYNC_STATUS_POLL_PERIOD 172} 173 174void ps3stor_print(struct ps3_stordev *sd) 175{ 176} 177