1
// AMD PCscsi boot support.
3
// Copyright (C) 2012 Red Hat Inc.
6
// Paolo Bonzini <pbonzini@redhat.com>
8
// based on lsi-scsi.c which is written by:
9
// Gerd Hoffman <kraxel@redhat.com>
11
// This file may be distributed under the terms of the GNU LGPLv3 license.
13
#include "util.h" // dprintf
14
#include "pci.h" // foreachpci
15
#include "config.h" // CONFIG_*
16
#include "biosvar.h" // GET_GLOBAL
17
#include "pci_ids.h" // PCI_DEVICE_ID
18
#include "pci_regs.h" // PCI_VENDOR_ID
19
#include "boot.h" // bootprio_find_scsi_device
20
#include "blockcmd.h" // scsi_drive_setup
21
#include "paravirt.h" // runningOnQEMU
25
#define ESP_TCMID 0x04
28
#define ESP_WBUSID 0x10
31
#define ESP_RSTAT 0x10
32
#define ESP_RINTR 0x14
33
#define ESP_RFLAGS 0x1c
35
#define ESP_DMA_CMD 0x40
36
#define ESP_DMA_STC 0x44
37
#define ESP_DMA_SPA 0x48
38
#define ESP_DMA_WBC 0x4c
39
#define ESP_DMA_WAC 0x50
40
#define ESP_DMA_STAT 0x54
41
#define ESP_DMA_SMDLA 0x58
42
#define ESP_DMA_WMAC 0x58c
44
#define ESP_CMD_DMA 0x80
45
#define ESP_CMD_RESET 0x02
46
#define ESP_CMD_TI 0x10
47
#define ESP_CMD_ICCS 0x11
48
#define ESP_CMD_SELATN 0x42
50
#define ESP_STAT_DI 0x01
51
#define ESP_STAT_CD 0x02
52
#define ESP_STAT_MSG 0x04
53
#define ESP_STAT_TC 0x10
55
#define ESP_INTR_DC 0x20
59
struct pci_device *pci;
66
esp_scsi_dma(u32 iobase, u32 buf, u32 len, int read)
68
outb(len & 0xff, iobase + ESP_TCLO);
69
outb((len >> 8) & 0xff, iobase + ESP_TCMID);
70
outb((len >> 16) & 0xff, iobase + ESP_TCHI);
71
outl(buf, iobase + ESP_DMA_SPA);
72
outl(len, iobase + ESP_DMA_STC);
73
outb(read ? 0x83 : 0x03, iobase + ESP_DMA_CMD);
77
esp_scsi_cmd(struct esp_lun_s *llun, struct disk_op_s *op,
78
u8 *cdbcmd, u16 target, u16 lun, u16 blocksize)
80
u32 iobase = GET_GLOBAL(llun->iobase);
84
outb(target, iobase + ESP_WBUSID);
87
* We need to pass the LUN at the beginning of the command, and the FIFO
88
* is only 16 bytes, so we cannot support 16-byte CDBs. The alternative
89
* would be to use DMA for the 17-byte command too, which is quite
92
outb(lun, iobase + ESP_FIFO);
94
cdbcmd[1] |= lun << 5;
95
for (i = 0; i < 12; i++)
96
outb(cdbcmd[i], iobase + ESP_FIFO);
97
outb(ESP_CMD_SELATN, iobase + ESP_CMD);
100
u8 stat = inb(iobase + ESP_RSTAT);
102
/* Detect disconnected device. */
103
if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) {
104
return DISK_RET_ENOTREADY;
107
/* HBA reads command, clears CD, sets TC -> do DMA if needed. */
108
if (state == 0 && (stat & ESP_STAT_TC)) {
110
if (op->count && blocksize) {
112
u32 count = (u32)op->count * blocksize;
113
esp_scsi_dma(iobase, (u32)op->buf_fl, count,
114
cdb_is_read(cdbcmd, blocksize));
115
outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD);
120
/* At end of DMA TC is set again -> complete command. */
121
if (state == 1 && (stat & ESP_STAT_TC)) {
123
outb(ESP_CMD_ICCS, iobase + ESP_CMD);
127
/* Finally read data from the message in phase. */
128
if (state == 2 && (stat & ESP_STAT_MSG)) {
130
status = inb(iobase + ESP_FIFO);
131
inb(iobase + ESP_FIFO);
138
return DISK_RET_SUCCESS;
141
return DISK_RET_EBADTRACK;
145
esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
147
if (!CONFIG_ESP_SCSI)
148
return DISK_RET_EBADTRACK;
150
struct esp_lun_s *llun =
151
container_of(op->drive_g, struct esp_lun_s, drive);
153
return esp_scsi_cmd(llun, op, cdbcmd,
154
GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun),
159
esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
161
struct esp_lun_s *llun = malloc_fseg(sizeof(*llun));
166
memset(llun, 0, sizeof(*llun));
167
llun->drive.type = DTYPE_ESP_SCSI;
168
llun->drive.cntl_id = pci->bdf;
170
llun->target = target;
172
llun->iobase = iobase;
174
char *name = znprintf(16, "esp %02x:%02x.%x %d:%d",
175
pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
176
pci_bdf_to_fn(pci->bdf), target, lun);
177
int prio = bootprio_find_scsi_device(pci, target, lun);
178
int ret = scsi_drive_setup(&llun->drive, name, prio);
190
esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
192
esp_scsi_add_lun(pci, iobase, target, 0);
196
init_esp_scsi(struct pci_device *pci)
199
u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
200
& PCI_BASE_ADDRESS_IO_MASK;
202
dprintf(1, "found esp at %02x:%02x.%x, io @ %x\n",
203
pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
204
pci_bdf_to_fn(bdf), iobase);
206
pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
209
outb(ESP_CMD_RESET, iobase + ESP_CMD);
212
for (i = 0; i <= 7; i++)
213
esp_scsi_scan_target(pci, iobase, i);
222
if (!CONFIG_ESP_SCSI || !runningOnQEMU())
225
dprintf(3, "init esp\n");
227
struct pci_device *pci;
229
if (pci->vendor != PCI_VENDOR_ID_AMD
230
|| pci->device != PCI_DEVICE_ID_AMD_SCSI)