This list is closed, nobody may subscribe to it.
2004 |
Jan
(53) |
Feb
(78) |
Mar
(34) |
Apr
(26) |
May
(25) |
Jun
(34) |
Jul
(16) |
Aug
(16) |
Sep
(2) |
Oct
(58) |
Nov
(13) |
Dec
(32) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(62) |
Feb
(4) |
Mar
(40) |
Apr
(9) |
May
(13) |
Jun
(26) |
Jul
(32) |
Aug
(24) |
Sep
(18) |
Oct
(18) |
Nov
(14) |
Dec
|
2006 |
Jan
(15) |
Feb
(2) |
Mar
(23) |
Apr
(2) |
May
(2) |
Jun
(13) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2007 |
Jan
(1) |
Feb
(45) |
Mar
|
Apr
(13) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(31) |
Dec
(5) |
2008 |
Jan
(6) |
Feb
(34) |
Mar
(113) |
Apr
(40) |
May
(19) |
Jun
(5) |
Jul
(41) |
Aug
(13) |
Sep
(53) |
Oct
(4) |
Nov
(53) |
Dec
|
2009 |
Jan
(1) |
Feb
(29) |
Mar
(66) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(163) |
Nov
|
Dec
(91) |
From: Albert H. <he...@us...> - 2005-10-02 18:10:40
|
Update of /cvsroot/gc-linux/linux/drivers/video In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17228/drivers/video Modified Files: gcngx.c Log Message: Move to io_remap_pfn_range interface. Index: gcngx.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/video/gcngx.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- gcngx.c 24 Jun 2005 10:59:50 -0000 1.4 +++ gcngx.c 2 Oct 2005 18:10:28 -0000 1.5 @@ -301,8 +301,8 @@ /* our special case, map the memory info */ vma->vm_flags |= VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (io_remap_page_range(vma,vma->vm_start, - VIDEO_MMAP_BASE, + if (io_remap_pfn_range(vma,vma->vm_start, + VIDEO_MMAP_BASE >> PAGE_SHIFT, len, vma->vm_page_prot)) { |
From: Albert H. <he...@us...> - 2005-10-02 18:10:12
|
Update of /cvsroot/gc-linux/linux/drivers/video In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17088/drivers/video Modified Files: gcnfb.c Log Message: Reduce dmesg noise. Index: gcnfb.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/video/gcnfb.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- gcnfb.c 6 Jan 2005 20:16:53 -0000 1.9 +++ gcnfb.c 2 Oct 2005 18:10:00 -0000 1.10 @@ -536,7 +536,9 @@ { int i; +/* printk(KERN_INFO "Setting mode %s\n", gcnfb_current_video_mode->name); +*/ gcnfb_set_framebuffer(info->fix.smem_start); /* initialize video registers */ @@ -626,7 +628,6 @@ printk("gcnfb: options = %s\n", options); while ((this_opt = strsep(&options, ",")) != NULL) { - printk("this_opt = %s\n", this_opt); if (!*this_opt) continue; @@ -637,8 +638,6 @@ else if (!strcmp(this_opt, "ywrap")) ypan = 2; else if (!strncmp(this_opt, "tv=", 3)) { - printk("detected \"tv=\"\n"); - printk("cmd line: %s\n", this_opt); if (!strncmp(this_opt + 3, "PAL", 3)) gcnfb_current_video_mode = gcnfb_video_modes + GCNFB_VM_PAL50; |
From: Albert H. <he...@us...> - 2005-09-25 20:09:10
|
Update of /cvsroot/gc-linux/linux/drivers/block In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4560/drivers/block Modified Files: gcn-sd.c Log Message: Make use of the exi idi transfer mode on reads to save some cpu cycles. Added write support to MMC/SD cards. Added support for hot plugging MMC/SD cards. Index: gcn-sd.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-sd.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- gcn-sd.c 14 Sep 2005 19:52:47 -0000 1.4 +++ gcn-sd.c 25 Sep 2005 20:08:57 -0000 1.5 @@ -55,6 +55,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/kthread.h> #include <linux/major.h> #include <linux/blkdev.h> #include <linux/hdreg.h> @@ -80,7 +81,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_LICENSE("GPL"); -static char sd_driver_version[] = "0.1-isobel"; +static char sd_driver_version[] = "0.3-isobel"; #define sd_printk(level, format, arg...) \ printk(level DRV_MODULE_NAME ": " format , ## arg) @@ -139,6 +140,12 @@ /* R3 is (R1, OCR) 5 bytes in SPI mode */ +/* data response */ +#define DR_SPI_MASK 0x1f +#define DR_SPI_DATA_ACCEPTED 0x05 +#define DR_SPI_DATA_REJECTED_CRC_ERROR 0x0b +#define DR_SPI_DATA_REJECTED_WRITE_ERROR 0x0d + /* this is still a missing command in the current MMC framework ... */ #define MMC_READ_OCR 58 @@ -179,7 +186,7 @@ }; enum { - __SD_MEDIA_CHANGED = 0 + __SD_MEDIA_CHANGED = 0, }; /* @@ -228,11 +235,17 @@ struct request_queue *queue; spinlock_t queue_lock; - int ref_count; + int refcnt; + + struct task_struct *io_thread; + wait_queue_head_t io_waitq; + struct request *req; struct exi_device *exi_device; }; +static void sd_kill(struct sd_host *host); + /* * MMC/SD data structures manipulation. * @@ -480,7 +493,36 @@ /* */ static inline void spi_read(struct sd_host *host, void *data, size_t len) { - exi_dev_read(host->exi_device, data, len); + /* + * Houston, we have a problem. + * + * The EXI hardware implementation seems to use a shift register which + * outputs data from the MSB to the MOSI line and inputs data from + * the MISO line into the LSB. + * When a read operation is performed, data from the MISO line + * is entered into the shift register LSB as expected. But also the + * data already present in the shift register is sent out through the + * MOSI line from the MSB. + * This is in fact the "feature" that enabled tmbinc to dump the IPL. + * + * When interfacing with SD cards, this causes us a serious problem. + * We are required to send all ones (1s) while reading data from + * the SD card. Otherwise, the card can interpret the data sent as + * commands (if they start with the bit pattern 01 for example). + * + * If we use the EXI immediate mode transfer, we can workaround the + * situation by writing all 1s to the DATA register before reading + * (this is indeed automatically done by the EXI layer). + * But we simply can't do that when using EXI DMA transfers (these + * kind of transfers do not allow bidirectional operation). + * + * Given that no EXI DMA read transfers seem reliable, we fallback + * to the "interrupt-driven" immediate mode of the EXI layer. + * This will help reducing CPU monopolization on large reads. + * + */ + exi_transfer(exi_get_exi_channel(host->exi_device), data, len, + EXI_OP_READ, EXI_CMD_IDI); } /* cycles are expressed in 8 clock cycles */ @@ -516,7 +558,6 @@ static int sd_read_data(struct sd_host *host, void *data, size_t len, int token) { int retval = 0; - int chunk, chunk_size = 31; if (token) { retval = spi_wait_for_resp(host, token, 0xff, @@ -524,53 +565,57 @@ if (retval < 0) goto out; } + spi_read(host, data, len); + retval = 0; - /* - * Houston, we have a problem. - * - * The EXI hardware implementation seems to use a shift register which - * outputs data from the MSB to the MOSI line and inputs data from - * the MISO line into the LSB. - * When a read operation is performed, data from the MISO line - * is entered into the shift register LSB as expected. But also the - * data already present in the shift register is sent out through the - * MOSI line from the MSB. - * This is in fact the "feature" that enabled tmbinc to dump the IPL. - * - * When interfacing with SD cards, this causes us a serious problem. - * We are required to send all ones (1s) while reading data from - * the SD card. Otherwise, the card can interpret the data sent as - * commands (if they start with the bit pattern 01 for example). - * - * If we use the EXI immediate mode transfer, we can workaround the - * situation by writing all 1s to the DATA register before reading - * (this is indeed automatically done by the EXI layer). - * But we simply can't do that when using EXI DMA transfers (these - * kind of transfers do not allow bidirectional operation). - * - * Given the fact that recently read data will be sent back to the - * card as host output, we can end up with funny and not so funny - * situations. - * For example, if the data you are reading contains the byte - * sequence: - * - 40 00 00 00 00 95 - * it will cause a software reset of the card - * - * If we enable CRC mode we can minimize the problem, but the risk - * is there. - * - */ -#if 1 - /* we enforce immediate mode by using transfers of less than 32 bytes */ - while (len > 0) { - chunk = (len >= chunk_size) ? chunk_size : len; - spi_read(host, data, chunk); - len -= chunk; - data += chunk; +out: + return retval; +} + +/* + * + */ +static int sd_write_data(struct sd_host *host, void *data, size_t len, int token) +{ + u16 crc; + u8 t; + int retval = 0; + + /* FIXME, rewrite this a bit */ + { + crc = 0; + u8 *d = data; + int l = len; + + while (l-- > 0) + crc = crc_xmodem_update(crc, *d++); } -#else - spi_read(host, data, len); -#endif + + /* send the write block token */ + t = token; + spi_write(host, &t, sizeof(t)); + + /* send the data */ + spi_write(host, data, len); + + /* send the crc */ + spi_write(host, &crc, sizeof(crc)); + + /* get the card data response */ + retval = spi_wait_for_resp(host, 0x01, 0x11, host->write_timeout); + if (retval < 0) + goto out; + if ((retval & DR_SPI_MASK) != DR_SPI_DATA_ACCEPTED) { + DBG("data response=%02x\n", retval); + retval = -EIO; + goto out; + } + + /* wait for the busy signal to clear */ + retval = spi_wait_for_resp(host, 0xff, 0xff, host->write_timeout); + if (retval < 0) + goto out; + retval = 0; out: @@ -705,8 +750,6 @@ } out: - //spi_wait_for_resp(host, 0xff, 0xff, host->read_timeout); - /* burn extra cycles and deselect card */ sd_end_command(host); @@ -722,6 +765,46 @@ /* * */ +static int sd_generic_write(struct sd_host *host, + u8 opcode, u32 arg, + void *data, size_t len, int token) +{ + struct sd_command *cmd = &host->cmd; + int retval; + + /* build raw command */ + sd_cmd(cmd, opcode, arg); + + /* select card, send command and wait for response */ + retval = sd_start_command(host, cmd); + if (retval < 0) + goto out; + if (retval != 0x00) { + retval = -EIO; + goto out; + } + + /* send data token, data and crc, get data response */ + retval = sd_write_data(host, data, len, token); + if (retval < 0) + goto out; + + retval = 0; + +out: + /* burn extra cycles and deselect card */ + sd_end_command(host); + + if (retval < 0) { + DBG("write, offset=%d, len=%d\n", arg, len); + } + + return retval; +} + +/* + * + */ static int sd_read_ocr(struct sd_host *host) { struct sd_command *cmd = &host->cmd; @@ -740,7 +823,7 @@ spi_read(host, &host->ocr, sizeof(host->ocr)); retval = 0; - out: +out: /* burn extra cycles and deselect card */ sd_end_command(host); return retval; @@ -796,6 +879,25 @@ /* * */ +static inline int sd_write_single_block(struct sd_host *host, + unsigned long start, + void *data, size_t len) +{ + int retval; + + retval = sd_generic_write(host, MMC_WRITE_BLOCK, start, + data, len, + MMC_SPI_TOKEN_START_SINGLE_BLOCK_WRITE); + if (retval < 0) + DBG("start=%lu, data=%p, len=%d, retval = %d\n", start, data, + len, retval); + + return retval; +} + +/* + * + */ static int sd_reset_sequence(struct sd_host *host) { struct sd_command *cmd = &host->cmd; @@ -876,7 +978,7 @@ break; } if ((retval & R1_SPI_ILLEGAL_COMMAND)) { - DBG("probably a MMC card was found\n"); + /* this looks like a MMC card */ break; } } @@ -981,7 +1083,7 @@ size_t block_len; /* in bytes */ unsigned long start; void *buf = req->buffer; - int retval = 1; + int retval; start = req->sector << KERNEL_SECTOR_SHIFT; nr_blocks = req->current_nr_sectors >> @@ -998,10 +1100,8 @@ } - if (retval < 0) - retval = 0; /* request not completed */ - else - retval = 1; /* request done */ + /* number of kernel sectors transferred */ + retval = i << (host->card.csd.read_blkbits - KERNEL_SECTOR_SHIFT); return retval; } @@ -1011,9 +1111,87 @@ */ static int sd_write_request(struct sd_host *host, struct request *req) { - sd_printk(KERN_ERR, "write support pending\n"); - end_request(req, 0); - return 0; + int i; + unsigned long nr_blocks; /* in card blocks */ + size_t block_len; /* in bytes */ + unsigned long start; + void *buf = req->buffer; + int retval; + + /* FIXME, should use 2^WRITE_BL_LEN blocks */ + + /* kernel sectors and card write blocks are both 512 bytes long */ + start = req->sector << KERNEL_SECTOR_SHIFT; + nr_blocks = req->current_nr_sectors; + block_len = 1 << KERNEL_SECTOR_SHIFT; + + for (i = 0; i < nr_blocks; i++) { + retval = sd_write_single_block(host, start, buf, block_len); + if (retval < 0) + break; + + start += block_len; + buf += block_len; + + } + + /* number of kernel sectors transferred */ + retval = i; + + return retval; +} + +/* + * Input/Output thread. Sends and receives packets. + */ +static int sd_io_thread(void *param) +{ + struct sd_host *host = param; + struct request *req; + int uptodate, nr_sectors; + unsigned long flags; + int retval; + + set_user_nice(current, -20); + current->flags |= PF_NOFREEZE; + set_current_state(TASK_RUNNING); + + while(!kthread_should_stop()) { + for(;;) { + spin_lock_irqsave(&host->lock, flags); + if (!host->req) { + spin_unlock_irqrestore(&host->lock, flags); + break; + } + req = host->req; + host->req = NULL; + spin_unlock_irqrestore(&host->lock, flags); + + spin_lock(&host->queue_lock); + blk_start_queue(host->queue); + spin_unlock(&host->queue_lock); + + /* proceed with i/o requests */ + if (rq_data_dir(req) == WRITE) { + retval = sd_write_request(host, req); + } else { + retval = sd_read_request(host, req); + } + + if (retval <= 0) { + uptodate = 0; + nr_sectors = 0; + } else { + uptodate = (retval > 0)?1:0; + nr_sectors = retval; + } + + if (!end_that_request_first(req, uptodate, nr_sectors)) + end_that_request_last(req); + } + wait_event(host->io_waitq, host->req || kthread_should_stop()); + } + return 0; } /* @@ -1024,22 +1202,20 @@ struct sd_host *host = q->queuedata; struct request *req; unsigned long nr_sectors; /* in kernel sectors */ - int retval; + unsigned long flags; nr_sectors = host->card.csd.capacity << (host->card.csd.read_blkbits - KERNEL_SECTOR_SHIFT); while ((req = elv_next_request(q))) { - /* keep our reads within limits */ - if (req->sector + req->current_nr_sectors > nr_sectors) { - sd_printk(KERN_ERR, "reading past end\n"); + /* pulling the card out while mounted is bold... */ + if (exi_is_dying(host->exi_device)) { + sd_printk(KERN_ERR, "card in use removed, aborting\n"); end_request(req, 0); continue; } - - /* changing media during flight is not a good idea... */ - if ((host->flags & SD_MEDIA_CHANGED)) { + if (test_bit(__SD_MEDIA_CHANGED, &host->flags)) { sd_printk(KERN_ERR, "media changed, aborting\n"); end_request(req, 0); continue; @@ -1049,15 +1225,28 @@ if (!blk_fs_request(req)) continue; - /* proceed with i/o requests */ - if (rq_data_dir(req) == WRITE) { - retval = sd_write_request(host, req); - } else { - retval = sd_read_request(host, req); + /* keep our reads within limits */ + if (req->sector + req->current_nr_sectors > nr_sectors) { + sd_printk(KERN_ERR, "reading past end\n"); + end_request(req, 0); + continue; } - end_request(req, retval); - if (!retval) - sd_printk(KERN_ERR, "request failed\n"); + + /* schedule the request if there transfer slot is free */ + spin_lock_irqsave(&host->lock, flags); + if (host->req) { + blk_stop_queue(q); + spin_unlock_irqrestore(&host->lock, flags); + break; + } + blkdev_dequeue_request(req); + host->req = req; + blk_stop_queue(q); + spin_unlock_irqrestore(&host->lock, flags); + + /* wake up the i/o thread */ + wake_up(&host->io_waitq); + break; } } @@ -1079,18 +1268,12 @@ down(&open_lock); /* honor exclusive open mode */ - if (host->ref_count == -1 || - (host->ref_count && (filp->f_flags & O_EXCL))) { + if (host->refcnt == -1 || + (host->refcnt && (filp->f_flags & O_EXCL))) { retval = -EBUSY; goto out; } - /* FIXME, read only mode for now */ - if (1 && (filp->f_mode & FMODE_WRITE)) { - retval = -EROFS; - goto out; - } - /* this takes care of revalidating the media if needed */ check_disk_change(inode->i_bdev); @@ -1100,9 +1283,9 @@ } if ((filp->f_flags & O_EXCL)) - host->ref_count = -1; + host->refcnt = -1; else - host->ref_count++; + host->refcnt++; out: up(&open_lock); @@ -1119,10 +1302,15 @@ down(&open_lock); - if (host->ref_count > 0) - host->ref_count--; - else - host->ref_count = 0; + if (host->refcnt > 0) + host->refcnt--; + else { + host->refcnt = 0; + } + + /* kill the device if we are dying and no more openers exist */ + if (!host->refcnt && exi_is_dying(host->exi_device)) + sd_kill(host); up(&open_lock); @@ -1142,13 +1330,12 @@ if (test_bit(__SD_MEDIA_CHANGED, &host->flags)) return 1; - /* otherwise check if the serial number of the card changed */ + /* check if the serial number of the card changed */ last_serial = host->card.cid.serial; retval = sd_read_cid(host); if (!retval && last_serial == host->card.cid.serial && last_serial) { clear_bit(__SD_MEDIA_CHANGED, &host->flags); } else { - sd_printk(KERN_INFO, "did you remove/insert a card? :)\n"); set_bit(__SD_MEDIA_CHANGED, &host->flags); } @@ -1174,9 +1361,6 @@ goto out; } - /* FIXME, restricted to read only for now ... */ - set_disk_ro(host->disk, 1); - /* inform the block layer about various sizes */ blk_queue_hardsect_size(host->queue, 1 << host->card.csd.read_blkbits); set_capacity(host->disk, host->card.csd.capacity); @@ -1243,12 +1427,10 @@ int retval; channel = to_channel(exi_get_exi_channel(host->exi_device)); - - spin_lock_init(&host->queue_lock); - host->ref_count = 0; + host->refcnt = 0; retval = -ENOMEM; - + spin_lock_init(&host->queue_lock); queue = blk_init_queue(sd_do_request, &host->queue_lock); if (!queue) { sd_printk(KERN_ERR, "error initializing queue\n"); @@ -1258,6 +1440,7 @@ blk_queue_dma_alignment(queue, EXI_DMA_ALIGN); blk_queue_max_phys_segments(queue, 1); blk_queue_max_hw_segments(queue, 1); + blk_queue_max_sectors(queue, 8); queue->queuedata = host; host->queue = queue; @@ -1271,15 +1454,26 @@ disk->fops = &sd_fops; sprintf(disk->disk_name, "%s%c", SD_NAME, 'a' + channel); sprintf(disk->devfs_name, "%s/target%d", SD_NAME, channel); - disk->queue = host->queue; disk->private_data = host; + disk->queue = host->queue; host->disk = disk; + init_waitqueue_head(&host->io_waitq); + host->io_thread = kthread_run(sd_io_thread, host, + "ksdiod/%c", 'a' + channel); + if (IS_ERR(host->io_thread)) { + sd_printk(KERN_ERR, "error creating io thread\n"); + goto err_io_thread; + } + retval = 0; goto out; +err_io_thread: + del_gendisk(host->disk); + put_disk(host->disk); err_alloc_disk: - blk_cleanup_queue(host->queue); + blk_put_queue(host->queue); err_blk_init_queue: out: return retval; @@ -1293,9 +1487,17 @@ if (host->disk) { del_gendisk(host->disk); put_disk(host->disk); + host->disk = NULL; + } + if (host->queue) { + blk_put_queue(host->queue); + host->queue = NULL; + } + + if (!IS_ERR(host->io_thread)) { + kthread_stop(host->io_thread); + wake_up(&host->io_waitq); } - if (host->queue) - blk_cleanup_queue(host->queue); } /* @@ -1321,7 +1523,6 @@ goto err_blk_dev; } add_disk(host->disk); - } return retval; @@ -1342,7 +1543,25 @@ /* * */ -static int __devinit sd_probe(struct exi_device *exi_device) +static void sd_kill(struct sd_host *host) +{ + struct exi_device *exi_device = host->exi_device; + + if (host) { + sd_exit(host); + if (host->exi_device) + exi_device_put(host->exi_device); + host->exi_device = NULL; + kfree(host); + } + exi_set_dying(exi_device, 0); + exi_set_drvdata(exi_device, NULL); +} + +/* + * + */ +static int sd_probe(struct exi_device *exi_device) { struct sd_host *host; int retval; @@ -1372,17 +1591,15 @@ /* * */ -static void __devexit sd_remove(struct exi_device *exi_device) +static void sd_remove(struct exi_device *exi_device) { struct sd_host *host = exi_get_drvdata(exi_device); - exi_set_drvdata(exi_device, NULL); - if (host) { - sd_exit(host); - if (host->exi_device) - exi_device_put(host->exi_device); - host->exi_device = NULL; - kfree(host); + if (host->refcnt > 0) { + sd_printk(KERN_ERR, "hey! attempt to remove device in use!\n"); + exi_set_dying(exi_device, 1); + } else { + sd_kill(host); } } |
From: Albert H. <he...@us...> - 2005-09-25 19:56:00
|
Update of /cvsroot/gc-linux/linux/drivers/exi In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2087/drivers/exi Modified Files: exi-hw.h exi-hw.c exi-driver.c Log Message: Added a interrupt-driven immediate (aka idi) transfer mode to the EXI layer. Added support for pluggable devices on memcard slots. Index: exi-driver.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/exi-driver.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- exi-driver.c 20 Mar 2005 17:10:38 -0000 1.9 +++ exi-driver.c 25 Sep 2005 19:55:50 -0000 1.10 @@ -17,9 +17,9 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> -#include <linux/exi.h> - +#include <linux/kthread.h> #include <linux/delay.h> +#include <linux/exi.h> #define DRV_MODULE_NAME "exi-driver" #define DRV_DESCRIPTION "Nintendo GameCube EXpansion Interface driver" @@ -27,7 +27,7 @@ "Todd Jeffreys <to...@vo...>, " \ "Albert Herranz" -static char exi_driver_version[] = "3.0"; +static char exi_driver_version[] = "3.1-isobel"; extern struct device exi_bus_devices[EXI_MAX_CHANNELS]; @@ -73,7 +73,6 @@ return "Unknown"; } - /* * Internal. Check if an exi device matches a given exi device id. */ @@ -125,6 +124,12 @@ return 0; } +/* + * Device release. + */ +static void exi_device_release(struct device *dev) +{ +} /* * Internal. Initialize an exi_device structure. @@ -137,16 +142,16 @@ exi_device->eid.id = EXI_ID_INVALID; exi_device->eid.channel = channel; exi_device->eid.device = device; - exi_device->frequency = -1; + exi_device->frequency = EXI_FREQ_SCAN; exi_device->exi_channel = to_exi_channel(channel); - device_initialize(&exi_device->dev); exi_device->dev.parent = &exi_bus_devices[channel]; exi_device->dev.bus = &exi_bus_type; + sprintf(exi_device->dev.bus_id, "%01x:%01x", channel, device); exi_device->dev.platform_data = to_exi_channel(channel); + exi_device->dev.release = exi_device_release; - sprintf(exi_device->dev.bus_id, "%01x:%01x", channel, device); } /** @@ -164,6 +169,7 @@ return exi_device; } + /** * exi_device_put - Releases a use of the exi device * @exi_device: device that's been disconnected @@ -184,6 +190,7 @@ struct exi_device *exi_get_exi_device(struct exi_channel *exi_channel, int device) { + // FIXME, maybe exi_device_get it too return &exi_devices[to_channel(exi_channel)][device]; } @@ -225,6 +232,9 @@ if (exi_driver->remove) exi_driver->remove(exi_device); + if (!exi_is_dying(exi_device)) + exi_device->eid.id = EXI_ID_INVALID; + return 0; } @@ -260,50 +270,56 @@ /* + * Internal. Re-scan a given device. + */ +static void exi_device_rescan(struct exi_device *exi_device) +{ + unsigned int id; + + /* do nothing if the device is marked to die */ + if (exi_is_dying(exi_device)) + return; + + /* now ID the device */ + id = exi_get_id(exi_device); + + if (exi_device->eid.id != EXI_ID_INVALID) { + /* device removed or changed */ + exi_printk(KERN_INFO, "removed [%s] id=0x%08x %s\n", + exi_device->dev.bus_id, + exi_device->eid.id, + exi_name_id(exi_device->eid.id)); + device_unregister(&exi_device->dev); + exi_device->eid.id = EXI_ID_INVALID; + } + + if (id != EXI_ID_INVALID) { + /* a new device has been found */ + exi_printk(KERN_INFO, "added [%s] id=0x%08x %s\n", + exi_device->dev.bus_id, + id, exi_name_id(id)); + exi_device->eid.id = id; + device_register(&exi_device->dev); + } + + exi_update_ext_status(exi_get_exi_channel(exi_device)); +} + +/* * Internal. Re-scan a given exi channel, looking for added, changed and * removed exi devices. - * XXX Currently, only _new_ devices are taken into account. */ static void exi_channel_rescan(struct exi_channel *exi_channel) { struct exi_device *exi_device; - unsigned int channel, device, id; - - spin_lock(&exi_channel->lock); + unsigned int channel, device; /* add the exi devices underneath the parents */ for (device = 0; device < EXI_DEVICES_PER_CHANNEL; ++device) { channel = to_channel(exi_channel); exi_device = &exi_devices[channel][device]; - - /* now ID the device */ - id = exi_get_id(exi_channel, device, EXI_FREQ_SCAN); - - /* - * We only process currently _new_ devices here. - */ - if (id != EXI_ID_INVALID) { - exi_printk(KERN_INFO, "[%s] id=0x%08x %s\n", - exi_device->dev.bus_id, - id, exi_name_id(id)); - - if (exi_device->eid.id == EXI_ID_INVALID) { - /* a new device has been found */ - exi_device->eid.id = id; - device_register(&exi_device->dev); - } else { - /* device changed */ - /* remove, add */ - } - } else { - if (exi_device->eid.id != EXI_ID_INVALID) { - /* device removed */ - /* remove */ - } - } + exi_device_rescan(exi_device); } - - spin_unlock(&exi_channel->lock); } /* @@ -321,6 +337,40 @@ } +static struct task_struct *exi_bus_task; +wait_queue_head_t exi_bus_waitq; + +/* + * Internal. Looks for new, changed or removed devices. + */ +static int exi_bus_thread(void *__unused) +{ + struct exi_channel *exi_channel; + struct exi_device *exi_device; + unsigned int channel; + int is_loaded, was_loaded; + + while(!kthread_should_stop()) { + sleep_on_timeout(&exi_bus_waitq, HZ); + + /* scan the memcard slot channels for device changes */ + for (channel = 0; channel <= 1; ++channel) { + exi_channel = to_exi_channel(channel); + + is_loaded = exi_get_ext_line(exi_channel); + was_loaded = (exi_channel->flags & EXI_EXT)?1:0; + + if (is_loaded ^ was_loaded) { + exi_device = &exi_devices[channel][0]; + exi_device_rescan(exi_device); + } + } + } + + return 0; +} + + static struct exi_device exi_devices[EXI_MAX_CHANNELS][EXI_DEVICES_PER_CHANNEL]; static struct bus_type exi_bus_type = { @@ -378,6 +428,13 @@ /* now enumerate through the bus and add all detected devices */ exi_bus_rescan(); + /* setup a thread to manage plugable devices */ + init_waitqueue_head(&exi_bus_waitq); + exi_bus_task = kthread_run(exi_bus_thread, NULL, "kexid"); + if (IS_ERR(exi_bus_task)) { + exi_printk(KERN_WARNING, "failed to start exi kernel thread\n"); + } + return 0; err_bus_register: Index: exi-hw.h =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/exi-hw.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- exi-hw.h 14 Sep 2005 19:21:47 -0000 1.5 +++ exi-hw.h 25 Sep 2005 19:55:50 -0000 1.6 @@ -42,6 +42,8 @@ #define EXI_READ 0 #define EXI_WRITE 1 +#define EXI_IDI_MAX_SIZE 4 + #define EXI_IRQ 4 @@ -106,8 +108,9 @@ int channel; unsigned long flags; -#define EXI_SELECTED (1<<0) -#define EXI_DMABUSY (1<<1) +#define EXI_SELECTED (1<<0) +#define EXI_DMABUSY (1<<1) +#define EXI_EXT (1<<8) spinlock_t io_lock; /* serializes access to CSR */ void __iomem *io_base; @@ -116,7 +119,7 @@ struct exi_device *device_selected; wait_queue_head_t wait_queue; - struct exi_command *dma_cmd; + struct exi_command *queued_cmd; struct exi_command post_cmd; unsigned long csr; @@ -125,6 +128,9 @@ struct exi_event_handler events[EXI_MAX_EVENTS]; }; +extern int exi_get_ext_line(struct exi_channel *exi_channel); +extern void exi_update_ext_status(struct exi_channel *exi_channel); + extern int exi_hw_init(char *); extern void exi_hw_exit(void); Index: exi-hw.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/exi-hw.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- exi-hw.c 14 Sep 2005 19:47:20 -0000 1.10 +++ exi-hw.c 25 Sep 2005 19:55:50 -0000 1.11 @@ -76,6 +76,7 @@ # define DBG(fmt, args...) #endif +extern wait_queue_head_t exi_bus_waitq; static void exi_tasklet(unsigned long param); @@ -261,11 +262,87 @@ } /* + * Internal. Start a transfer using "interrupt-driven immediate" mode. + */ +static void exi_start_idi_transfer_raw(struct exi_channel *exi_channel, + void *data, size_t len, int mode) +{ + void __iomem *io_base = exi_channel->io_base; + u32 __iomem *csr_reg = io_base + EXI_CSR; + u32 val = ~0; + unsigned long flags; + + BUG_ON(len < 1 || len > 4); + + if ((mode & EXI_OP_WRITE)) { + switch(len) { + case 1: + val = *((u8*)data) << 24; + break; + case 2: + val = *((u16*)data) << 16; + break; + case 3: + val = *((u16*)data) << 16; + val |= *((u8*)data+2) << 8; + break; + case 4: + val = *((u32*)data); + break; + default: + break; + } + } + + writel(val, io_base + EXI_DATA); + + /* enable the Transfer Complete interrupt */ + spin_lock_irqsave(&exi_channel->io_lock, flags); + writel(readl(csr_reg) | EXI_CSR_TCINTMASK, csr_reg); + spin_unlock_irqrestore(&exi_channel->io_lock, flags); + + /* start the transfer */ + writel(EXI_CR_TSTART | EXI_CR_TLEN(len) | (mode&0xf), io_base + EXI_CR); +} + +/* + * Internal. Finish a transfer using "interrupt-driven immediate" mode. + */ +static void exi_end_idi_transfer_raw(struct exi_channel *exi_channel, + void *data, size_t len, int mode) +{ + void __iomem *io_base = exi_channel->io_base; + u32 val = ~0; + + BUG_ON(len < 1 || len > 4); + + if ((mode&0xf) != EXI_OP_WRITE) { + val = readl(io_base + EXI_DATA); + switch(len) { + case 1: + *((u8*)data) = (u8)(val >> 24); + break; + case 2: + *((u16*)data) = (u16)(val >> 16); + break; + case 3: + *((u16*)data) = (u16)(val >> 16); + *((u8*)data+2) = (u8)(val >> 8); + break; + case 4: + *((u32*)data) = (u32)(val); + break; + default: + break; + } + } +} + +/* * Internal. Start a transfer using DMA mode. */ -static inline void exi_start_dma_transfer_raw(struct exi_channel *exi_channel, - dma_addr_t data, size_t len, - int mode) +static void exi_start_dma_transfer_raw(struct exi_channel *exi_channel, + dma_addr_t data, size_t len, int mode) { void __iomem *io_base = exi_channel->io_base; u32 __iomem *csr_reg = io_base + EXI_CSR; @@ -297,8 +374,7 @@ /* * Internal. Busy-wait until a DMA mode transfer operation completes. */ -static inline -void exi_wait_for_dma_transfer_raw(struct exi_channel *exi_channel) +static void exi_wait_for_transfer_raw(struct exi_channel *exi_channel) { u32 __iomem *cr_reg = exi_channel->io_base + EXI_CR; u32 __iomem *csr_reg = exi_channel->io_base + EXI_CSR; @@ -319,74 +395,136 @@ spin_unlock_irqrestore(&exi_channel->io_lock, flags); } +static void exi_command_done(struct exi_command *cmd); -/** - * exi_dma_transfer_raw - performs an exi transfer in DMA mode - * @exi_channel: channel - * @data: address of data being read/writen (32 byte aligned) - * @len: length of data (32 byte aligned) - * @mode: direction of transfer (EXI_OP_READ or EXI_OP_WRITE) - * - * Read or write data on a given EXI channel, using DMA mode, and - * busy-wait until transfer is done. - * +/* + * Internal. Check if an exi channel has delayed work to do. */ -void exi_dma_transfer_raw(struct exi_channel *exi_channel, - dma_addr_t data, size_t len, int mode) +static void exi_check_pending_work(void) { - if (len <= 0) - return; + struct exi_channel *exi_channel; - exi_start_dma_transfer_raw(exi_channel, data, len, mode); - exi_wait_for_dma_transfer_raw(exi_channel); + exi_channel_for_each(exi_channel) { + if (exi_channel->csr) { + tasklet_schedule(&exi_channel->tasklet); + } + } } +/* + * Internal. Finish a DMA transfer. + * Caller holds the channel lock. + */ +static void exi_end_dma_transfer(struct exi_channel *exi_channel) +{ + struct exi_command *cmd; + cmd = exi_channel->queued_cmd; + if (cmd) { + BUG_ON(!(exi_channel->flags & EXI_DMABUSY)); -static void exi_command_done(struct exi_command *cmd); + exi_channel->flags &= ~EXI_DMABUSY; + dma_unmap_single(&exi_channel->device_selected->dev, + cmd->dma_addr, cmd->dma_len, + (cmd->opcode == EXI_OP_READ)? + DMA_FROM_DEVICE:DMA_TO_DEVICE); + + exi_channel->queued_cmd = NULL; + } +} /* - * Internal. Check if an exi channel has delayed work to do. + * Internal. Finish an "interrupt-driven immediate" transfer. + * Caller holds the channel lock. + * + * If more data is pending transfer, schedules a new transfer. + * Returns zero if no more transfers are required, non-zero otherwise. + * */ -static void exi_check_pending_work(void) +static int exi_end_idi_transfer(struct exi_channel *exi_channel) { - struct exi_channel *exi_channel; + struct exi_command *cmd; + int len, offset; + unsigned int balance = 16 /* / sizeof(u32) */; - exi_channel_for_each(exi_channel) { - if (exi_channel->csr) { - tasklet_schedule(&exi_channel->tasklet); + cmd = exi_channel->queued_cmd; + if (cmd) { + BUG_ON((exi_channel->flags & EXI_DMABUSY)); + + len = (cmd->bytes_left > 4)?4:cmd->bytes_left; + offset = cmd->len - cmd->bytes_left; + exi_end_idi_transfer_raw(exi_channel, + cmd->data + offset, len, + cmd->opcode); + cmd->bytes_left -= len; + + if (balance && cmd->bytes_left > 0) { + offset += len; + len = (cmd->bytes_left > balance)? + balance:cmd->bytes_left; + exi_transfer_raw(exi_channel, + cmd->data + offset, len, cmd->opcode); + cmd->bytes_left -= len; + } + + if (cmd->bytes_left > 0) { + offset = cmd->len - cmd->bytes_left; + len = (cmd->bytes_left > 4)?4:cmd->bytes_left; + + exi_start_idi_transfer_raw(exi_channel, + cmd->data + offset, len, + cmd->opcode); + } else { + exi_channel->queued_cmd = NULL; } } + + return (exi_channel->queued_cmd)?1:0; } /* - * Internal. Wait until a DMA transfer completes and launch callbacks. + * Internal. Wait until a single transfer completes, and launch callbacks + * when the whole transfer is completed. */ -static inline void exi_wait_for_dma_transfer(struct exi_channel *exi_channel) +static int exi_wait_for_transfer_one(struct exi_channel *exi_channel) { struct exi_command *cmd; unsigned long flags; + int pending = 0; spin_lock_irqsave(&exi_channel->lock, flags); - exi_wait_for_dma_transfer_raw(exi_channel); + exi_wait_for_transfer_raw(exi_channel); - exi_channel->flags &= ~EXI_DMABUSY; - cmd = exi_channel->dma_cmd; + cmd = exi_channel->queued_cmd; if (cmd) { - dma_unmap_single(&exi_channel->device_selected->dev, - cmd->dma_addr, cmd->dma_len, - (cmd->opcode == EXI_OP_READ)? - DMA_FROM_DEVICE:DMA_TO_DEVICE); - exi_channel->dma_cmd = NULL; + if ((exi_channel->flags & EXI_DMABUSY)) { + /* dma transfers need just one transfer */ + exi_end_dma_transfer(exi_channel); + } else { + pending = exi_end_idi_transfer(exi_channel); + } + spin_unlock_irqrestore(&exi_channel->lock, flags); - exi_command_done(cmd); - return; + + if (!pending) + exi_command_done(cmd); + goto out; } spin_unlock_irqrestore(&exi_channel->lock, flags); +out: + return pending; } +/* + * Internal. Wait until a full transfer completes and launch callbacks. + */ +static void exi_wait_for_transfer(struct exi_channel *exi_channel) +{ + while(exi_wait_for_transfer_one(exi_channel)) + cpu_relax(); +} /* * Internal. Call any done hooks. @@ -511,11 +649,24 @@ opcode = cmd->opcode; data = cmd->data; + /* interrupt driven immediate transfer... */ + if ((cmd->flags & EXI_CMD_IDI)) { + exi_channel->queued_cmd = cmd; + exi_channel->flags &= ~EXI_DMABUSY; + + cmd->bytes_left = cmd->len; + len = (cmd->bytes_left > 4)?4:cmd->bytes_left; + exi_start_idi_transfer_raw(exi_channel, data, len, opcode); + + retval = 1; /* wait */ + goto done; + } + /* * We can't do DMA transfers unless we have at least 32 bytes. * And we won't do DMA transfers if user requests that. */ - if (len < EXI_DMA_ALIGN+1 || (cmd->flags & EXI_NODMA)) { + if (len < EXI_DMA_ALIGN+1 || (cmd->flags & EXI_CMD_NODMA)) { exi_transfer_raw(exi_channel, data, len, opcode); goto done; } @@ -594,7 +745,7 @@ cmd->done = exi_cmd_post_transfer; } - exi_channel->dma_cmd = cmd; + exi_channel->queued_cmd = cmd; exi_channel->flags |= EXI_DMABUSY; cmd->dma_len = len; @@ -631,11 +782,11 @@ spin_lock_irqsave(&exi_channel->lock, flags); /* ensure atomic operations are serialized */ - while (exi_channel->dma_cmd) { + while (exi_channel->queued_cmd) { DBG("cmd %d while dma in flight on channel %d\n", cmd->opcode, exi_channel->channel); spin_unlock_irqrestore(&exi_channel->lock, flags); - exi_wait_for_dma_transfer(exi_channel); + exi_wait_for_transfer(exi_channel); spin_lock_irqsave(&exi_channel->lock, flags); } @@ -703,7 +854,7 @@ retval = exi_run_command(cmd); if (retval > 0) { if (in_atomic() || irqs_disabled()) { - exi_wait_for_dma_transfer(cmd->exi_channel); + exi_wait_for_transfer(cmd->exi_channel); } else { wait_for_completion(&complete); } @@ -752,55 +903,15 @@ * Read or write data on a given EXI channel. */ void exi_transfer(struct exi_channel *exi_channel, void *data, size_t len, - int opcode) + int opcode, unsigned long flags) { struct exi_command cmd; exi_op_transfer(&cmd, exi_channel, data, len, opcode); + cmd.flags |= flags; exi_run_command_and_wait(&cmd); } - -/** - * exi_get_id - Returns the EXI ID of a device - * @exi_channel: channel - * @device: device number on channel - * @freq: clock frequency index - * - * Returns the EXI ID of an EXI device on a given channel. - * Caller holds the channel lock. - */ -u32 exi_get_id(struct exi_channel *exi_channel, unsigned int device, - unsigned int freq) -{ - u32 __iomem *csr_reg = exi_channel->io_base + EXI_CSR; - u32 id = EXI_ID_INVALID; - u16 cmd = 0; - - exi_select_raw(exi_channel, device, freq); - __exi_transfer_raw_u16(exi_channel, &cmd, EXI_OP_WRITE); - __exi_transfer_raw_u32(exi_channel, &id, EXI_OP_READ); - exi_deselect_raw(exi_channel); - - /* - * We return a EXI_ID_NONE if there is some unidentified device - * inserted in memcard slot A or memcard slot B. - * This, for example, allows the SD/MMC driver to see cards. - */ - if (id == EXI_ID_INVALID) { - if ((__to_channel(exi_channel) == 0 || - __to_channel(exi_channel) == 1) - && device == 0) { - if (readl(csr_reg) & EXI_CSR_EXT) { - id = EXI_ID_NONE; - } - } - } - - return id; -} - - /* * Internal. Count number of busy exi channels given a channel mask. * Caller holds the channel lock. @@ -887,8 +998,8 @@ DBG("channel=%d, csr=%08lx\n", exi_channel->channel, exi_channel->csr); - if (exi_channel->dma_cmd) { - DBG("tasklet while dma in flight on channel %d, csr = %08lx\n", + if (exi_channel->queued_cmd) { + DBG("tasklet while xfer in flight on channel %d, csr = %08lx\n", exi_channel->channel, exi_channel->csr); } @@ -942,7 +1053,10 @@ spin_unlock_irqrestore(&exi_channel->io_lock, flags); if ((status & EXI_CSR_TCINT)) { - exi_wait_for_dma_transfer(exi_channel); + exi_wait_for_transfer_one(exi_channel); + } + if ((status & EXI_CSR_EXTIN)) { + wake_up(&exi_bus_waitq); } if (exi_channel->csr && !exi_is_selected(exi_channel)) { @@ -1080,7 +1194,7 @@ static void exi_quiesce_channel(struct exi_channel *exi_channel, u32 csr_mask) { /* wait for dma transfers to complete */ - exi_wait_for_dma_transfer_raw(exi_channel); + exi_wait_for_transfer_raw(exi_channel); /* ack and mask all interrupts */ writel(EXI_CSR_TCINT | EXI_CSR_EXIINT | EXI_CSR_EXTIN | csr_mask, @@ -1099,6 +1213,67 @@ } } +/** + * exi_get_id - Returns the EXI ID of a device + * @exi_channel: channel + * @device: device number on channel + * @freq: clock frequency index + * + * Returns the EXI ID of an EXI device on a given channel. + * Might sleep. + */ +u32 exi_get_id(struct exi_device *exi_device) +{ + struct exi_channel *exi_channel = exi_device->exi_channel; + u32 __iomem *csr_reg = exi_channel->io_base + EXI_CSR; + u32 id = EXI_ID_INVALID; + u16 cmd = 0; + + /* ask for the EXI id */ + exi_dev_select(exi_device); + exi_dev_write(exi_device, &cmd, sizeof(cmd)); + exi_dev_read(exi_device, &id, sizeof(id)); + exi_dev_deselect(exi_device); + + /* + * We return a EXI_ID_NONE if there is some unidentified device + * inserted in memcard slot A or memcard slot B. + * This, for example, allows the SD/MMC driver to see cards. + */ + if (id == EXI_ID_INVALID) { + if ((__to_channel(exi_channel) == 0 || + __to_channel(exi_channel) == 1) + && exi_device->eid.device == 0) { + if (readl(csr_reg) & EXI_CSR_EXT) { + id = EXI_ID_NONE; + } + } + } + + return id; +} + +/* + * Tells if there is a device inserted in one of the memory card slots. + */ +int exi_get_ext_line(struct exi_channel *exi_channel) +{ + u32 __iomem *csr_reg = exi_channel->io_base + EXI_CSR; + return (readl(csr_reg) & EXI_CSR_EXT)?1:0; +} + +/* + * Saves the current insertion status of a given channel. + */ +void exi_update_ext_status(struct exi_channel *exi_channel) +{ + if (exi_get_ext_line(exi_channel)) { + exi_channel->flags |= EXI_EXT; + } else { + exi_channel->flags &= ~EXI_EXT; + } +} + /* * Pseudo-Internal. Initialize basic channel structures and hardware. */ @@ -1115,7 +1290,7 @@ exi_channel_init(exi_channel, channel); } - /* calm down the hardware and allow external insertions */ + /* calm down the hardware and allow extractions */ exi_quiesce_all_channels(EXI_CSR_EXTINMASK); /* register the exi interrupt handler */ @@ -1143,7 +1318,6 @@ EXPORT_SYMBOL(exi_select_raw); EXPORT_SYMBOL(exi_deselect_raw); EXPORT_SYMBOL(exi_transfer_raw); -EXPORT_SYMBOL(exi_dma_transfer_raw); EXPORT_SYMBOL(exi_select); EXPORT_SYMBOL(exi_deselect); |
From: Albert H. <he...@us...> - 2005-09-25 19:56:00
|
Update of /cvsroot/gc-linux/linux/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2087/include/linux Modified Files: exi.h Log Message: Added a interrupt-driven immediate (aka idi) transfer mode to the EXI layer. Added support for pluggable devices on memcard slots. Index: exi.h =================================================================== RCS file: /cvsroot/gc-linux/linux/include/linux/exi.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- exi.h 14 Sep 2005 19:24:19 -0000 1.12 +++ exi.h 25 Sep 2005 19:55:50 -0000 1.13 @@ -48,7 +48,8 @@ struct exi_device_id eid; int frequency; - unsigned long flags; + unsigned flags; +#define EXI_DEV_DYING (1<<0) struct device dev; }; @@ -95,6 +96,22 @@ dev_set_drvdata(&exi_dev->dev, data); } +static inline int exi_is_dying(struct exi_device *exi_device) +{ + return exi_device->flags & EXI_DEV_DYING; +} + +static inline int exi_set_dying(struct exi_device *exi_device, int status) +{ + if (status) + exi_device->flags |= EXI_DEV_DYING; + else + exi_device->flags &= ~EXI_DEV_DYING; + + return exi_is_dying(exi_device); +} + +extern u32 exi_get_id(struct exi_device *exi_device); /* * EXpansion Interface channels. @@ -140,10 +157,12 @@ #define EXI_OP_NOP -1 unsigned long flags; -#define EXI_NODMA (1<<0) +#define EXI_CMD_NODMA (1<<0) +#define EXI_CMD_IDI (1<<1) void *data; size_t len; + size_t bytes_left; dma_addr_t dma_addr; size_t dma_len; @@ -193,20 +212,6 @@ cmd->len = len; } -static inline void exi_op_read(struct exi_command *cmd, - struct exi_channel *exi_channel, - void *data, size_t len) -{ - exi_op_transfer(cmd, exi_channel, data, len, EXI_OP_READ); -} - -static inline void exi_op_write(struct exi_command *cmd, - struct exi_channel *exi_channel, - void *data, size_t len) -{ - exi_op_transfer(cmd, exi_channel, data, len, EXI_OP_WRITE); -} - /* * EXpansion Interface interfaces. @@ -234,35 +239,35 @@ * Standard. */ -extern u32 exi_get_id(struct exi_channel *exi_channel, - unsigned int device, unsigned int freq); - int exi_select(struct exi_device *exi_device); void exi_deselect(struct exi_channel *exi_channel); void exi_transfer(struct exi_channel *exi_channel, - void *data, size_t len, int opcode); + void *data, size_t len, int opcode, unsigned long flags); -#define exi_dev_select(d) exi_select(d) +static inline int exi_dev_select(struct exi_device *exi_device) +{ + return exi_select(exi_device); +} static inline void exi_dev_deselect(struct exi_device *exi_device) { - return exi_deselect(exi_device->exi_channel); + exi_deselect(exi_device->exi_channel); } static inline void exi_dev_transfer(struct exi_device *exi_device, - void *data, size_t len, int opcode) + void *data, size_t len, int opcode, unsigned long flags) { - return exi_transfer(exi_device->exi_channel, data, len, opcode); + exi_transfer(exi_device->exi_channel, data, len, opcode, flags); } static inline void exi_dev_read(struct exi_device *dev, void *data, size_t len) { - exi_dev_transfer(dev, data, len, EXI_OP_READ); + exi_dev_transfer(dev, data, len, EXI_OP_READ, 0); } static inline void exi_dev_write(struct exi_device *dev, void *data, size_t len) { - exi_dev_transfer(dev, data, len, EXI_OP_WRITE); + exi_dev_transfer(dev, data, len, EXI_OP_WRITE, 0); } static inline int exi_dev_set_freq(struct exi_device *dev, unsigned int freq) @@ -318,12 +323,12 @@ static inline void exi_lite_read(int channel, void *data, size_t len) { - exi_transfer(to_exi_channel(channel), data, len, EXI_OP_READ); + exi_transfer(to_exi_channel(channel), data, len, EXI_OP_READ, 0); } static inline void exi_lite_write(int channel, void *data, size_t len) { - exi_transfer(to_exi_channel(channel), data, len, EXI_OP_WRITE); + exi_transfer(to_exi_channel(channel), data, len, EXI_OP_WRITE, 0); } static inline int exi_lite_register_event(int channel, int event_id, |
From: Arthur O. <aot...@us...> - 2005-09-24 16:26:22
|
Update of /cvsroot/gc-linux/CVSROOT In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12871 Removed Files: syncmail Log Message: SourceForge already provides a site-wide installation of the cvs-syncmail script under it's `sitedocs' project. Use that instead while getting rid of the local copy that breaks on imports. --- syncmail DELETED --- |
From: <aot...@us...> - 2005-09-24 16:25:47
|
Update of /cvsroot/gc-linux/CVSROOT In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12646 Modified Files: loginfo Log Message: SourceForge already provides a site-wide installation of the cvs-syncmail script under it's `sitedocs' project. Use that instead while getting rid of the local copy that breaks on imports. Index: loginfo =================================================================== RCS file: /cvsroot/gc-linux/CVSROOT/loginfo,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- loginfo 23 Jan 2004 12:10:38 -0000 1.2 +++ loginfo 24 Sep 2005 16:25:37 -0000 1.3 @@ -24,4 +24,4 @@ #DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog # or #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog -DEFAULT $CVSROOT/CVSROOT/syncmail -u %{sVv} gc-...@li... +DEFAULT /cvsroot/sitedocs/CVSROOT/cvstools/syncmail -u %{sVv} gc-...@li... |
From: <he...@us...> - 2005-09-14 19:52:58
|
Update of /cvsroot/gc-linux/linux/drivers/block In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16983 Modified Files: Kconfig gcn-sd.c Log Message: MMC/SD card block driver rewrite. Both MMC and SD cards are properly detected, including their size. Only read support is enabled (no writes yet). Performance is not optimal as the source code explains. Solutions? Index: Kconfig =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/Kconfig,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- Kconfig 6 Jul 2005 18:28:01 -0000 1.17 +++ Kconfig 14 Sep 2005 19:52:47 -0000 1.18 @@ -107,20 +107,22 @@ config GAMECUBE_SD tristate "Nintendo GameCube SD and MMC memory card (EXPERIMENTAL)" - depends on GAMECUBE && GAMECUBE_EXI && EXPERIMENTAL && BROKEN + depends on GAMECUBE && GAMECUBE_EXI && EXPERIMENTAL help - This enables support for SD and MMC cards - WARNING: driver is in alpha stage. Only reading supported. Card - is reported as around 100MB, its size is not read from the card. - Cards are NOT hot-pluggable. Compilation as module is broken. + This enables support for using SD and MMC cards through + the Nintendo SD Card Adapter (DOL-019) or compatible hardware. + + Currently, only read support is enabled. You probably want to compile FAT support, and the required - codepages, or mount wil complain. See Filesystems -> DOS/FAT/NT + codepages, or mount will complain. See Filesystems -> DOS/FAT/NT filesystems and Filesystems -> Native Language Support - - For schematic to connect the SD or MMC card, and more notes and - warnings, see drivers/block/gcn-sd.c + Say Y if you want to include this driver in the kernel. + + To compile this driver as a module, choose M here: the + module will be called gcn-sd. + config ATARI_ACSI tristate "Atari ACSI support" depends on ATARI && BROKEN Index: gcn-sd.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-sd.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- gcn-sd.c 6 Jul 2005 18:28:02 -0000 1.3 +++ gcn-sd.c 14 Sep 2005 19:52:47 -0000 1.4 @@ -1,9 +1,11 @@ /* * drivers/block/gcn-sd.c * - * Nintendo GameCube SD/MMC memory card driver - * Copyright (C) 2004-2005 The GameCube Linux Team - * Copyright (C) 2004,2005 by Rob Reilink (ro...@re...) + * MMC/SD card block driver for the Nintendo GameCube + * Copyright (C) 2005 The GameCube Linux Team + * Copyright (C) 2004,2005 Rob Reylink + * Copyright (C) 2005 Todd Jeffreys + * Copyright (C) 2005 Albert Herranz [...1712 lines suppressed...] + if (register_blkdev(SD_MAJOR, DRV_MODULE_NAME)) { + sd_printk(KERN_ERR, "unable to register major %d\n", SD_MAJOR); + retval = -EIO; + goto out; + } + + retval = exi_driver_register(&sd_driver); + + out: + return retval; +} + +static void __exit sd_exit_module(void) +{ + unregister_blkdev(SD_MAJOR, DRV_MODULE_NAME); + exi_driver_unregister(&sd_driver); +} + +module_init(sd_init_module); +module_exit(sd_exit_module); |
From: <he...@us...> - 2005-09-14 19:47:29
|
Update of /cvsroot/gc-linux/linux/drivers/exi In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16337 Modified Files: exi-hw.c Log Message: Export useful symbol to_channel. Fix read/write support related code. Index: exi-hw.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/exi-hw.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- exi-hw.c 25 Apr 2005 19:29:43 -0000 1.9 +++ exi-hw.c 14 Sep 2005 19:47:20 -0000 1.10 @@ -290,7 +290,7 @@ spin_unlock_irqrestore(&exi_channel->io_lock, flags); /* start the transfer */ - writel(EXI_CR_TSTART | EXI_CR_DMA | (mode&7), io_base + EXI_CR); + writel(EXI_CR_TSTART | EXI_CR_DMA | (mode&0xf), io_base + EXI_CR); } @@ -1138,6 +1138,7 @@ EXPORT_SYMBOL(to_exi_channel); +EXPORT_SYMBOL(to_channel); EXPORT_SYMBOL(exi_select_raw); EXPORT_SYMBOL(exi_deselect_raw); |
From: <he...@us...> - 2005-09-14 19:24:28
|
Update of /cvsroot/gc-linux/linux/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10887 Modified Files: exi.h Log Message: Added a small function to allow setting per-device frequencies. Index: exi.h =================================================================== RCS file: /cvsroot/gc-linux/linux/include/linux/exi.h,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- exi.h 25 Apr 2005 19:29:43 -0000 1.11 +++ exi.h 14 Sep 2005 19:24:19 -0000 1.12 @@ -265,6 +265,16 @@ exi_dev_transfer(dev, data, len, EXI_OP_WRITE); } +static inline int exi_dev_set_freq(struct exi_device *dev, unsigned int freq) +{ + BUG_ON(freq > EXI_MAX_FREQ); + + dev->frequency = freq; + + return freq; +} + + /* |
From: <he...@us...> - 2005-09-14 19:21:55
|
Update of /cvsroot/gc-linux/linux/drivers/exi In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9652 Modified Files: exi-hw.h Log Message: Small fix to make immediate read/write operations possible. Index: exi-hw.h =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/exi-hw.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- exi-hw.h 20 Mar 2005 17:10:38 -0000 1.4 +++ exi-hw.h 14 Sep 2005 19:21:47 -0000 1.5 @@ -29,8 +29,15 @@ #define EXI_DEVICES_PER_CHANNEL 3 /* number of devices per EXI channel */ #define EXI_MAX_EVENTS 3 /* types of events on the EXI bus */ +#define EXI_CLK_1MHZ 0 +#define EXI_CLK_2MHZ 1 +#define EXI_CLK_4MHZ 2 +#define EXI_CLK_8MHZ 3 +#define EXI_CLK_16MHZ 4 +#define EXI_CLK_32MHZ 5 + #define EXI_MAX_FREQ 7 -#define EXI_FREQ_SCAN 3 +#define EXI_FREQ_SCAN EXI_CLK_8MHZ #define EXI_READ 0 #define EXI_WRITE 1 @@ -53,12 +60,12 @@ #define EXI_CSR_TCINTMASK (1<<2) #define EXI_CSR_TCINT (1<<3) #define EXI_CSR_CLKMASK (0x7<<4) -#define EXI_CSR_CLK_1MHZ (0x0<<4) -#define EXI_CSR_CLK_2MHZ (0x1<<4) -#define EXI_CSR_CLK_4MHZ (0x2<<4) -#define EXI_CSR_CLK_8MHZ (0x3<<4) -#define EXI_CSR_CLK_16MHZ (0x4<<4) -#define EXI_CSR_CLK_32MHZ (0x5<<4) +#define EXI_CSR_CLK_1MHZ (EXI_CLK_1MHZ<<4) +#define EXI_CSR_CLK_2MHZ (EXI_CLK_2MHZ<<4) +#define EXI_CSR_CLK_4MHZ (EXI_CLK_4MHZ<<4) +#define EXI_CSR_CLK_8MHZ (EXI_CLK_8MHZ<<4) +#define EXI_CSR_CLK_16MHZ (EXI_CLK_16MHZ<<4) +#define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4) #define EXI_CSR_CSMASK (0x7<<7) #define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */ #define EXI_CSR_CS_1 (0x2<<7) /* Chip Select 010 */ @@ -143,12 +150,12 @@ * information currently stored there is leaked to the \ * MOSI line, confusing some hardware. \ */ \ - if (mode & EXI_OP_WRITE) \ + if ((mode & EXI_OP_WRITE)) \ _on_write; \ writel(_val, data_reg); \ \ /* start transfer */ \ - _val = EXI_CR_TSTART | EXI_CR_TLEN(sizeof(_type)) | (mode&7); \ + _val = EXI_CR_TSTART | EXI_CR_TLEN(sizeof(_type)) | (mode&0xf); \ writel(_val, cr_reg); \ \ /* wait for transfer completion */ \ @@ -161,7 +168,7 @@ writel(readl(csr_reg) | EXI_CSR_TCINT, csr_reg); \ spin_unlock_irqrestore(&exi_channel->io_lock, flags); \ \ - if (!(mode & EXI_OP_WRITE)) { \ + if ((mode&0xf) != EXI_OP_WRITE) { /* read or read-write */ \ _val = readl(data_reg); \ _on_read; \ } \ |
From: Albert H. <alb...@ya...> - 2005-09-11 11:16:02
|
> in/out_be(16|32)(). ioread/write(16|32)be() are > simply wrappers around > these. Can we safely start using them now in drivers? If so, I'll start porting drivers to the new interfaces and testing them. After that we can get rid of any io.h tweaks, and eventually removing io.h from cvs. Cheers, Albert ______________________________________________ Renovamos el Correo Yahoo! Nuevos servicios, más seguridad http://correo.yahoo.es |
From: <a.o...@bl...> - 2005-09-11 11:07:25
|
On Sun, Sep 11, 2005 at 12:59:16PM +0200, Albert Herranz wrote: > > That change doesn't touch the accessors bit, so I > > don't see where the > > problem is.. > > There's no problem. That's the problem. Your patch > does actually nothing. > > > The appropriate accessors _do_ exist. None of the > > drivers doing > > I/O actually use them, unfortunately. > > We can't use them yet, as you already mentioned it. in/out_be(16|32)(). ioread/write(16|32)be() are simply wrappers around these. > > I think I clarified it enough in the commit message. > > Nothing has been > > broken, intentionally or unintentionally. Like I > > said, patch exists, and > > until it makes it into mainline, > > include/asm-ppc/io.h remains in CVS. > > Yes, nothing is broken. And nothing changed. > > That's why I wondered, why the patch? Just cvs noise? > Or did I miss something subtle? Noise, yes. But a step towards eventually moving it out of CVS. Arthur |
From: Albert H. <alb...@ya...> - 2005-09-11 10:59:24
|
> That change doesn't touch the accessors bit, so I > don't see where the > problem is.. There's no problem. That's the problem. Your patch does actually nothing. > The appropriate accessors _do_ exist. None of the > drivers doing > I/O actually use them, unfortunately. We can't use them yet, as you already mentioned it. > I think I clarified it enough in the commit message. > Nothing has been > broken, intentionally or unintentionally. Like I > said, patch exists, and > until it makes it into mainline, > include/asm-ppc/io.h remains in CVS. Yes, nothing is broken. And nothing changed. That's why I wondered, why the patch? Just cvs noise? Or did I miss something subtle? Cheers, Albert ______________________________________________ Renovamos el Correo Yahoo! Nuevos servicios, más seguridad http://correo.yahoo.es |
From: <a.o...@bl...> - 2005-09-11 10:50:40
|
On Sun, Sep 11, 2005 at 11:01:27AM +0200, Albert Herranz wrote: > --- Arthur Othieno <a.o...@bl...> escribi?: > > > We still have to maintain io.h for the > > > read{b,w,l}/write{b,w,l} tweak anyway... > > > > No. We don't. These are accessors for PCI and other > > inherently > > little-endian busses, only. In any case, the ones > > we're using > > for gamecube don't provide proper memory barriers. > > We use that accessors in the GameCube to access i/o > mapped devices, and that spaces are already guarded > and cache-inhibited so we _don't_ need memory barriers > to guarantee ordered access to "memory" (see ppc cache > model and memory coherence). That change doesn't touch the accessors bit, so I don't see where the problem is.. > And we use that accessors because of the current lack > of the appropiate ones. So, we _do_ need them (or we > need to get the necessary patch). All drivers > performing i/o currently use them. The appropriate accessors _do_ exist. None of the drivers doing I/O actually use them, unfortunately. > > > So currently, and until someone adds big endian > > > ioread*/iowrite* support, this change doesn't make > > too > > > much sense. > > > > These are still queued up in patchwork. They should > > make it upstream > > RSN whenever paulus pushes to Linus, like he just > > did for ppc64. > > So, what's the _real_ effect of your patch? > Why not wait for the ioread/iowrite stuff and submit a > patch that _actually_ does something? I think I clarified it enough in the commit message. Nothing has been broken, intentionally or unintentionally. Like I said, patch exists, and until it makes it into mainline, include/asm-ppc/io.h remains in CVS. Arthur |
From: Albert H. <alb...@ya...> - 2005-09-11 09:01:36
|
--- Arthur Othieno <a.o...@bl...> escribió: > > We still have to maintain io.h for the > > read{b,w,l}/write{b,w,l} tweak anyway... > > No. We don't. These are accessors for PCI and other > inherently > little-endian busses, only. In any case, the ones > we're using > for gamecube don't provide proper memory barriers. We use that accessors in the GameCube to access i/o mapped devices, and that spaces are already guarded and cache-inhibited so we _don't_ need memory barriers to guarantee ordered access to "memory" (see ppc cache model and memory coherence). And we use that accessors because of the current lack of the appropiate ones. So, we _do_ need them (or we need to get the necessary patch). All drivers performing i/o currently use them. > > So currently, and until someone adds big endian > > ioread*/iowrite* support, this change doesn't make > too > > much sense. > > These are still queued up in patchwork. They should > make it upstream > RSN whenever paulus pushes to Linus, like he just > did for ppc64. So, what's the _real_ effect of your patch? Why not wait for the ioread/iowrite stuff and submit a patch that _actually_ does something? Cheers, Albert ______________________________________________ Renovamos el Correo Yahoo! Nuevos servicios, más seguridad http://correo.yahoo.es |
From: <a.o...@bl...> - 2005-09-11 01:09:06
|
On Sun, Sep 11, 2005 at 02:38:43AM +0200, Albert Herranz wrote: > --- aot...@us... escribi?: > > Instead of working around this with even more #ifdef > > kludge, > > just provide these definitions in the > > platform-specific file. > > > > Besides, this will be moving to include/asm-powerpc/ > > RSN, and, having > > to maintain ~550 lines for a 3 line delta doesn't > > seem very practical. > > We still have to maintain io.h for the > read{b,w,l}/write{b,w,l} tweak anyway... No. We don't. These are accessors for PCI and other inherently little-endian busses, only. In any case, the ones we're using for gamecube don't provide proper memory barriers. > So currently, and until someone adds big endian > ioread*/iowrite* support, this change doesn't make too > much sense. These are still queued up in patchwork. They should make it upstream RSN whenever paulus pushes to Linus, like he just did for ppc64. Arthur |
From: Albert H. <alb...@ya...> - 2005-09-11 00:38:53
|
--- aot...@us... escribió: > Instead of working around this with even more #ifdef > kludge, > just provide these definitions in the > platform-specific file. > > Besides, this will be moving to include/asm-powerpc/ > RSN, and, having > to maintain ~550 lines for a 3 line delta doesn't > seem very practical. We still have to maintain io.h for the read{b,w,l}/write{b,w,l} tweak anyway... So currently, and until someone adds big endian ioread*/iowrite* support, this change doesn't make too much sense. Cheers, Albert ______________________________________________ Renovamos el Correo Yahoo! Nuevos servicios, más seguridad http://correo.yahoo.es |
From: <aot...@us...> - 2005-09-10 21:18:31
|
Update of /cvsroot/gc-linux/linux/arch/ppc/platforms In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29152/arch/ppc/platforms Modified Files: gamecube.c Log Message: include/asm-ppc/io.h expects all platforms that are !APUS to provide definitions for isa_{io,mem}_base, pci_dram_offset. Instead of working around this with even more #ifdef kludge, just provide these definitions in the platform-specific file. Besides, this will be moving to include/asm-powerpc/ RSN, and, having to maintain ~550 lines for a 3 line delta doesn't seem very practical. Index: gamecube.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gamecube.c,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- gamecube.c 10 Aug 2005 11:54:35 -0000 1.34 +++ gamecube.c 10 Sep 2005 21:18:24 -0000 1.35 @@ -26,6 +26,15 @@ #include "gamecube.h" +/* + * include/asm-ppc/io.h assumes everyone else that is not APUS provides + * these. Since we don't have either PCI or ISA busses, these are only + * here so things actually compile. + */ +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; + static unsigned long gamecube_find_end_of_memory(void) { |
From: <aot...@us...> - 2005-09-10 21:18:31
|
Update of /cvsroot/gc-linux/linux/include/asm-ppc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29152/include/asm-ppc Modified Files: io.h Log Message: include/asm-ppc/io.h expects all platforms that are !APUS to provide definitions for isa_{io,mem}_base, pci_dram_offset. Instead of working around this with even more #ifdef kludge, just provide these definitions in the platform-specific file. Besides, this will be moving to include/asm-powerpc/ RSN, and, having to maintain ~550 lines for a 3 line delta doesn't seem very practical. Index: io.h =================================================================== RCS file: /cvsroot/gc-linux/linux/include/asm-ppc/io.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- io.h 23 Jun 2005 20:02:21 -0000 1.8 +++ io.h 10 Sep 2005 21:18:24 -0000 1.9 @@ -34,7 +34,7 @@ #include <asm/mpc83xx.h> #elif defined(CONFIG_85xx) #include <asm/mpc85xx.h> -#elif defined(CONFIG_APUS) || defined(CONFIG_GAMECUBE) +#elif defined(CONFIG_APUS) #define _IO_BASE 0 #define _ISA_MEM_BASE 0 #define PCI_DRAM_OFFSET 0 |
From: <aot...@us...> - 2005-08-30 23:33:31
|
Update of /cvsroot/gc-linux/linux/arch/ppc/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24191/arch/ppc/kernel Modified Files: cputable.c Log Message: Re-order this yet again. Push "750Cxe (83214)" below "750CXe Gekko (82214)" and "745/755" below that. Index: cputable.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/kernel/cputable.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- cputable.c 29 Aug 2005 19:50:20 -0000 1.11 +++ cputable.c 30 Aug 2005 23:33:23 -0000 1.12 @@ -198,10 +198,10 @@ .num_pmcs = 4, .cpu_setup = __setup_cpu_750 }, - { /* 750CXe "Gekko" (83214) */ - .pvr_mask = 0xffffffff, - .pvr_value = 0x00083214, - .cpu_name = "750CXe", + { /* 750CX (80100 and 8010x?) */ + .pvr_mask = 0xfffffff0, + .pvr_value = 0x00080100, + .cpu_name = "750CX", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -212,10 +212,10 @@ .num_pmcs = 4, .cpu_setup = __setup_cpu_750cx }, - { /* 745/755 */ - .pvr_mask = 0xfffff000, - .pvr_value = 0x00083000, - .cpu_name = "745/755", + { /* 750CX (82201 and 82202) */ + .pvr_mask = 0xfffffff0, + .pvr_value = 0x00082200, + .cpu_name = "750CX", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -224,12 +224,12 @@ .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750cx }, - { /* 750CX (80100 and 8010x?) */ + { /* 750CXe (82214) */ .pvr_mask = 0xfffffff0, - .pvr_value = 0x00080100, - .cpu_name = "750CX", + .pvr_value = 0x00082210, + .cpu_name = "750CXe", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -240,10 +240,10 @@ .num_pmcs = 4, .cpu_setup = __setup_cpu_750cx }, - { /* 750CX (82201 and 82202) */ - .pvr_mask = 0xfffffff0, - .pvr_value = 0x00082200, - .cpu_name = "750CX", + { /* 750CXe "Gekko" (83214) */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x00083214, + .cpu_name = "750CXe", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -254,10 +254,10 @@ .num_pmcs = 4, .cpu_setup = __setup_cpu_750cx }, - { /* 750CXe (82214) */ - .pvr_mask = 0xfffffff0, - .pvr_value = 0x00082210, - .cpu_name = "750CXe", + { /* 745/755 */ + .pvr_mask = 0xfffff000, + .pvr_value = 0x00083000, + .cpu_name = "745/755", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -266,7 +266,7 @@ .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750 }, { /* 750FX rev 1.x */ .pvr_mask = 0xffffff00, |
From: <he...@us...> - 2005-08-30 16:52:02
|
Update of /cvsroot/gc-linux/linux/arch/ppc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28757 Modified Files: Kconfig Log Message: It seems nothing is really broken, it looks like a design feature/decision. All existing device driver code references and empiric tests seem to confirm that the Gekko, as used in the GameCube, does not maintain cache coherency and needs explicit cache management. Setting CONFIG_NOT_COHERENT_CACHE=y here enables the Kernel DMA API to explicitly handle cache coherency, making it work as expected. Index: Kconfig =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/Kconfig,v retrieving revision 1.31 retrieving revision 1.32 diff -u -d -r1.31 -r1.32 --- Kconfig 29 Aug 2005 20:25:18 -0000 1.31 +++ Kconfig 30 Aug 2005 16:51:53 -0000 1.32 @@ -274,11 +274,10 @@ depends on 6xx || POWER3 || POWER4 default y -# FIXME: This is meant for cache incoherent cores, which is not the case for -# 750CXe (Gekko). However, according to isobel, turning this off stalls I/O -# for drivers using the DMA API (gcn-{dvd,bba}). For now this remains a -# band-aid for something else that's broken.. -# +# Although 750CXe (Gekko) seems to be cache coherent capable, the GAMECUBE +# does not maintain cache coherency with respect to dma enabled devices +# like the BBA, DI, ARAM, etc. +# We need Y here if we want a working kernel dma api. config NOT_COHERENT_CACHE bool depends on 4xx || 8xx || E200 || GAMECUBE |
From: <aot...@us...> - 2005-08-29 22:17:02
|
Update of /cvsroot/gc-linux/linux/arch/ppc/configs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26293/arch/ppc/configs Modified Files: gamecube_defconfig Log Message: Turn CONFIG_NOT_COHERENT_CACHE back on for now. Looks like everything that uses the DMA API stalls on I/O, according to isobel. Investigate. Index: gamecube_defconfig =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/configs/gamecube_defconfig,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- gamecube_defconfig 29 Aug 2005 19:50:20 -0000 1.34 +++ gamecube_defconfig 29 Aug 2005 22:16:54 -0000 1.35 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.13 -# Mon Aug 29 14:26:43 2005 +# Mon Aug 29 18:14:04 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y @@ -80,6 +80,7 @@ # CONFIG_WANT_EARLY_SERIAL is not set CONFIG_EMBEDDEDBOOT=y CONFIG_PPC_STD_MMU=y +CONFIG_NOT_COHERENT_CACHE=y # # Platform options @@ -171,6 +172,8 @@ CONFIG_LOWMEM_SIZE=0x30000000 CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xff100000 +CONFIG_CONSISTENT_SIZE=0x00200000 CONFIG_BOOT_LOAD=0x00800000 # |
From: <aot...@us...> - 2005-08-29 20:25:26
|
Update of /cvsroot/gc-linux/linux/arch/ppc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1248/arch/ppc Modified Files: Kconfig Log Message: Turn CONFIG_NOT_COHERENT_CACHE back on for now. Looks like everything that uses the DMA API stalls on I/O, according to isobel. Investigate. Index: Kconfig =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/Kconfig,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- Kconfig 29 Aug 2005 19:50:20 -0000 1.30 +++ Kconfig 29 Aug 2005 20:25:18 -0000 1.31 @@ -274,9 +274,14 @@ depends on 6xx || POWER3 || POWER4 default y +# FIXME: This is meant for cache incoherent cores, which is not the case for +# 750CXe (Gekko). However, according to isobel, turning this off stalls I/O +# for drivers using the DMA API (gcn-{dvd,bba}). For now this remains a +# band-aid for something else that's broken.. +# config NOT_COHERENT_CACHE bool - depends on 4xx || 8xx || E200 + depends on 4xx || 8xx || E200 || GAMECUBE default y endmenu |
From: <aot...@us...> - 2005-08-29 19:50:30
|
Update of /cvsroot/gc-linux/linux/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26847/include/linux Modified Files: fb.h Log Message: Merge 2.6.13 Index: fb.h =================================================================== RCS file: /cvsroot/gc-linux/linux/include/linux/fb.h,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- fb.h 23 Jun 2005 20:02:21 -0000 1.13 +++ fb.h 29 Aug 2005 19:50:21 -0000 1.14 @@ -527,11 +527,11 @@ u32 offset; /* current offset to buffer */ u32 buf_align; /* byte alignment of each bitmap */ u32 scan_align; /* alignment per scanline */ - u32 access_align; /* alignment per read/write */ + u32 access_align; /* alignment per read/write (bits) */ u32 flags; /* see FB_PIXMAP_* */ /* access methods */ - void (*outbuf)(struct fb_info *info, u8 *addr, u8 *src, unsigned int size); - u8 (*inbuf) (struct fb_info *info, u8 *addr); + void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size); + void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size); }; @@ -825,18 +825,9 @@ extern int fb_prepare_logo(struct fb_info *fb_info); extern int fb_show_logo(struct fb_info *fb_info); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); -extern void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf, - u8 *dst, u32 d_pitch, u8 *src, u32 idx, - u32 height, u32 shift_high, u32 shift_low, u32 mod); -extern void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf, - u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, - u32 height); -extern void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf, - u8 *dst, u32 d_pitch, u8 *src, u32 idx, +extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, u32 shift_high, u32 shift_low, u32 mod); -extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf, - u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, - u32 height); +extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height); extern void fb_set_suspend(struct fb_info *info, int state); extern int fb_get_color_depth(struct fb_var_screeninfo *var); extern int fb_get_options(char *name, char **option); |