int android_request_firmware(const struct firmware **firmware_p, const char *name, struct device *device) { int ret = 0; struct firmware *firmware; char filename[256]; const char *raw_filename = name; *firmware_p = firmware = A_MALLOC(sizeof(*firmware)); if (!firmware) return -ENOMEM; A_MEMZERO(firmware, sizeof(*firmware)); sprintf(filename, "%s/%s", fwpath, raw_filename); #ifdef TARGET_EUROPA if (strcmp(raw_filename, "softmac")==0) { sprintf(filename, "/data/.nvmac.info"); } #endif /* TARGET_EUROPA */ do { size_t length, bufsize, bmisize; if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) { break; } else { length = ret; } bufsize = ALIGN(length, PAGE_SIZE); bmisize = A_ROUND_UP(length, 4); bufsize = max(bmisize, bufsize); firmware->data = vmalloc(bufsize); firmware->size = length; if (!firmware->data) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Cannot allocate buffer for firmware\n", __FUNCTION__)); ret = -ENOMEM; break; } if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length)); ret = -1; break; } } while (0); if (ret<0) { if (firmware) { if (firmware->data) vfree(firmware->data); A_FREE(firmware); } *firmware_p = NULL; } else { ret = 0; } return ret; }
int android_request_firmware(const struct firmware **firmware_p, const char *name, struct device *device) { int ret = 0; struct firmware *firmware; char filename[256]; const char *raw_filename = name; *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) return -ENOMEM; sprintf(filename, "%s/%s", fwpath, raw_filename); do { size_t length, bufsize, bmisize; if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) { break; } else { length = ret; } bufsize = ALIGN(length, PAGE_SIZE); bmisize = A_ROUND_UP(length, 4); bufsize = max(bmisize, bufsize); firmware->data = vmalloc(bufsize); firmware->size = bmisize; if (!firmware->data) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Cannot allocate buffer for firmware\n", __FUNCTION__)); ret = -ENOMEM; break; } if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length)); ret = -1; break; } } while (0); if (ret<0) { if (firmware) { if (firmware->data) vfree(firmware->data); kfree(firmware); } *firmware_p = NULL; } else { ret = 0; } return ret; }
/* * Allocate nbytes from the arena. At this point, which_arena should * be set to 0 for the default (and only) arena. A future allocation * module may support multiple separate arenas. */ LOCAL void * cmnos_allocram(void * which_arena, A_UINT32 nbytes) { void *ptr = (void *)allocram_current_addr; //nbytes = A_ROUND_UP(nbytes, A_CACHE_LINE_SIZE); nbytes = A_ROUND_UP(nbytes, 4); if (nbytes <= allocram_remaining_bytes) { allocram_remaining_bytes -= nbytes; allocram_current_addr += nbytes; } else { A_PRINTF("RAM allocation (%d bytes) failed!\n", nbytes); //A_ASSERT(0); adf_os_assert(0); } return ptr; }
LOCAL void * cmnos_allocram_init(void *arena_start, A_UINT32 arena_sz) { A_UINT32 astart = (A_UINT32)arena_start; #if defined(__XTENSA__) /* * This hacky line converts from a text or data RAM address * into a data RAM address. (It's all the same on MIPS, but * text and data are different address spaces on Xtensa.) */ //astart = TARG_RAM_ADDRS(TARG_RAM_OFFSET(astart)); #endif #if 0 if (arena_sz == 0) { /* Default arena_sz to most of available RAM */ arena_sz = TARG_RAM_SZ - (A_UINT32)TARG_RAM_OFFSET(astart); arena_sz -= HOST_INTEREST->hi_end_RAM_reserve_sz; } #endif /* Clear entire area */ // A_MEMSET(astart, 0, arena_sz); /* Adjust for cache line alignment */ #if 0 allocram_current_addr = A_ROUND_UP(astart, A_CACHE_LINE_SIZE); arena_sz -= (allocram_current_addr-astart); #else allocram_current_addr = astart; #endif allocram_remaining_bytes = arena_sz; //A_DCACHE_FLUSH(); //A_PRINTF("cmnos_allocram_init: start=0x%x size=%d\n", // allocram_current_addr, allocram_remaining_bytes); return NULL; /* Future implementation may return an arena handle */ }
int main (int argc, char **argv) { int c, s, fd; unsigned int address, length; unsigned int count, param; char filename[PATH_MAX], ifname[IFNAMSIZ]; unsigned int cmd; struct ifreq ifr; char *buffer; struct stat filestat; int flag; int target_version = -1; int target_type = -1; unsigned int bitwise_mask; progname = argv[0]; if (argc == 1) usage(); flag = 0; memset(filename, '\0', sizeof(filename)); memset(ifname, '\0', IFNAMSIZ); strcpy(ifname, "eth1"); s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket"); while (1) { int option_index = 0; static struct option long_options[] = { {"get", 0, NULL, 'g'}, {"set", 0, NULL, 's'}, {"read", 0, NULL, 'r'}, {"test", 0, NULL, 't'}, {"file", 1, NULL, 'f'}, {"done", 0, NULL, 'd'}, {"write", 0, NULL, 'w'}, {"begin", 0, NULL, 'b'}, {"count", 1, NULL, 'c'}, {"param", 1, NULL, 'p'}, {"length", 1, NULL, 'l'}, {"execute", 0, NULL, 'e'}, {"address", 1, NULL, 'a'}, {"interface", 1, NULL, 'i'}, {"info", 0, NULL, 'I'}, {"and", 1, NULL, 'n'}, {"or", 1, NULL, 'o'}, {"quiet", 0, NULL, 'q'}, {"uncompress", 0, NULL, 'u'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "rwtebdgsIqf:l:a:p:i:c:n:o:", long_options, &option_index); if (c == -1) break; switch (c) { case 'r': cmd = BMI_READ_MEMORY; break; case 'w': cmd = BMI_WRITE_MEMORY; break; case 'e': cmd = BMI_EXECUTE; break; case 'b': cmd = BMI_SET_APP_START; break; case 'd': cmd = BMI_DONE; break; case 'g': cmd = BMI_READ_SOC_REGISTER; break; case 's': cmd = BMI_WRITE_SOC_REGISTER; break; case 't': cmd = BMI_TEST; break; case 'f': memset(filename, '\0', sizeof(filename)); strncpy(filename, optarg, sizeof(filename)); flag |= FILE_FLAG; break; case 'l': length = atoi(optarg); flag |= LENGTH_FLAG; break; case 'a': address = strtoul(optarg, NULL, 0); flag |= ADDRESS_FLAG; break; case 'p': param = strtoul(optarg, NULL, 0); flag |= PARAM_FLAG; break; case 'c': count = atoi(optarg); flag |= COUNT_FLAG; break; case 'i': memset(ifname, '\0', 8); strcpy(ifname, optarg); break; case 'I': cmd = BMI_GET_TARGET_INFO; break; case 'n': flag |= PARAM_FLAG | AND_OP_FLAG | BITWISE_OP_FLAG; bitwise_mask = strtoul(optarg, NULL, 0); break; case 'o': flag |= PARAM_FLAG | BITWISE_OP_FLAG; bitwise_mask = strtoul(optarg, NULL, 0); break; case 'q': flag |= QUIET_FLAG; break; case 'u': flag |= UNCOMPRESS_FLAG; break; default: usage(); } } strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); /* Verify that the Target is alive. If not, wait for it. */ { int rv; static int waiting_msg_printed = 0; buffer = (char *)MALLOC(sizeof(struct bmi_target_info)); ((int *)buffer)[0] = AR6000_XIOCTL_TARGET_INFO; ifr.ifr_data = buffer; while ((rv=ioctl(s, AR6000_IOCTL_EXTENDED, &ifr)) < 0) { if (errno == ENODEV) { /* * Give the Target device a chance to start. * Then loop back and see if it's alive. */ if (!waiting_msg_printed) { nqprintf("bmiloader is waiting for Target....\n"); waiting_msg_printed = 1; } usleep(100000); /* Wait for 100ms */ } else { printf("Unexpected error on AR6000_XIOCTL_TARGET_INFO: %d\n", rv); exit(1); } } target_version = ((int *)buffer)[0]; target_type = ((int *)buffer)[1]; free(buffer); } switch(cmd) { case BMI_DONE: nqprintf("BMI Done\n"); buffer = (char *)MALLOC(4); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_DONE; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } free(buffer); break; case BMI_TEST: if ((flag & (COUNT_FLAG | LENGTH_FLAG | ADDRESS_FLAG)) == (COUNT_FLAG | LENGTH_FLAG | ADDRESS_FLAG)) { nqprintf("BMI Test (address: 0x%x, length: %d, count: %d)\n", address, length, count); buffer = (char *)MALLOC(16); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_TEST; ((int *)buffer)[1] = address; ((int *)buffer)[2] = length; ((int *)buffer)[3] = count; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } free(buffer); } else usage(); break; case BMI_READ_MEMORY: if ((flag & (ADDRESS_FLAG | LENGTH_FLAG | FILE_FLAG)) == (ADDRESS_FLAG | LENGTH_FLAG | FILE_FLAG)) { nqprintf( "BMI Read Memory (address: 0x%x, length: %d, filename: %s)\n", address, length, filename); if ((fd = open(filename, O_CREAT|O_WRONLY|O_TRUNC, 00644)) < 0) { perror("Could not create a file"); exit(1); } buffer = (char *)MALLOC(MAX_BUF + 12); { unsigned int remaining = length; while (remaining) { length = (remaining > MAX_BUF) ? MAX_BUF : remaining; ((int *)buffer)[0] = AR6000_XIOCTL_BMI_READ_MEMORY; ((int *)buffer)[1] = address; /* * We round up the requested length because some * SDIO Host controllers can't handle other lengths; * but we still only write the requested number of * bytes to the file. */ ((int *)buffer)[2] = A_ROUND_UP(length, 4); ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } else { write(fd, buffer, length); } remaining -= length; address += length; } } close(fd); free(buffer); } else usage(); break; case BMI_WRITE_MEMORY: if (!(flag & ADDRESS_FLAG)) { usage(); /* no address specified */ } if (!(flag & (FILE_FLAG | PARAM_FLAG))) { usage(); /* no data specified */ } if ((flag & FILE_FLAG) && (flag & PARAM_FLAG)) { usage(); /* too much data specified */ } if ((flag & UNCOMPRESS_FLAG) && !(flag & FILE_FLAG)) { usage(); /* uncompress only works with a file */ } if (flag & FILE_FLAG) { nqprintf( "BMI Write %sMemory (address: 0x%x, filename: %s)\n", ((flag & UNCOMPRESS_FLAG) ? "compressed " : ""), address, filename); if ((fd = open(filename, O_RDONLY)) < 0) { perror("Could not open file"); exit(1); } memset(&filestat, '\0', sizeof(struct stat)); buffer = (char *)MALLOC(MAX_BUF + 12); fstat(fd, &filestat); length = filestat.st_size; if (flag & UNCOMPRESS_FLAG) { /* Initiate compressed stream */ ((int *)buffer)[0] = AR6000_XIOCTL_BMI_LZ_STREAM_START; ((int *)buffer)[1] = address; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } } } else { /* PARAM_FLAG */ nqprintf( "BMI Write Memory (address: 0x%x, value: 0x%x)\n", address, param); length = sizeof(param); buffer = (char *)MALLOC(length + 12); *(unsigned int *)(&buffer[12]) = param; fd = -1; } /* * Write length bytes of data to memory. * Data is either present in buffer OR * needs to be read from fd in MAX_BUF chunks. * * Within the kernel, the implementation of * AR6000_XIOCTL_BMI_WRITE_MEMORY further * limits the size of each transfer over the * interconnect according to BMI protocol * limitations. */ { unsigned int remaining = length; int *pLength; while (remaining) { length = (remaining > MAX_BUF) ? MAX_BUF : remaining; if (flag & UNCOMPRESS_FLAG) { /* 0 pad last word of data to avoid messy uncompression */ ((A_UINT32 *)buffer)[2+((length-1)/4)] = 0; if (read(fd, &buffer[8], length) != length) { perror("read from compressed file failed"); exit(1); } ((int *)buffer)[0] = AR6000_XIOCTL_BMI_LZ_DATA; pLength = &((int *)buffer)[1]; } else { if (fd > 0) { if (read(fd, &buffer[12], length) != length) { perror("read from file failed"); exit(1); } } ((int *)buffer)[0] = AR6000_XIOCTL_BMI_WRITE_MEMORY; ((int *)buffer)[1] = address; pLength = &((int *)buffer)[2]; } /* * We round up the requested length because some * SDIO Host controllers can't handle other lengths. * This generally isn't a problem for users, but it's * something to be aware of. */ *pLength = A_ROUND_UP(length, 4); ifr.ifr_data = buffer; while (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } remaining -= length; address += length; } } free(buffer); if (fd > 0) { close(fd); if (flag & UNCOMPRESS_FLAG) { /* * Close compressed stream and open a new (fake) * one. This serves mainly to flush Target caches. */ ((int *)buffer)[0] = AR6000_XIOCTL_BMI_LZ_STREAM_START; ((int *)buffer)[1] = 0; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } } } break; case BMI_READ_SOC_REGISTER: if ((flag & (ADDRESS_FLAG)) == (ADDRESS_FLAG)) { nqprintf("BMI Read Register (address: 0x%x)\n", address); buffer = (char *)MALLOC(8); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_READ_SOC_REGISTER; ((int *)buffer)[1] = address; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } param = ((int *)buffer)[0]; if (quiet()) { printf("0x%x\n", param); } else { printf("Return Value from target: 0x%x\n", param); } free(buffer); } else usage(); break; case BMI_WRITE_SOC_REGISTER: if ((flag & (ADDRESS_FLAG | PARAM_FLAG)) == (ADDRESS_FLAG | PARAM_FLAG)) { int origvalue = 0; if (flag & BITWISE_OP_FLAG) { /* first read */ buffer = (char *)MALLOC(8); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_READ_SOC_REGISTER; ((int *)buffer)[1] = address; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } param = ((int *)buffer)[0]; origvalue = param; free(buffer); /* now modify */ if (flag & AND_OP_FLAG) { param &= bitwise_mask; } else { param |= bitwise_mask; } /* fall through to write out the parameter */ } if (flag & BITWISE_OP_FLAG) { if (quiet()) { printf("0x%x\n", origvalue); } else { printf("BMI Bit-Wise (%s) modify Register (address: 0x%x, orig:0x%x, new: 0x%x, mask:0x%X)\n", (flag & AND_OP_FLAG) ? "AND" : "OR", address, origvalue, param, bitwise_mask ); } } else{ nqprintf("BMI Write Register (address: 0x%x, param: 0x%x)\n", address, param); } buffer = (char *)MALLOC(12); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER; ((int *)buffer)[1] = address; ((int *)buffer)[2] = param; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } free(buffer); } else usage(); break; case BMI_EXECUTE: if ((flag & (ADDRESS_FLAG | PARAM_FLAG)) == (ADDRESS_FLAG | PARAM_FLAG)) { nqprintf("BMI Execute (address: 0x%x, param: 0x%x)\n", address, param); buffer = (char *)MALLOC(12); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_EXECUTE; ((int *)buffer)[1] = address; ((int *)buffer)[2] = param; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } param = ((int *)buffer)[0]; if (quiet()) { printf("0x%x\n", param); } else { printf("Return Value from target: 0x%x\n", param); } free(buffer); } else usage(); break; case BMI_SET_APP_START: if ((flag & ADDRESS_FLAG) == ADDRESS_FLAG) { nqprintf("BMI Set App Start (address: 0x%x)\n", address); buffer = (char *)MALLOC(8); ((int *)buffer)[0] = AR6000_XIOCTL_BMI_SET_APP_START; ((int *)buffer)[1] = address; ifr.ifr_data = buffer; if (ioctl(s, AR6000_IOCTL_EXTENDED, &ifr) < 0) { err(1, ifr.ifr_name); } free(buffer); } else usage(); break; case BMI_GET_TARGET_INFO: nqprintf("BMI Target Info:\n"); printf("TARGET_TYPE=%s\n", (target_type == TARGET_TYPE_AR6001) ? "AR6001" : ((target_type == TARGET_TYPE_AR6002) ? "AR6002" : (((target_type == TARGET_TYPE_AR6003) ? "AR6003" : "unknown")))); printf("TARGET_VERSION=0x%x\n", target_version); break; default: usage(); } exit (0); }
A_STATUS download_binary (HIF_DEVICE *hifDevice, A_UINT32 address, wchar_t *fileName, wchar_t *fileRoot, A_BOOL bCompressed, AR6K_BIN_CACHE_INFO *pBinCache) { A_STATUS status = A_OK; A_UCHAR *buffer = NULL; A_UINT32 length = 0; A_UINT32 fileSize = 0; A_UINT32 next_address=0; A_INT32 file_left = 0; size_t nSize; wchar_t filePath[128]; HANDLE fd = NULL; BY_HANDLE_FILE_INFORMATION finfo; A_BOOL fillCache = FALSE; A_MEMZERO(&finfo, sizeof(finfo)); if ( wcslen(fileName) + wcslen(fileRoot) > 127 ) { ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: File Name Very Long :: ====>"); return A_ERROR; } wcscpy(filePath,fileRoot); wcscat(filePath,fileName); ATHR_DISPLAY_MSG (L"file %s \n",filePath); do { if (pBinCache->Valid) { /* binary cache is valid */ if (bCompressed) { status = BMILZStreamStart (hifDevice, address); if (A_FAILED(status)) { break; } } if (bCompressed) { A_UINT32 lastWord = 0; A_UINT32 lastWordOffset = pBinCache->ActualLength & ~0x3; A_UINT32 unalignedBytes = pBinCache->ActualLength & 0x3; if (unalignedBytes) { /* copy the last word into a zero padded buffer */ A_MEMCPY(&lastWord, &pBinCache->pData[lastWordOffset], unalignedBytes); } status = BMILZData(hifDevice, pBinCache->pData, lastWordOffset); if (A_FAILED(status)) { break; } if (unalignedBytes) { status = BMILZData(hifDevice, (A_UINT8 *)&lastWord, 4); } } else { status = BMIWriteMemory(hifDevice, address, pBinCache->pData, A_ROUND_UP(pBinCache->ActualLength,4)); } if (bCompressed && A_SUCCESS(status)) { // // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. // status = BMILZStreamStart (hifDevice, 0x00); if (A_FAILED(status)) { break; } } /* all done */ break; } //Determine the length of the file if ( (fd = CreateFile (filePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { status = A_ERROR; ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: File Not Found :: ====> %s", filePath); break; } if (!GetFileInformationByHandle(fd, &finfo)) { ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: File Size Error :: ====> %s", filePath); status = A_ERROR; break; } fileSize = finfo.nFileSizeLow; file_left = fileSize; if ((pBinCache->pData != NULL) && (!pBinCache->Static)) { /* binary caching is supported */ A_ASSERT(!pBinCache->Valid); if (fileSize <= pBinCache->MaxLength) { /* size if good, flag to cache this binary when read from the filesystem */ fillCache = TRUE; pBinCache->ActualLength = 0; /* reset */ } else { /* cache is not big enough to hold data */ A_ASSERT(FALSE); ATHR_DISPLAY_MSG (L"AR6K::WARNING!!!! :: File :%s (%d bytes) too big for cache (max=%d)", filePath, fileSize, pBinCache->MaxLength); } } // // zero data buffer and init length // buffer = (A_UCHAR *)A_MALLOC(MAX_BUF); if (NULL == buffer) { status = A_ERROR; break; } if (bCompressed) { status = BMILZStreamStart (hifDevice, address); if (status != A_OK) { break; } } while (file_left) { length = (file_left < (MAX_BUF)) ? file_left : MAX_BUF; if (bCompressed) { // // 0 pad last word of data to avoid messy uncompression // ((A_UINT32 *)buffer)[((length-1)/4)] = 0; } if (!ReadFile( fd, buffer, length, &nSize, NULL) || nSize != length) { ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: ReadFile Error :: ====>"); status = A_ERROR; break; } next_address = address + fileSize - file_left; // // We round up the requested length because some SDIO Host controllers can't handle other lengths. // This generally isn't a problem for users, but it's something to be aware of. // length = A_ROUND_UP(length, 4); if (bCompressed) { status = BMILZData(hifDevice, buffer, length); } else { status = BMIWriteMemory(hifDevice, next_address, buffer, length); } if (status != A_OK) { break; } if (fillCache) { CopyChunkToBinCache(pBinCache, buffer, length); } if (file_left >= MAX_BUF) { file_left = file_left - MAX_BUF; } else { file_left = 0; } }; if (status != A_OK) { break; } if (fillCache) { /* cache was filled, mark it valid */ pBinCache->Valid = TRUE; } if (bCompressed) { // // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. // status = BMILZStreamStart (hifDevice, 0x00); if (status != A_OK) { break; } } } while (FALSE); if (buffer) { free (buffer); buffer = NULL; } if (fd) { CloseHandle (fd); } return status; }