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