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