![]() |
00001 /******************************************************************************* 00002 * 00003 * Freescale Semiconductor Inc. 00004 * (c) Copyright 2004-2014 Freescale Semiconductor, Inc. 00005 * ALL RIGHTS RESERVED. 00006 * 00007 ****************************************************************************//*! 00008 * 00009 * @file etpu_inj.c 00010 * 00011 * @author Milan Brejl [r54529] 00012 * 00013 * @version 1.0 00014 * 00015 * @date 17-Mar-2014 00016 * 00017 * @brief This file contains API for using the eTPU function 00018 * Direct Injection (INJ). 00019 * 00020 ****************************************************************************//*! 00021 * 00022 * @mainpage 00023 * 00024 * The eTPU INJ APIs @ref etpu_inj.c/.h includes API functions for eTPU 00025 * function Direct Injection. 00026 * 00027 * Each instance of the INJ eTPU function controls a single INJ channel together 00028 * with up to 3 BANK channels. The BANK channels can be common for more INJ 00029 * instances. 00030 * 00031 * This eTPU function enables to generate complex angle- and time-based output 00032 * patterns, primarily dedicated to direct injection timing control. 00033 * The INJ channel can control the outputs of up to 3 additional channels, 00034 * called BANK channels (e.g. Boost, Batt, ...). 00035 * 00036 * An injection sequence consists of injections. Each injection starts at a 00037 * defined angle (angle_start) and consists of phases. Each phase is defined 00038 * by output states of the INJ and all the BANK channels, a phase duration, 00039 * and options to generate DMA requests at the beginning of the phase. 00040 * The number of injections and the number of phases in each injection is 00041 * configurable. More INJ channels (individual injectors) may use separate 00042 * injection sequences, or can share the same sequence. 00043 * 00044 * There is an INJ parameter tdc_angle, relative to which all angles are 00045 * defined. Positive angles precede the tdc_angle, negative angles come after. 00046 * INJ parameter angle_irq which defines a tdc_angle-relative angle at which 00047 * an IRQ request is generated. The CPU may reconfigure the injection sequence 00048 * setting on this interrupt, but not later then the first injection 00049 * angle_start is reached. If the CPU does not reconfigure, the actual 00050 * injection sequence definition is used. 00051 * INJ parameter angle_stop defines the latest tdc_angle-relative angle when 00052 * the whole injection sequence must be finished. If it is not, all INJ and 00053 * BANK outputs are turned to inactive state, whatever injection phase is 00054 * active. 00055 * 00056 * The CPU can monitor the INJ operation using INJ state variables 00057 * injection_counter, phase_counter and error. The reported error flags are: 00058 * @ref INJ_ERROR_PREV_INJ_NOT_FINISHED - injection sequence can not start while 00059 * another INJ channel occupies the BANK channels. The injection sequence 00060 * is not generated. The global parameter INJ_active_bank_chans keeps 00061 * track of which BANK channels are in use. 00062 * @ref INJ_ERROR_LATE_START_ANGLE_1ST - the 1st injection start-angle was about 00063 * to be scheduled in past, hence the whole injection sequence was skipped. 00064 * @ref INJ_ERROR_LATE_START_ANGLE_NTH - the 2nd or later injection start-angle 00065 * was about to be scheduled in past, hence the rest of the injection 00066 * sequence was skipped. 00067 * @ref INJ_ERROR_STOPPED_BY_STOP_ANGLE - the injection sequence was not finished 00068 * before the stop-angle and hence the injection was hard-stopped at the 00069 * stop-angle. 00070 * 00071 *******************************************************************************/ 00072 /******************************************************************************* 00073 * Includes 00074 *******************************************************************************/ 00075 #include "etpu_inj.h" /* private header file */ 00076 #include "etpu_util.h" /* utility routines for working with the eTPU */ 00077 00078 /******************************************************************************* 00079 * Global variables 00080 *******************************************************************************/ 00081 extern uint32_t fs_etpu_data_ram_start; 00082 extern uint32_t fs_etpu_data_ram_ext; 00083 00084 /******************************************************************************* 00085 * FUNCTION: fs_etpu_inj_init 00086 ****************************************************************************//*! 00087 * @brief This function initializes eTPU channels to run INJ function. 00088 * 00089 * @note The following actions are performed in order: 00090 * -# Use user-defined CPBA or allocate new eTPU DATA RAM 00091 * -# Write chan config registers and FM bits 00092 * -# Write channel parameters 00093 * -# Write HSR 00094 * -# Set channel priority 00095 * 00096 * @param *p_inj_instance - This is a pointer to the instance structure 00097 * @ref inj_instance_t. 00098 * @param *p_inj_config - This is a pointer to the structure of configuration 00099 * parameters @ref inj_config_t. 00100 * 00101 * @return Error codes that can be returned are: 00102 * - @ref FS_ETPU_ERROR_MALLOC - eTPU DATA RAM memory allocation error 00103 * - @ref FS_ETPU_ERROR_NONE - No error 00104 * 00105 * @warning This function does not configure the pins, only the eTPU channels. 00106 *******************************************************************************/ 00107 uint32_t fs_etpu_inj_init( 00108 struct inj_instance_t *p_inj_instance, 00109 struct inj_config_t *p_inj_config) 00110 { 00111 uint8_t chan_num_inj; 00112 uint8_t chan_num_bank_1; 00113 uint8_t chan_num_bank_2; 00114 uint8_t chan_num_bank_3; 00115 uint8_t priority; 00116 uint32_t *cpba; 00117 uint32_t *cpba_injections; 00118 uint32_t *cpba_phases; 00119 uint8_t injection_count; 00120 uint8_t phase_count = 0; 00121 struct inj_injection_config_t *p_injection_config; 00122 uint32_t *p_phase_config; 00123 uint8_t bank_chan_count = 0; 00124 uint8_t inactive_polarities = 0; 00125 uint24_t bank_chans = 0; 00126 uint32_t bank_chans_mask = 0; 00127 uint32_t cr; 00128 uint8_t i,j; 00129 00130 chan_num_inj = p_inj_instance->chan_num_inj; 00131 chan_num_bank_1 = p_inj_instance->chan_num_bank_1; 00132 chan_num_bank_2 = p_inj_instance->chan_num_bank_2; 00133 chan_num_bank_3 = p_inj_instance->chan_num_bank_3; 00134 priority = p_inj_instance->priority; 00135 cpba = p_inj_instance->cpba; 00136 cpba_injections = p_inj_instance->cpba_injections; 00137 cpba_phases = p_inj_instance->cpba_phases; 00138 00139 /* Use user-defined CPBA or allocate new eTPU DATA RAM for chan. parameters */ 00140 if(cpba == 0) 00141 { 00142 cpba = fs_etpu_malloc(FS_ETPU_INJ_NUM_PARMS); 00143 if(cpba == 0) 00144 { 00145 return(FS_ETPU_ERROR_MALLOC); 00146 } 00147 else 00148 { 00149 p_inj_instance->cpba = cpba; 00150 } 00151 } 00152 /* Use user-defined CPBA or allocate new eTPU DATA RAM for injections */ 00153 injection_count = p_inj_config->injection_count; 00154 if(cpba_injections == 0) 00155 { 00156 cpba_injections = 00157 fs_etpu_malloc(FS_ETPU_INJ_INJECTION_STRUCT_SIZE * injection_count); 00158 if(cpba_injections == 0) 00159 { 00160 return(FS_ETPU_ERROR_MALLOC); 00161 } 00162 else 00163 { 00164 p_inj_instance->cpba_injections = cpba_injections; 00165 } 00166 } 00167 /* Use user-defined CPBA or allocate new eTPU DATA RAM for inj. phases */ 00168 if(cpba_phases == 0) 00169 { 00170 /* Sum number of all injection phases */ 00171 p_injection_config = p_inj_config->p_injection_config; 00172 for(i=0; i<injection_count; i++) 00173 { 00174 phase_count += p_injection_config->phase_count; 00175 p_injection_config++; 00176 } 00177 00178 cpba_phases = fs_etpu_malloc(FS_ETPU_INJ_PHASE_STRUCT_SIZE * phase_count); 00179 if(cpba_phases == 0) 00180 { 00181 return(FS_ETPU_ERROR_MALLOC); 00182 } 00183 else 00184 { 00185 p_inj_instance->cpba_phases = cpba_phases; 00186 } 00187 } 00188 00189 /* Write chan config registers and FM bits */ 00190 cr = (FS_ETPU_INJ_TABLE_SELECT << 24) + 00191 (FS_ETPU_INJ_FUNCTION_NUMBER << 16) + 00192 (((uint32_t)cpba - fs_etpu_data_ram_start) >> 3); 00193 eTPU->CHAN[chan_num_inj].CR.R = cr; 00194 eTPU->CHAN[chan_num_inj].SCR.R = (uint32_t)p_inj_instance->polarity_inj 00195 + FS_ETPU_INJ_FM1_CHANNEL_INJ; 00196 if(chan_num_bank_3 != FS_ETPU_INJ_BANK_CHAN_NOT_USED) 00197 { 00198 bank_chan_count = 1; 00199 bank_chans = chan_num_bank_3; 00200 bank_chans_mask = 1<<chan_num_bank_3; 00201 inactive_polarities = p_inj_instance->polarity_bank; 00202 eTPU->CHAN[chan_num_bank_3].CR.R = cr; 00203 eTPU->CHAN[chan_num_bank_3].SCR.R = (uint32_t)p_inj_instance->polarity_bank 00204 + FS_ETPU_INJ_FM1_CHANNEL_BANK; 00205 } 00206 if(chan_num_bank_2 != FS_ETPU_INJ_BANK_CHAN_NOT_USED) 00207 { 00208 bank_chan_count++; 00209 bank_chans = (bank_chans << 8) | chan_num_bank_2; 00210 bank_chans_mask |= 1<<chan_num_bank_2; 00211 inactive_polarities = (inactive_polarities << 1) | p_inj_instance->polarity_bank; 00212 eTPU->CHAN[chan_num_bank_2].CR.R = cr; 00213 eTPU->CHAN[chan_num_bank_2].SCR.R = (uint32_t)p_inj_instance->polarity_bank 00214 + FS_ETPU_INJ_FM1_CHANNEL_BANK; 00215 } 00216 if(chan_num_bank_1 != FS_ETPU_INJ_BANK_CHAN_NOT_USED) 00217 { 00218 bank_chan_count++; 00219 bank_chans = (bank_chans << 8) | chan_num_bank_1; 00220 bank_chans_mask |= 1<<chan_num_bank_1; 00221 inactive_polarities = (inactive_polarities << 1) | p_inj_instance->polarity_bank; 00222 eTPU->CHAN[chan_num_bank_1].CR.R = cr; 00223 eTPU->CHAN[chan_num_bank_1].SCR.R = (uint32_t)p_inj_instance->polarity_bank 00224 + FS_ETPU_INJ_FM1_CHANNEL_BANK; 00225 } 00226 inactive_polarities = (inactive_polarities << 1) | p_inj_instance->polarity_inj; 00227 00228 /* Write channel parameters */ 00229 /* 24-bit */ 00230 *(cpba + ((FS_ETPU_INJ_OFFSET_P_INJECTION_FIRST - 1)>>2)) = (uint32_t)cpba_injections - fs_etpu_data_ram_start; 00231 *(cpba + ((FS_ETPU_INJ_OFFSET_P_INJECTION - 1)>>2)) = 0; 00232 *(cpba + ((FS_ETPU_INJ_OFFSET_P_PHASE - 1)>>2)) = 0; 00233 *(cpba + ((FS_ETPU_INJ_OFFSET_BANK_CHANS - 1)>>2)) = bank_chans; 00234 *(cpba + ((FS_ETPU_INJ_OFFSET_ANGLE_IRQ - 1)>>2)) = p_inj_config->angle_irq; 00235 *(cpba + ((FS_ETPU_INJ_OFFSET_ANGLE_STOP - 1)>>2)) = p_inj_config->angle_stop; 00236 *(cpba + ((FS_ETPU_INJ_OFFSET_TDC_ANGLE - 1)>>2)) = p_inj_instance->tdc_angle; 00237 *(cpba + ((FS_ETPU_INJ_OFFSET_TDC_ANGLE_ACTUAL - 1)>>2)) = p_inj_instance->tdc_angle; 00238 00239 /* 8-bit */ 00240 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_INJECTION_COUNT ) = injection_count; 00241 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_INJECTION_COUNTER) = 0; 00242 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_PHASE_COUNTER ) = 0; 00243 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_BANK_CHANS_COUNT ) = bank_chan_count; 00244 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_ERROR ) = 0; 00245 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_INACTIVE_POLARITIES) = inactive_polarities; 00246 00247 /* 32-bit */ 00248 *(cpba + (FS_ETPU_INJ_OFFSET_BANK_CHANS_MASK >>2)) = bank_chans_mask; 00249 00250 /* Write array of injection parameters */ 00251 p_injection_config = p_inj_config->p_injection_config; 00252 00253 for(i=0; i<injection_count; i++) 00254 { 00255 phase_count = p_injection_config->phase_count; 00256 p_phase_config = p_injection_config->p_phase_config; 00257 00258 /* 24-bit */ 00259 *(cpba_injections + ((FS_ETPU_INJ_OFFSET_P_PHASE_FIRST - 1)>>2)) = (uint32_t)cpba_phases - fs_etpu_data_ram_start; 00260 *(cpba_injections + ((FS_ETPU_INJ_OFFSET_ANGLE_START - 1)>>2)) = p_injection_config->angle_start; 00261 /* 8-bit */ 00262 *((uint8_t*)cpba_injections + FS_ETPU_INJ_OFFSET_PHASE_COUNT ) = phase_count; 00263 00264 for(j=0; j<phase_count; j++) 00265 { 00266 /* 32-bit */ 00267 *cpba_phases = *p_phase_config; 00268 p_phase_config++; 00269 cpba_phases += FS_ETPU_INJ_PHASE_STRUCT_SIZE >> 2; 00270 } 00271 00272 p_injection_config++; 00273 cpba_injections += FS_ETPU_INJ_INJECTION_STRUCT_SIZE >> 2; 00274 } 00275 00276 /* Write HSR and Set channel priority*/ 00277 eTPU->CHAN[chan_num_inj].HSRR.R = FS_ETPU_INJ_HSR_INIT; 00278 fs_etpu_enable(chan_num_inj, priority); 00279 if(chan_num_bank_1 != FS_ETPU_INJ_BANK_CHAN_NOT_USED) 00280 { 00281 eTPU->CHAN[chan_num_bank_1].HSRR.R = FS_ETPU_INJ_HSR_INIT; 00282 fs_etpu_enable(chan_num_bank_1, priority); 00283 } 00284 if(chan_num_bank_2 != FS_ETPU_INJ_BANK_CHAN_NOT_USED) 00285 { 00286 eTPU->CHAN[chan_num_bank_2].HSRR.R = FS_ETPU_INJ_HSR_INIT; 00287 fs_etpu_enable(chan_num_bank_2, priority); 00288 } 00289 if(chan_num_bank_3 != FS_ETPU_INJ_BANK_CHAN_NOT_USED) 00290 { 00291 eTPU->CHAN[chan_num_bank_3].HSRR.R = FS_ETPU_INJ_HSR_INIT; 00292 fs_etpu_enable(chan_num_bank_3, priority); 00293 } 00294 00295 return(FS_ETPU_ERROR_NONE); 00296 } 00297 00298 /******************************************************************************* 00299 * FUNCTION: fs_etpu_inj_config 00300 ****************************************************************************//*! 00301 * @brief This function changes the INJ configuration. 00302 * 00303 * @note The following actions are performed in order: 00304 * -# Read channel parameter from eTPU DATA RAM to check no injection 00305 * sequence is active on this injector. 00306 * -# Write configuration parameter values to eTPU DATA RAM 00307 * -# Write HSR 00308 * 00309 * @warning The new injection sequence definition (array of injections and array 00310 * of phases of each injection) must fit into the eTPU DATA RAM 00311 * already allocated. 00312 * 00313 * @param *p_inj_instance - This is a pointer to the instance structure 00314 * @ref inj_instance_t. 00315 * @param *p_inj_config - This is a pointer to the structure of configuration 00316 * parameters @ref inj_config_t. 00317 * 00318 * @return Error codes that can be returned are: 00319 * - @ref FS_ETPU_ERROR_NONE - No error, injection parameters were set. 00320 * - @ref FS_ETPU_ERROR_TIMING - The injection parameters were not set 00321 * because the injection sequence is active. During this time 00322 * the injection parameters cannot be updated. 00323 * 00324 *******************************************************************************/ 00325 uint32_t fs_etpu_inj_config( 00326 struct inj_instance_t *p_inj_instance, 00327 struct inj_config_t *p_inj_config) 00328 { 00329 uint32_t *cpba; 00330 uint32_t *cpbae; 00331 uint32_t *cpba_injections; 00332 uint32_t *cpba_phases; 00333 uint8_t injection_idx; 00334 uint8_t injection_count; 00335 uint8_t phase_count; 00336 struct inj_injection_config_t *p_injection_config; 00337 uint32_t *p_phase_config; 00338 uint8_t i,j; 00339 00340 cpba = p_inj_instance->cpba; 00341 cpba_injections = p_inj_instance->cpba_injections; 00342 cpba_phases = p_inj_instance->cpba_phases; 00343 00344 /* Check if the injection sequence is not active */ 00345 injection_idx = *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_INJECTION_COUNTER); 00346 if(injection_idx != 0) 00347 { 00348 /* An injection sequence is active on this injector */ 00349 return(FS_ETPU_ERROR_TIMING); 00350 } 00351 else 00352 { 00353 /* Write channel parameters */ 00354 /* 24-bit - use cpbae to prevent from overwriting bits 31:24 */ 00355 cpbae = cpba + (0x4000 >> 2); /* sign-extended memory area */ 00356 *(cpbae + ((FS_ETPU_INJ_OFFSET_ANGLE_IRQ - 1)>>2)) = p_inj_config->angle_irq; 00357 *(cpbae + ((FS_ETPU_INJ_OFFSET_ANGLE_STOP - 1)>>2)) = p_inj_config->angle_stop; 00358 00359 /* 8-bit */ 00360 injection_count = p_inj_config->injection_count; 00361 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_INJECTION_COUNT) = injection_count; 00362 00363 /* Write array of injection parameters */ 00364 p_injection_config = p_inj_config->p_injection_config; 00365 00366 for(i=0; i<injection_count; i++) 00367 { 00368 phase_count = p_injection_config->phase_count; 00369 p_phase_config = p_injection_config->p_phase_config; 00370 00371 /* 24-bit */ 00372 *(cpba_injections + ((FS_ETPU_INJ_OFFSET_P_PHASE_FIRST - 1)>>2)) = (uint32_t)cpba_phases - fs_etpu_data_ram_start; 00373 *(cpba_injections + ((FS_ETPU_INJ_OFFSET_ANGLE_START - 1)>>2)) = p_injection_config->angle_start; 00374 /* 8-bit */ 00375 *((uint8_t*)cpba_injections + FS_ETPU_INJ_OFFSET_PHASE_COUNT ) = phase_count; 00376 00377 for(j=0; j<phase_count; j++) 00378 { 00379 /* 32-bit */ 00380 *cpba_phases = *p_phase_config; 00381 p_phase_config++; 00382 cpba_phases += FS_ETPU_INJ_PHASE_STRUCT_SIZE >> 2; 00383 } 00384 00385 p_injection_config++; 00386 cpba_injections += FS_ETPU_INJ_INJECTION_STRUCT_SIZE >> 2; 00387 } 00388 /* Write HSR to run UPDATE on eTPU, which reschedules the new start_angle[0] */ 00389 eTPU->CHAN[p_inj_instance->chan_num_inj].HSRR.R = FS_ETPU_INJ_HSR_UPDATE; 00390 00391 return(FS_ETPU_ERROR_NONE); 00392 } 00393 } 00394 00395 /******************************************************************************* 00396 * FUNCTION: fs_etpu_inj_get_states 00397 ****************************************************************************//*! 00398 * @brief This function reads INJ state variables, including error flags, 00399 * and clears the eTPU error after reading. 00400 * 00401 * @note The following actions are performed in order: 00402 * -# Read state parameter values from eTPU DATA RAM 00403 * -# Clear INJ error 00404 * 00405 * @param *p_inj_instance - This is a pointer to the instance structure 00406 * @ref inj_instance_t. 00407 * @param *p_inj_states - This is a pointer to the return structure of states 00408 * @ref inj_states_t. 00409 * 00410 * @return Error codes that can be returned are: 00411 * - @ref FS_ETPU_ERROR_NONE - No error 00412 * 00413 *******************************************************************************/ 00414 uint32_t fs_etpu_inj_get_states( 00415 struct inj_instance_t *p_inj_instance, 00416 struct inj_states_t *p_inj_states) 00417 { 00418 uint32_t *cpba; 00419 00420 cpba = p_inj_instance->cpba; 00421 00422 /* Read INJ channel parameters */ 00423 p_inj_states->injection_idx = *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_INJECTION_COUNTER); 00424 p_inj_states->phase_idx = *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_PHASE_COUNTER); 00425 p_inj_states->error = *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_ERROR); 00426 /* Clear INJ error */ 00427 *((uint8_t*)cpba + FS_ETPU_INJ_OFFSET_ERROR) = 0; 00428 00429 return(FS_ETPU_ERROR_NONE); 00430 } 00431 00432 /******************************************************************************* 00433 * 00434 * Copyright: 00435 * Freescale Semiconductor, INC. All Rights Reserved. 00436 * You are hereby granted a copyright license to use, modify, and 00437 * distribute the SOFTWARE so long as this entire notice is 00438 * retained without alteration in any modified and/or redistributed 00439 * versions, and that such modified versions are clearly identified 00440 * as such. No licenses are granted by implication, estoppel or 00441 * otherwise under any patents or trademarks of Freescale 00442 * Semiconductor, Inc. This software is provided on an "AS IS" 00443 * basis and without warranty. 00444 * 00445 * To the maximum extent permitted by applicable law, Freescale 00446 * Semiconductor DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 00447 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 00448 * PARTICULAR PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 00449 * REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 00450 * AND ANY ACCOMPANYING WRITTEN MATERIALS. 00451 * 00452 * To the maximum extent permitted by applicable law, IN NO EVENT 00453 * SHALL Freescale Semiconductor BE LIABLE FOR ANY DAMAGES WHATSOEVER 00454 * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 00455 * BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER 00456 * PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. 00457 * 00458 * Freescale Semiconductor assumes no responsibility for the 00459 * maintenance and support of this software 00460 ******************************************************************************/ 00461 /******************************************************************************* 00462 * 00463 * REVISION HISTORY: 00464 * 00465 * FILE OWNER: Milan Brejl [r54529] 00466 * 00467 * Revision 1.0 2014/03/17 r54529 00468 * Minor comment and formating improvements. 00469 * Ready for eTPU Engine Control Library release 1.0. 00470 * 00471 * Revision 0.2 2013/08/02 r54529 00472 * fs_etpu_inj_update() removed, fs_etpu_inj_config() modified so that it can be 00473 * used anytime to update the injection parameters. During the injection 00474 * sequence activity the injection parameters cannot be updated and 00475 * fs_etpu_inj_config() returns FS_ETPU_ERROR_TIMING. 00476 * Separate polarity for Inj and Bank channels. 00477 * 00478 * Revision 0.1 2012/05/17 r54529 00479 * Initial version of file. 00480 ******************************************************************************/
Generated by ![]() |
© Freescale Semiconductor Inc. 2004 - 2012. All Rights Reserved. |