1 /*
2 * OpenBIOS LSI driver
3 *
4 * Copyright (C) 2018 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
5 *
6 * Based upon drivers/esp.c
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2
11 *
12 */
13
14 #include "config.h"
15 #include "libc/byteorder.h"
16 #include "libc/vsprintf.h"
17 #include "libopenbios/bindings.h"
18 #include "drivers/drivers.h"
19 #include "scsi.h"
20
21 typedef struct sd_private sd_private_t;
22 typedef struct lsi_table lsi_table_t;
23 typedef struct lsi_private lsi_private_t;
24
25 struct sd_private {
26 unsigned int bs;
27 const char *media_str[2];
28 uint32_t sectors;
29 uint8_t media;
30 uint8_t id;
31 uint8_t present;
32 char model[40];
33 lsi_private_t *lsi;
34 };
35
36 struct lsi_table {
37 uint32_t id;
38 uint32_t id_addr;
39 uint32_t msg_out_len;
40 uint32_t msg_out_ptr;
41 uint32_t cmd_len;
42 uint32_t cmd_ptr;
43 uint32_t data_in_len;
44 uint32_t data_in_ptr;
45 uint32_t status_len;
46 uint32_t status_ptr;
47 uint32_t msg_in_len;
48 uint32_t msg_in_ptr;
49 };
50
51 struct lsi_private {
52 volatile uint8_t *mmio;
53 uint32_t *scripts;
54 uint32_t *scripts_iova;
55 lsi_table_t *table;
56 lsi_table_t *table_iova;
57 volatile uint8_t *buffer;
58 volatile uint8_t *buffer_iova;
59 sd_private_t sd[8];
60 };
61
62 #ifdef CONFIG_DEBUG_LSI
63 #define DPRINTF(fmt, args...) \
64 do { printk(fmt , ##args); } while (0)
65 #else
66 #define DPRINTF(fmt, args...)
67 #endif
68
69 /* DECLARE data structures for the nodes. */
70 DECLARE_UNNAMED_NODE(ob_sd, INSTALL_OPEN, sizeof(sd_private_t *));
71 DECLARE_UNNAMED_NODE(ob_lsi, INSTALL_OPEN, sizeof(lsi_private_t **));
72
73 #ifdef CONFIG_DEBUG_LSI
dump_drive(sd_private_t * drive)74 static void dump_drive(sd_private_t *drive)
75 {
76 printk("SCSI DRIVE @%lx:\n", (unsigned long)drive);
77 printk("id: %d\n", drive->id);
78 printk("media: %s\n", drive->media_str[0]);
79 printk("media: %s\n", drive->media_str[1]);
80 printk("model: %s\n", drive->model);
81 printk("sectors: %d\n", drive->sectors);
82 printk("present: %d\n", drive->present);
83 printk("bs: %d\n", drive->bs);
84 }
85 #endif
86
87 #define PHASE_DO 0
88 #define PHASE_DI 1
89 #define PHASE_CMD 2
90 #define PHASE_ST 3
91 #define PHASE_MO 6
92 #define PHASE_MI 7
93
94 #define LSI_DSTAT 0x0c
95 #define LSI_DSA 0x10
96 #define LSI_ISTAT0 0x14
97 #define LSI_DSP 0x2c
98 #define LSI_SIST0 0x42
99 #define LSI_SIST1 0x43
100
101 #define LSI_ISTAT0_DIP 0x01
102 #define LSI_ISTAT0_SIP 0x02
103
104 /* Indirection table */
105 #define LSI_TABLE_OFFSET(x) (((uintptr_t)&(x)) - ((uintptr_t)lsi->table))
106
107 #define LSI_TABLE_MSG_OUT_OFFSET 0x0
108 #define LSI_TABLE_CMD_OFFSET 0x2
109 #define LSI_TABLE_DATA_OFFSET 0x20
110 #define LSI_TABLE_STATUS_OFFSET 0x10
111 #define LSI_TABLE_MSG_IN_OFFSET 0x12
112
113 static void
init_scripts(lsi_private_t * lsi)114 init_scripts(lsi_private_t *lsi)
115 {
116 /* Initialise SCRIPTS for the commands we are interested in */
117
118 /* 1 - INQUIRY / READ CAPACITY */
119
120 /* 1.0 Select with ATN */
121 lsi->scripts[0x0] = __cpu_to_le32(0x47000000);
122 lsi->scripts[0x1] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
123
124 /* 1.1 Select LUN */
125 lsi->scripts[0x2] = __cpu_to_le32(0x10000000 | (PHASE_MO << 24));
126 lsi->scripts[0x3] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_out_len));
127
128 /* 1.2 Send command */
129 lsi->scripts[0x4] = __cpu_to_le32(0x10000000 | (PHASE_CMD << 24));
130 lsi->scripts[0x5] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->cmd_len));
131
132 /* 1.3 Data in */
133 lsi->scripts[0x6] = __cpu_to_le32(0x10000000 | (PHASE_DI << 24));
134 lsi->scripts[0x7] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->data_in_len));
135
136 /* 1.4 Status */
137 lsi->scripts[0x8] = __cpu_to_le32(0x10000000 | (PHASE_ST << 24));
138 lsi->scripts[0x9] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->status_len));
139
140 /* 1.5 Message in */
141 lsi->scripts[0xa] = __cpu_to_le32(0x10000000 | (PHASE_MI << 24));
142 lsi->scripts[0xb] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_in_len));
143
144 /* 1.6 Wait disconnect */
145 lsi->scripts[0xc] = __cpu_to_le32(0x48000000);
146 lsi->scripts[0xd] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
147
148 /* 1.7 Interrupt */
149 lsi->scripts[0xe] = __cpu_to_le32(0x98080000);
150 lsi->scripts[0xf] = 0x0;
151
152
153 /* 2 - TEST UNIT READY */
154
155 /* 2.0 Select with ATN */
156 lsi->scripts[0x10] = __cpu_to_le32(0x47000000);
157 lsi->scripts[0x11] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
158
159 /* 2.1 Select LUN */
160 lsi->scripts[0x12] = __cpu_to_le32(0x10000000 | (PHASE_MO << 24));
161 lsi->scripts[0x13] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_out_len));
162
163 /* 2.2 Send command */
164 lsi->scripts[0x14] = __cpu_to_le32(0x10000000 | (PHASE_CMD << 24));
165 lsi->scripts[0x15] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->cmd_len));
166
167 /* 2.3 Status */
168 lsi->scripts[0x16] = __cpu_to_le32(0x10000000 | (PHASE_ST << 24));
169 lsi->scripts[0x17] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->status_len));
170
171 /* 2.4 Message in */
172 lsi->scripts[0x18] = __cpu_to_le32(0x10000000 | (PHASE_MI << 24));
173 lsi->scripts[0x19] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_in_len));
174
175 /* 2.5 Wait disconnect */
176 lsi->scripts[0x1a] = __cpu_to_le32(0x48000000);
177 lsi->scripts[0x1b] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
178
179 /* 2.6 Interrupt */
180 lsi->scripts[0x1c] = __cpu_to_le32(0x98080000);
181 lsi->scripts[0x1d] = 0x0;
182
183
184 /* 3 - READ 10 */
185
186 /* 3.0 Select with ATN */
187 lsi->scripts[0x20] = __cpu_to_le32(0x47000000);
188 lsi->scripts[0x21] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
189
190 /* 3.1 Select LUN */
191 lsi->scripts[0x22] = __cpu_to_le32(0x10000000 | (PHASE_MO << 24));
192 lsi->scripts[0x23] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_out_len));
193
194 /* 3.2 Send command */
195 lsi->scripts[0x24] = __cpu_to_le32(0x10000000 | (PHASE_CMD << 24));
196 lsi->scripts[0x25] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->cmd_len));
197
198 /* 3.3 Message in */
199 lsi->scripts[0x26] = __cpu_to_le32(0x10000000 | (PHASE_MI << 24));
200 lsi->scripts[0x27] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_in_len));
201
202 /* 3.6 Interrupt */
203 lsi->scripts[0x28] = __cpu_to_le32(0x98080000);
204 lsi->scripts[0x29] = 0x0;
205
206 /* 3.7 Wait reselect */
207 lsi->scripts[0x2a] = __cpu_to_le32(0x50000000);
208 lsi->scripts[0x2b] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
209
210 /* 3.8 Message in */
211 lsi->scripts[0x2c] = __cpu_to_le32(0x10000000 | (PHASE_MI << 24));
212 lsi->scripts[0x2d] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->msg_in_len));
213
214 /* 3.9 Data in */
215 lsi->scripts[0x2e] = __cpu_to_le32(0x10000000 | (PHASE_DI << 24));
216 lsi->scripts[0x2f] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->data_in_len));
217
218 /* 3.10 Wait disconnect */
219 lsi->scripts[0x30] = __cpu_to_le32(0x48000000);
220 lsi->scripts[0x31] = __cpu_to_le32(LSI_TABLE_OFFSET(lsi->table->id));
221
222 /* 3.11 Interrupt */
223 lsi->scripts[0x32] = __cpu_to_le32(0x98080000);
224 lsi->scripts[0x33] = 0x0;
225 }
226
227 static void
init_table(lsi_private_t * lsi)228 init_table(lsi_private_t *lsi)
229 {
230 uint32_t dsa;
231
232 /* Initialise indirect table */
233 lsi->table->msg_out_ptr = __cpu_to_le32((uintptr_t)&lsi->buffer_iova[LSI_TABLE_MSG_OUT_OFFSET]);
234 lsi->table->cmd_ptr = __cpu_to_le32((uintptr_t)&lsi->buffer_iova[LSI_TABLE_CMD_OFFSET]);
235 lsi->table->data_in_ptr = __cpu_to_le32((uintptr_t)&lsi->buffer_iova[LSI_TABLE_DATA_OFFSET]);
236 lsi->table->status_ptr = __cpu_to_le32((uintptr_t)&lsi->buffer_iova[LSI_TABLE_STATUS_OFFSET]);
237 lsi->table->msg_in_ptr = __cpu_to_le32((uintptr_t)&lsi->buffer_iova[LSI_TABLE_MSG_IN_OFFSET]);
238
239 /* Set the DSA to point to the base of our data table */
240 dsa = (uintptr_t)lsi->table_iova;
241 lsi->mmio[LSI_DSA] = dsa & 0xff;
242 lsi->mmio[LSI_DSA + 1] = (dsa >> 8) & 0xff;
243 lsi->mmio[LSI_DSA + 2] = (dsa >> 16) & 0xff;
244 lsi->mmio[LSI_DSA + 3] = (dsa >> 24) & 0xff;
245 }
246
247 static unsigned int
lsi_interrupt_status(lsi_private_t * lsi)248 lsi_interrupt_status(lsi_private_t *lsi)
249 {
250 uint32_t istat, sist0, sist1, dstat;
251
252 /* Wait for interrupt status */
253 while ((istat = lsi->mmio[LSI_ISTAT0]) == 0);
254
255 if (istat & LSI_ISTAT0_SIP) {
256 /* If SCSI interrupt, clear SCSI interrupt registers */
257 sist0 = lsi->mmio[LSI_SIST0];
258 sist1 = lsi->mmio[LSI_SIST1];
259
260 if (sist0 != 0 || sist1 != 0) {
261 return 1;
262 }
263 }
264
265 if (istat & LSI_ISTAT0_DIP) {
266 /* If DMA interrupt, clear DMA interrupt register */
267 dstat = lsi->mmio[LSI_DSTAT];
268
269 if ((dstat & 0x7f) != 0x4) {
270 return 1;
271 }
272 }
273
274 return 0;
275 }
276
277 static unsigned int
inquiry(lsi_private_t * lsi,sd_private_t * sd)278 inquiry(lsi_private_t *lsi, sd_private_t *sd)
279 {
280 const char *media[2] = { "UNKNOWN", "UNKNOWN"};
281 uint8_t *buffer;
282
283 // Setup command = Inquiry
284 memset((uint8_t *)&lsi->buffer[LSI_TABLE_CMD_OFFSET], 0, 7);
285 lsi->buffer[LSI_TABLE_MSG_OUT_OFFSET] = 0x80;
286 lsi->table->msg_out_len = __cpu_to_le32(0x1);
287
288 lsi->buffer[LSI_TABLE_CMD_OFFSET] = INQUIRY;
289 lsi->table->cmd_len = __cpu_to_le32(0x6);
290
291 lsi->buffer[LSI_TABLE_CMD_OFFSET + 4] = 36;
292 lsi->table->data_in_len = __cpu_to_le32(36);
293
294 lsi->table->status_len = __cpu_to_le32(0x1);
295 lsi->table->msg_in_len = __cpu_to_le32(0x1);
296
297 lsi->table->id = __cpu_to_le32((sd->id << 16));
298 lsi->table->id_addr = __cpu_to_le32(&lsi->scripts_iova[0x2]);
299
300 /* Write DSP to start DMA engine */
301 uint32_t dsp = (uintptr_t)lsi->scripts_iova;
302 lsi->mmio[LSI_DSP] = dsp & 0xff;
303 lsi->mmio[LSI_DSP + 1] = (dsp >> 8) & 0xff;
304 lsi->mmio[LSI_DSP + 2] = (dsp >> 16) & 0xff;
305 lsi->mmio[LSI_DSP + 3] = (dsp >> 24) & 0xff;
306
307 if (lsi_interrupt_status(lsi)) {
308 sd->present = 0;
309 sd->media = -1;
310 return 0;
311 }
312
313 buffer = (uint8_t *)&lsi->buffer[LSI_TABLE_DATA_OFFSET];
314 sd->present = 1;
315 sd->media = buffer[0];
316
317 switch (sd->media) {
318 case TYPE_DISK:
319 media[0] = "disk";
320 media[1] = "hd";
321 break;
322 case TYPE_ROM:
323 media[0] = "cdrom";
324 media[1] = "cd";
325 break;
326 }
327 sd->media_str[0] = media[0];
328 sd->media_str[1] = media[1];
329 memcpy(sd->model, &buffer[16], 16);
330 sd->model[17] = '\0';
331
332 return 1;
333 }
334
335 static unsigned int
read_capacity(lsi_private_t * lsi,sd_private_t * sd)336 read_capacity(lsi_private_t *lsi, sd_private_t *sd)
337 {
338 uint8_t *buffer;
339
340 // Setup command = Read Capacity
341 memset((uint8_t *)&lsi->buffer[LSI_TABLE_CMD_OFFSET], 0, 11);
342 lsi->buffer[LSI_TABLE_MSG_OUT_OFFSET] = 0x80;
343 lsi->table->msg_out_len = __cpu_to_le32(0x1);
344
345 lsi->buffer[LSI_TABLE_CMD_OFFSET] = READ_CAPACITY;
346 lsi->table->cmd_len = __cpu_to_le32(0x11);
347
348 lsi->table->data_in_len = __cpu_to_le32(0x8);
349
350 lsi->table->status_len = __cpu_to_le32(0x1);
351 lsi->table->msg_in_len = __cpu_to_le32(0x1);
352
353 lsi->table->id = __cpu_to_le32((sd->id << 16));
354 lsi->table->id_addr = __cpu_to_le32(&lsi->scripts_iova[0x2]);
355
356 /* Write DSP to start DMA engine */
357 uint32_t dsp = (uintptr_t)lsi->scripts_iova;
358 lsi->mmio[LSI_DSP] = dsp & 0xff;
359 lsi->mmio[LSI_DSP + 1] = (dsp >> 8) & 0xff;
360 lsi->mmio[LSI_DSP + 2] = (dsp >> 16) & 0xff;
361 lsi->mmio[LSI_DSP + 3] = (dsp >> 24) & 0xff;
362
363 if (lsi_interrupt_status(lsi)) {
364 sd->sectors = 0;
365 sd->bs = 0;
366 DPRINTF("read_capacity id %d failed\n", sd->id);
367 return 0;
368 }
369
370 buffer = (uint8_t *)&lsi->buffer[LSI_TABLE_DATA_OFFSET];
371 sd->bs = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
372 sd->sectors = ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]) * (sd->bs / 512);
373
374 DPRINTF("read_capacity id %d bs %d sectors %d\n", sd->id, sd->bs,
375 sd->sectors);
376 return 1;
377 }
378
379 static unsigned int
test_unit_ready(lsi_private_t * lsi,sd_private_t * sd)380 test_unit_ready(lsi_private_t *lsi, sd_private_t *sd)
381 {
382 /* Setup command = Test Unit Ready */
383 memset((uint8_t *)&lsi->buffer[LSI_TABLE_CMD_OFFSET], 0, 7);
384 lsi->buffer[LSI_TABLE_MSG_OUT_OFFSET] = 0x80;
385 lsi->table->msg_out_len = __cpu_to_le32(0x1);
386
387 lsi->buffer[LSI_TABLE_CMD_OFFSET] = TEST_UNIT_READY;
388 lsi->table->cmd_len = __cpu_to_le32(0x6);
389
390 lsi->table->status_len = __cpu_to_le32(0x1);
391 lsi->table->msg_in_len = __cpu_to_le32(0x1);
392
393 lsi->table->id = __cpu_to_le32((sd->id << 16));
394 lsi->table->id_addr = __cpu_to_le32(&lsi->scripts_iova[0x12]);
395
396 /* Write DSP to start DMA engine */
397 uint32_t dsp = (uintptr_t)&lsi->scripts_iova[0x10];
398 lsi->mmio[LSI_DSP] = dsp & 0xff;
399 lsi->mmio[LSI_DSP + 1] = (dsp >> 8) & 0xff;
400 lsi->mmio[LSI_DSP + 2] = (dsp >> 16) & 0xff;
401 lsi->mmio[LSI_DSP + 3] = (dsp >> 24) & 0xff;
402
403 if (lsi_interrupt_status(lsi)) {
404 DPRINTF("test_unit_ready id %d failed\n", sd->id);
405 return 0;
406 }
407
408 DPRINTF("test_unit_ready id %d success\n", sd->id);
409 return 1;
410 }
411
412 static void
ob_lsi_dma_alloc(lsi_private_t ** lsi)413 ob_lsi_dma_alloc(__attribute__((unused)) lsi_private_t **lsi)
414 {
415 call_parent_method("dma-alloc");
416 }
417
418 static void
ob_lsi_dma_free(lsi_private_t ** lsi)419 ob_lsi_dma_free(__attribute__((unused)) lsi_private_t **lsi)
420 {
421 call_parent_method("dma-free");
422 }
423
424 static void
ob_lsi_dma_map_in(lsi_private_t ** lsi)425 ob_lsi_dma_map_in(__attribute__((unused)) lsi_private_t **lsi)
426 {
427 call_parent_method("dma-map-in");
428 }
429
430 static void
ob_lsi_dma_map_out(lsi_private_t ** lsi)431 ob_lsi_dma_map_out(__attribute__((unused)) lsi_private_t **lsi)
432 {
433 call_parent_method("dma-map-out");
434 }
435
436 static void
ob_lsi_dma_sync(lsi_private_t ** lsi)437 ob_lsi_dma_sync(__attribute__((unused)) lsi_private_t **lsi)
438 {
439 call_parent_method("dma-sync");
440 }
441
442 // offset is in sectors
443 static int
ob_sd_read_sector(lsi_private_t * lsi,sd_private_t * sd,int offset)444 ob_sd_read_sector(lsi_private_t *lsi, sd_private_t *sd, int offset)
445 {
446 uint32_t dsp;
447
448 DPRINTF("ob_sd_read_sector id %d sector=%d\n",
449 sd->id, offset);
450
451 // Setup command = Read(10)
452 memset((uint8_t *)&lsi->buffer[LSI_TABLE_CMD_OFFSET], 0, 10);
453 lsi->buffer[LSI_TABLE_MSG_OUT_OFFSET] = 0x80;
454 lsi->table->msg_out_len = __cpu_to_le32(0x1);
455
456 lsi->buffer[LSI_TABLE_CMD_OFFSET] = READ_10;
457 lsi->buffer[LSI_TABLE_CMD_OFFSET + 2] = (offset >> 24) & 0xff;
458 lsi->buffer[LSI_TABLE_CMD_OFFSET + 3] = (offset >> 16) & 0xff;;
459 lsi->buffer[LSI_TABLE_CMD_OFFSET + 4] = (offset >> 8) & 0xff;
460 lsi->buffer[LSI_TABLE_CMD_OFFSET + 5] = offset & 0xff;
461 lsi->buffer[LSI_TABLE_CMD_OFFSET + 7] = 0;
462 lsi->buffer[LSI_TABLE_CMD_OFFSET + 8] = 1;
463 lsi->table->cmd_len = __cpu_to_le32(0xa);
464
465 lsi->table->data_in_len = __cpu_to_le32(sd->bs);
466
467 lsi->table->status_len = __cpu_to_le32(0x1);
468 lsi->table->msg_in_len = __cpu_to_le32(0x2);
469
470 lsi->table->id = __cpu_to_le32((sd->id << 16));
471 lsi->table->id_addr = __cpu_to_le32(&lsi->scripts_iova[0x22]);
472
473 /* Write DSP to start DMA engine */
474 dsp = (uintptr_t)&lsi->scripts_iova[0x20];
475 lsi->mmio[LSI_DSP] = dsp & 0xff;
476 lsi->mmio[LSI_DSP + 1] = (dsp >> 8) & 0xff;
477 lsi->mmio[LSI_DSP + 2] = (dsp >> 16) & 0xff;
478 lsi->mmio[LSI_DSP + 3] = (dsp >> 24) & 0xff;
479
480 if (lsi_interrupt_status(lsi)) {
481 return 1;
482 }
483
484 // Reslect and data transfer
485 lsi->table->msg_in_len = __cpu_to_le32(0x1);
486
487 lsi->table->data_in_len = __cpu_to_le32(sd->bs);
488
489 /* Write DSP to start DMA engine */
490 dsp = (uintptr_t)&lsi->scripts_iova[0x2a];
491 lsi->mmio[LSI_DSP] = dsp & 0xff;
492 lsi->mmio[LSI_DSP + 1] = (dsp >> 8) & 0xff;
493 lsi->mmio[LSI_DSP + 2] = (dsp >> 16) & 0xff;
494 lsi->mmio[LSI_DSP + 3] = (dsp >> 24) & 0xff;
495
496 if (lsi_interrupt_status(lsi)) {
497 return 1;
498 }
499
500 return 0;
501 }
502
503 static void
ob_sd_read_blocks(sd_private_t ** sd)504 ob_sd_read_blocks(sd_private_t **sd)
505 {
506 cell n = POP(), cnt = n;
507 ucell blk = POP();
508 char *dest = (char*)POP();
509 int pos, spb, sect_offset;
510 lsi_private_t *lsi = (*sd)->lsi;
511
512 DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n );
513
514 if ((*sd)->bs == 0) {
515 PUSH(0);
516 return;
517 }
518 spb = (*sd)->bs / 512;
519 while (n) {
520 sect_offset = blk / spb;
521 pos = (blk - sect_offset * spb) * 512;
522
523 if (ob_sd_read_sector(lsi, *sd, sect_offset)) {
524 DPRINTF("ob_sd_read_blocks: error\n");
525 RET(0);
526 }
527 while (n && pos < spb * 512) {
528 memcpy(dest, (uint8_t *)&lsi->buffer[LSI_TABLE_DATA_OFFSET] + pos, 512);
529 pos += 512;
530 dest += 512;
531 n--;
532 blk++;
533 }
534 }
535 PUSH(cnt);
536 }
537
538 static void
ob_sd_block_size(sd_private_t ** sd)539 ob_sd_block_size(__attribute__((unused))sd_private_t **sd)
540 {
541 PUSH(512);
542 }
543
544 static void
ob_sd_open(sd_private_t ** sd)545 ob_sd_open(__attribute__((unused))sd_private_t **sd)
546 {
547 int ret = 1;
548 phandle_t ph;
549
550 PUSH(find_ih_method("sd-private", my_self()));
551 fword("execute");
552 *sd = cell2pointer(POP());
553
554 #ifdef CONFIG_DEBUG_LSI
555 {
556 char *args;
557
558 fword("my-args");
559 args = pop_fstr_copy();
560 DPRINTF("opening drive args %s\n", args);
561 free(args);
562 }
563 #endif
564
565 selfword("open-deblocker");
566
567 /* interpose disk-label */
568 ph = find_dev("/packages/disk-label");
569 fword("my-args");
570 PUSH_ph( ph );
571 fword("interpose");
572
573 RET ( -ret );
574 }
575
576 static void
ob_sd_close(sd_private_t ** sd)577 ob_sd_close(__attribute__((unused)) sd_private_t **sd)
578 {
579 selfword("close-deblocker");
580 }
581
582 NODE_METHODS(ob_sd) = {
583 { "open", ob_sd_open },
584 { "close", ob_sd_close },
585 { "read-blocks", ob_sd_read_blocks },
586 { "block-size", ob_sd_block_size },
587 };
588
589 static void
ob_lsi_decodeunit(lsi_private_t ** lsi_p)590 ob_lsi_decodeunit(__attribute__((unused)) lsi_private_t **lsi_p)
591 {
592 /* ( str len -- id ) */
593 fword("parse-hex");
594 }
595
596 static void
ob_lsi_encodeunit(lsi_private_t ** lsi_p)597 ob_lsi_encodeunit(__attribute__((unused)) lsi_private_t **lsi_p)
598 {
599 /* ( id -- str len ) */
600 fword("pocket");
601 fword("tohexstr");
602 }
603
604 static void
ob_lsi_open(lsi_private_t ** lsi_p)605 ob_lsi_open(__attribute__((unused)) lsi_private_t **lsi_p)
606 {
607 PUSH(-1);
608 }
609
610 static void
ob_lsi_close(lsi_private_t ** lsi_p)611 ob_lsi_close(__attribute__((unused)) lsi_private_t **lsi_p)
612 {
613 return;
614 }
615
616 NODE_METHODS(ob_lsi) = {
617 { "open" , ob_lsi_open },
618 { "close" , ob_lsi_close },
619 { "decode-unit", ob_lsi_decodeunit },
620 { "encode-unit", ob_lsi_encodeunit },
621 { "dma-alloc", ob_lsi_dma_alloc },
622 { "dma-free", ob_lsi_dma_free },
623 { "dma-map-in", ob_lsi_dma_map_in },
624 { "dma-map-out", ob_lsi_dma_map_out },
625 { "dma-sync", ob_lsi_dma_sync },
626 };
627
628 static void
add_alias(const char * device,const char * alias)629 add_alias(const char *device, const char *alias)
630 {
631 phandle_t aliases;
632
633 DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias);
634
635 aliases = find_dev("/aliases");
636 set_property(aliases, alias, device, strlen(device) + 1);
637 }
638
639 int
ob_lsi_init(const char * path,uint64_t mmio,uint64_t ram)640 ob_lsi_init(const char *path, uint64_t mmio, uint64_t ram)
641 {
642 int id, diskcount = 0, cdcount = 0, *counter_ptr;
643 char nodebuff[256], aliasbuff[256];
644 phandle_t ph = get_cur_dev();
645 lsi_private_t *lsi;
646 int i;
647 ucell addr;
648
649 BIND_NODE_METHODS(ph, ob_lsi);
650
651 lsi = malloc(sizeof(lsi_private_t));
652 if (!lsi) {
653 DPRINTF("Can't allocate LSI private structure\n");
654 return -1;
655 }
656
657 /* Buffer for commands */
658 PUSH(0x1000);
659 feval("dma-alloc");
660 addr = POP();
661 lsi->buffer = cell2pointer(addr);
662
663 PUSH(addr);
664 PUSH(0x1000);
665 PUSH(0);
666 feval("dma-map-in");
667 addr = POP();
668 lsi->buffer_iova = cell2pointer(addr);
669
670 PUSH(0x40 * sizeof(uint32_t));
671 feval("dma-alloc");
672 addr = POP();
673 lsi->scripts = cell2pointer(addr);
674
675 PUSH(addr);
676 PUSH(0x40 * sizeof(uint32_t));
677 PUSH(0);
678 feval("dma-map-in");
679 addr = POP();
680 lsi->scripts_iova = cell2pointer(addr);
681
682 PUSH(sizeof(lsi_table_t));
683 feval("dma-alloc");
684 addr = POP();
685 lsi->table = cell2pointer(addr);
686
687 PUSH(addr);
688 PUSH(sizeof(lsi_table_t));
689 PUSH(0);
690 feval("dma-map-in");
691 addr = POP();
692 lsi->table_iova = cell2pointer(addr);
693
694 set_int_property(ph, "#address-cells", 1);
695 set_int_property(ph, "#size-cells", 0);
696
697 /* Initialise SCRIPTS */
698 lsi->mmio = (uint8_t *)(uint32_t)mmio;
699 init_scripts(lsi);
700 init_table(lsi);
701
702 /* Scan the SCSI bus */
703 for (id = 0; id < 8; id++) {
704 lsi->sd[id].id = id;
705 if (!inquiry(lsi, &lsi->sd[id])) {
706 DPRINTF("Unit %d not present\n", id);
707 continue;
708 }
709
710 /* Clear Unit Attention condition from reset */
711 for (i = 0; i < 5; i++) {
712 if (test_unit_ready(lsi, &lsi->sd[id])) {
713 break;
714 }
715 }
716 if (i == 5) {
717 DPRINTF("Unit %d present but won't become ready\n", id);
718 continue;
719 }
720 DPRINTF("Unit %d present\n", id);
721 read_capacity(lsi, &lsi->sd[id]);
722
723 #ifdef CONFIG_DEBUG_LSI
724 dump_drive(&lsi->sd[id]);
725 #endif
726 }
727
728 for (id = 0; id < 8; id++) {
729 if (!lsi->sd[id].present)
730 continue;
731
732 lsi->sd[id].lsi = lsi;
733
734 fword("new-device");
735 push_str("sd");
736 fword("device-name");
737 push_str("block");
738 fword("device-type");
739 fword("is-deblocker");
740 PUSH(id);
741 fword("encode-int");
742 PUSH(0);
743 fword("encode-int");
744 fword("encode+");
745 push_str("reg");
746 fword("property");
747
748 PUSH(pointer2cell(&lsi->sd[id]));
749 feval("value sd-private");
750
751 BIND_NODE_METHODS(get_cur_dev(), ob_sd);
752 fword("finish-device");
753
754 snprintf(nodebuff, sizeof(nodebuff), "%s/sd@%d",
755 get_path_from_ph(ph), id);
756
757 if (lsi->sd[id].media == TYPE_ROM) {
758 counter_ptr = &cdcount;
759 } else {
760 counter_ptr = &diskcount;
761 }
762 if (*counter_ptr == 0) {
763 add_alias(nodebuff, lsi->sd[id].media_str[0]);
764 add_alias(nodebuff, lsi->sd[id].media_str[1]);
765 }
766 snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
767 lsi->sd[id].media_str[0], *counter_ptr);
768 add_alias(nodebuff, aliasbuff);
769 snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
770 lsi->sd[id].media_str[1], *counter_ptr);
771 add_alias(nodebuff, aliasbuff);
772 }
773
774 return 0;
775 }
776