aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/vmlinux.lds.S
blob: 56fe6bc81fee45804a61c37fb189ccf73a0b72e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* ld script to make s390 Linux kernel
 * Written by Martin Schwidefsky (schwidefsky@de.ibm.com)
 */

#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>

#ifndef CONFIG_64BIT
OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
OUTPUT_ARCH(s390)
ENTRY(_start)
jiffies = jiffies_64 + 4;
#else
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
OUTPUT_ARCH(s390:64-bit)
ENTRY(_start)
jiffies = jiffies_64;
#endif

PHDRS {
	text PT_LOAD FLAGS(5);	/* R_E */
	data PT_LOAD FLAGS(7);	/* RWE */
	note PT_NOTE FLAGS(0);	/* ___ */
}

SECTIONS
{
	. = 0x00000000;
	.text : {
	_text = .;		/* Text and read-only data */
		HEAD_TEXT
		TEXT_TEXT
		SCHED_TEXT
		LOCK_TEXT
		KPROBES_TEXT
		IRQENTRY_TEXT
		*(.fixup)
		*(.gnu.warning)
	} :text = 0x0700

	_etext = .;		/* End of text section */

	NOTES :text :note

	RODATA

#ifdef CONFIG_SHARED_KERNEL
	. = ALIGN(0x100000);	/* VM shared segments are 1MB aligned */
#endif

	. = ALIGN(PAGE_SIZE);
	_eshared = .;		/* End of shareable data */
	_sdata = .;		/* Start of data section */

	EXCEPTION_TABLE(16) :data

	RW_DATA_SECTION(0x100, PAGE_SIZE, THREAD_SIZE)

	_edata = .;		/* End of data section */

	/* will be freed after init */
	. = ALIGN(PAGE_SIZE);	/* Init code and data */
	__init_begin = .;

	INIT_TEXT_SECTION(PAGE_SIZE)

	/*
	 * .exit.text is discarded at runtime, not link time,
	 * to deal with references from __bug_table
	*/
	.exit.text : {
		EXIT_TEXT
	}

	/* early.c uses stsi, which requires page aligned data. */
	. = ALIGN(PAGE_SIZE);
	INIT_DATA_SECTION(0x100)

	PERCPU_SECTION(0x100)
	. = ALIGN(PAGE_SIZE);
	__init_end = .;		/* freed after init ends here */

	BSS_SECTION(0, 2, 0)

	_end = . ;

	/* Debugging sections.	*/
	STABS_DEBUG
	DWARF_DEBUG

	/* Sections to be discarded */
	DISCARDS
}
lude "usbh/dev/hid.h" #include "usbh/internal.h" #if USBHHID_DEBUG_ENABLE_TRACE #define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) #else #define udbgf(f, ...) do {} while(0) #define udbg(f, ...) do {} while(0) #endif #if USBHHID_DEBUG_ENABLE_INFO #define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) #else #define uinfof(f, ...) do {} while(0) #define uinfo(f, ...) do {} while(0) #endif #if USBHHID_DEBUG_ENABLE_WARNINGS #define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) #else #define uwarnf(f, ...) do {} while(0) #define uwarn(f, ...) do {} while(0) #endif #if USBHHID_DEBUG_ENABLE_ERRORS #define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) #else #define uerrf(f, ...) do {} while(0) #define uerr(f, ...) do {} while(0) #endif #define USBH_HID_REQ_GET_REPORT 0x01 #define USBH_HID_REQ_GET_IDLE 0x02 #define USBH_HID_REQ_GET_PROTOCOL 0x03 #define USBH_HID_REQ_SET_REPORT 0x09 #define USBH_HID_REQ_SET_IDLE 0x0A #define USBH_HID_REQ_SET_PROTOCOL 0x0B /*===========================================================================*/ /* USB Class driver loader for HID */ /*===========================================================================*/ USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES]; static void _hid_init(void); static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void _hid_unload(usbh_baseclassdriver_t *drv); static void _stop_locked(USBHHIDDriver *hidp); static const usbh_classdriver_vmt_t class_driver_vmt = { _hid_init, _hid_load, _hid_unload }; const usbh_classdriverinfo_t usbhhidClassDriverInfo = { "HID", &class_driver_vmt }; static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHHIDDriver *hidp; if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, 0x03, -1, -1) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; if ((ifdesc->bAlternateSetting != 0) || (ifdesc->bNumEndpoints < 1)) { return NULL; } /* alloc driver */ for (i = 0; i < HAL_USBHHID_MAX_INSTANCES; i++) { if (USBHHIDD[i].dev == NULL) { hidp = &USBHHIDD[i]; goto alloc_ok; } } uwarn("Can't alloc HID driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ hidp->epin.status = USBH_EPSTATUS_UNINITIALIZED; #if HAL_USBHHID_USE_INTERRUPT_OUT hidp->epout.status = USBH_EPSTATUS_UNINITIALIZED; #endif hidp->ifnum = ifdesc->bInterfaceNumber; usbhEPSetName(&dev->ctrl, "HID[CTRL]"); /* parse the configuration descriptor */ if_iterator_t iif; generic_iterator_t iep; iif.iad = 0; iif.curr = descriptor; iif.rem = rem; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_INT)) { uinfof("INT IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&hidp->epin, dev, epdesc); usbhEPSetName(&hidp->epin, "HID[IIN ]"); #if HAL_USBHHID_USE_INTERRUPT_OUT } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_INT)) { uinfof("INT OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&hidp->epout, dev, epdesc); usbhEPSetName(&hidp->epout, "HID[IOUT]"); #endif } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if (hidp->epin.status != USBH_EPSTATUS_CLOSED) { goto deinit; } if (ifdesc->bInterfaceSubClass != 0x01) { hidp->type = USBHHID_DEVTYPE_GENERIC; uinfof("HID: bInterfaceSubClass=%02x, generic HID", ifdesc->bInterfaceSubClass); if (ifdesc->bInterfaceSubClass != 0x00) { uinfof("HID: bInterfaceSubClass=%02x is an invalid bInterfaceSubClass value", ifdesc->bInterfaceSubClass); } } else if (ifdesc->bInterfaceProtocol == 0x01) { hidp->type = USBHHID_DEVTYPE_BOOT_KEYBOARD; uinfo("HID: BOOT protocol keyboard found"); } else if (ifdesc->bInterfaceProtocol == 0x02) { hidp->type = USBHHID_DEVTYPE_BOOT_MOUSE; uinfo("HID: BOOT protocol mouse found"); } else { uerrf("HID: bInterfaceProtocol=%02x is an invalid boot protocol, abort", ifdesc->bInterfaceProtocol); goto deinit; } hidp->state = USBHHID_STATE_ACTIVE; return (usbh_baseclassdriver_t *)hidp; deinit: /* Here, the enpoints are closed, and the driver is unlinked */ return NULL; } static void _hid_unload(usbh_baseclassdriver_t *drv) { USBHHIDDriver *const hidp = (USBHHIDDriver *)drv; chSemWait(&hidp->sem); _stop_locked(hidp); hidp->state = USBHHID_STATE_STOP; chSemSignal(&hidp->sem); } static void _in_cb(usbh_urb_t *urb) { USBHHIDDriver *const hidp = (USBHHIDDriver *)urb->userData; switch (urb->status) { case USBH_URBSTATUS_OK: if (hidp->config->cb_report) { hidp->config->cb_report(hidp, urb->actualLength); } break; case USBH_URBSTATUS_DISCONNECTED: uwarn("HID: URB IN disconnected"); return; case USBH_URBSTATUS_TIMEOUT: //no data break; default: uerrf("HID: URB IN status unexpected = %d", urb->status); break; } usbhURBObjectResetI(&hidp->in_urb); usbhURBSubmitI(&hidp->in_urb); } void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg) { osalDbgCheck(hidp && cfg); osalDbgCheck(cfg->report_buffer && (cfg->protocol <= USBHHID_PROTOCOL_REPORT)); chSemWait(&hidp->sem); if (hidp->state == USBHHID_STATE_READY) { chSemSignal(&hidp->sem); return; } osalDbgCheck(hidp->state == USBHHID_STATE_ACTIVE); hidp->config = cfg; /* init the URBs */ uint32_t report_len = hidp->epin.wMaxPacketSize; if (report_len > cfg->report_len) report_len = cfg->report_len; usbhURBObjectInit(&hidp->in_urb, &hidp->epin, _in_cb, hidp, cfg->report_buffer, report_len); /* open the int IN/OUT endpoints */ usbhEPOpen(&hidp->epin); #if HAL_USBHHID_USE_INTERRUPT_OUT if (hidp->epout.status == USBH_EPSTATUS_CLOSED) { usbhEPOpen(&hidp->epout); } #endif usbhhidSetProtocol(hidp, cfg->protocol); usbhURBSubmit(&hidp->in_urb); hidp->state = USBHHID_STATE_READY; chSemSignal(&hidp->sem); } static void _stop_locked(USBHHIDDriver *hidp) { if (hidp->state == USBHHID_STATE_ACTIVE) return; osalDbgCheck(hidp->state == USBHHID_STATE_READY); usbhEPClose(&hidp->epin); #if HAL_USBHHID_USE_INTERRUPT_OUT if (hidp->epout.status != USBH_EPSTATUS_UNINITIALIZED) { usbhEPClose(&hidp->epout); } #endif hidp->state = USBHHID_STATE_ACTIVE; } void usbhhidStop(USBHHIDDriver *hidp) { chSemWait(&hidp->sem); _stop_locked(hidp); chSemSignal(&hidp->sem); } usbh_urbstatus_t usbhhidGetReport(USBHHIDDriver *hidp, uint8_t report_id, usbhhid_reporttype_t report_type, void *data, uint16_t len) { osalDbgCheck(hidp); osalDbgAssert((uint8_t)report_type <= USBHHID_REPORTTYPE_FEATURE, "wrong report type"); return usbhControlRequest(hidp->dev, USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_GET_REPORT, ((uint8_t)report_type << 8) | report_id, hidp->ifnum, len, data); } usbh_urbstatus_t usbhhidSetReport(USBHHIDDriver *hidp, uint8_t report_id, usbhhid_reporttype_t report_type, const void *data, uint16_t len) { osalDbgCheck(hidp); osalDbgAssert((uint8_t)report_type <= USBHHID_REPORTTYPE_FEATURE, "wrong report type"); return usbhControlRequest(hidp->dev, USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_SET_REPORT, ((uint8_t)report_type << 8) | report_id, hidp->ifnum, len, (void *)data); } usbh_urbstatus_t usbhhidGetIdle(USBHHIDDriver *hidp, uint8_t report_id, uint8_t *duration) { osalDbgCheck(hidp); return usbhControlRequest(hidp->dev, USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_GET_IDLE, report_id, hidp->ifnum, 1, duration); } usbh_urbstatus_t usbhhidSetIdle(USBHHIDDriver *hidp, uint8_t report_id, uint8_t duration) { osalDbgCheck(hidp); return usbhControlRequest(hidp->dev, USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_SET_IDLE, (duration << 8) | report_id, hidp->ifnum, 0, NULL); } usbh_urbstatus_t usbhhidGetProtocol(USBHHIDDriver *hidp, uint8_t *protocol) { osalDbgCheck(hidp); return usbhControlRequest(hidp->dev, USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_GET_PROTOCOL, 0, hidp->ifnum, 1, protocol); } usbh_urbstatus_t usbhhidSetProtocol(USBHHIDDriver *hidp, uint8_t protocol) { osalDbgCheck(hidp); osalDbgAssert(protocol <= 1, "invalid protocol"); return usbhControlRequest(hidp->dev, USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_SET_PROTOCOL, protocol, hidp->ifnum, 0, NULL); } static void _hid_object_init(USBHHIDDriver *hidp) { osalDbgCheck(hidp != NULL); memset(hidp, 0, sizeof(*hidp)); hidp->info = &usbhhidClassDriverInfo; hidp->state = USBHHID_STATE_STOP; chSemObjectInit(&hidp->sem, 1); } static void _hid_init(void) { uint8_t i; for (i = 0; i < HAL_USBHHID_MAX_INSTANCES; i++) { _hid_object_init(&USBHHIDD[i]); } } #endif