2 * Copyright (C) 2012-2018, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
16 #include <sys/types.h>
17 #include <sys/select.h>
19 #include <aros/debug.h>
28 #include <proto/exec.h>
29 #include <proto/oop.h>
33 #include "ahci_intern.h"
37 #define kprintf(fmt, args...) device_printf(NULL, fmt ,##args)
39 typedef uint8_t u_int8_t
;
40 typedef uint16_t u_int16_t
;
41 typedef uint32_t u_int32_t
;
42 typedef uint64_t u_int64_t
;
43 typedef unsigned int u_int
;
45 #define le16toh(x) AROS_LE2WORD(x)
46 #define le32toh(x) AROS_LE2LONG(x)
47 #define htole32(x) AROS_LONG2LE(x)
48 #define htole16(x) AROS_WORD2LE(x)
50 #define PAGE_SIZE 4096
54 #define KKASSERT(expr) ASSERT(expr)
56 int kvsnrprintf(char *str
, size_t size
, int radix
, const char *format
, va_list ap
);
57 int kvsnprintf(char *str
, size_t size
, const char *format
, va_list ap
);
58 int ksnprintf(char *buff
, size_t len
, const char *fmt
, ...);
59 int kvcprintf(char const *fmt
, void (*func
)(int, void*), void *arg
, int radix
, va_list ap
);
61 static inline void bug_c(int c
, void *info
)
66 static inline int device_printf(device_t dev
, const char *fmt
, ...)
71 err
= kvcprintf(fmt
, bug_c
, NULL
, 10, args
);
77 #define panic(fmt, args...) do { Forbid(); device_printf(NULL, fmt ,##args); Disable(); for (;;); } while (0);
79 static inline void *kmalloc(size_t size
, unsigned where
, unsigned flags
)
81 return AllocVec(size
, flags
);
84 static inline void kfree(void *ptr
, unsigned where
)
89 static inline void crit_enter(void)
94 static inline void crit_exit(void)
99 typedef struct Task
*thread_t
;
101 static inline int kthread_create(void (*func
)(void *), void *arg
, thread_t
*tdp
, const char *fmt
, ...)
107 kvsnprintf(name
, sizeof(name
), fmt
, args
);
110 name
[sizeof(name
)-1] = 0;
112 *tdp
= NewCreateTask(TASKTAG_NAME
, name
,
118 return (*tdp
== NULL
) ? ENOMEM
: 0;
122 typedef u_int16_t pci_vendor_id_t
;
123 typedef u_int16_t pci_product_id_t
;
124 typedef u_int32_t pcireg_t
;
126 static inline u_int32_t
pci_read_config(device_t dev
, int reg
, int width
)
129 struct AHCIBase
*AHCIBase
= dev
->dev_AHCIBase
;
130 OOP_MethodID HiddPCIDeviceMethodBase
= AHCIBase
->ahci_HiddPCIDeviceMethodBase
;
131 struct pHidd_PCIDevice_ReadConfigByte cb
;
132 struct pHidd_PCIDevice_ReadConfigWord cw
;
133 struct pHidd_PCIDevice_ReadConfigLong cl
;
134 OOP_Object
*Device
= dev
->dev_Object
;
138 cb
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_ReadConfigByte
;
140 val
= (u_int32_t
)OOP_DoMethod(Device
, (OOP_Msg
)&cb
);
144 cw
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_ReadConfigWord
;
146 val
= (u_int32_t
)OOP_DoMethod(Device
, (OOP_Msg
)&cw
);
150 cl
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_ReadConfigLong
;
152 val
= (u_int32_t
)OOP_DoMethod(Device
, (OOP_Msg
)&cl
);
159 static inline void pci_write_config(device_t dev
, int reg
, u_int32_t val
, int width
)
161 struct AHCIBase
*AHCIBase
= dev
->dev_AHCIBase
;
162 OOP_MethodID HiddPCIDeviceMethodBase
= AHCIBase
->ahci_HiddPCIDeviceMethodBase
;
163 struct pHidd_PCIDevice_WriteConfigByte cb
;
164 struct pHidd_PCIDevice_WriteConfigWord cw
;
165 struct pHidd_PCIDevice_WriteConfigLong cl
;
166 OOP_Object
*Device
= dev
->dev_Object
;
170 cb
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_WriteConfigByte
;
173 OOP_DoMethod(Device
, (OOP_Msg
)&cb
);
177 cw
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_WriteConfigWord
;
179 cw
.val
= val
& 0xffff;
180 OOP_DoMethod(Device
, (OOP_Msg
)&cw
);
184 cl
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_WriteConfigLong
;
187 OOP_DoMethod(Device
, (OOP_Msg
)&cl
);
193 static inline u_int16_t
pci_get_vendor(device_t dev
)
195 return (u_int16_t
)pci_read_config(dev
, PCIR_VENDOR
, 2);
198 static inline u_int16_t
pci_get_device(device_t dev
)
200 return (u_int16_t
)pci_read_config(dev
, PCIR_DEVICE
, 2);
203 static inline u_int8_t
pci_get_class(device_t dev
)
205 return (u_int8_t
)pci_read_config(dev
, PCIR_CLASS
, 1);
208 static inline u_int8_t
pci_get_subclass(device_t dev
)
210 return (u_int8_t
)pci_read_config(dev
, PCIR_SUBCLASS
, 1);
214 typedef IPTR bus_size_t
;
215 typedef IPTR bus_addr_t
;
222 typedef struct bus_dma_tag
*bus_dma_tag_t
;
224 #define BUS_DMA_MAX_SLABS 16
225 #define BUS_DMA_MAX_SEGMENTS 1024
227 typedef IPTR bus_space_tag_t
;
228 typedef APTR bus_dmamap_t
;
229 typedef IPTR bus_space_handle_t
;
230 typedef int bus_dma_filter_t(void *arg
, bus_addr_t paddr
);
232 #define BUS_SPACE_MAXADDR ~0
233 #define BUS_SPACE_MAXADDR_32BIT ((ULONG)~0)
235 int bus_dma_tag_create(bus_dma_tag_t parent
, bus_size_t alignment
, bus_size_t boundary
, bus_addr_t lowaddr
, bus_addr_t highaddr
, bus_dma_filter_t
*filter
, void *filterarg
, bus_size_t maxsize
, int nsegments
, bus_size_t maxsegsz
, int flags
, bus_dma_tag_t
*dmat
);
237 int bus_dma_tag_destroy(bus_dma_tag_t tag
);
239 #define BUS_DMA_ALLOCNOW 0
240 #define BUS_DMA_ZERO MEMF_CLEAR
242 int bus_dmamem_alloc(bus_dma_tag_t tag
, void **vaddr
, unsigned flags
, bus_dmamap_t
*map
);
244 bus_size_t
bus_dma_tag_getmaxsize(bus_dma_tag_t tag
);
246 void bus_dmamem_free(bus_dma_tag_t tag
, void *vaddr
, bus_dmamap_t map
);
248 int bus_dmamap_create(bus_dma_tag_t tag
, unsigned flags
, bus_dmamap_t
*map
);
250 void bus_dmamap_destroy(bus_dma_tag_t tag
, bus_dmamap_t map
);
252 typedef void bus_dmamap_callback_t(void *info
, bus_dma_segment_t
*segs
, int nsegs
, int error
);
254 #define BUS_DMA_NOWAIT 0
255 #define BUS_DMA_WAITOK 0
257 int bus_dmamap_load(bus_dma_tag_t tag
, bus_dmamap_t map
, void *data
, size_t len
, bus_dmamap_callback_t
*callback
, void *info
, unsigned flags
);
259 #define BUS_DMASYNC_PREREAD 0
260 #define BUS_DMASYNC_PREWRITE DMA_ReadFromRAM
261 #define BUS_DMASYNC_POSTREAD (1 << 31)
262 #define BUS_DMASYNC_POSTWRITE (1 << 31) | DMA_ReadFromRAM
264 void bus_dmamap_sync(bus_dma_tag_t tag
, bus_dmamap_t map
, unsigned flags
);
266 void bus_dmamap_unload(bus_dma_tag_t tag
, bus_dmamap_t map
);
268 /* Generic bus operations */
269 enum bus_resource_t
{
274 #define AHCI_IRQ_RID 0
277 bus_space_tag_t res_tag
;
278 bus_space_handle_t res_handle
;
282 #define RF_SHAREABLE (1 << 0)
283 #define RF_ACTIVE (1 << 1)
285 struct resource
*bus_alloc_resource_any(device_t dev
, enum bus_resource_t type
, int *rid
, u_int flags
);
287 int bus_release_resource(device_t dev
, enum bus_resource_t type
, int rid
, struct resource
*res
);
289 static inline bus_space_tag_t
rman_get_bustag(struct resource
*r
)
294 static inline bus_space_handle_t
rman_get_bushandle(struct resource
*r
)
296 return r
->res_handle
;
300 typedef void driver_intr_t(void *arg
);
302 #define INTR_MPSAFE 0
304 int bus_setup_intr(device_t dev
, struct resource
*r
, int flags
, driver_intr_t handler
, void *arg
, void **cookiep
, void *serializer
);
306 int bus_teardown_intr(device_t dev
, struct resource
*r
, void *cookie
);
310 static inline int bus_space_subregion(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
, size_t size
, bus_space_handle_t
*result
)
312 *result
= ioh
+ offset
;
316 #define BUS_SPACE_BARRIER_READ 0
317 #define BUS_SPACE_BARRIER_WRITE 0
319 static inline void bus_space_barrier(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
, size_t size
, unsigned flags
)
321 /* FIXME: Sync bus area */
324 static inline u_int32_t
bus_space_read_4(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
)
326 return *(u_int32_t
*)(ioh
+ offset
);
329 static inline void bus_space_write_4(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
, u_int32_t val
)
331 *(u_int32_t
*)(ioh
+ offset
) = val
;
335 /* Generic device info */
336 static inline void *device_get_softc(device_t dev
)
338 return dev
->dev_softc
;
341 /* Lock management */
344 struct SignalSemaphore sem
;
348 static inline void lockinit(struct lock
*lock
, const char *name
, unsigned flags
, unsigned count
)
351 InitSemaphore(&lock
->sem
);
354 static inline void lockuninit(struct lock
*lock
)
359 #define LK_RELEASE (1 << 0)
360 #define LK_EXCLUSIVE (1 << 1)
361 #define LK_CANRECURSE (1 << 2)
362 #define LK_NOWAIT (1 << 3)
364 static inline int lockmgr(struct lock
*lock
, int flags
)
368 flags
&= (LK_EXCLUSIVE
| LK_NOWAIT
| LK_RELEASE
);
371 ObtainSemaphoreShared(&lock
->sem
);
373 case LK_EXCLUSIVE
| LK_NOWAIT
:
374 err
= (AttemptSemaphore(&lock
->sem
) == FALSE
) ? 1 : 0;
377 ObtainSemaphore(&lock
->sem
);
380 ReleaseSemaphore(&lock
->sem
);
388 #define atomic_clear_int(ptr, val) AROS_ATOMIC_AND(*(ptr), ~(val))
389 #define atomic_set_int(ptr, val) AROS_ATOMIC_OR(*(ptr), (val))
393 typedef void timeout_t (void *);
396 struct Task
*co_Task
;
399 void callout_init_mp(struct callout
*c
);
401 void callout_init(struct callout
*c
);
403 void callout_stop(struct callout
*c
);
405 void callout_stop_sync(struct callout
*c
);
407 int callout_reset(struct callout
*c
, unsigned int ticks
, void (*func
)(void *), void *arg
);
409 struct sysctl_ctx_list
{};
411 /* BSD style TailQs */
412 #define TAILQ_HEAD(sname,type) struct sname { struct type *tqh_first; struct type **tqh_last; }
413 #define TAILQ_ENTRY(type) struct { struct type *tqe_next; struct type **tqe_prev; }
414 #define TAILQ_FIRST(head) ((head)->tqh_first)
415 #define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == NULL)
416 #define TAILQ_INIT(head) do { \
417 (head)->tqh_first = NULL; \
418 (head)->tqh_last = &(head)->tqh_first; \
420 #define TAILQ_NEXT(elm,field) ((elm)->field.tqe_next)
421 #define TAILQ_REMOVE(head,elm,field) do { \
422 if ((elm)->field.tqe_next) \
423 (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \
425 (head)->tqh_last = (elm)->field.tqe_prev; \
426 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
428 #define TAILQ_INSERT_TAIL(head,elm,field) do { \
429 (elm)->field.tqe_next = NULL; \
430 (elm)->field.tqe_prev = (head)->tqh_last; \
431 *(head)->tqh_last = (elm); \
432 (head)->tqh_last = &(elm)->field.tqe_next; \
434 #define TAILQ_FOREACH(elm,head,field) \
435 for ((elm) = ((head)->tqh_first); \
436 (elm) != NULL; (elm)=(elm)->field.tqe_next)
438 #define device_get_name(dev) "ahci.device "
439 #define device_get_unit(dev) ((dev)->dev_HostID)
445 #define M_ZERO MEMF_CLEAR
447 static const int bootverbose
= 0;
450 static inline int ffs(unsigned int bits
)
454 for (i
= 0; i
< 32; i
++, bits
>>= 1)
462 void ahci_ata_io_complete(struct ata_xfer
*xa
);
464 #endif /* AHCI_AROS_H */