xref: /freebsd/sys/dev/hptnr/hptnr_os_bsd.c (revision 718cf2ccb9956613756ab15d7a0e28f2c8e91cab)
11fdeb165SXin LI /* $Id: os_bsd.c,v 1.13 2010/05/11 03:12:11 lcn Exp $ */
21fdeb165SXin LI /*-
3*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4*718cf2ccSPedro F. Giffuni  *
51fdeb165SXin LI  * HighPoint RAID Driver for FreeBSD
61fdeb165SXin LI  * Copyright (C) 2005-2011 HighPoint Technologies, Inc. All Rights Reserved.
71fdeb165SXin LI  * All rights reserved.
81fdeb165SXin LI  *
91fdeb165SXin LI  * Redistribution and use in source and binary forms, with or without
101fdeb165SXin LI  * modification, are permitted provided that the following conditions
111fdeb165SXin LI  * are met:
121fdeb165SXin LI  * 1. Redistributions of source code must retain the above copyright
131fdeb165SXin LI  *    notice, this list of conditions and the following disclaimer.
141fdeb165SXin LI  * 2. Redistributions in binary form must reproduce the above copyright
151fdeb165SXin LI  *    notice, this list of conditions and the following disclaimer in the
161fdeb165SXin LI  *    documentation and/or other materials provided with the distribution.
171fdeb165SXin LI  *
181fdeb165SXin LI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
191fdeb165SXin LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201fdeb165SXin LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211fdeb165SXin LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
221fdeb165SXin LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231fdeb165SXin LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241fdeb165SXin LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251fdeb165SXin LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261fdeb165SXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271fdeb165SXin LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281fdeb165SXin LI  * SUCH DAMAGE.
291fdeb165SXin LI  *
301fdeb165SXin LI  * $FreeBSD$
311fdeb165SXin LI  */
321fdeb165SXin LI 
331fdeb165SXin LI #include <dev/hptnr/hptnr_config.h>
341fdeb165SXin LI #include <dev/hptnr/os_bsd.h>
351fdeb165SXin LI 
361fdeb165SXin LI BUS_ADDRESS get_dmapool_phy_addr(void *osext, void * dmapool_virt_addr);
371fdeb165SXin LI 
381fdeb165SXin LI /* hardware access */
391fdeb165SXin LI HPT_U8   os_inb  (void *port) { return inb((unsigned)(HPT_UPTR)port); }
401fdeb165SXin LI HPT_U16  os_inw  (void *port) { return inw((unsigned)(HPT_UPTR)port); }
411fdeb165SXin LI HPT_U32  os_inl  (void *port) { return inl((unsigned)(HPT_UPTR)port); }
421fdeb165SXin LI 
431fdeb165SXin LI void os_outb (void *port, HPT_U8 value) { outb((unsigned)(HPT_UPTR)port, (value)); }
441fdeb165SXin LI void os_outw (void *port, HPT_U16 value) { outw((unsigned)(HPT_UPTR)port, (value)); }
451fdeb165SXin LI void os_outl (void *port, HPT_U32 value) { outl((unsigned)(HPT_UPTR)port, (value)); }
461fdeb165SXin LI 
471fdeb165SXin LI void os_insw (void *port, HPT_U16 *buffer, HPT_U32 count)
481fdeb165SXin LI { insw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
491fdeb165SXin LI 
501fdeb165SXin LI void os_outsw(void *port, HPT_U16 *buffer, HPT_U32 count)
511fdeb165SXin LI { outsw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
521fdeb165SXin LI 
531fdeb165SXin LI HPT_U32 __dummy_reg = 0;
541fdeb165SXin LI 
551fdeb165SXin LI /* PCI configuration space */
561fdeb165SXin LI HPT_U8  os_pci_readb (void *osext, HPT_U8 offset)
571fdeb165SXin LI {
581fdeb165SXin LI     return  pci_read_config(((PHBA)osext)->pcidev, offset, 1);
591fdeb165SXin LI }
601fdeb165SXin LI 
611fdeb165SXin LI HPT_U16 os_pci_readw (void *osext, HPT_U8 offset)
621fdeb165SXin LI {
631fdeb165SXin LI     return  pci_read_config(((PHBA)osext)->pcidev, offset, 2);
641fdeb165SXin LI }
651fdeb165SXin LI 
661fdeb165SXin LI HPT_U32 os_pci_readl (void *osext, HPT_U8 offset)
671fdeb165SXin LI {
681fdeb165SXin LI     return  pci_read_config(((PHBA)osext)->pcidev, offset, 4);
691fdeb165SXin LI }
701fdeb165SXin LI 
711fdeb165SXin LI void os_pci_writeb (void *osext, HPT_U8 offset, HPT_U8 value)
721fdeb165SXin LI {
731fdeb165SXin LI     pci_write_config(((PHBA)osext)->pcidev, offset, value, 1);
741fdeb165SXin LI }
751fdeb165SXin LI 
761fdeb165SXin LI void os_pci_writew (void *osext, HPT_U8 offset, HPT_U16 value)
771fdeb165SXin LI {
781fdeb165SXin LI     pci_write_config(((PHBA)osext)->pcidev, offset, value, 2);
791fdeb165SXin LI }
801fdeb165SXin LI 
811fdeb165SXin LI void os_pci_writel (void *osext, HPT_U8 offset, HPT_U32 value)
821fdeb165SXin LI {
831fdeb165SXin LI     pci_write_config(((PHBA)osext)->pcidev, offset, value, 4);
841fdeb165SXin LI }
851fdeb165SXin LI 
861fdeb165SXin LI BUS_ADDRESS get_dmapool_phy_addr(void *osext, void * dmapool_virt_addr)
871fdeb165SXin LI {
881fdeb165SXin LI 	return (BUS_ADDRESS)vtophys(dmapool_virt_addr);
891fdeb165SXin LI }
901fdeb165SXin LI 
911fdeb165SXin LI HPT_U32 pcicfg_read_dword(HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg)
921fdeb165SXin LI {
931fdeb165SXin LI 	return (HPT_U32)pci_cfgregread(bus, dev, func, reg, 4);;
941fdeb165SXin LI }/* PCI space access */
951fdeb165SXin LI 
961fdeb165SXin LI void *os_map_pci_bar(
971fdeb165SXin LI     void *osext,
981fdeb165SXin LI     int index,
991fdeb165SXin LI     HPT_U32 offset,
1001fdeb165SXin LI     HPT_U32 length
1011fdeb165SXin LI )
1021fdeb165SXin LI {
1031fdeb165SXin LI 	PHBA hba = (PHBA)osext;
1041fdeb165SXin LI 	HPT_U32 base;
1051fdeb165SXin LI 
1061fdeb165SXin LI 	hba->pcibar[index].rid = 0x10 + index * 4;
1071fdeb165SXin LI 	base = pci_read_config(hba->pcidev, hba->pcibar[index].rid, 4);
1081fdeb165SXin LI 
1091fdeb165SXin LI 	if (base & 1) {
1101fdeb165SXin LI 		hba->pcibar[index].type = SYS_RES_IOPORT;
111eff83876SJustin Hibbits 		hba->pcibar[index].res = bus_alloc_resource_any(hba->pcidev,
112eff83876SJustin Hibbits 			hba->pcibar[index].type, &hba->pcibar[index].rid, RF_ACTIVE);
1131fdeb165SXin LI 		hba->pcibar[index].base = (void *)(unsigned long)(base & ~0x1);
1141fdeb165SXin LI 	} else {
1151fdeb165SXin LI 		hba->pcibar[index].type = SYS_RES_MEMORY;
116eff83876SJustin Hibbits 		hba->pcibar[index].res = bus_alloc_resource_any(hba->pcidev,
117eff83876SJustin Hibbits 			hba->pcibar[index].type, &hba->pcibar[index].rid, RF_ACTIVE);
1181fdeb165SXin LI 		hba->pcibar[index].base = (char *)rman_get_virtual(hba->pcibar[index].res) + offset;
1191fdeb165SXin LI 	}
1201fdeb165SXin LI 
1211fdeb165SXin LI 	return hba->pcibar[index].base;
1221fdeb165SXin LI }
1231fdeb165SXin LI 
1241fdeb165SXin LI void os_unmap_pci_bar(void *osext, void *base)
1251fdeb165SXin LI {
1261fdeb165SXin LI 	PHBA hba = (PHBA)osext;
1271fdeb165SXin LI 	int index;
1281fdeb165SXin LI 
1291fdeb165SXin LI 	for (index=0; index<6; index++) {
1301fdeb165SXin LI 		if (hba->pcibar[index].base==base) {
1311fdeb165SXin LI 			bus_release_resource(hba->pcidev, hba->pcibar[index].type,
1321fdeb165SXin LI 				hba->pcibar[index].rid, hba->pcibar[index].res);
1331fdeb165SXin LI 			hba->pcibar[index].base = 0;
1341fdeb165SXin LI 			return;
1351fdeb165SXin LI 		}
1361fdeb165SXin LI 	}
1371fdeb165SXin LI }
1381fdeb165SXin LI 
1391fdeb165SXin LI void freelist_reserve(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT count)
1401fdeb165SXin LI {
1411fdeb165SXin LI     PVBUS_EXT vbus_ext = osext;
1421fdeb165SXin LI 
1431fdeb165SXin LI     if (vbus_ext->ext_type!=EXT_TYPE_VBUS)
1441fdeb165SXin LI         vbus_ext = ((PHBA)osext)->vbus_ext;
1451fdeb165SXin LI 
1461fdeb165SXin LI     list->next = vbus_ext->freelist_head;
1471fdeb165SXin LI     vbus_ext->freelist_head = list;
1481fdeb165SXin LI     list->dma = 0;
1491fdeb165SXin LI     list->size = size;
1501fdeb165SXin LI     list->head = 0;
1511fdeb165SXin LI #if DBG
1521fdeb165SXin LI     list->reserved_count =
1531fdeb165SXin LI #endif
1541fdeb165SXin LI     list->count = count;
1551fdeb165SXin LI }
1561fdeb165SXin LI 
1571fdeb165SXin LI void *freelist_get(struct freelist *list)
1581fdeb165SXin LI {
1591fdeb165SXin LI     void * result;
1601fdeb165SXin LI     if (list->count) {
1611fdeb165SXin LI         HPT_ASSERT(list->head);
1621fdeb165SXin LI         result = list->head;
1631fdeb165SXin LI         list->head = *(void **)result;
1641fdeb165SXin LI         list->count--;
1651fdeb165SXin LI         return result;
1661fdeb165SXin LI     }
1671fdeb165SXin LI     return 0;
1681fdeb165SXin LI }
1691fdeb165SXin LI 
1701fdeb165SXin LI void freelist_put(struct freelist * list, void *p)
1711fdeb165SXin LI {
1721fdeb165SXin LI     HPT_ASSERT(list->dma==0);
1731fdeb165SXin LI     list->count++;
1741fdeb165SXin LI     *(void **)p = list->head;
1751fdeb165SXin LI     list->head = p;
1761fdeb165SXin LI }
1771fdeb165SXin LI 
1781fdeb165SXin LI void freelist_reserve_dma(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT alignment, HPT_UINT count)
1791fdeb165SXin LI {
1801fdeb165SXin LI     PVBUS_EXT vbus_ext = osext;
1811fdeb165SXin LI 
1821fdeb165SXin LI     if (vbus_ext->ext_type!=EXT_TYPE_VBUS)
1831fdeb165SXin LI         vbus_ext = ((PHBA)osext)->vbus_ext;
1841fdeb165SXin LI 
1851fdeb165SXin LI     list->next = vbus_ext->freelist_dma_head;
1861fdeb165SXin LI     vbus_ext->freelist_dma_head = list;
1871fdeb165SXin LI     list->dma = 1;
1881fdeb165SXin LI     list->alignment = alignment;
1891fdeb165SXin LI     list->size = size;
1901fdeb165SXin LI     list->head = 0;
1911fdeb165SXin LI #if DBG
1921fdeb165SXin LI     list->reserved_count =
1931fdeb165SXin LI #endif
1941fdeb165SXin LI     list->count = count;
1951fdeb165SXin LI }
1961fdeb165SXin LI 
1971fdeb165SXin LI void *freelist_get_dma(struct freelist *list, BUS_ADDRESS *busaddr)
1981fdeb165SXin LI {
1991fdeb165SXin LI     void *result;
2001fdeb165SXin LI     HPT_ASSERT(list->dma);
2011fdeb165SXin LI     result = freelist_get(list);
2021fdeb165SXin LI     if (result)
2031fdeb165SXin LI         *busaddr = *(BUS_ADDRESS *)((void **)result+1);
2041fdeb165SXin LI     return result;
2051fdeb165SXin LI }
2061fdeb165SXin LI 
2071fdeb165SXin LI void freelist_put_dma(struct freelist *list, void *p, BUS_ADDRESS busaddr)
2081fdeb165SXin LI {
2091fdeb165SXin LI     HPT_ASSERT(list->dma);
2101fdeb165SXin LI     list->count++;
2111fdeb165SXin LI     *(void **)p = list->head;
2121fdeb165SXin LI     *(BUS_ADDRESS *)((void **)p+1) = busaddr;
2131fdeb165SXin LI     list->head = p;
2141fdeb165SXin LI }
2151fdeb165SXin LI 
2161fdeb165SXin LI HPT_U32 os_get_stamp(void)
2171fdeb165SXin LI {
2181fdeb165SXin LI     HPT_U32 stamp;
2191fdeb165SXin LI     do { stamp = random(); } while (stamp==0);
2201fdeb165SXin LI     return stamp;
2211fdeb165SXin LI }
2221fdeb165SXin LI 
2231fdeb165SXin LI void os_stallexec(HPT_U32 microseconds)
2241fdeb165SXin LI {
2251fdeb165SXin LI     DELAY(microseconds);
2261fdeb165SXin LI }
2271fdeb165SXin LI 
2281fdeb165SXin LI static void os_timer_for_ldm(void *arg)
2291fdeb165SXin LI {
2301fdeb165SXin LI 	PVBUS_EXT vbus_ext = (PVBUS_EXT)arg;
2311fdeb165SXin LI 	ldm_on_timer((PVBUS)vbus_ext->vbus);
2321fdeb165SXin LI }
2331fdeb165SXin LI 
2341fdeb165SXin LI void  os_request_timer(void * osext, HPT_U32 interval)
2351fdeb165SXin LI {
2361fdeb165SXin LI 	PVBUS_EXT vbus_ext = osext;
2371fdeb165SXin LI 
2381fdeb165SXin LI 	HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);
2391fdeb165SXin LI 
24085c9dd9dSSteven Hartland 	callout_reset_sbt(&vbus_ext->timer, SBT_1US * interval, 0,
24185c9dd9dSSteven Hartland 	    os_timer_for_ldm, vbus_ext, 0);
2421fdeb165SXin LI }
2431fdeb165SXin LI 
2441fdeb165SXin LI HPT_TIME os_query_time(void)
2451fdeb165SXin LI {
2461fdeb165SXin LI 	return ticks * (1000000 / hz);
2471fdeb165SXin LI }
2481fdeb165SXin LI 
2491fdeb165SXin LI void os_schedule_task(void *osext, OSM_TASK *task)
2501fdeb165SXin LI {
2511fdeb165SXin LI 	PVBUS_EXT vbus_ext = osext;
2521fdeb165SXin LI 
2531fdeb165SXin LI 	HPT_ASSERT(task->next==0);
2541fdeb165SXin LI 
2551fdeb165SXin LI 	if (vbus_ext->tasks==0)
2561fdeb165SXin LI 		vbus_ext->tasks = task;
2571fdeb165SXin LI 	else {
2581fdeb165SXin LI 		OSM_TASK *t = vbus_ext->tasks;
2591fdeb165SXin LI 		while (t->next) t = t->next;
2601fdeb165SXin LI 		t->next = task;
2611fdeb165SXin LI 	}
2621fdeb165SXin LI 
2631fdeb165SXin LI 	if (vbus_ext->worker.ta_context)
2641fdeb165SXin LI 		TASK_ENQUEUE(&vbus_ext->worker);
2651fdeb165SXin LI }
2661fdeb165SXin LI 
2671fdeb165SXin LI int os_revalidate_device(void *osext, int id)
2681fdeb165SXin LI {
2691fdeb165SXin LI 
2701fdeb165SXin LI     return 0;
2711fdeb165SXin LI }
2721fdeb165SXin LI 
2731fdeb165SXin LI int os_query_remove_device(void *osext, int id)
2741fdeb165SXin LI {
275090234abSXin LI     return 0;
2761fdeb165SXin LI }
2771fdeb165SXin LI 
2781fdeb165SXin LI HPT_U8 os_get_vbus_seq(void *osext)
2791fdeb165SXin LI {
2801fdeb165SXin LI     return ((PVBUS_EXT)osext)->sim->path_id;
2811fdeb165SXin LI }
2821fdeb165SXin LI 
2831fdeb165SXin LI int  os_printk(char *fmt, ...)
2841fdeb165SXin LI {
2851fdeb165SXin LI     va_list args;
2861fdeb165SXin LI     static char buf[512];
2871fdeb165SXin LI 
2881fdeb165SXin LI     va_start(args, fmt);
2891fdeb165SXin LI     vsnprintf(buf, sizeof(buf), fmt, args);
2901fdeb165SXin LI     va_end(args);
2911fdeb165SXin LI     return printf("%s: %s\n", driver_name, buf);
2921fdeb165SXin LI }
2931fdeb165SXin LI 
2941fdeb165SXin LI #if DBG
2951fdeb165SXin LI void os_check_stack(const char *location, int size){}
2961fdeb165SXin LI 
2971fdeb165SXin LI void __os_dbgbreak(const char *file, int line)
2981fdeb165SXin LI {
2991fdeb165SXin LI     printf("*** break at %s:%d ***", file, line);
3001fdeb165SXin LI     while (1);
3011fdeb165SXin LI }
3021fdeb165SXin LI 
3031fdeb165SXin LI int hpt_dbg_level = 1;
3041fdeb165SXin LI #endif
305