1 /*
2  *   OpenBIOS ESP driver
3  *
4  *   Copyright (C) 2004 Jens Axboe <axboe@suse.de>
5  *   Copyright (C) 2005 Stefan Reinauer
6  *
7  *   Credit goes to Hale Landis for his excellent ata demo software
8  *   OF node handling and some fixes by Stefan Reinauer
9  *
10  *   This program is free software; you can redistribute it and/or
11  *   modify it under the terms of the GNU General Public License
12  *   version 2
13  *
14  */
15 
16 #include "config.h"
17 #include "libopenbios/bindings.h"
18 #include "kernel/kernel.h"
19 #include "libc/byteorder.h"
20 #include "libc/vsprintf.h"
21 
22 #include "drivers/drivers.h"
23 #include "asm/io.h"
24 #include "scsi.h"
25 #include "asm/dma.h"
26 #include "esp.h"
27 #include "libopenbios/ofmem.h"
28 
29 #define BUFSIZE         4096
30 
31 #ifdef CONFIG_DEBUG_ESP
32 #define DPRINTF(fmt, args...)                   \
33     do { printk(fmt , ##args); } while (0)
34 #else
35 #define DPRINTF(fmt, args...)
36 #endif
37 
38 struct esp_dma {
39     volatile struct sparc_dma_registers *regs;
40     enum dvma_rev revision;
41 };
42 
43 typedef struct sd_private {
44     unsigned int bs;
45     const char *media_str[2];
46     uint32_t sectors;
47     uint8_t media;
48     uint8_t id;
49     uint8_t present;
50     char model[40];
51 } sd_private_t;
52 
53 struct esp_regs {
54     unsigned char regs[ESP_REG_SIZE];
55 };
56 
57 typedef struct esp_private {
58     volatile struct esp_regs *ll;
59     uint32_t buffer_dvma;
60     unsigned int irq;        /* device IRQ number    */
61     struct esp_dma espdma;
62     unsigned char *buffer;
63     sd_private_t sd[8];
64 } esp_private_t;
65 
66 static esp_private_t *global_esp;
67 
68 /* DECLARE data structures for the nodes.  */
69 DECLARE_UNNAMED_NODE(ob_sd, INSTALL_OPEN, sizeof(sd_private_t *));
70 DECLARE_UNNAMED_NODE(ob_esp, INSTALL_OPEN, sizeof(esp_private_t *));
71 
72 #ifdef CONFIG_DEBUG_ESP
dump_drive(sd_private_t * drive)73 static void dump_drive(sd_private_t *drive)
74 {
75     printk("SCSI DRIVE @%lx:\n", (unsigned long)drive);
76     printk("id: %d\n", drive->id);
77     printk("media: %s\n", drive->media_str[0]);
78     printk("media: %s\n", drive->media_str[1]);
79     printk("model: %s\n", drive->model);
80     printk("sectors: %d\n", drive->sectors);
81     printk("present: %d\n", drive->present);
82     printk("bs: %d\n", drive->bs);
83 }
84 #endif
85 
86 static int
do_command(esp_private_t * esp,sd_private_t * sd,int cmdlen,int replylen)87 do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen)
88 {
89     int status;
90 
91     // Set SCSI target
92     esp->ll->regs[ESP_BUSID] = sd->id & 7;
93     // Set DMA address
94     esp->espdma.regs->st_addr = esp->buffer_dvma;
95     // Set DMA length
96     esp->ll->regs[ESP_TCLOW] = cmdlen & 0xff;
97     esp->ll->regs[ESP_TCMED] = (cmdlen >> 8) & 0xff;
98     // Set DMA direction and enable DMA
99     esp->espdma.regs->cond_reg = DMA_ENABLE;
100     // Set ATN, issue command
101     esp->ll->regs[ESP_CMD] = ESP_CMD_SELA | ESP_CMD_DMA;
102     // Wait for DMA to complete. Can this fail?
103     while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
104     // Check status
105     status = esp->ll->regs[ESP_STATUS];
106     // Clear interrupts to avoid guests seeing spurious interrupts
107     (void)esp->ll->regs[ESP_INTRPT];
108 
109     DPRINTF("do_command: id %d, cmd[0] 0x%x, status 0x%x\n", sd->id, esp->buffer[1], status);
110 
111     /* Target didn't want all command data? */
112     if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT) {
113         return status;
114     }
115     if (replylen == 0) {
116         return 0;
117     }
118     /* Target went to status phase instead of data phase? */
119     if ((status & ESP_STAT_PMASK) == ESP_STATP) {
120         return status;
121     }
122 
123     // Get reply
124     // Set DMA address
125     esp->espdma.regs->st_addr = esp->buffer_dvma;
126     // Set DMA length
127     esp->ll->regs[ESP_TCLOW] = replylen & 0xff;
128     esp->ll->regs[ESP_TCMED] = (replylen >> 8) & 0xff;
129     // Set DMA direction
130     esp->espdma.regs->cond_reg = DMA_ST_WRITE | DMA_ENABLE;
131     // Transfer
132     esp->ll->regs[ESP_CMD] = ESP_CMD_TI | ESP_CMD_DMA;
133     // Wait for DMA to complete
134     while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
135     // Check status
136     status = esp->ll->regs[ESP_STATUS];
137     // Clear interrupts to avoid guests seeing spurious interrupts
138     (void)esp->ll->regs[ESP_INTRPT];
139 
140     DPRINTF("do_command_reply: status 0x%x\n", status);
141 
142     if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT)
143         return status;
144     else
145         return 0; // OK
146 }
147 
148 // offset is in sectors
149 static int
ob_sd_read_sector(esp_private_t * esp,sd_private_t * sd,int offset)150 ob_sd_read_sector(esp_private_t *esp, sd_private_t *sd, int offset)
151 {
152     DPRINTF("ob_sd_read_sector id %d sector=%d\n",
153             sd->id, offset);
154 
155     // Setup command = Read(10)
156     memset(esp->buffer, 0, 11);
157     esp->buffer[0] = 0x80;
158     esp->buffer[1] = READ_10;
159 
160     esp->buffer[3] = (offset >> 24) & 0xff;
161     esp->buffer[4] = (offset >> 16) & 0xff;
162     esp->buffer[5] = (offset >> 8) & 0xff;
163     esp->buffer[6] = offset & 0xff;
164 
165     esp->buffer[8] = 0;
166     esp->buffer[9] = 1;
167 
168     if (do_command(esp, sd, 11, sd->bs))
169         return 0;
170 
171     return 0;
172 }
173 
174 static unsigned int
read_capacity(esp_private_t * esp,sd_private_t * sd)175 read_capacity(esp_private_t *esp, sd_private_t *sd)
176 {
177     // Setup command = Read Capacity
178     memset(esp->buffer, 0, 11);
179     esp->buffer[0] = 0x80;
180     esp->buffer[1] = READ_CAPACITY;
181 
182     if (do_command(esp, sd, 11, 8)) {
183         sd->sectors = 0;
184         sd->bs = 0;
185         DPRINTF("read_capacity id %d failed\n", sd->id);
186         return 0;
187     }
188     sd->bs = (esp->buffer[4] << 24) | (esp->buffer[5] << 16) | (esp->buffer[6] << 8) | esp->buffer[7];
189     sd->sectors = ((esp->buffer[0] << 24) | (esp->buffer[1] << 16) | (esp->buffer[2] << 8) | esp->buffer[3]) * (sd->bs / 512);
190 
191     DPRINTF("read_capacity id %d bs %d sectors %d\n", sd->id, sd->bs,
192             sd->sectors);
193     return 1;
194 }
195 
196 static unsigned int
test_unit_ready(esp_private_t * esp,sd_private_t * sd)197 test_unit_ready(esp_private_t *esp, sd_private_t *sd)
198 {
199     /* Setup command = Test Unit Ready */
200     memset(esp->buffer, 0, 7);
201     esp->buffer[0] = 0x80;
202     esp->buffer[1] = TEST_UNIT_READY;
203 
204     if (do_command(esp, sd, 7, 0)) {
205         DPRINTF("test_unit_ready id %d failed\n", sd->id);
206         return 0;
207     }
208 
209     DPRINTF("test_unit_ready id %d success\n", sd->id);
210     return 1;
211 }
212 
213 static unsigned int
inquiry(esp_private_t * esp,sd_private_t * sd)214 inquiry(esp_private_t *esp, sd_private_t *sd)
215 {
216     const char *media[2] = { "UNKNOWN", "UNKNOWN"};
217 
218     // Setup command = Inquiry
219     memset(esp->buffer, 0, 7);
220     esp->buffer[0] = 0x80;
221     esp->buffer[1] = INQUIRY;
222 
223     esp->buffer[5] = 36;
224 
225     if (do_command(esp, sd, 7, 36)) {
226         sd->present = 0;
227         sd->media = -1;
228         return 0;
229     }
230     sd->present = 1;
231     sd->media = esp->buffer[0];
232 
233     switch (sd->media) {
234     case TYPE_DISK:
235         media[0] = "disk";
236         media[1] = "hd";
237         break;
238     case TYPE_ROM:
239         media[0] = "cdrom";
240         media[1] = "cd";
241         break;
242     }
243     sd->media_str[0] = media[0];
244     sd->media_str[1] = media[1];
245     memcpy(sd->model, &esp->buffer[16], 16);
246     sd->model[17] = '\0';
247 
248     return 1;
249 }
250 
251 static void
ob_esp_dma_alloc(esp_private_t ** esp)252 ob_esp_dma_alloc(__attribute__((unused)) esp_private_t **esp)
253 {
254     call_parent_method("dma-alloc");
255 }
256 
257 static void
ob_esp_dma_free(esp_private_t ** esp)258 ob_esp_dma_free(__attribute__((unused)) esp_private_t **esp)
259 {
260     call_parent_method("dma-free");
261 }
262 
263 static void
ob_esp_dma_map_in(esp_private_t ** esp)264 ob_esp_dma_map_in(__attribute__((unused)) esp_private_t **esp)
265 {
266     call_parent_method("dma-map-in");
267 }
268 
269 static void
ob_esp_dma_map_out(esp_private_t ** esp)270 ob_esp_dma_map_out(__attribute__((unused)) esp_private_t **esp)
271 {
272     call_parent_method("dma-map-out");
273 }
274 
275 static void
ob_esp_dma_sync(esp_private_t ** esp)276 ob_esp_dma_sync(__attribute__((unused)) esp_private_t **esp)
277 {
278     call_parent_method("dma-sync");
279 }
280 
281 static void
ob_sd_read_blocks(sd_private_t ** sd)282 ob_sd_read_blocks(sd_private_t **sd)
283 {
284     cell n = POP(), cnt = n;
285     ucell blk = POP();
286     char *dest = (char*)POP();
287     int pos, spb, sect_offset;
288 
289     DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n );
290 
291     if ((*sd)->bs == 0) {
292         PUSH(0);
293         return;
294     }
295     spb = (*sd)->bs / 512;
296     while (n) {
297         sect_offset = blk / spb;
298         pos = (blk - sect_offset * spb) * 512;
299 
300         if (ob_sd_read_sector(global_esp, *sd, sect_offset)) {
301             DPRINTF("ob_sd_read_blocks: error\n");
302             RET(0);
303         }
304         while (n && pos < spb * 512) {
305             memcpy(dest, global_esp->buffer + pos, 512);
306             pos += 512;
307             dest += 512;
308             n--;
309             blk++;
310         }
311     }
312     PUSH(cnt);
313 }
314 
315 static void
ob_sd_block_size(sd_private_t ** sd)316 ob_sd_block_size(__attribute__((unused))sd_private_t **sd)
317 {
318     PUSH(512);
319 }
320 
321 static void
ob_sd_open(sd_private_t ** sd)322 ob_sd_open(__attribute__((unused))sd_private_t **sd)
323 {
324     int ret = 1, id;
325     phandle_t ph;
326 
327     fword("my-unit");
328     id = POP();
329     POP(); // unit id is 2 ints but we only need one.
330     *sd = &global_esp->sd[id];
331 
332 #ifdef CONFIG_DEBUG_ESP
333     {
334         char *args;
335 
336         fword("my-args");
337         args = pop_fstr_copy();
338         DPRINTF("opening drive %d args %s\n", id, args);
339         free(args);
340     }
341 #endif
342 
343     selfword("open-deblocker");
344 
345     /* interpose disk-label */
346     ph = find_dev("/packages/disk-label");
347     fword("my-args");
348     PUSH_ph( ph );
349     fword("interpose");
350 
351     RET ( -ret );
352 }
353 
354 static void
ob_sd_close(sd_private_t ** sd)355 ob_sd_close(__attribute__((unused)) sd_private_t **sd)
356 {
357     selfword("close-deblocker");
358 }
359 
360 NODE_METHODS(ob_sd) = {
361     { "open",           ob_sd_open },
362     { "close",          ob_sd_close },
363     { "read-blocks",    ob_sd_read_blocks },
364     { "block-size",     ob_sd_block_size },
365     { "dma-alloc",      ob_esp_dma_alloc   },
366     { "dma-free",       ob_esp_dma_free    },
367     { "dma-map-in",     ob_esp_dma_map_in  },
368     { "dma-map-out",    ob_esp_dma_map_out },
369     { "dma-sync",       ob_esp_dma_sync    },
370 };
371 
372 
373 static int
espdma_init(unsigned int slot,uint64_t base,unsigned long offset,struct esp_dma * espdma)374 espdma_init(unsigned int slot, uint64_t base, unsigned long offset,
375             struct esp_dma *espdma)
376 {
377     espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10);
378 
379     if (espdma->regs == NULL) {
380         DPRINTF("espdma_init: cannot map registers\n");
381         return -1;
382     }
383 
384     DPRINTF("dma1: ");
385 
386     switch ((espdma->regs->cond_reg) & DMA_DEVICE_ID) {
387     case DMA_VERS0:
388         espdma->revision = dvmarev0;
389         DPRINTF("Revision 0 ");
390         break;
391     case DMA_ESCV1:
392         espdma->revision = dvmaesc1;
393         DPRINTF("ESC Revision 1 ");
394         break;
395     case DMA_VERS1:
396         espdma->revision = dvmarev1;
397         DPRINTF("Revision 1 ");
398         break;
399     case DMA_VERS2:
400         espdma->revision = dvmarev2;
401         DPRINTF("Revision 2 ");
402         break;
403     case DMA_VERHME:
404         espdma->revision = dvmahme;
405         DPRINTF("HME DVMA gate array ");
406         break;
407     case DMA_VERSPLUS:
408         espdma->revision = dvmarevplus;
409         DPRINTF("Revision 1 PLUS ");
410         break;
411     default:
412         DPRINTF("unknown dma version %x",
413                (espdma->regs->cond_reg) & DMA_DEVICE_ID);
414         /* espdma->allocated = 1; */
415         break;
416     }
417     DPRINTF("\n");
418 
419     push_str("/iommu/sbus/espdma");
420     fword("find-device");
421 
422     /* set reg */
423     PUSH(slot);
424     fword("encode-int");
425     PUSH(offset);
426     fword("encode-int");
427     fword("encode+");
428     PUSH(0x00000010);
429     fword("encode-int");
430     fword("encode+");
431     push_str("reg");
432     fword("property");
433 
434     return 0;
435 }
436 
437 static void
ob_esp_decodeunit(esp_private_t ** esp)438 ob_esp_decodeunit(__attribute__((unused)) esp_private_t **esp)
439 {
440     fword("decode-unit-scsi");
441 }
442 
443 
444 static void
ob_esp_encodeunit(esp_private_t ** esp)445 ob_esp_encodeunit(__attribute__((unused)) esp_private_t **esp)
446 {
447     fword("encode-unit-scsi");
448 }
449 
450 NODE_METHODS(ob_esp) = {
451     { "decode-unit",    ob_esp_decodeunit  },
452     { "encode-unit",    ob_esp_encodeunit  },
453     { "dma-alloc",      ob_esp_dma_alloc   },
454     { "dma-free",       ob_esp_dma_free    },
455     { "dma-map-in",     ob_esp_dma_map_in  },
456     { "dma-map-out",    ob_esp_dma_map_out },
457     { "dma-sync",       ob_esp_dma_sync    },
458 };
459 
460 static void
add_alias(const char * device,const char * alias)461 add_alias(const char *device, const char *alias)
462 {
463     DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias);
464     push_str("/aliases");
465     fword("find-device");
466     push_str(device);
467     fword("encode-string");
468     push_str(alias);
469     fword("property");
470 }
471 
472 int
ob_esp_init(unsigned int slot,uint64_t base,unsigned long espoffset,unsigned long dmaoffset)473 ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset,
474             unsigned long dmaoffset)
475 {
476     int id, diskcount = 0, cdcount = 0, *counter_ptr;
477     char nodebuff[256], aliasbuff[256];
478     esp_private_t *esp;
479     ucell addr;
480     unsigned int i;
481 
482     DPRINTF("Initializing SCSI...");
483 
484     esp = malloc(sizeof(esp_private_t));
485     if (!esp) {
486         DPRINTF("Can't allocate ESP private structure\n");
487         return -1;
488     }
489 
490     global_esp = esp;
491 
492     if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) {
493         return -1;
494     }
495     /* Get the IO region */
496     esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset,
497                              sizeof(struct esp_regs));
498     if (esp->ll == NULL) {
499         DPRINTF("Can't map ESP registers\n");
500         return -1;
501     }
502 
503     push_str("/iommu/sbus/espdma");
504     fword("find-device");
505     fword("new-device");
506 
507     push_str("esp");
508     fword("device-name");
509 
510     /* set device type */
511     push_str("scsi");
512     fword("device-type");
513 
514     /* QEMU's ESP emulation does not support mixing DMA and FIFO messages. By
515        setting this attribute, we prevent the Solaris ESP kernel driver from
516        trying to use this feature when booting a disk image (and failing) */
517     PUSH(0x58);
518     fword("encode-int");
519     push_str("scsi-options");
520     fword("property");
521 
522     PUSH(0x24);
523     fword("encode-int");
524     PUSH(0);
525     fword("encode-int");
526     fword("encode+");
527     push_str("intr");
528     fword("property");
529 
530     PUSH(slot);
531     fword("encode-int");
532     PUSH(espoffset);
533     fword("encode-int");
534     fword("encode+");
535     PUSH(0x00000010);
536     fword("encode-int");
537     fword("encode+");
538     push_str("reg");
539     fword("property");
540 
541     PUSH(0x02625a00);
542     fword("encode-int");
543     push_str("clock-frequency");
544     fword("property");
545 
546     REGISTER_NODE_METHODS(ob_esp, "/iommu/sbus/espdma/esp");
547 
548     fword("finish-device");
549 
550     fword("my-self");
551     push_str("/iommu/sbus/espdma/esp");
552     feval("open-dev to my-self");
553     PUSH(BUFSIZE);
554     feval("dma-alloc");
555     addr = POP();
556     esp->buffer = cell2pointer(addr);
557 
558     PUSH(addr);
559     PUSH(BUFSIZE);
560     PUSH(1);
561     feval("dma-map-in");
562     addr = POP();
563     esp->buffer_dvma = addr;
564     feval("to my-self");
565 
566     if (!esp->buffer || !esp->buffer_dvma) {
567         DPRINTF("Can't get a DVMA buffer\n");
568         return -1;
569     }
570 
571     // Chip reset
572     esp->ll->regs[ESP_CMD] = ESP_CMD_RC;
573 
574     DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp,
575             (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma);
576     DPRINTF("done\n");
577     DPRINTF("Initializing SCSI devices...");
578 
579     for (id = 0; id < 8; id++) {
580         esp->sd[id].id = id;
581         if (!inquiry(esp, &esp->sd[id])) {
582             DPRINTF("Unit %d not present\n", id);
583             continue;
584         }
585         /* Clear Unit Attention condition from reset */
586         for (i = 0; i < 5; i++) {
587             if (test_unit_ready(esp, &esp->sd[id])) {
588                 break;
589             }
590         }
591         if (i == 5) {
592             DPRINTF("Unit %d present but won't become ready\n", id);
593             continue;
594         }
595         DPRINTF("Unit %d present\n", id);
596         read_capacity(esp, &esp->sd[id]);
597 
598 #ifdef CONFIG_DEBUG_ESP
599         dump_drive(&esp->sd[id]);
600 #endif
601     }
602 
603     for (id = 0; id < 8; id++) {
604         if (!esp->sd[id].present)
605             continue;
606         push_str("/iommu/sbus/espdma/esp");
607         fword("find-device");
608         fword("new-device");
609         push_str("sd");
610         fword("device-name");
611         push_str("block");
612         fword("device-type");
613         fword("is-deblocker");
614         PUSH(id);
615         fword("encode-int");
616         PUSH(0);
617         fword("encode-int");
618         fword("encode+");
619         push_str("reg");
620         fword("property");
621         fword("finish-device");
622         snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0",
623                  id);
624         REGISTER_NODE_METHODS(ob_sd, nodebuff);
625         if (esp->sd[id].media == TYPE_ROM) {
626             counter_ptr = &cdcount;
627         } else {
628             counter_ptr = &diskcount;
629         }
630         if (*counter_ptr == 0) {
631             add_alias(nodebuff, esp->sd[id].media_str[0]);
632             add_alias(nodebuff, esp->sd[id].media_str[1]);
633         }
634         snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
635                  esp->sd[id].media_str[0], *counter_ptr);
636         add_alias(nodebuff, aliasbuff);
637         snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
638                  esp->sd[id].media_str[1], *counter_ptr);
639         add_alias(nodebuff, aliasbuff);
640         snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id);
641         add_alias(nodebuff, aliasbuff);
642         snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id);
643         add_alias(nodebuff, aliasbuff);
644         (*counter_ptr)++;
645     }
646     DPRINTF("done\n");
647 
648     return 0;
649 }
650